[Problem] Register Zeiten zu lang, Probleme bei DSL Störung

xrated

Aktives Mitglied
Mitglied seit
2 Jul 2012
Beiträge
823
Punkte für Reaktionen
2
Punkte
18
Ich weiß nicht genau wie lang die Registery intervals bei 1&1 sind aber vorhin sah ich was von 4 Std. Das ist viel zu lange, geht gar nicht.

Das allgemeine Problem mit dynamischen IPs, wie viele bereits kennen, ist nun wenn meinerseits ein täglicher IP Wechsel stattfindet, funktioniert die Registrierung so lange nicht bis sie abgelaufen und erneuert wird.
Deswegen habe ich ein Script welches ein ein sip reload nach dem ddns update macht.
Manchmal ist aber die Internet Verbindung zu lange down z.B. bei einer 5min. Störung und der sip reload findet dann nicht statt weil der ddns nicht korrekt antwortet.
Ich kann in dem Script auch nicht ewig warten, weil das mit cron alle paar Minuten gestartet wird und die sich sonst gegenseitig stören.

Gibts da irgendeine Lösung in Asterisk die Register Zeiten zu verkürzen? maxexpiry ist ja nur für incoming register, bringt also nix.
Ich habe jetzt das Script verändert so das der sip reload stattfindet sobald der ddns wieder ok ist, hätte mich aber interessiert ob das auch anders geht.

Man kann sowas auch nicht monitoren weil Asterisk nur brav registered sagt.

qualify prüft ja imho auch nur ob der Remote Peer verfügbar ist, den hab ich auf 1h gesetzt weil ich früher bei Vodafone sonst das Problem hatte das ich auf "untrusted" gesetzt wurde.
 
Zuletzt bearbeitet:
1&1 an dynamnischen IPs ist leider sehr sehr unschön (weshalbs bei mir mittlerweile auf einem vServer mit statischer IP liegt). Die Registerzeiten bekommest Du nicht runter.
Einzige Variante wäre, den

Code:
asterisk -rx "sip reload"

Befehl mit in das ddns-Skript einzubauen, respektive wenn dort ein IP-Chaange erkannt wird, den reload ausführen zu lassen. Dann bist Du sozusagen immer "hinter dem change" und es könnte angenehmer funktionieren.
Rein praktisch rate ich aber in der tat jedem von 1&1 an dynamischer IP ab (und die behaupten, sie hätten das beste Netz :mad:)
 
res_stun_monitor prüft in einstellbarem Interval die eigene WAN Adresse mittels eines STUN Servers und veranlasst bei Erkennen eines Adresswechsels ein sip reload.

Man kann die Ablaufzeit von Registrierungen direkt in der register Anweisung beeinflussen, dazu ~Sekunden am Ende anhängen. Die Frage ist allerdings, ob der Provider damit einverstanden ist. Die TCom lehnt Registrierungen mit unter 1h ab.
 
Mit ~3600 sehe ich leider auch keine Änderung.
Wenn res_stun_monitor einen Adresswechsel erkennt aber der ddns Eintrag noch auf die alte IP läuft, funktioniert das dann überhaupt?
Der ISP macht ja glaube keine Namensauflösung, Asterisk macht das und registriert sich dann mit der alten IP vom externhost Parameter als Quelle?
Deswegen prüfe ich in meinem Skript erst ob der ddns aktuell ist und mache erst danach den reload.
Und ohne ddns gehts ja afaik nicht, weil sonst private IPs im SIP Header stehen.

Code:
#!/bin/bash
#############
###<Notes>###
#############
#astipupdate script, detects public, ddns and sip peer ip change , blocks unwanted sip traffic.
#Version 1.3
#copy this script to /etc/init.d and activate it with update-rc.d astipupdate defaults
#enable in cron like: */3 * * * * root /etc/init.d/astipupdate updateall &> /dev/null
#if you wait too long between ddns checks, the host may not respond
#dont do it too often either, or the script may not finish in time because it waits for dns ttl timeout (usually 60secs)
#and dsl reconnects may take some time
#2014-2016 by xrated


