Xarx.es

Dèries. La meua llibreta d'anotacions.

Script Ddnsupd De Nslu2 Para Solucionar Incompetencia De ONO

Mi experiencia con los routers de ONO lleva años siendo mala (sí, ya se… cambia de proveedor!).

He sufrido con un Scientific Atlanta epr2320 y, recientemente, con un Netgear cg3100d. Y la conclusión es que entiendo los comentarios en internet recomendando usarlos únicamente como modems.

Ya me explayaré sobre el tema. Pero la cuestión es que en los firmwares más recientes han capado las habilidades del router. Por ejemplo ya no son accesibles a través de ssh ni saben manejar dyndns. Y también hay problemas al redireccionar puertos. Vamos una joya de cacharro (o de firmware, que igual el cacharro puede y algunos no lo dejan).

La situación es que necesitaba poner en marcha una actualización de ip dinámica en dyndns. Aunque hay soluciones como dyndns o tinydyndns en los repositorios (ubuntu-debian) he decidido utilizar una opción que ya conocía… así que rescaté un script que usaba en un nslu2 y que aquí incluyo:

Script de Actualización de IP para dyndns (ddnsupd.sh) download
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#!/bin/sh
# DynDNS Update Client for the Linux NSLU2
#
# Script version - (used for user-agent)
VER=NSLU2-Linux-DNSUPD-0.9.4beta

# User configurable Section
#
# USER=<dnsuser>
# PASSWD=<dnspasswd>
# DOMAIN=<domain.name.org,domain2.name.org,domain3.name.org>
# SYSTEM=[dyndns|statdns|custom]
# WILDCARD=[ON|OFF|NOCHG]
# MX=[mailexchanger.name.org|NOCHG]
# BACKMX=[YES|NO|NOCHG]
# OFFLINE=[YES|NO] or leave blank

USER=usuario_en_dyndns.org
PASSWD=clave_del_usuario
DOMAIN=el_dominio.que_toque.cx
SYSTEM=dyndns
WILDCARD=ON
MX=NOCHG
BACKMX=NOCHG
OFFLINE=

# Var folder, Set VAR to either '/var' or '/opt/var', '/opt/var' recommended for Unslung users
VAR=/var

# Update using either 'http' or 'https' (openssl and wget-ssl are needed for https)
HTTP=https
# For https set SSL=--no-check-certificate
SSL=--no-check-certificate

# Paths to program files
WGET=/usr/bin/wget
FIND=/usr/bin/find
CHMOD=/bin/chmod
MKDIR=/bin/mkdir
GREP=/bin/grep
ECHO=/bin/echo
DATE=/bin/date
CAT=/bin/cat
SED=/bin/sed
CP=/bin/cp
RM=/bin/rm
# A beep command equivalent to 'printf "\a"'
#BEEP='Set_Led beep1'  #unslung
# sgtes para slugos o debian
#BEEP='/sbin/leds beep'
BEEP='/usr/bin/beep'

# Dyndns script update section
# 
# Check and create folders
if [ ! -d ${VAR}/log ]; then
  ${MKDIR} -p ${VAR}/log
  ${CHMOD} 755 ${VAR}/log
fi
if [ ! -d ${VAR}/tmp ]; then
  ${MKDIR} -p ${VAR}/tmp
  ${CHMOD} 755 ${VAR}/tmp
fi

# Check and create err.ip
if [ ! -f ${VAR}/tmp/err.ip ]
then
  ${ECHO} "off" > ${VAR}/tmp/err.ip
fi

# Check for Fatal error file,  disable script and error beep if file exists
if [ -f ${VAR}/log/dyndns.fatal.error ]
then
  ${BEEP}
  ${BEEP}
  exit 0
fi

# Fetch current IP Address.
###########################
# 
# --- original:
# ${WGET} -q -t 1 -T 30 -U ${VER} -O ${VAR}/tmp/now.ip http://checkip.dyndns.com:8245/
# --- increased parameter t (tries) to avoid error "not updated: read error on ip fetch") 
#     into ip_hist.log
${WGET} -q -t 12 -T 30 -U ${VER} -O ${VAR}/tmp/now.ip http://checkip.dyndns.com:8245/
# --- This could be changed to get the ip address from router >  > ${VAR}/tmp/now.ip 

