mirror of
https://github.com/EV21/dynb.git
synced 2025-12-26 16:39:32 +01:00
✨ add dynb.sh
This commit is contained in:
416
dynb.sh
Executable file
416
dynb.sh
Executable file
@@ -0,0 +1,416 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
## Copyright (c) 2021 Eduard Veit
|
||||
## All rights reserved. This program and the accompanying materials
|
||||
## are made available under the terms of the MIT license
|
||||
## which accompanies this distribution, and is available at
|
||||
## https://opensource.org/licenses/MIT
|
||||
|
||||
_version=0.1.0
|
||||
|
||||
###################
|
||||
## Configuration ##
|
||||
###################
|
||||
|
||||
_dyn_domain=dyndns.example.com
|
||||
|
||||
## service provider could be inwx
|
||||
_serviceProvider=inwx
|
||||
|
||||
## update method options: domrobot, dyndns
|
||||
_update_method=domrobot
|
||||
|
||||
## ip mode could be either: 4, 6 or dual for dualstack
|
||||
_ip_mode=dual
|
||||
|
||||
## If you are using the DomRobot RPC-API enter your credentials for the web interface login here
|
||||
## If you are using the DynDNS2 protocol enter your credentials here
|
||||
_username=
|
||||
_password=
|
||||
|
||||
## TTL (time to live) minimum allowed value by inwx is 300 (5 minutes)
|
||||
TTL=300
|
||||
|
||||
## The IP-Check sites (some sites have different urls for v4 and v6)
|
||||
## pro tip: use your own ip check server for privacy
|
||||
## it could be as simple as that...
|
||||
## create an index.php with <?php echo $_SERVER['REMOTE_ADDR']; ?>
|
||||
_ipv4_checker=api64.ipify.org
|
||||
_ipv6_checker=api64.ipify.org
|
||||
_DNS_checkServer=1.1.1.1
|
||||
|
||||
######################################################
|
||||
## You don't need to change the following variables ##
|
||||
_INWX_JSON_API_URL=https://api.domrobot.com/jsonrpc/
|
||||
_new_IPv4=
|
||||
_new_IPv6=
|
||||
_dns_records=
|
||||
_main_domain=
|
||||
_has_getopt=
|
||||
_is_IPv4_enabled=false
|
||||
_is_IPv6_enabled=false
|
||||
|
||||
[[ -x $(command -v jq 2> /dev/null) ]] || {
|
||||
echo "This script depends on jq and it is not available." >&2
|
||||
exit 1
|
||||
}
|
||||
[[ -x $(command -v curl 2> /dev/null) ]] || {
|
||||
echo "This script depends on curl and it is not available." >&2
|
||||
exit 1
|
||||
}
|
||||
[[ -x $(command -v getopt 2> /dev/null) ]] || {
|
||||
_has_getopt=false
|
||||
}
|
||||
|
||||
_help_message="$(cat << 'EOF'
|
||||
dynb - dynamic DNS update script for bash
|
||||
|
||||
Usage
|
||||
-------
|
||||
dynb [options]
|
||||
|
||||
-h, --help displays this help message
|
||||
-i | --ip-mode [ 4 | 6 | dual ] updates type A (IPv4) and AAAA (IPv6) records
|
||||
-m | --update-method [dyndns | domrobot] choose if you want to use DynDNS2 or the DomRobot RPC-API
|
||||
-s | --service-provider inwx set your provider in case you are using DynDNS2
|
||||
-d | --domain "dyndns.example.com" set the domain you want to update
|
||||
-u | --username "user42" depends on your selected update method and your provider
|
||||
-p | --password "SuperSecretPassword" depends on your selected update method and your provider
|
||||
|
||||
##### examples #####
|
||||
dynb --ip-mode dualstack --update-method domrobot --domain dyndns.example.com --username user42 --password SuperSecretPassword
|
||||
dynb --ip-mode dualstack --update-method dyndns --service-provider inwx --domain dyndns.example.com --username user42 --password SuperSecretPassword
|
||||
EOF
|
||||
)"
|
||||
|
||||
# The main domain or another identifier for the zone is required for the updateRecord call
|
||||
function getMainDomain() {
|
||||
request=$( echo "{}" | \
|
||||
jq '(.method="'nameserver.list'")' | \
|
||||
jq '(.params.user="'$_username'")' | \
|
||||
jq '(.params.pass="'$_password'")'
|
||||
)
|
||||
|
||||
response=$(curl --silent \
|
||||
--request POST $_INWX_JSON_API_URL \
|
||||
--header "Content-Type: application/json" \
|
||||
--data "$request" | jq '.resData.domains[] | select(inside(.domain="'"$_dyn_domain"'"))'
|
||||
)
|
||||
_main_domain=$( echo "$response" | jq --raw-output '.domain' )
|
||||
}
|
||||
|
||||
function fetchDNSRecords() {
|
||||
request=$( echo "{}" | \
|
||||
jq '(.method="'nameserver.info'")' | \
|
||||
jq '(.params.user="'$_username'")' | \
|
||||
jq '(.params.pass="'$_password'")' | \
|
||||
jq '(.params.domain="'"$_main_domain"'")' | \
|
||||
jq '(.params.name="'"$_dyn_domain"'")'
|
||||
)
|
||||
|
||||
response=$( curl --silent \
|
||||
--request POST $_INWX_JSON_API_URL \
|
||||
--header "Content-Type: application/json" \
|
||||
--data "$request"
|
||||
)
|
||||
|
||||
_dns_records=$( echo $response | jq '.resData.record[]' )
|
||||
}
|
||||
|
||||
# requires parameter A or AAAA
|
||||
# result to stdout
|
||||
function getRecordID() {
|
||||
echo $_dns_records | jq 'select(.type == "'${1}'") | .id'
|
||||
}
|
||||
|
||||
# requires parameter A or AAAA
|
||||
# result to stdout
|
||||
function getDNSIP() {
|
||||
echo $_dns_records | jq --raw-output 'select(.type == "'${1}'") | .content'
|
||||
}
|
||||
|
||||
# requires parameter
|
||||
# 1. param: 4 or 6 for ip version
|
||||
# 2. param: IP check server address
|
||||
# result to stdout
|
||||
function getRemoteIP() {
|
||||
curl --silent --ipv${1} --dns-servers 1.1.1.1 --location ${2}
|
||||
}
|
||||
|
||||
# requires parameter
|
||||
# 1. param: 4 or 6 as ip version
|
||||
function updateRecord() {
|
||||
if [[ ${1} == 4 ]]; then
|
||||
ID=$(getRecordID A)
|
||||
IP=$_new_IPv4
|
||||
fi
|
||||
if [[ ${1} == 6 ]]; then
|
||||
ID=$(getRecordID AAAA)
|
||||
IP=$_new_IPv6
|
||||
fi
|
||||
if [[ $IP != "" ]]; then
|
||||
request=$( echo "{}" | \
|
||||
jq '(.method="'nameserver.updateRecord'")' | \
|
||||
jq '(.params.user="'$_username'")' | \
|
||||
jq '(.params.pass="'$_password'")' | \
|
||||
jq '(.params.id="'$ID'")' | \
|
||||
jq '(.params.content="'$IP'")' | \
|
||||
jq '(.params.ttl="'$TTL'")'
|
||||
)
|
||||
response=$(curl --silent \
|
||||
--request POST $_INWX_JSON_API_URL \
|
||||
--header "Content-Type: application/json" \
|
||||
--data "$request"
|
||||
)
|
||||
echo -e "$(echo "$response" | jq --raw-output '.msg')\n Domain: $_dyn_domain\n new IPv${1}: $IP"
|
||||
fi
|
||||
}
|
||||
|
||||
# using DynDNS2 protocol
|
||||
function dynupdate() {
|
||||
INWX_DYNDNS_UPDATE_URL="https://dyndns.inwx.com/nic/update?"
|
||||
if [[ $_serviceProvider == "inwx" ]]; then
|
||||
dyndns_update_url=$INWX_DYNDNS_UPDATE_URL
|
||||
fi
|
||||
if [[ $_is_IPv4_enabled == true ]] && [[ $_is_IPv6_enabled == true ]]; then
|
||||
dyndns_update_url="${dyndns_update_url}myip=${_new_IPv4}&myipv6=${_new_IPv6}"
|
||||
fi
|
||||
if [[ $_is_IPv4_enabled == true ]] && [[ $_is_IPv6_enabled == false ]]; then
|
||||
dyndns_update_url="${dyndns_update_url}myip=${_new_IPv4}"
|
||||
fi
|
||||
if [[ $_is_IPv4_enabled == false ]] && [[ $_is_IPv6_enabled == true ]]; then
|
||||
dyndns_update_url="${dyndns_update_url}myipv6=${_new_IPv6}"
|
||||
fi
|
||||
|
||||
result=$(curl --silent --user $_username:$_password "${dyndns_update_url}" )
|
||||
case $result in
|
||||
good )
|
||||
echo "The DynDNS update has been executed."
|
||||
return
|
||||
;;
|
||||
nochg )
|
||||
echo "Nothing has changed, IP addresses are still up to date."
|
||||
return
|
||||
;;
|
||||
abuse )
|
||||
echo "You are not allowed to run this command more than once in 60 seconds."
|
||||
return
|
||||
;;
|
||||
badauth )
|
||||
echo "Your username and/or password is wrong."
|
||||
return
|
||||
;;
|
||||
!yours )
|
||||
echo "The domain does not belong to your user account"
|
||||
return
|
||||
;;
|
||||
notfqdn )
|
||||
echo "Hostname $_dyn_domain is invalid"
|
||||
return
|
||||
;;
|
||||
nohost )
|
||||
echo "No hostname has been specified"
|
||||
return
|
||||
;;
|
||||
numhost )
|
||||
echo "Too many hostnames have been specified for this update"
|
||||
return
|
||||
;;
|
||||
dnserr )
|
||||
echo "There is an internal error in the dyndns update system"
|
||||
return
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# requires parameter
|
||||
# 1. param: 4 or 6 for IP version
|
||||
function ipHasChanged() {
|
||||
if [[ ${1} == 4 ]]; then
|
||||
remote_ip=$(getRemoteIP 4 $_ipv4_checker)
|
||||
if [[ $_update_method == domrobot ]]; then
|
||||
dns_ip=$(getDNSIP A)
|
||||
else
|
||||
dns_ip=$(dig @${_DNS_checkServer} in a +short "$_dyn_domain")
|
||||
fi
|
||||
fi
|
||||
if [[ ${1} == 6 ]]; then
|
||||
remote_ip=$(getRemoteIP 6 $_ipv6_checker)
|
||||
if [[ $_update_method == domrobot ]]; then
|
||||
dns_ip=$(getDNSIP AAAA)
|
||||
else
|
||||
dns_ip=$(dig @${_DNS_checkServer} in aaaa +short "$_dyn_domain")
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$remote_ip" == "$dns_ip" ]]; then
|
||||
return 0
|
||||
else
|
||||
if [[ ${1} == 4 ]]; then
|
||||
_new_IPv4=$remote_ip
|
||||
#echo "New IPv4: $_new_IPv4 old was: $dns_ip"
|
||||
else
|
||||
_new_IPv6=$remote_ip
|
||||
#echo "New IPv6: $_new_IPv6 old was: $dns_ip"
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
###############
|
||||
## arguments ##
|
||||
###############
|
||||
|
||||
ARGS=
|
||||
if [[ $_has_getopt == "" ]] && [[ $(uname) == Linux ]]; then
|
||||
ARGS=$(getopt --options "hvi:,d:,m:,s:,u:,p:" --longoptions "help,version,link,ip-mode:,domain:,update-method:,service-provider:,username:,password:" -- "$@");
|
||||
fi
|
||||
eval set -- "$ARGS";
|
||||
unset ARGS
|
||||
|
||||
function processParameters() {
|
||||
while true; do
|
||||
case $1 in
|
||||
-h | --help )
|
||||
echo "$_help_message"
|
||||
exit 0
|
||||
;;
|
||||
-v | --version )
|
||||
echo $_version
|
||||
exit 0
|
||||
;;
|
||||
--link )
|
||||
ln --verbose --symbolic "$(realpath "$0")" "$HOME/.local/bin/dynb"
|
||||
exit 0
|
||||
;;
|
||||
-i | --ip-mode )
|
||||
_ip_mode=$2
|
||||
shift 2
|
||||
;;
|
||||
-d | --domain )
|
||||
_dyn_domain=$2
|
||||
shift 2
|
||||
;;
|
||||
-m | --update-method )
|
||||
_update_method=$2
|
||||
shift 2
|
||||
;;
|
||||
-s | --service-provider )
|
||||
_serviceProvider=$2
|
||||
shift 2
|
||||
;;
|
||||
-u | --username )
|
||||
_username=$2
|
||||
shift 2
|
||||
;;
|
||||
-p | --password )
|
||||
_password=$2
|
||||
shift 2
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
##################
|
||||
## dependencies ##
|
||||
##################
|
||||
|
||||
function checkDependencies() {
|
||||
[[ -x $(command -v curl 2> /dev/null) ]] || {
|
||||
echo "This script depends on curl and it is not available." >&2
|
||||
exit 1
|
||||
}
|
||||
[[ -x $(command -v jq 2> /dev/null) ]] || {
|
||||
if [[ $_update_method != dyndns* ]]; then
|
||||
echo "This script depends on jq and it is not available." >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
[[ -x $(command -v getopt 2> /dev/null) ]] || {
|
||||
_has_getopt=false
|
||||
}
|
||||
}
|
||||
|
||||
##################
|
||||
## MAIN section ##
|
||||
##################
|
||||
|
||||
FILE=$(dirname "$0")/.env
|
||||
if test -f "$FILE"; then
|
||||
# shellcheck source=.env
|
||||
# shellcheck disable=SC1091
|
||||
source "$FILE"
|
||||
fi
|
||||
|
||||
if [[ $_has_getopt == "" ]] && [[ $(uname) == Linux ]]; then
|
||||
processParameters "$@"
|
||||
fi
|
||||
|
||||
checkDependencies
|
||||
|
||||
if [[ $_ip_mode == d* ]]; then
|
||||
_is_IPv4_enabled=true
|
||||
_is_IPv6_enabled=true
|
||||
fi
|
||||
if [[ $_ip_mode == *4* ]]; then
|
||||
_is_IPv4_enabled=true
|
||||
fi
|
||||
if [[ $_ip_mode == *6* ]]; then
|
||||
_is_IPv6_enabled=true
|
||||
fi
|
||||
|
||||
if [[ $_update_method == "domrobot" ]]; then
|
||||
getMainDomain
|
||||
fetchDNSRecords
|
||||
if [[ $_is_IPv4_enabled == true ]]; then
|
||||
ipHasChanged 4
|
||||
if [[ $? == 1 ]]; then
|
||||
updateRecord 4
|
||||
fi
|
||||
fi
|
||||
if [[ $_is_IPv6_enabled == true ]]; then
|
||||
ipHasChanged 6
|
||||
if [[ $? == 1 ]]; then
|
||||
updateRecord 6
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ $_update_method == "dyndns" ]]; then
|
||||
changed=0
|
||||
if [[ $_is_IPv4_enabled == true ]]; then
|
||||
ipHasChanged 4
|
||||
(( changed += $? ))
|
||||
fi
|
||||
if [[ $_is_IPv6_enabled == true ]]; then
|
||||
ipHasChanged 6
|
||||
(( changed += $? ))
|
||||
fi
|
||||
if [[ $changed -gt 0 ]]; then
|
||||
dynupdate
|
||||
fi
|
||||
fi
|
||||
|
||||
unset _DNS_checkServer
|
||||
unset _dns_records
|
||||
unset _dyn_domain
|
||||
unset _has_getopt
|
||||
unset _help_message
|
||||
unset _INWX_JSON_API_URL
|
||||
unset _ip_mode
|
||||
unset _ipv4_checker
|
||||
unset _ipv6_checker
|
||||
unset _is_IPv4_enabled
|
||||
unset _is_IPv6_enabled
|
||||
unset _main_domain
|
||||
unset _new_IPv4
|
||||
unset _new_IPv6
|
||||
unset _password
|
||||
unset _username
|
||||
unset _serviceProvider
|
||||
unset _version
|
||||
|
||||
exit 0
|
||||
Reference in New Issue
Block a user