#parameters:
#start = permit sip traffic only for trusted hosts via iptables (use VPN if you need to connect other networks)
#updatepeer = update iptables if sip peer ip changes and reload asterisk if parameter set
#(reload can be avoided by using dnsmgr in Asterisk)
#updatepublic = reloads asterisk on public ip change, make sure ddns resolves to new ip before doing this
#(not needed if updateddns is running also, parameter only usefull if ddns is not updated by this script)
#updateddns = update dyndns on public ip change and reload asterisk (dnsmgr doesnt work here, seems it doesnt monitor own ip)
#updateall = consists of updateddns and updatepeer


#Please note: When using NAT, dynamic DNS and externhost parameter in Asterisk, after your public IP changes its important
#that an SIP register is done with DDNS resolving to correct IP (also on this machine). Otherwise your phone
#will not be reachable. Imagine the SIP registration is valid for 2 hours (some providers are doing this) and
#after your public ip changes, an sip reload is done to issue new sip registration. The provider will not know
#our new address if the DDNS record still points to the old IP. So the system will not be reachable until it
#will register again (in 2 hours). This is why this script respects also DNS TTL times to make sure the issued
#sip reload command in Asterisk is done after Ping to DDNS record responds with new IP. Using externrefresh
#parameter and res_stun_monitor in Asterisk has no effect on this issue, it will not trigger any new SIP register.


#A word to SRV records and srvlookup parameter in Asterisk. srvlookup in Asterisk is currently supported only for
#outbound calls when FQDN names are specified in Dial Command.


##############
###</Notes>###
##############


### BEGIN INIT INFO
# Provides:             astipupdate
# Required-Start:       $network $asterisk
# Required-Stop:
# Default-Start:        2 3 4 5
# Default-Stop:         0 1 6
# Short-Description:    astipupdate ip change detector
# Description:          astipupdate updates public ip, sip peers, ddns and blocks unwanted sip traffic
### END INIT INFO




########################
##Start Configuration ##
########################


nic=eth0
sipport=5060
localnet=192.168.5.0/24


# allowed sip hosts
# info: when using dns names for sip peers, ip may change and iptables will not update them.
# start script regularly with cron and updatepeer parameter if this is the case.
# the script will also reload sip in asterisk on host ip changes.
# some dns names will point to multiple child dns names via round robin,
# make sure you dont enter the parent dns entry or alias i.e. sip.personal-voip.de.
# restart of service is needed when changes on this list are done.
# warning: use only dns names in list below, otherwise the host command will not work which detects ip changes (updatepeer)
sippeer[0]="sip.freevoipdeal.com" #host has known ip changes
#sippeer[1]="cgw.pbx-network.de" #parent is sip.personal-voip.de
sippeer[1]="fritz.box" #fritzbox is running as sip client and ata
#sippeer[2]="sip-proxy01.pbx-network.de"
#sippeer[3]="sip-proxy02.pbx-network.de"
#sippeer[4]="sip-proxy03.pbx-network.de"
#sippeer[5]="ast01.pbx-network.de"
#sippeer[6]="ast02.pbx-network.de"
#sippeer[7]="ast03.pbx-network.de"
#sippeer[8]="ast04.pbx-network.de"
#sippeer[9]="ast05.pbx-network.de"


# range of allowed sip peers
#siprange[0]="46.182.250.0/24" #equada (pbx network)
#siprange[1]="193.106.16.0/22" #equada (pbx network)
#siprange[2]="46.182.248.0/21" #pbx network
siprange[0]="212.227.67.0/24" #1und1
siprange[1]="212.227.18.0/24" #1und1
siprange[2]="192.168.200.0/24" #vpn


# setting for peer checking
astreloadonpeeripchange=no #reload asterisk if peer changes ip? instead you can use dnsmgr.conf to avoid reload


# dyndns settings
dynupdatesperhour=2 # the maximum of updates that should happen per hour to not abuse the provider
dyncheckcount=3 # how often try to check n 10s intervals after ddns was updated and ttl expired (standard is 60secs)
                #3 means 60s + 3x10s = 90s max so you should not schedule cron more often then every 2min
