Pejman Moghadam / Debian

Debian 10 - GnuDIP Dynamic DNS


TCP Implementation with tinydns


Public domain


Server: /opt/gnudip/gnudip-passwd.txt

# To create hashed passwords : echo -n PASSWORD | md5sum
#
# Hashed-password                Domain      Name
25f9e794323b453885f5181f1b624d0b example.com machine01
6ebe76c9fb411be97b3b0d48b791a7c9 example.com ftp

Server: /opt/gnudip/gnudip-server.sh

#!/bin/bash
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
CWD=$(dirname $(readlink -f $0))
MYPID=$$

################################################################################
# Configuration

RECORDS="$CWD/records"
LOGGER="logger -t gnudip-server[$MYPID]"
HPASSFILE="$CWD/gnudip-passwd.txt"
TTL=60

# Message format USER:HPASS:DOMAIN:RCODE:IPADDR
# USER+DOMAIN:128 HPASS:32 RCODE:1 IPADDR:15 Colons:4
MAXMSGLEN=180
READTMOUT=3

################################################################################
# Read and sanitize client IP 

# xinetd supplies client IP
CLIENTIP=$(echo $REMOTE_HOST)

IPSW=1
if [[ $CLIENTIP =~ ^[0-9]{1,3}(\.[0-9]{1,3}){2}\.[0-9]{1,3}$ ]]; then
    IP=($(echo $CLIENTIP | sed -e 's,\., ,g'))
    [[
            ${IP[0]} -le 255 &&
            ${IP[1]} -le 255 &&
            ${IP[2]} -le 255 &&
            ${IP[3]} -le 255
    ]]
    IPSW=$?
fi
if [ "$IPSW" == "1" ]; then
    echo "Client IP address is not valid" | $LOGGER
    echo 1
    exit
fi

echo "Got new connection from $CLIENTIP" | $LOGGER

################################################################################
# Generate and send salt 

SALT=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 10)
echo "$SALT"

################################################################################
# Read and sanitize request message 

read -n $MAXMSGLEN -t $READTMOUT MSG
MSG=$(echo $MSG | tr -dc A-Za-z0-9:.-)

echo "Message: $MSG" | $LOGGER

N=$(echo "$MSG" | grep -o ':' | wc -l)
if [ "$N" != "3" ] && [ "$N" != "4" ]; then
    echo "Message should have 3-or-4 colons" | $LOGGER
    echo 1
    exit
fi

################################################################################
# Splitting and re-sanitizing request message

USER="$(echo $MSG | cut -d: -f1)"
USER=$(echo $USER | tr -dc A-Za-z0-9-)
LEN=${#USER}
if [ "$LEN" == "0" ]; then
    echo "Username length is zero" | $LOGGER
    echo 1
    exit
fi

HPASS="$(echo $MSG | cut -d: -f2)"
HPASS=$(echo $HPASS | tr -dc A-Za-z0-9)
LEN=${#HPASS}
if [ "$LEN" != "32" ]; then
    echo "Hashed password length should be 32" | $LOGGER
    echo 1
    exit
fi

DOMAIN="$(echo $MSG | cut -d: -f3)"
DOMAIN=$(echo $DOMAIN | tr -dc A-Za-z0-9.-)
LEN=${#DOMAIN}
if [ "$LEN" -lt "3" ]; then
    echo "Domain name length is less than 3" | $LOGGER
    echo 1
    exit
fi

# Request code 0 and 1 not implemented yet / TODO
RCODE="$(echo $MSG | cut -d: -f4)"
#if [ "$RCODE" != "0" ] && [ "$RCODE" != "1" ] && [ "$RCODE" != "2" ]; then
if [ "$RCODE" != "2" ]; then
    echo "Unknown request code" | $LOGGER
    echo 1
    exit
fi

# Not used, because rcode 0 not implemented / Sanitize before use / IPv4
#IPADDR="$(echo $MSG | cut -d: -f5)"

################################################################################
# Fetch and sanitize credential

CRED=$(egrep -v '^#|^ *$' "$HPASSFILE" | egrep " $USER$" | head -n1)
if [ "$CRED" == "" ]; then
    echo "User not found: $USER" | $LOGGER
    echo 1
    exit
fi

REALHPASS=$(echo $CRED | cut -d' ' -f1)
REALHPASS=$(echo $REALHPASS | tr -dc A-Za-z0-9)
LEN=${#REALHPASS}
if [ "$LEN" != "32" ]; then
        echo "Real hashed password length should be 32" | $LOGGER
        echo 1
        exit
fi
REALHPASS=$(echo -n "$REALHPASS.$SALT" | md5sum | sed 's, .*,,')

REALDOMAIN=$(echo $CRED | cut -d' ' -f2)
REALDOMAIN=$(echo $REALDOMAIN | tr -dc A-Za-z0-9.-)
LEN=${#REALDOMAIN}
if [ "$LEN" -lt "3" ]; then
        echo "Real domain name length is less than 3" | $LOGGER
        echo 1
        exit
fi

if [ "$HPASS" != "$REALHPASS" ] || [ "$DOMAIN" != "$REALDOMAIN" ]; then
    echo "Invalid login" | $LOGGER
    echo 1
    exit
fi

# for rcode 0 , client ip address should be changed / TODO
# for rcode 1 , juest delete old record if exist / get ip from connection(??)
# rcode 2 implementation :
################################################################################
# Check if DNS record exist / TODO: DNS Abstraction

TINYDNS="1.2.3.4"
N=$(dnsq a $USER.$DOMAIN $TINYDNS | 
    egrep "^answer: $USER.$DOMAIN " | egrep -c " $CLIENTIP$")
if [ "$N" != "0" ]; then
    echo "Record exist, nothing to do!" | $LOGGER
    echo 0
    exit
fi

################################################################################
# Create and send DNS record to add / TODO: DNS Abstraction

RECORD="+$USER.$DOMAIN:$CLIENTIP:$TTL"
echo "$RECORD" >> "$RECORDS/$DOMAIN-$MYPID"
echo "Login OK: $RECORD" | $LOGGER
echo 0
exit

Server: /opt/gnudip/gnudip-apply.sh

#!/bin/bash
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
CWD=$(dirname $(readlink -f $0))
RECORDS="$CWD/records"
DOMAINSDIR="/opt/tinydns-scripts/domains"
RESTART="/opt/tinydns-scripts/create-data-file.sh"
TINYDNS="1.2.3.4"

if [ ! -d "$RECORDS" ]; then
    mkdir -p $RECORDS
    chown nobody:nogroup $RECORDS
fi

N=$(ls $RECORDS | wc -l)
if [ "$N" == "0" ] ;then
    exit
fi

RSTSW=0
for F in $(find $RECORDS -type f); do
    RECORD=$(cat $F | head -n1)
    PREFIX=$(echo $RECORD | cut -d: -f1)
    NAME=${PREFIX:1}
    DOMAIN=$(echo $NAME | sed -e 's/^[^\.]*\.//g')
    IP=$(echo $RECORD | cut -d: -f2)
    echo $PREFIX
    echo $NAME
    echo $IP
    N=$(dnsq a $NAME $TINYDNS | egrep "^answer: $NAME " | egrep -c " $IP$")
    if [ "$N" != "0" ]; then
            continue
    fi
    RSTSW=1
    sed -i "/^$PREFIX:/d" "$DOMAINSDIR/$DOMAIN"
    echo $RECORD >> "$DOMAINSDIR/$DOMAIN"
    rm $F
done

[ "$RSTSW" == "1" ] && $RESTART

Server: /opt/gnudip/gnudip-apply-loop.sh

#!/bin/bash
#
# Start inside screen :
# env SCREENDIR="/var/run/screen/S-root/" screen -dmS GNUDIP /opt/gnudip/gnudip-apply-loop.sh
#
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
CWD=$(dirname $(readlink -f $0))
APPLY="$CWD/gnudip-apply.sh"
SLEEP=5

while :;do
    $APPLY
    sleep $SLEEP
done

Server: Add to /etc/services

gnudip          3495/tcp

Server: /etc/xinetd.d/gnudip

service gnudip
{
    disable     = no
    flags       = IPv4
    socket_type = stream
    protocol    = tcp
    wait        = no
    user        = nobody
    server      = /opt/gnudip/gnudip-server.sh
    bind        = 0.0.0.0
}

Server: /etc/rc.local

env SCREENDIR="/var/run/screen/S-root/" screen -dmS GNUDIP /opt/gnudip/gnudip-apply-loop.sh

Client: /root/scripts/gnudip-client.sh

#!/bin/bash
#
# Usage :
# ncat ddns.topdns.ir 3495 -e gnudip-client.sh
#

PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
MYPID=$$
LOGGER="logger -t gnudip-client[$MYPID]"

USER="machine01"
PASS="123456789"
DOMAIN="example.com"

read SALT
echo "Salt: $SALT" | $LOGGER 
REQ="$USER:$(echo -n "$(echo -n "$PASS" | md5sum | sed 's, .*,,').$SALT" | md5sum | sed 's, .*,,'):$DOMAIN:2"
echo "$REQ" | $LOGGER 
echo "$REQ"
read RESP
echo "Response $RESP" | $LOGGER

Client: /etc/crontab

* * * * *   root    /usr/bin/ncat ddns.topdns.ir 3495 -e /root/scripts/gnudip-client.sh &> /dev/null

Links

http://gnudip2.sourceforge.net/
http://gnudip2.sourceforge.net/gnudip-www/
http://gnudip2.sourceforge.net/gnudip-www/latest/gnudip/html/protocol.html
http://gnudip2.sourceforge.net/gnudip-www/latest/gnudip/html/protocol_sample.txt
http://gnudip2.sourceforge.net/gnudip-www/latest/gnudip/html/client/UNIX/
http://gnudip2.sourceforge.net/gnudip-www/latest/maintenance_commands.html
http://gnudip2.sourceforge.net/gnudip-www/latest/remote.html
http://gnudip2.sourceforge.net/gnudip-www/latest/INSTALL.html
http://gnudip2.sourceforge.net/gnudip-www/latest/BACKEND.html
http://gnudip2.sourceforge.net/gnudip-www/latest/TODO.html
http://gnudip2.sourceforge.net/gnudip-www/gnudip-2.3.5-www.tar.gz
http://up.nl.eu.org/projects/gnudip.html
https://github.com/rodajc/gnudiphttp/
https://fossies.org/linux/misc/dns/old/gnudip-2.3.5.tar.gz/

BY: Pejman Moghadam
TAG: gnudip, xinetd, ddns, dns, tinydns
DATE: 2021-06-02 07:07:36


Pejman Moghadam / Debian [ TXT ]