# Verify the data is good.
PAT='Current IP Address: *[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*'
if ${GREP} "$PAT" ${VAR}/tmp/now.ip >/dev/null;
then
  MYIP="`${SED} -e 's|.*Address: ||; s|</body>.*||' ${VAR}/tmp/now.ip`"
  # On good IP data.
  # Check for IP history.
  if [ -f ${VAR}/tmp/old.ip ]
  then
    # On history found.
    if [ "`${CAT} ${VAR}/tmp/err.ip`" = "on" ]
    then
      ${ECHO} "`${DATE} +%Y%m%d.%H%M%S` - not updated: Network connection restored." >> ${VAR}/log/ip_hist.log;
      # Turn err.ip Off
      ${ECHO} "off" > ${VAR}/tmp/err.ip
    fi
    # Check for settings change
    if [ ! "`${CAT} ${VAR}/tmp/update.para`" = "${USER}:${PASSWD}:${DOMAIN}:${SYSTEM}:${WILDCARD}:${MX}:${BACKMX}:${OFFLINE}:" ]
    then
      ${WGET} -q -t 1 -T 30 -U ${VER} -O ${VAR}/tmp/upd.ip ${SSL} "${HTTP}://${USER}:${PASSWD}@members.dyndns.org/nic/update?system=${SYSTEM}&hostname=${DOMAIN}&myip=${MYIP}&wildcard=${WILDCARD}&mx=${MX}&backmx=${BACKMX}&offline=${OFFLINE}";
      # Log the settings change and notify user.
      ${ECHO} "`${DATE} +%Y%m%d.%H%M%S` - Settings - `${CAT} ${VAR}/tmp/upd.ip`" >> ${VAR}/log/ip_hist.log;
      ${ECHO} "`${DATE} +%x`" > ${VAR}/tmp/day.ip;
      ${RM} -f ${VAR}/tmp/old.ip;
      ${CP} ${VAR}/tmp/now.ip ${VAR}/tmp/old.ip;
      ${ECHO} "${USER}:${PASSWD}:${DOMAIN}:${SYSTEM}:${WILDCARD}:${MX}:${BACKMX}:${OFFLINE}:" > ${VAR}/tmp/update.para;
      ${BEEP}
    fi
    # Check for IP Change
    if [ "`${CAT} ${VAR}/tmp/now.ip`" = "`${CAT} ${VAR}/tmp/old.ip`" ]
    then
      # On no IP change
      # Check if 28 day refresh is needed.
      # you must enter the appropriate paths for the find command
      # but do not use variables in the string or it may not work correctly 
      /usr/bin/find /var/tmp/ -name old.ip -mtime +27 -exec rm {} \;
      if  [ -f ${VAR}/tmp/old.ip ]
      then
        # On no refresh needed.
        # Check for Next day. 
        if [ ! "`${CAT} ${VAR}/tmp/day.ip`" = "`${DATE} +%x`" ]
        then
          # On day change
          # Log entry
          ${ECHO} "`${DATE} +%Y%m%d.%H%M%S` - No update - `${CAT} ${VAR}/tmp/upd.ip`" >> ${VAR}/log/ip_hist.log;
          ${ECHO} "`${DATE} +%x`" > ${VAR}/tmp/day.ip;
        fi
      else
        # On refresh needed.
        # Do a 28 Day refresh and Notify user with a distinguishable beep.
        ${WGET} -q -t 1 -T 30 -U ${VER} -O ${VAR}/tmp/upd.ip ${SSL} "${HTTP}://${USER}:${PASSWD}@members.dyndns.org/nic/update?system=${SYSTEM}&hostname=${DOMAIN}&myip=${MYIP}&wildcard=${WILDCARD}&mx=${MX}&backmx=${BACKMX}&offline=${OFFLINE}";
        echo "`${DATE} +%Y%m%d.%H%M%S` - Refresh - `${CAT} ${VAR}/tmp/upd.ip`" >> ${VAR}/log/ip_hist.log;
        echo "`${DATE} +%x`" > ${VAR}/tmp/day.ip;
        ${CP} ${VAR}/tmp/now.ip ${VAR}/tmp/old.ip;
        ${BEEP}
      fi
    else
      # On IP change
      # Update DynDNS with new IP Address. 
      ${WGET} -q -t 1 -T 30 -U ${VER} -O ${VAR}/tmp/upd.ip ${SSL} "${HTTP}://${USER}:${PASSWD}@members.dyndns.org/nic/update?system=${SYSTEM}&hostname=${DOMAIN}&myip=${MYIP}&wildcard=${WILDCARD}&mx=${MX}&backmx=${BACKMX}&offline=${OFFLINE}";
      # Log the IP change and notify user.
      ${ECHO} "`${DATE} +%Y%m%d.%H%M%S` - Update - `${CAT} ${VAR}/tmp/upd.ip`" >> ${VAR}/log/ip_hist.log;
      ${ECHO} "`${DATE} +%x`" > ${VAR}/tmp/day.ip;
      ${RM} -f ${VAR}/tmp/old.ip;
      ${CP} ${VAR}/tmp/now.ip ${VAR}/tmp/old.ip;
      ${BEEP}
    fi
  else
    # On No History
    # Initialize client and Update DynDNS.
    # Check err.ip status
    if [ "`${CAT} ${VAR}/tmp/err.ip`" = "on" ]
    then
      # Log Service Restoral.
      ${ECHO} "`${DATE} +%Y%m%d.%H%M%S` - not updated: Network connection restored." >> ${VAR}/log/ip_hist.log;
    fi
    # Set err.ip off
    ${ECHO} "off" > ${VAR}/tmp/err.ip
    ${WGET} -q -t 1 -T 30 -U ${VER} -O ${VAR}/tmp/upd.ip ${SSL} "${HTTP}://${USER}:${PASSWD}@members.dyndns.org/nic/update?system=${SYSTEM}&hostname=${DOMAIN}&myip=${MYIP}&wildcard=${WILDCARD}&mx=${MX}&backmx=${BACKMX}&offline=${OFFLINE}";
    ${ECHO} "`${DATE} +%Y%m%d.%H%M%S` - Initialise - `${CAT} ${VAR}/tmp/upd.ip`" >> ${VAR}/log/ip_hist.log;
    ${ECHO} "`${DATE} +%x`" > ${VAR}/tmp/day.ip;
    ${CP} ${VAR}/tmp/now.ip ${VAR}/tmp/old.ip;
    ${ECHO} "${USER}:${PASSWD}:${DOMAIN}:${SYSTEM}:${WILDCARD}:${MX}:${BACKMX}:${OFFLINE}:" > ${VAR}/tmp/update.para
    ${BEEP}
  fi
  # Analyse and report any Fatal error return strings
  if ${GREP} "\!yours\|notfqdn\|abuse\|nohost\|badagent\|badauth\|badsys\|dnserr\|numhost\|911\|\!donator" ${VAR}/tmp/upd.ip >/dev/null
  then
    ${ECHO} "`${DATE} +%x` - Fatal Error Returned from Dyndns - `${CAT} ${VAR}/tmp/upd.ip` - Correct the error then delete this file to re-enable" > ${VAR}/log/dyndns.fatal.error;
    ${BEEP}
    ${BEEP}
    #
    # Place holder - for example - to send fatal error report by email
    # #############
    #
  fi