dynuseragent="astip ddns update/1.3 [email protected]"


# dynip profiles
# choose from: noip:dyndns,dnsdynamic,dyndnss,twodns,goip,ddns,freedns,duckdns (not all tested)
# please note: goip and others may have a special user for updating
# for duckdns,freedns no user is required, use token as password
# noip may not work anylonger (badauth message)
#dynprofile[0]=duckdns
#dyndomain[0]=somewhere.duckdns.org
#dynuser[0]=nouser
#dynpass[0]=yourtoken








#######################
###END CONFIGURATION###
#######################


pidfolder="/run/asterisk"
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
currdate=$(date)
NAME="astipupdate"
DESC="astipupdate ip change detector"
iptablesbin="/sbin/iptables"
logfile="/var/log/asterisk/astupdate.log" #make sure this is not readable by everyone as this may contain ddns passwords
logfolder=$(dirname "$logfile")
# Gracefully exit if the package has been removed.
test -x "$iptablesbin" || exit 0
[ -d "$logfolder" ] || mkdir "$logfolder"
[ -f "$logfile" ] || touch /var/log/asterisk/astupdate.log


#################


d_start() {
# adds all needed sip peers to iptables
echo "$(date) start: astipupdate daemon ..." | tee -a "$logfile"
if [ "$sipport" -gt 0 ] && [ -n "$nic" ]; then


    if ([ -n "$localnet" ]) || ([ -n "$sippeer[0]" ] || [ -n "$siprange[0]" ]); then


        #allow all loopback traffic
        iptables -A INPUT -i lo -j ACCEPT 2>> "$logfile"
        iptables -A OUTPUT -o lo -j ACCEPT 2>> "$logfile"


        #allow SIP in your local lan
        if [ -n "$localnet" ]; then
            iptables -A INPUT -i "$nic" -p udp --source "$localnet" --dport "$sipport" -j ACCEPT 2>> "$logfile"
            iptables -A OUTPUT -o "$nic" -p udp --destination "$localnet" --dport "$sipport" -j ACCEPT 2>> "$logfile"
        fi


        #allow SIP to/from all defined sip peers
        if [ -n "$sippeer[0]" ]; then


            for peer in "${!sippeer[@]}"; do
                iptables -A INPUT -i "$nic" -p udp --source ${sippeer[$peer]} --dport "$sipport" -j ACCEPT 2>> "$logfile"
                iptables -A OUTPUT -o "$nic" -p udp --destination ${sippeer[$peer]} --dport "$sipport" -j ACCEPT 2>> "$logfile"
            done
        fi
        if [ -n "$siprange[0]" ]; then


            for range in "${!siprange[@]}"; do
                iptables -A INPUT -i "$nic" -p udp --source ${siprange[$range]} --dport "$sipport" -j ACCEPT 2>> "$logfile"
                iptables -A OUTPUT -o "$nic" -p udp --destination ${siprange[$range]} --dport "$sipport" -j ACCEPT 2>> "$logfile"
            done
        fi


        #new chain for remaining sip traffic (has to be last, otherwise all sip traffic will be blocked)
        iptables -N SIPLOGGING  #new chain LOGGING
        #all remaining sip traffic will be sent to chain SIPLOGGING
        iptables -A INPUT -i "$nic" -p udp --dport "$sipport" -j SIPLOGGING 2>> "$logfile" #every remaining incoming sip goes to chain
        iptables -A OUTPUT -o "$nic" -p udp --dport "$sipport" -j SIPLOGGING 2>> "$logfile" #if somebody internally abuses our system and wants to reach other sip servers
        iptables -A SIPLOGGING -m limit --limit 2/min -j LOG --log-prefix "IPTables-Dropped-SIP " 2>> "$logfile" #limit sip traffic in this chain
        iptables -A SIPLOGGING -j DROP 2>> "$logfile"  #drop remaining sip


    else
        echo "$(date) start: cannot start astipupdate, localnet or sippeer/siprange empty in config" | tee -a "$logfile"
        exit 1
    fi




else
    echo "$(date) start: cannot start astipupdate, sip port or nic empty in config" | tee -a "$logfile"
fi
d_public # write initial public ip to file
}


