commodoro
Occasional Visitor
I wanted to share one of my projects with the forum, maybe it's useless and it's just a pure exercise in style, also considering that I'm not an expert in shell scripting.
The problem I wanted to solve is the following, I'am inside in a double NAT environment, with the Asus router in cascade with the one provided by my ISP, with static config for the WAN interface. I wanted to be sure that the DDNS was always aligned and updated if necessary, the provider that I have chosen is duckdns.org.
I noticed that using this configuration, if my ISP changes my public IP, my RT-AX58U does not recognize the change as the WAN port does not change state, and therefore all WAN reboot processes are not triggered, including the DDNS update.
Hence the idea of creating the following script, which does nothing other than retrive the IP inside the inadyn cache file and, based on a list, invokes online services to know the external IP, compares the two values and if they are different refresh the DDNS.
To install
I hope this can be useful for someone
Greetings
Commodoro
The problem I wanted to solve is the following, I'am inside in a double NAT environment, with the Asus router in cascade with the one provided by my ISP, with static config for the WAN interface. I wanted to be sure that the DDNS was always aligned and updated if necessary, the provider that I have chosen is duckdns.org.
I noticed that using this configuration, if my ISP changes my public IP, my RT-AX58U does not recognize the change as the WAN port does not change state, and therefore all WAN reboot processes are not triggered, including the DDNS update.
Hence the idea of creating the following script, which does nothing other than retrive the IP inside the inadyn cache file and, based on a list, invokes online services to know the external IP, compares the two values and if they are different refresh the DDNS.
Bash:
#!/bin/sh
#############################################################################################################
# Based list check external IP and DDNS refresh for Asuswrt-Merlin #
# By Commodoro #
# 20/04/2024 - v1.0.0 #
#############################################################################################################
#set -x
CACHEPATH=/var/cache/inadyn/
ONLYNAME=$(basename "$0" .sh)
LOCKFILE=/tmp/lock/$ONLYNAME.lock
LOCKFILE=~/"${ONLYNAME}".lock
REGEXVALIDIP='^(([1-9]?[0-9]|1[0-9][0-9]|2([0-4][0-9]|5[0-5]))\.){3}([1-9]?[0-9]|1[0-9][0-9]|2([0-4][0-9]|5[0-5]))$'
URLS='https://api.seeip.org https://myip.dnsomatic.com/ https://api.ipify.org https://api.my-ip.io/v2/ip.txt https://ipv4.getmyip.dev https://ident.me'
logger_helper() {
logger -st "customDdnsRefresh[$$]" "$1"
}
if [ -e "${LOCKFILE}" ] && kill -0 "$(cat "${LOCKFILE}")"; then
logger_helper "already running"
exit 1
fi
# make sure the lockfile is removed when we exit and then claim it
trap 'rm -f "${LOCKFILE}"; exit' INT TERM EXIT
echo $$ > "${LOCKFILE}"
directory_exist_and_not_empty() {
if [ -z "$*" ]
then
logger_helper "No path to check, please verify the call to directory_exist_and_not_empty function in script code"
return 1
else
if [ -d "$1" ] && [ "$(ls -A "$1")" ]
then
return 0
else
logger_helper "Directory $1 not exist or is empty, nothing to do"
return 1
fi
fi
}
invoke_remote_ip_check() {
#a sort of load balancing for the call of the check sites, based on the minute of running of the script and on the length of the vector of the sites to be invoked
MINUTE=$(date +"%M")
SIZE=$(echo "${URLS}" | awk '{while (match($0, / /)) {count++; $0=substr($0, RSTART+RLENGTH)}} END {print count+1}')
INDEX=$((MINUTE%SIZE))
#since in busybox there is no access to the vector on an index basis, workaround with for and checking the position of the element with the index calculated above
LOOP=0
for url in ${URLS}; do
if [ ${LOOP} -eq ${INDEX} ]; then
logger_helper "use service ${url}"
#Save response of curl
RESP=$(curl -fs "${url}" 2>&1)
#remove no useful data from response and verify is it a valid IP
IP="$( echo "${RESP}" | head -n 1 | grep -Eo "${REGEXVALIDIP}")"
if [ -n "$IP" ]; then
#check if content inadyn.cache is the same
if [ "$IP" = "$(cat "${CACHEPATH}"/"$1")" ]; then
return 0
else
return 2
fi
else
LOOP=$((LOOP+1))
fi
else
LOOP=$((LOOP+1))
fi
done
return 1
}
if directory_exist_and_not_empty "${CACHEPATH}"; then
FILES=$(ls "${CACHEPATH}")
invoke_remote_ip_check "${FILES}"
RET="$?"
if [ "${RET}" -eq 0 ]; then
logger_helper "DDNS are still valid"
elif [ "${RET}" -eq 2 ]; then
logger_helper "$(service restart_ddns ) DDNS refreshed"
else
logger_helper "Error invoke url to check external ip"
fi
else
logger_helper "DDNS not enabled"
fi
exit 0
To install
- log in with ssh to the router
- move to the /jffs/scripts/ directory
Bash:
cd /jffs/script/
- create an empty file named customDdnsRefresh.sh
Bash:
vi customDdnsRefresh.sh
- copy the code inside the file
- issue the authorization for execution
Bash:
chmod 755 customDdnsRefresh.sh
- add the schedule you want to the cru, I use it every minute
Bash:
cru a ddns_refresh "*/1 * * * * /jffs/scripts/customDdnsRefresh.sh"
- To confirm that everything is working correctly, you can see the following entry in the log:
Code:April 20 19:52:00 customDdnsRefresh[2430]: use the service https://ipv4.getmyip.dev April 20 19:52:01 customDdnsRefresh[2430]: DDNS are still valid
I hope this can be useful for someone
Greetings
Commodoro
Last edited: