How to securely update easydns using dyndns

1. Create the following C program:

#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <syslog.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/wait.h>

void _syslog(int err, const char *format, ...){
    va_list args;
    va_start(args, format);
    vsyslog(LOG_DAEMON | err, format, args);
    va_end(args);
}

void getIfAddress(const char *iface, char *answer, int ans_size){
    struct ifreq devinfo;
    int device;
    device = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
    strncpy(devinfo.ifr_name, iface, IFNAMSIZ);
    if(ioctl(device, SIOCGIFADDR, &devinfo) >= 0){
        strncpy(answer,
          (const char*)inet_ntoa(((struct sockaddr_in*)&devinfo.ifr_addr)->sin_addr.s_addr),
          ans_size);
    } else {
        answer[0]='\0';
    }
    close(device);
}

void sighandler(int sig){
    _syslog(LOG_DEBUG, "Received signal %d\n", sig);
}

int main(int argc, char **argv){
    if(argc>2){
        int i;
        char address[16];
        struct sigaction sigh;

        /* Signal handler for SIGHUP */
        sigh.sa_handler = sighandler;
        sigemptyset(&(sigh.sa_mask));
        sigaction(SIGHUP, &sigh, NULL);

        /* Allocate memory */
        char **addresses = (char**)malloc((argc-2)*sizeof(char*));
        for(i=0; i<argc-2; i++){
            addresses[i] = (char*)malloc(16*sizeof(char));
            addresses[i][0]='\0';
        }

        while(1){
            _syslog(LOG_DEBUG, "Starting interface checks\n");
            for(i=2; i<argc; i++){
                getIfAddress(argv[i], address, 16);
                if((address[0]) && (strncmp(address, addresses[i-2], 16)!=0)){
                    _syslog(LOG_INFO, "Updating address for interface %s to %s (was %s)\n",
                            argv[i],
                            address, addresses[i-2][0]?addresses[i-2]:"none");
                    /* Perform the update */
                    setenv("PPP_LOCAL", address, 1);
                    setenv("PPP_IFACE", argv[i], 1);
                    if(WEXITSTATUS(system(argv[1]))==0){
                        strncpy(addresses[i-2], address, 16);
                    }
                }
            }
            sleep(600);
        }
    }
}

This program simply obtains the ip addresses assigned to interfaces (specified as the second, third, etc parameter), and if they have changed assigns the information to the environment variables PPP_LOCAL and PPP_IFACE, then calls the script specified as parameter 1.

Compile it with:

gcc -o iface_monitor iface_monitor.c

Strip it:

strip iface_monitor

Install it in /usr/local/sbin.

2. Create script /usr/local/bin/dyndns

#!/bin/sh

# See: http://support.easydns.com/tutorials/dynamicUpdateSpecs.php

# PPP_LOCAL and PPP_IFACE must be set
if test -z "$PPP_LOCAL" -o -z "$PPP_IFACE"; then
        echo "PPP_LOCAL and PPP_IFACE environment variables need to be set"
        exit 1
fi

# The hostnames corresponding to ppp0, ppp1, etc
HOST[0]="gw1.my.domain"
HOST[1]="gw2.my.domain"

# Edit these and set for your own purposes
TLD="co.za"
LOGIN="myname"
PASSWD="mypassword"

# Location of binaries
WGET="/usr/bin/wget"
EGREP="/bin/egrep"

# Determine iface number
PPP_IFACE_NUM=${PPP_IFACE#ppp}

# Set URL
URL="https://members.easydns.com/dyn/dyndns.php?hostname=${HOST[$PPP_IFACE_NUM]}&myip=${PPP_LOCAL}&tld=${TLD}"
${WGET} -O- --http-user="${LOGIN}" --http-passwd="${PASSWD}" "${URL}" 2>/dev/null | \
    ${EGREP} -q NOERROR
exit $?

3. Create a init.d script:

        
#!/bin/sh
# Install as /etc/init.d/iface_monitor

PATH=/sbin:/bin:/usr/local/bin:/usr/local/sbin

test -x /usr/local/sbin/iface_monitor || exit 0

case "$1" in
        start)
                echo -n "Starting iface_monitor: iface_monitor"
                start-stop-daemon --start --quiet --background \
                        --make-pidfile --pidfile /var/run/iface_monitor.pid \
                        --exec /usr/local/sbin/iface_monitor -- \
                        /usr/local/bin/dyndns ppp0 ppp1
                echo "."
                ;;
        stop)
                echo -n "Stopping iface_monitor: iface_monitor"
                start-stop-daemon --stop --quiet --pidfile /var/run/iface_monitor.pid
                echo "."
                ;;
        restart|force-reload)
                echo -n "Restarting iface_monitor: iface_monitor... "
                start-stop-daemon --stop --signal 1 --quiet --pidfile \
                        /var/run/iface_monitor.pid
                echo "done."
                ;;
        *)
                echo "Usage: /etc/init.d/ntp-server {start|stop|restart|force-reload}"
                exit 1
                ;;
esac

exit 0

4. Create a script for pppd to kick iface_monitor when the interfaces come up:

#!/bin/sh
# Install this file as /etc/ppp/ip-up.d/dyndns
/etc/init.d/iface_monitor restart


5. configure the service to start at bootup

update-rc.d iface_monitor start 38 S . stop 62 0 6 .

6. Start the service

/etc/init.d/iface_monitor start

7. To force a graceful update, restart the iface_monitor service:

/etc/init.d/iface_monitor restart

This will force a check, but will only update the ip if it has changed.

8. To force an update, stop and start the iface_monitor service:

/etc/init.d/iface_monitor stop
/etc/init.d/iface_monitor start

This page was last modified on 28 August 2006, at 17:32. This page has been accessed 1,129 times.

  
Powered by MediaWiki

Copyright © 1999-2009, Cape Linux Users Group | All contents are under GNU Free Documentation Licence | For all queries, join our mailing lists!