d_stop() {
# sets iptables back to defaults
echo "$(date) stop: astipupdate daemon ..." | tee -a "$logfile"
iptables -F 2>> "$logfile"
iptables -X 2>> "$logfile"
iptables -P INPUT ACCEPT 2>> "$logfile"
iptables -P FORWARD ACCEPT 2>> "$logfile"
iptables -P OUTPUT ACCEPT 2>> "$logfile"
}


###############


d_astreload() {
# reloads asterisk if called by peer or ddns sub


# reload sip in asterisk if sip peer was changed
if [ "$do_astpeerreload" = "yes" ] && [ "$astreloadonpeeripchange" = "yes" ]; then
    echo "$(date) sip peer: reload asterisk" | tee -a "$logfile"
    asterisk -rx "sip reload" 2>> "$logfile"
fi


# reload sip in asterisk if ddns was changed
if [ "$do_astddnsreload" = "yes" ]; then
    echo "$(date) ddns: will reload asterisk because ddns changed" | tee -a "$logfile"
    asterisk -rx "sip reload" 2>> "$logfile"
    if [ "$?" != 0 ]; then
        echo "$(date) ddns: warning, reload asterisk was not successfull!" | tee -a "$logfile"
    fi
fi




}


d_checkast() {
# checks if asterisk is alive
check_ast=$( ps -A | grep asterisk )
if [ -z "$check_ast" ]; then
    echo "$(date) checkast: asterisk doesnt run, no public and peer ip check will be done!" | tee -a "$logfile"
else
    echo "$(date) checkast: asterisk is running"
fi
}


d_public() {
# checks public ip and reloads asterisk if neccessary
# reload of asterisk makes sense when the isp uses very long register intervals i.e. 1h. If your public ip changes
# and register is not renewed, your pbx is not reachable until it will reregister
# make sure your dyndns entry points to correct address, otherwise sip reload will have no effect because the other sip peer will still get old ip when registering


if [ -n "$check_ast" ]; then


    if [ -f ${pidfolder}/publicip.pid ]; then
        stored_publicip=$(cat ${pidfolder}/publicip.pid)
    fi
    #wget http://checkip.dyndns.org/ -q -O - | grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' > "${pidfolder}/publicip.pid"
    wget -qO- ipinfo.io/ip > "${pidfolder}/publicip.pid"
    if [ -z "$stored_publicip" ]; then
        echo "$(date) public ip: script runs 1st time, no checking of changed public ip possible" | tee -a "$logfile"
    else
        current_publicip=$(cat $pidfolder/publicip.pid)
        if [ "$current_publicip" != "$stored_publicip" ] && [ -n "$current_publicip" ]; then
            echo "$(date) public ip: ${current_hostip} changed to ${current_publicip}, detected on ${currdate}" | tee -a "$logfile"
            asterisk -rx "sip reload" 2>> "$logfile"
        elif [ -z "$current_publicip" ]; then
            echo "$(date) public ip: could not get actual ip" | tee -a "$logfile"
        else
            echo "$(date) public ip: ${current_publicip} no change detected"
        fi
    fi
fi


}


#################


