1
0
mirror of https://github.com/EV21/dynb.git synced 2025-12-26 16:39:32 +01:00

24 Commits

Author SHA1 Message Date
317abdbcec doc: 📝 document environment variables 2021-11-03 18:09:44 +01:00
4faba4e600 refactor: ♻️ method extractions and other beautifications 2021-11-03 18:09:43 +01:00
84784248c3 fix: 🐛 fix loop and error handling in case of connection issues 2021-11-03 18:09:43 +01:00
b083080c9d doc: 📝 document example of an docker-compose.yml file 2021-11-03 18:09:42 +01:00
48df7c7646 feat: add Dockerfile 2021-11-03 18:09:42 +01:00
b1f6c5a0fd doc: 📝 document loop mode and mention dig as requirement 2021-11-03 18:09:42 +01:00
17e23e7623 feat: add loop mode 2021-11-03 18:09:41 +01:00
bb1e0db9bf doc: 📝 update example of .env in README.md 2021-11-03 18:09:41 +01:00
29c2f62292 change: 🔃 rename environment variables 2021-11-03 18:09:41 +01:00
c85d5eaaee feat: add support for Duck DNS as DynDNS2 provider 2021-11-03 18:09:40 +01:00
3221f29d71 feat: add support for deSEC as DynDNS2 provider 2021-11-03 18:09:40 +01:00
706b6d84c1 feat: add completion
 add man page
2021-11-03 18:09:39 +01:00
6d9bf8a2ae feat: 🔃 replace getopt with argbash 2021-11-03 18:09:39 +01:00
6a14d00256 fix: 🐛 fix error handling 2021-11-03 18:09:39 +01:00
dff0c1c178 refactor: ♻️ main code 2021-11-03 18:09:38 +01:00
9bac611ddf feat: add interpretaton of status codes and act accordingly 2021-11-03 18:09:38 +01:00
1bb0f44d28 feat: make network interface configurable 2021-11-03 18:09:38 +01:00
730858344c fix: 🐛 fix sourcing of config file
♻️ do some shellcheck fixes
2021-11-03 18:09:02 +01:00
e3781a87bb feat: add DynDNS2 support for dynv6.com 2021-11-03 17:00:44 +01:00
fa5086f197 doc: 📝 CHANGELOG.md 2021-11-03 17:00:21 +01:00
3fa15b4d9d minor: 📝 .gitchangelog.rc 2021-11-03 16:59:05 +01:00
2c90e74bf5 doc: 📝 add example.env 2021-11-03 16:57:53 +01:00
cddcd9cfca add: 📝 README.md 2021-11-03 16:56:55 +01:00
616c1d47c1 add: dynb.sh 2021-11-03 16:56:39 +01:00
3 changed files with 153 additions and 95 deletions

View File

@@ -1,6 +1,17 @@
# Changelog # Changelog
## 0.1.2 (2021-04-23)
### Documentation
* :memo: document environment variables. [Eduard Veit]
### Other
* :recycle: refactor: method extractions and other beautifications. [Eduard Veit]
## 0.1.1 (2021-04-23) ## 0.1.1 (2021-04-23)
### Fix ### Fix

View File

