Menu

"SIP failure when DNS fails" or "internal phones don't work when internet is down" -- DIY solution

Anxifer
2016-07-30
2016-09-05
  • Anxifer

    Anxifer - 2016-07-30

    Yes I know, we have dnsmasq as caching dns-proxy installed on the system which should take care of the annoying problem, that you can't use your internal phones when internet is down, but it doesn't. At least not always Or even at all. I don't know. I personally never had an raspbx installation where internal sip registrations "survived" the internet link going down.

    So what can we do?
    First take a look at what we've got: dnsmasq
    Which is a good thing because it's capable of using more than one hosts file.

    So we "just" need to write a little quick 'n dirty shell script that creates this additional hosts file for us, which contains the addresses of our external sip servers and tell dsnmasq to use it. Simple, isn't ist? ;-)

    OK, but before we start scripting we need some prerequisites:
    1. nslookup (part of the dnsutils package)
    2. rcconf (for managing system services the easy way)
    3. daemon (to run our tiny script as a service)
    => apt-get install dnsutils rcconf daemon

    Then we can put together our little "dns-resolve-robot", let's call it lookup_sip_servers and put it in /usr/local/bin, which first checks if a given external (!!!) dns server (e.g. google-dns) is up and then looks up the IPs of our external sip servers, echoing them and their respective hostnames into our additional hosts file.

    So here we go:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    #!/bin/bash
    
    SLEEPTIME=10s
    SLEEPMULTIPLIER=12
    DNS_SERVERS="8.8.8.8"
    HOSTS="sip.easybell.de tel.t-online.de"
    TEMPFILE=/dev/shm/dns_answer
    HOSTFILE=/var/run/dnsmasq/hosts.dnsmasq
    
    while [ true ]; do
        COUNTER=0
        for h in $HOSTS; do
            for d in $DNS_SERVERS; do
                if [ $(nc -zvn $d 53 2>&1 | egrep -ic "succeeded") -gt 0 ]; then
                    nslookup $h $d >$TEMPFILE
                    IP=$(cat $TEMPFILE | grep Address | awk '{print $2}' | tail -n 1)
                    ALIASES=$(cat $TEMPFILE | egrep -ic "canonical name")
                    if [ $ALIASES -lt 1 ]; then
                        if [ $COUNTER -lt 1 ]; then
                            echo -e $IP'\t\t'$h >$HOSTFILE
                        (( COUNTER ++ ))
                        else
                            echo -e $IP'\t\t'$h >>$HOSTFILE
                        fi
                    else
                        ALIASLIST=$(cat $TEMPFILE | grep "canonical name" | awk '{print $5}' | rev | cut -c 2- | rev)
                        if [ $COUNTER -lt 1 ]; then
                            echo -e -n $IP'\t\t'$h'\t' $ALIASLIST >$HOSTFILE
                            (( COUNTER ++ ))
                        else
                            echo -e $IP'\t\t'$h'\t'$ALIASLIST >>$HOSTFILE
                        fi
                    fi
                fi
            rm -f $TEMPFILE
            done
        done
        for (( i=1; i<=$SLEEPMULTIPLIER; i++ )); do
            sleep $SLEEPTIME
        done
    done
    
    rm -f $TEMPFILE
    exit 0
    

    |
    OK, an endless loop ist definetely not the most soophisticatdt way to do it, but it gets the job done.
    Originally I intended tu use multiple external DNS servers, hence the respective for-loop still being there.
    EDIT: I don't know why parts of the code are not visible, but if you're interested in it just copy and paste the whole section into your local editor.
    Our created additional hosts file then looks like this:.:

    212.172.97.124          sip.easybell.de
    217.0.23.100            tel.t-online.de ims.voip.t-ipnet.de ims001.voip.t-ipnet.de b-epp-001.isp.t-ipnet.de
    

    |
    Now we tell dnsmasq to use this addtional hosts file. Therefore we put a dnsmasq.conf in /etc/dnsmasq.d containing the following line:

    addn-hosts=/var/run/dnsmasq/hosts.dnsmasq
    

    |
    While still having momentum we can now install our little script as a system (startup) service by puttin another tiny script, let's also call it lookup_sip_servers, in /etc/init.d:

    ### BEGIN INIT INFO
    # Provides:             lookup_sip_servers
    # Required-Start:       $syslog
    # Default-Start:        2 3 4 5
    # Required-Stop:
    # Default-Stop:         0 1 6
    # Short-Description:    lookup_sip_servers
    # Description:          periodically checks DNS records of certain hostnames via nslookup and echos them
    #                       to a custom hostz file
    ### END INIT INFO
    
    PIDFILE=/var/run/lookup_sip_servers.pid
    # LOG=/var/log/messages
    
    case "$1" in
    
        start)
            if [ -e $PIDFILE ]; then
                echo -e "\nDaemon seems to be running already.\n
                        Use: '/etc/init.d/lookup_sip_servers restart' to restart."
            else
                echo -en '\nStarting lookup_sip_servers...'
                daemon -U -n lookup_sip_servers -X /usr/local/bin/lookup_sip_servers -F $PIDFILE
                while [ ! -e $PIDFILE ];do
                    sleep 1s;
                done
                PID=$(cat $PIDFILE)
                echo -e ' done. (PID='$PID')'
            fi
        ;;
    
        stop)
            if [ -e $PIDFILE ]; then
                PID=$(cat $PIDFILE)
                echo -en '\nStopping lookup_sip_servers (PID='$PID')...'
                kill $PID
                while [ -e $PIDFILE ];do
                    sleep 1s
                done
                echo -e ' done.'
            else
                echo -e "\nDaemon seems not to be running."
            fi
        ;;
    
        restart)
            $0 stop
            $0 start
        ;;
    
        *)
        echo -e "\nUsage: /etc/init.d/lookup_sip_servers (start|stop|restart)\n"
        exit 1
    
    esac
    
    exit 0
    

    |
    'and activate its execution at boot time with rcconf.

    The end.

    I hope somebody finds this to be useful...

     

    Last edit: Anxifer 2016-07-31
  • advocate

    advocate - 2016-09-05

    I cannot help you with the script because I don't know anything about programming, but consider this:

    You don't need dnsmasq to provide real IP addresses. If your internet is down, there's no need for a real IP address because you're not going to get through anyway. You just need dnsmasq to return SOMETHING so that Asterisk doesn't freeze. That something could be 10.10.10.10 for all you care.

    That fact may make the script easier to write..

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.