d_ddns() {
# dynip updater


# reset variable
do_astddnsreload=""


# get last change hour and actual hour
lastrun_hour=$(if [ -f $pidfolder/ddnschangedate.pid ]; then ls -l $pidfolder/ddnschangedate.pid | awk {'print $8'} | awk -F':' '{print $1}';fi)
current_hour=$(date | awk {'print $4'} | awk -F':' '{print $1}')
# reset counter if hour doesnt match
if [ "$lastrun_hour" != "$current_hour" ]; then
    echo 0 > $pidfolder/ddnschangesperhour.pid
fi


#current_ip=$(wget http://checkip.dyndns.org/ -q -O - | grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}')
current_ip=$(wget -qO- ipinfo.io/ip)
echo $current_ip > "${pidfolder}/ddnsip.pid"


if [ -z "$current_ip" ]; then
    echo "$(date) ddns: could not get your public ip, is internet up?" | tee -a "$logfile"
else


    for index in "${!dyndomain[@]}"; do
        current_dynip="" #reset variable
        #current_dynip=$(ping -c 1 ${dyndomain[$index]} | awk '{ print $3 }' | head -n1 | tr -d '()')
        #current_dynip=$(host ${dyndomain[$index]} | awk '{ print $4 }' | head -n1)
        current_dynip=$(dig +short ${dyndomain[$index]})
        #if [ "$current_dynip" = "found:" ]; then #for host
        #if [[ "$current_dynip" == "ping: unknown host"* ]]; then #for ping
        if [ -z "$current_dynip" ]; then
            echo "$(date) ddns: could not find a dns record for ${dyndomain[$index]}, does it exist?" | tee -a "$logfile"
        elif [ "$current_dynip" != "$current_ip" ] && [ -n "$current_dynip" ]; then
            #ddnsipchanged=yes
            echo "$(date) ddns: ${dyndomain[$index]} ${current_dynip}, doesnt match to public ip ${current_ip}" | tee -a "$logfile"


                echo "$(date) ddns ${dyndomain[$index]} was updated" >> "${pidfolder}/ddnschangedate.pid" #write to file, so we know time when ddns was attempted to be changed
                if [ ! -f "$pidfolder/ddnschangesperhour.pid" ]; then
                    echo 0 > "$pidfolder/ddnschangesperhour.pid"
                else
                    ddnschanges=$(cat $pidfolder/ddnschangesperhour.pid) #get from file how often it was changed in last hour
                    ddnschanges=$(( $ddnschanges + 1 )) #increase +1
                    echo $ddnschanges > "$pidfolder/ddnschangesperhour.pid"
                fi


                if [ "$ddnschanges" -gt "$dynupdatesperhour" ]; then
                    echo "$(date) ddns: ${dyndomain[$index]} cannot update because it was tried already $ddnschanges times and limit is $dynupdatesperhour per hour" | tee -a "$logfile"
                else
                    if [ "${dynprofile[$index]}" = "noip" ]; then
                        wget -U "${dynuseragent}" -a $logfile -O - "http://${dynuser[$index]}:${dynpass[$index]}@dynupdate.no-ip.com/nic/update?hostname=${dyndomain[$index]}&myip=$current_ip"
                        wgetcode=$?
                    elif [ "${dynprofile[$index]}" = "dyndns" ]; then
                        wget -U "${dynuseragent}" -a $logfile -O - "http://${dynuser[$index]}:${dynpass[$index]}@members.dyndns.org/nic/update?hostname=${dyndomain[$index]}&myip=$current_ip"
                        wgetcode=$?
                    elif [ "${dynprofile[$index]}" = "dnsdynamic" ]; then
                        wget -U "${dynuseragent}" -a $logfile -O - "http://${dynuser[$index]}:${dynpass[$index]}@www.dnsdynamic.org/api/?hostname=${dyndomain[$index]}&myip=$current_ip"
                        wgetcode=$?
                    elif [ "${dynprofile[$index]}" = "dyndnss" ]; then
                        wget -U "${dynuseragent}" -a $logfile -O - "http://www.dyndnss.net/?user=${dynuser[$index]}&pass=${dynpass[$index]}&domain=${dyndomain[$index]}&updater=other"
                        wgetcode=$?
                    elif [ "${dynprofile[$index]}" = "twodns" ]; then
                        wget -U "${dynuseragent}" -a $logfile -O - "http://${dynuser[$index]}:${dynpass[$index]}@update.twodns.de/update?hostname=${dyndomain[$index]}&ip=$current_ip"
                        wgetcode=$?
                    elif [ "${dynprofile[$index]}" = "goip" ]; then
                        wget -U "${dynuseragent}" -a $logfile -O - "http://www.goip.de/setip?username=${dynuser[$index]}&password=${dynpass[$index]}&subdomain=${dyndomain[$index]}&ip=$current_ip"
                        wgetcode=$?
                    elif [ "${dynprofile[$index]}" = "ddnss" ]; then
                        wget -U "${dynuseragent}" -a $logfile -O - "http://ddnss.de/upd.php?user=${dynuser[$index]}&pwd=${dynpass[$index]}&host=${dyndomain[$index]}"
                        wgetcode=$?
                    elif [ "${dynprofile[$index]}" = "freedns" ]; then
                        wget -U "${dynuseragent}" -a $logfile -O - "https://freedns.afraid.org/dynamic/update.php?${dynpass[$index]}"
                        wgetcode=$?
                    elif [ "${dynprofile[$index]}" = "duckdns" ]; then
                        duckdomain=${dyndomain[$index]%%.*} #delete longest match of pattern from the end
                        wget -U "${dynuseragent}" -a $logfile -O - "https://www.duckdns.org/update?domains=${duckdomain}&token=${dynpass[$index]}&ip=$current_ip"
                        wgetcode=$?
                    else
                        echo "$(date) ddns: ${dyndomain[$index]} could not update, no matching profile found!" | tee -a "$logfile"
                    fi
                    if [ ! "$wgetcode" = 0 ]; then
                        if [ "$wgetcode" = 1 ]; then
                            echo "$(date) ddns: ${dyndomain[$index]} wget update had generic error! return code was ${wgetcode}" | tee -a "$logfile"
                        elif [ "$wgetcode" = 2 ]; then
                            echo "$(date) ddns: ${dyndomain[$index]} wget update had parse command-line option error! return code was ${wgetcode}" | tee -a "$logfile"
                        elif [ "$wgetcode" = 3 ]; then
                            echo "$(date) ddns: ${dyndomain[$index]} wget update had file i/o error! return code was ${wgetcode}" | tee -a "$logfile"
                        elif [ "$wgetcode" = 4 ]; then
                            echo "$(date) ddns: ${dyndomain[$index]} wget update had network error! return code was ${wgetcode}" | tee -a "$logfile"
                        elif [ "$wgetcode" = 6 ]; then
                            echo "$(date) ddns: ${dyndomain[$index]} wget update had username/password authentication error! return code was ${wgetcode}" | tee -a "$logfile"
                        elif [ "$wgetcode" = 7 ]; then
                            echo "$(date) ddns: ${dyndomain[$index]} wget update had protocol error! return code was ${wgetcode}" | tee -a "$logfile"
                        elif [ "$wgetcode" = 8 ]; then
                            echo "$(date) ddns: ${dyndomain[$index]} server issued an error response! return code was ${wgetcode}" | tee -a "$logfile"
                        else
                            echo "$(date) ddns: ${dyndomain[$index]} wget update had an error! return code was ${wgetcode}" | tee -a "$logfile"
                        fi
                    else
                        echo "$(date) ddns: ${dyndomain[$index]} there was no wget error (return code ${wgetcode}), so ddns update may be successfull" | tee -a "$logfile"
                        #wait for dns cache to expire (normaly around 60sec) after ip update, otherwise asterisk will register with old ip
                        ddnsttl=$(dig +nocmd +noall +answer ${dyndomain[$index]} | awk '{ print $2 }')
                        echo "$(date) ddns: ${dyndomain[$index]} wait $ddnsttl seconds for ttl timeout" | tee -a "$logfile"
                        sleep $ddnsttl
                        while [ $dyncheckcount -ne 0 ]; do
                            sleep 10
                            #ping -c 1 ${dyndomain[$index]}
                            #if [ $? -eq 0 ]; then
                            #echo "$(date) ddns: dns ${dyndomain[$index]} resonds to new ip" | tee -a "$logfile"
                            #break
                            #else
                            #echo "$(date) ddns: last ping to ${dyndomain[$index]} didnt respond to new ip, trying max ${dyncheckcount}x again" | tee -a "$logfile"
                            #fi
                            current_dynip=$(host ${dyndomain[$index]} | awk '{ print $4 }' | head -n1)
                            if [ "$current_dynip" = "$current_ip" ]; then
                                do_astddnsreload="yes"
                                echo "$(date) ddns: ${dyndomain[$index]} resonds to new ip" | tee -a "$logfile"
                                break
                            else
                                echo "$(date) ddns: ${dyndomain[$index]} last ping didnt respond to new ip, trying max ${dyncheckcount}x again" | tee -a "$logfile"
                            fi


                            dyncheckcount=$(expr $dyncheckcount - 1)
                        done
                        if [ $dyncheckcount -eq 0 ]; then
                            echo "$(date) ddns: ${dyndomain[$index]} something went wrong, still doesnt resolve to new ip. Asterisk needs to be reloaded when ddns is back reachable." | tee -a "$logfile"
                            echo $(date) >> /tmp/astreload #for remembering needed reload
                        fi
                    fi
                fi
        else
            echo "$(date) ddns: ${dyndomain[$index]} no change detected. current dynip is ${current_dynip} and publicip is ${current_ip}" | tee -a "$logfile"
            if [ -f /tmp/astreload ]; then
                astreloadfile=$(cat /tmp/astreload)
                echo "$(date) ddns: will schedule asterisk reload, because previous ddns update on $(astreloadfile) failed" | tee -a "$logfile"
                d_astreload
                rm /tmp/astreload
            fi
        fi
    done


    # reload sip in asterisk if ddns was changed and asterisk is running
    if [ "$do_astddnsreload" = "yes" ] && [ -n "$check_ast" ]; then
        d_astreload
    fi


fi


}