@@ -11,7 +11,7 @@ IPv4 (A) and IPv6 (AAAA) record updates are supported.
- [⚙ Configuration](#-configuration) - [⚙ Configuration](#-configuration)
- [🏃 Run](#-run) - [🏃 Run](#-run)
- [⏰ Cron](#-cron) - [⏰ Cron](#-cron)
- [ docker](#-docker) - [🐟 docker](#-docker)
<!-- /TOC --> <!-- /TOC -->
## ✨ Update Methods ## ✨ Update Methods
@@ -140,3 +140,18 @@ services:
- DYNB_PASSWORD=SuperSecretPassword - DYNB_PASSWORD=SuperSecretPassword
- DYNB_INTERVAL=60 - DYNB_INTERVAL=60
``` ```
## environment variables
| variable | default value | description |
| --------------------- | --------------- | ----------- |
| DYNB_DYN_DOMAIN | undefined | required |
| DYNB_SERVICE_PROVIDER | undefined | required |
| DYNB_UPDATE_METHOD | undefined | required |
| DYNB_IP_MODE | undefined | required |
| DYNB_USERNAME | undefined | the requirement depends on your provider and the update method |
| DYNB_PASSWORD | undefined | the requirement depends on your provider and the update method |
| DYNB_TOKEN | undefined | the requirement depends on your provider and the update method |
| DYNB_INTERVAL | undefined | without this setting the script/docker container will run one time and exits |
| DYNB_DEBUG | undefined | more console outputs |
| DYNB_IPv4_CHECK_SITE | api64.ipify.org | You need a website or Web-API that outputs your remote IP |
| DYNB_IPv6_CHECK_SITE | api64.ipify.org | You need a website or Web-API that outputs your remote IP |
| DYNB_DNS_CHECK_SERVER | 1.1.1.1 | If you are using a local DNS Resolver/Server make sure it answers with the public answer |

220
dynb.sh
View File

@@ -65,7 +65,7 @@ _response=
_statusHostname= _statusHostname=
_statusUsername= _statusUsername=
_statusPassword= _statusPassword=
_version=0.1.1 _version=0.1.2
_userAgent="DynB/$_version github.com/EV21/dynb" _userAgent="DynB/$_version github.com/EV21/dynb"
_configFile=$HOME/.local/share/dynb/.env _configFile=$HOME/.local/share/dynb/.env
_statusFile=/tmp/dynb.status _statusFile=/tmp/dynb.status
@@ -345,13 +345,22 @@ function debugMode() {
fi fi
} }
function infoMessage() {
echo "$(logtime) INFO: $*"
}
function debugMessage() { function debugMessage() {
if debugMode; then if debugMode; then
echo "Debug: $*" echo "$(logtime) DEBUG: $*"
fi fi
} }
function echoerr() { printf "%s\n" "$*" >&2; } function errorMessage() { printf "$(logtime) ERROR: %s\n" "$*" >&2; }
function logtime() {
LOGTIME=$(date "+%Y-%m-%d %H:%M:%S")
echo "[$LOGTIME]"
}
# The main domain as an identifier for the dns zone is required for the updateRecord call # The main domain as an identifier for the dns zone is required for the updateRecord call
function getMainDomain() { function getMainDomain() {
@@ -473,7 +482,7 @@ function dynupdate() {
myipv6_str=ipv6 myipv6_str=ipv6
;; ;;
* ) * )
echoerr "$DYNB_SERVICE_PROVIDER is not supported" errorMessage "$DYNB_SERVICE_PROVIDER is not supported"
exit 1 exit 1
;; ;;
esac esac
@@ -516,64 +525,64 @@ function dynupdate() {
case $_response in case $_response in
good* | OK* | "addresses updated" ) good* | OK* | "addresses updated" )
if [[ $_response == "good 127.0.0.1" ]]; then if [[ $_response == "good 127.0.0.1" ]]; then
echoerr "Error: $_response: Request ignored." errorMessage "$_response: Request ignored."
return 1 return 1
else else
echo "$_response: The DynDNS update has been executed." infoMessage "$_response: The DynDNS update has been executed."
_errorCounter=0 _errorCounter=0
return 0 return 0
fi fi
;; ;;
nochg* ) nochg* )
echo "$_response: Nothing has changed, IP addresses are still up to date." infoMessage "$_response: Nothing has changed, IP addresses are still up to date."
return 1 return 1
;; ;;
abuse ) abuse )
echoerr "Error: $_response: Username is blocked due to abuse." errorMessage "$_response: Username is blocked due to abuse."
return 1 return 1
;; ;;
badauth | 401 ) badauth | 401 )
echoerr "Error: $_response: Invalid username password combination." errorMessage "$_response: Invalid username password combination."
return 1 return 1
;; ;;
badagent ) badagent )
echoerr "Error: $_response: Client disabled. Something is very wrong!" errorMessage "$_response: Client disabled. Something is very wrong!"
return 1 return 1
;; ;;
!donator ) !donator )
echoerr "Error: $_response: An update request was sent, including a feature that is not available to that particular user such as offline options." errorMessage "$_response: An update request was sent, including a feature that is not available to that particular user such as offline options."
return 1 return 1
;; ;;
!yours ) !yours )
echoerr "Error: $_response: The domain does not belong to your user account" errorMessage "$_response: The domain does not belong to your user account"
return 1 return 1
;; ;;
notfqdn ) notfqdn )
echoerr "Error: $_response: Hostname $DYNB_DYN_DOMAIN is invalid" errorMessage "$_response: Hostname $DYNB_DYN_DOMAIN is invalid"
return 1 return 1
;; ;;
nohost ) nohost )
echoerr "Error: $_response: Hostname supplied does not exist under specified account, enter new login credentials before performing an additional request." errorMessage "$_response: Hostname supplied does not exist under specified account, enter new login credentials before performing an additional request."
return 1 return 1
;; ;;
numhost ) numhost )
echoerr "Error: $_response: Too many hostnames have been specified for this update" errorMessage "$_response: Too many hostnames have been specified for this update"
return 1 return 1
;; ;;
dnserr ) dnserr )
echoerr "Error: $_response: There is an internal error in the dyndns update system. Retry update no sooner than 30 minutes." errorMessage "$_response: There is an internal error in the dyndns update system. Retry update no sooner than 30 minutes."
return 1 return 1
;; ;;
911 | 5* ) 911 | 5* )
echoerr "Error: $_response: A fatal error on provider side such as a database outage. Retry update no sooner than 30 minutes." errorMessage "$_response: A fatal error on provider side such as a database outage. Retry update no sooner than 30 minutes."
return 1 return 1
;; ;;
* ) * )
if [[ "$_response" == "$_status" ]]; then if [[ "$_response" == "$_status" ]]; then
echoerr "Error: An unknown response code has been received. $_response" errorMessage "An unknown response code has been received. $_response"
return 1 return 1
else else
echoerr "Error: unknown respnse code: $_response" errorMessage "unknown respnse code: $_response"
return 0 return 0
fi fi
;; ;;
@@ -589,14 +598,14 @@ function checkStatus() {
case $_status in case $_status in
nochg* ) nochg* )
if [[ _errorCounter -gt 1 ]]; then if [[ _errorCounter -gt 1 ]]; then
echoerr "Error: The update client was spamming unnecessary update requests, something might be wrong with your IP-Check site." errorMessage "The update client was spamming unnecessary update requests, something might be wrong with your IP-Check site."
echoerr "Fix your config an then delete $_statusFile" errorMessage "Fix your config an then delete $_statusFile or restart your docker container"
return 1 return 1
fi fi
;; ;;
nohost | !yours ) nohost | !yours )
if [[ "$_statusHostname" == "$DYNB_DYN_DOMAIN" && ( "$_statusUsername" == "$DYNB_USERNAME" || $_statusUsername == "$DYNB_TOKEN" ) ]]; then if [[ "$_statusHostname" == "$DYNB_DYN_DOMAIN" && ( "$_statusUsername" == "$DYNB_USERNAME" || $_statusUsername == "$DYNB_TOKEN" ) ]]; then
echoerr "Error: Hostname supplied does not exist under specified account, enter new login credentials before performing an additional request." errorMessage "Hostname supplied does not exist under specified account, enter new login credentials before performing an additional request."
return 1 return 1
else else
rm "$_statusFile" rm "$_statusFile"
@@ -605,7 +614,7 @@ function checkStatus() {
;; ;;
badauth | 401 ) badauth | 401 )
if [[ "$_statusUsername" == "$DYNB_USERNAME" && "$_statusPassword" == "$DYNB_PASSWORD" ]]; then if [[ "$_statusUsername" == "$DYNB_USERNAME" && "$_statusPassword" == "$DYNB_PASSWORD" ]]; then
echoerr "Error: Invalid username password combination." errorMessage "Invalid username password combination."
return 1 return 1
else else
rm "$_statusFile" rm "$_statusFile"
@@ -613,19 +622,19 @@ function checkStatus() {
return 0 return 0
;; ;;
badagent ) badagent )
echoerr "Error: Client is deactivated by provider." errorMessage "Client is deactivated by provider."
echo "Fix your config and then manually remove $_statusFile to reset the client blockade." echo "Fix your config and then manually remove $_statusFile to reset the client blockade."
echo "If it still fails file an issue at github or try another client :)" echo "If it still fails file an issue at github or try another client :)"
return 1 return 1
;; ;;
!donator ) !donator )
echoerr "Error: An update request was sent, including a feature that is not available to that particular user such as offline options." errorMessage "An update request was sent, including a feature that is not available to that particular user such as offline options."
echo "Fix your config and then manually remove $_statusFile to reset the client blockade" echo "Fix your config and then manually remove $_statusFile to reset the client blockade"
echo "If it still fails file an issue at github or try another client :)" echo "If it still fails file an issue at github or try another client :)"
return 1 return 1
;; ;;
abuse ) abuse )
echoerr "Error: Username is blocked due to abuse." errorMessage "Username is blocked due to abuse."
echo "Fix your config and then manually remove $_statusFile to reset the client blockade" echo "Fix your config and then manually remove $_statusFile to reset the client blockade"
echo "If it still fails file an issue at github or try another client :)" echo "If it still fails file an issue at github or try another client :)"
return 1 return 1
@@ -633,7 +642,7 @@ function checkStatus() {
911 | 5* ) 911 | 5* )
delta=$(( $(date +%s) - _eventTime )) delta=$(( $(date +%s) - _eventTime ))
if [[ $delta -lt 1800 ]]; then if [[ $delta -lt 1800 ]]; then
echoerr "$_status: The provider currently has an fatal error. DynB will wait for next update until 30 minutes have passed since last request, $(date --date=@$delta -u +%M) minutes already passed." errorMessage "$_status: The provider currently has an fatal error. DynB will wait for next update until 30 minutes have passed since last request, $(date --date=@$delta -u +%M) minutes already passed."
return 1 return 1
else else
rm "$_statusFile" rm "$_statusFile"
@@ -642,7 +651,7 @@ function checkStatus() {
;; ;;
* ) * )
if [[ _errorCounter -gt 1 ]]; then if [[ _errorCounter -gt 1 ]]; then
echoerr "Error: An unknown response code has repeatedly been received. $_response" errorMessage "An unknown response code has repeatedly been received. $_response"
return 1 return 1
else else
return 0 return 0
@@ -656,18 +665,18 @@ function checkStatus() {
function ipHasChanged() { function ipHasChanged() {
if [[ ${1} == 4 ]]; then if [[ ${1} == 4 ]]; then
remote_ip=$(getRemoteIP 4 $_ipv4_checker) remote_ip=$(getRemoteIP 4 $_ipv4_checker)
#TODO: this is doublicated code, refactor this some time #TODO: this is duplicated code, refactor this.
if [[ $? -gt 0 ]]; then if [[ $? -gt 0 ]]; then
echoerr "IPCheck (getRemoteIP) request failed $remote_ip" errorMessage "IPCheck (getRemoteIP 4) request failed $remote_ip"
return 0 return 0
fi fi
if [[ $DYNB_UPDATE_METHOD == domrobot ]]; then if [[ $DYNB_UPDATE_METHOD == domrobot ]]; then
dns_ip=$(getDNSIP A) dns_ip=$(getDNSIP A)
else else
dig_response=$(dig @${_DNS_checkServer} in a +short "$DYNB_DYN_DOMAIN") dig_response=$(dig @${_DNS_checkServer} in a +short "$DYNB_DYN_DOMAIN")
#TODO: this is doublicated code, refactor this some time #TODO: this is duplicated code, refactor this.
if [[ $dig_response == ";; connection timed out; no servers could be reached" ]]; then if [[ $dig_response == ";; connection timed out; no servers could be reached" ]]; then
echoerr "DNS request failed $dig_response" errorMessage "DNS request failed $dig_response"
return 0 return 0
fi fi
dns_ip=$dig_response dns_ip=$dig_response
@@ -675,18 +684,18 @@ function ipHasChanged() {
fi fi
if [[ ${1} == 6 ]]; then if [[ ${1} == 6 ]]; then
remote_ip=$(getRemoteIP 6 $_ipv6_checker) remote_ip=$(getRemoteIP 6 $_ipv6_checker)
#TODO: this is doublicated code, refactor this some time #TODO: this is duplicated code, refactor this.
if [[ $? -gt 0 ]]; then if [[ $? -gt 0 ]]; then
echoerr "IPCheck (getRemoteIP) request failed $remote_ip" errorMessage "IPCheck (getRemoteIP 6) request failed $remote_ip"
return 0 return 0
fi fi
if [[ $DYNB_UPDATE_METHOD == domrobot ]]; then if [[ $DYNB_UPDATE_METHOD == domrobot ]]; then
dns_ip=$(getDNSIP AAAA) dns_ip=$(getDNSIP AAAA)
else else
dig_response=$(dig @${_DNS_checkServer} in aaaa +short "$DYNB_DYN_DOMAIN") dig_response=$(dig @${_DNS_checkServer} in aaaa +short "$DYNB_DYN_DOMAIN")
#TODO: this is doublicated code, refactor this some time #TODO: this is duplicated code, refactor this.
if [[ $dig_response == ";; connection timed out; no servers could be reached" ]]; then if [[ $dig_response == ";; connection timed out; no servers could be reached" ]]; then
echoerr "DNS request failed $dig_response" errorMessage "DNS request failed $dig_response"
return 0 return 0
fi fi
dns_ip=$dig_response dns_ip=$dig_response
@@ -779,6 +788,15 @@ function handleParameters() {
if [[ $DYNB_DEBUG == true ]]; then if [[ $DYNB_DEBUG == true ]]; then
_debug=1 _debug=1
fi fi
if [[ -n $DYNB_IPv4_CHECK_SITE ]]; then
_ipv4_checker=$DYNB_IPv4_CHECK_SITE
fi
if [[ -n $DYNB_IPv6_CHECK_SITE ]]; then
_ipv6_checker=$DYNB_IPv6_CHECK_SITE
fi
if [[ -n $DYNB_DNS_CHECK_SERVER ]]; then
_DNS_checkServer=$DYNB_DNS_CHECK_SERVER
fi
return 0 return 0
} }
@@ -787,30 +805,31 @@ function handleParameters() {
################## ##################
function checkDependencies() { function checkDependencies() {
## If there will be more general dependencies use a loop failCounter=0
# for i in curl and some other stuff; do for i in curl dig; do
# if ! command -v $i >/dev/null 2>&1; then if ! command -v $i >/dev/null 2>&1; then
# echoerr "Error: could not find \"$i\", DynB depends on it. " errorMessage "could not find \"$i\", DynB depends on it. "
# exit 1 (( failCounter++ ))
# fi fi
# done done
[[ -x $(command -v jq 2> /dev/null) ]] || { [[ -x $(command -v jq 2> /dev/null) ]] || {
if [[ $DYNB_UPDATE_METHOD != dyndns* ]]; then if [[ $DYNB_UPDATE_METHOD != dyndns* ]]; then
echo "This script depends on jq and it is not available." >&2 echo "This script depends on jq and it is not available." >&2
exit 1 (( failCounter++ ))
fi fi
} }
if [[ failCounter -gt 0 ]]; then
exit 1
fi
} }
function doUnsets() { function doUnsets() {
unset _network_interface unset _network_interface
unset _DNS_checkServer unset _DNS_checkServer
unset _dns_records unset _dns_records
unset DYNB_DYN_DOMAIN
unset _has_getopt unset _has_getopt
unset _help_message unset _help_message
unset _INWX_JSON_API_URL unset _INWX_JSON_API_URL
unset DYNB_IP_MODE
unset _ipv4_checker unset _ipv4_checker
unset _ipv6_checker unset _ipv6_checker
unset _is_IPv4_enabled unset _is_IPv4_enabled
@@ -818,59 +837,75 @@ function doUnsets() {
unset _main_domain unset _main_domain
unset _new_IPv4 unset _new_IPv4
unset _new_IPv6 unset _new_IPv6
unset DYNB_PASSWORD
unset DYNB_USERNAME
unset DYNB_SERVICE_PROVIDER
unset _version unset _version
unset DYNB_DYN_DOMAIN
unset DYNB_USERNAME
unset DYNB_PASSWORD
unset DYNB_TOKEN
unset DYNB_SERVICE_PROVIDER
unset DYNB_IP_MODE
unset DYNB_INTERVAL
unset DYNB_IPv4_CHECK_SITE
unset DYNB_IPv6_CHECK_SITE
unset DYNB_DNS_CHECK_SERVER
unset DYNB_DEBUG
}
function doDomrobotUpdates() {
getMainDomain
fetchDNSRecords
if [[ $_is_IPv4_enabled == true ]]; then
ipHasChanged 4
if [[ $? == 1 ]]; then
updateRecord 4
else
debugMessage "Skip IPv4 record update, it is already up to date"
fi
fi
if [[ $_is_IPv6_enabled == true ]]; then
ipHasChanged 6
if [[ $? == 1 ]]; then
updateRecord 6
else
debugMessage "Skip IPv6 record update, it is already up to date"
fi
fi
}
function doDynDNS2Updates() {
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
if checkStatus; then
debugMessage "checkStatus has no errors, try update"
if dynupdate; then
debugMessage "DynDNS2 update success"
else
debugMessage "Save new status after dynupdate has failed"
setStatus "$_response" "$(date +%s)" $(( _errorCounter += 1 )) "$DYNB_DYN_DOMAIN" "${DYNB_USERNAME}" "${DYNB_PASSWORD}${DYNB_TOKEN}"
fi
else
debugMessage "Skip DynDNS2 update, checkStatus fetched previous error."
fi
else
debugMessage "Skip DynDNS2 update, IPs are up to date or there is a connection problem"
fi
} }
function doUpdates() { function doUpdates() {
if [[ $DYNB_UPDATE_METHOD == "domrobot" ]]; then if [[ $DYNB_UPDATE_METHOD == "domrobot" ]]; then
getMainDomain doDomrobotUpdates
fetchDNSRecords
if [[ $_is_IPv4_enabled == true ]]; then
ipHasChanged 4
if [[ $? == 1 ]]; then
updateRecord 4
else
debugMessage "Skip IPv4 record update, it is already up to date"
fi
fi
if [[ $_is_IPv6_enabled == true ]]; then
ipHasChanged 6
if [[ $? == 1 ]]; then
updateRecord 6
else
debugMessage "Skip IPv6 record update, it is already up to date"
fi
fi
fi fi
if [[ $DYNB_UPDATE_METHOD == "dyndns" ]]; then if [[ $DYNB_UPDATE_METHOD == "dyndns" ]]; then
changed=0 doDynDNS2Updates
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
if checkStatus; then
debugMessage "checkStatus has no errors, try update"
if dynupdate; then
debugMessage "DynDNS2 update success"
else
debugMessage "Save new status after dynupdate has failed"
setStatus "$_response" "$(date +%s)" $(( _errorCounter += 1 )) "$DYNB_DYN_DOMAIN" "${DYNB_USERNAME}" "${DYNB_PASSWORD}${DYNB_TOKEN}"
fi
else
debugMessage "Skip DynDNS2 update, checkStatus fetched previous error."
fi
else
debugMessage "Skip DynDNS2 update, IPs are up to date or there is a connection problem"
fi
fi fi
} }
@@ -900,9 +935,6 @@ function dynb() {
handleParameters handleParameters
## execute operations
if loopMode; then if loopMode; then
while : while :
do do