else
  # On IP read error
  # Check err.ip status
  if [ ! "`${CAT} ${VAR}/tmp/err.ip`" = "on" ]
  then
    # On err.ip = off - Log read error. 
    ${ECHO} "`${DATE} +%Y%m%d.%H%M%S` - not updated: read error on ip fetch" >> ${VAR}/log/ip_hist.log;
  fi
  # Set err.ip = On to allow only one error log on next run.
  ${ECHO} "on" > ${VAR}/tmp/err.ip
  # Notify user.
  ${BEEP}
  ${BEEP}
fi
# end

# ADD MANUALLY A CRON JOB CALLING THIS SCRIPT
# EXAMPLE FOR NSLU2:
# Set the interval of the next IP check using a crontab entry.
# Once every 15 minutes is good for a home server.
# */15 * * * * root /opt/bin/dnsupd &>/dev/null
#

El script se ejecuta temporizado desde cron y utiliza archivos temporales localizados en /var/tmp y también escribe un par de archivos de log situados en /var/log

La ventaja que le veo sobre la solución dyndns de los repositorios es que no utiliza un demonio más sino que lo lanza cron. Debe, por tanto, ser un script ejecutable con los permisos adecuados. Quizá como inconveniente tiene que los datos de configuración están en el mismo script (y accesibles).

Actualización: Con el nuevo firmware del router de Netgear (1.04.02) han añadido la función de DNS Dinámico. Eso si, tan solo usando DynDNS, ahora que en esta compañía fuerzan a entrar cada mes para no perder la entrada de DNS (o pasarse a sus servicios de pago).

Comentarios