################


d_peer() {
# checks ip of sip peer dns name and updates iptables if neccessary
# will also reload asterisk if enabled in config, because asterisk is doing dns lookup only once by default
# (instead of reload asterisk you can use dnsmgr.conf in asterisk, to enable dns lookups and avoid the manual reload)


if [ -n "$check_ast" ]; then


if [ -n "$sippeer[0]" ]; then
    stored_sipip="" #reset variable
    current_sipip=""
    do_astpeerreload=""
    for peer in "${!sippeer[@]}"
    do


        # check if ip was changed
        if [ -f ${pidfolder}/sip${peer}.pid ]; then
            stored_sipip=$(cat ${pidfolder}/sip${peer}.pid) #get current peer ip from file
        fi
        host ${sippeer[$peer]} | awk '{ print $4 }' > "${pidfolder}/sip${peer}.pid" #write actual peer ip to file
        if [ -z "$stored_sipip" ]; then #no check possible if run 1st time
            echo "$(date) sip peer: script runs 1st time for peer ${sippeer[$peer]}, no checking possible" | tee -a "$logfile"
        else
            current_sipip=$(cat ${pidfolder}/sip${peer}.pid)
            readiptables=$(iptables -L -n | grep ${current_sipip}) #reads iptables to see if we need to update it
            if [ "$current_sipip" != "$stored_sipip" ] && [ -n "$stored_sipip" ] && [ -n "$current_sipip" ]; then #did the ip change?
                echo "$(date) sip peer: ${sippeer[$peer]} with ip ${stored_sipip}, changed to new ip ${current_sipip}, change detected on ${currdate}" | tee -a "$logfile"
                do_astpeerreload="yes"
            elif [ -z "$current_sipip" ]; then
                echo "$(date) sip peer: could not get ip from sip peer ${sippeer[$peer]}" | tee -a "$logfile"
            else
                echo "$(date) sip peer: ${sippeer[$peer]} did not change since last run"
            fi


            if [ -z "$readiptables" ]; then #iptables does not contain entry?
                echo "$(date) sip peer: iptables does not contain new ip ${current_sipip}, will add ip" | tee -a "$logfile"
                iptables -A INPUT -i "$nic" -p udp --source ${sippeer[$peer]} --dport "$sipport" -j ACCEPT 2>> "$logfile"
                iptables -A OUTPUT -o "$nic" -p udp --destination ${sippeer[$peer]} --dport "$sipport" -j ACCEPT 2>> "$logfile"
            else
                echo "$(date) sip peer: iptables already contains ${sippeer[$peer]} with ip ${stored_sipip}"
            fi




        fi


        # reload sip in asterisk if sip peer was changed
        if [ "$do_astpeerreload" = "yes" ] && [ "$astreloadonpeeripchange" = "yes" ]; then
            d_astreload
        fi
    done
else
    echo "$(date) sip peer: no sip peer definied, nothing to check" | tee -a "$logfile"
fi


else
    echo "$(date) sip peer: asterisk is not running, cannot continue" | tee -a "$logfile"
fi


}


