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