####################


d_show() {


 echo -e "\nsip udp traffic on port $sipport is currently allowed to/from hosts:"


 if [ -n "$sippeer[0]" ]; then


    for peer in "${!sippeer[@]}"
    do
        echo " ${sippeer[$peer]}"
    done
 fi
 echo -e "ip ranges:"
  if [ -n "$siprange[0]" ]; then


    for range in "${!siprange[@]}"
    do
        echo " ${siprange[$range]}"
    done
 fi
 echo "do a iptables -L -n to check real settings in INPUT and OUTPUT chain"
}


#######################


#lsb functions
. /lib/lsb/init-functions


case "$1" in
  checkast)
        d_checkast
        ;;
  start)
        log_daemon_msg "Starting $DESC"
        log_progress_msg "$NAME"
        d_start
        log_end_msg $?
        ;;
  stop)
        log_daemon_msg "Stopping $DESC"
        log_progress_msg "$NAME"
        d_stop
        log_end_msg $?
        ;;
  restart)
        d_stop
        sleep 1
        d_start
        ;;
  show)
        d_show
        ;;
  updatepublic)
        d_checkast
        d_public
        ;;
  updatepeer)
        d_checkast
        d_peer
        ;;
  updateddns)
        d_checkast
        d_ddns
        ;;
  updateall)
        d_checkast
        d_ddns
        d_peer
    ;;
  *)
        echo "Usage: $PROGNAME {checkast|start|stop|restart|updatepublic|updatepeer|updateddns|updateall|show}" >&2
        exit 1
        ;;
esac


exit 0
 
Da hast Du natürlich Recht.

Es gibt einen Trick. Im sip.conf [general] ein externes Skript mit #exec einbinden. Dann braucht man nur noch eine externe HTTP Seite, die einem die eigene WAN Adresse zurückgibt, oder man fragt einen STUN Server ab. Das Ergebnis gibt man als
echo "externip=" & adresse an Asterisk. So wird bei jedem SIP Reload in Echtzeit die externe Adresse ermittelt.

https://leifmadsen.wordpress.com/2011/02/27/using-exec-to-set-externaddr-in-sip-conf/

Ab Asterisk 13 ist ja STUN wieder an Board, aber da ich 13 auf meinem Pi nicht zum Laufen bekommen habe kann ich nicht sagen, wie brauchbar das ist.
 
sehr schön, dann brauch ich von ausserhalb Asterisk nur noch die IP überwachen und man hat ddns nicht mehr als Fehlerquelle drin.
Die IP frage ich ab mit http://ipinfo.io/ip , gibts da noch eine andere Möglichkeit wo man nicht auf dritte angewiesen ist und ohne den Router abzufragen?

Bei Benutzung von STUN in Asterisk kann man da komplett auf externe Scripts verzichten?

Edit:
das ginge z.B.
stun -v stunserver.org 2>&1 1>/dev/null | grep MappedAddress | sed -e 's/.*MappedAddress = //' -e 's/:.*//' | uniq

Edit2:
in res_stun_monitor.conf steht das alle outbound registrations neu geladen werden. Die Frage ist ob das wirklich nur die registrations sind oder das komplette Modul neu geladen wird?

Edit3:
also laut Sourcen sieht das wirklich so aus als ob explizit nur ein reregister gemacht wird, das hilft natürlich auch nicht viel in dem Fall
 
Zuletzt bearbeitet:
Kostenlos!

Neueste Beiträge

Statistik des Forums

Themen
248,873
Beiträge
2,303,516
Mitglieder
378,533
Neuestes Mitglied
PatrickSt91