Add Dynamic DNS Script (#9)

* Initial commit for Dynamic DNS code. Not in a runnable state but as far as I can get for now.

* Bring shell script for Dynamic DNS to working order. Dry runs are going well. Have not tested against a production environment yet.

* Add instructions for No-IP in case it needs installed later..

* Variablize the full path to the keyfile. Enforce strict permissions on the file.

* Final updates after successful testing.

* Update instructions, add examples.

* Fix usage.

* Remove unnecessary asterisk.
This commit is contained in:
Hyperling 2023-07-23 13:14:47 -07:00 committed by GitHub
parent 5d9c5e495d
commit e383520ebb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 218 additions and 1 deletions

4
.gitignore vendored
View File

@ -14,6 +14,8 @@ Config/ReverseProxy/config/hosts/*
Config/ReverseProxy/config/load.conf.d/*
Config/ReverseProxy/config/mail.conf.d/*
# Ignore MailServer Files
# Ignore downloaded mail server files
Config/MailServer/setup.sh
# Ignore any private key information
private.key

View File

@ -0,0 +1,66 @@
# Dynamic DNS Updater
This script is meant to be added to cron if you are using afraid.org as your
dynamic DNS provider. Similar may be possible with sites such as dyn.org or
noip.com but are currently not supported in this project. Links to some of these
product's self-built solutions can be found below.
## Afraid.org Version 2 Instructions
1. Install this project.
```
git clone https://github.com/Hyperling/docker $PROJECT_DIR
```
1. Add your Afraid DNS account key to $PROJECT_DIR/Config/DynamicDNS/private.key
Account key can be found [here](https://freedns.afraid.org/dynamic/v2/).
1. Add this line to the system's cron scheduling using a command like `crontab -e`.
```
5 * * * * $PROJECT_DIR/Config/DynamicDNS/update_dns.sh
```
### TESTING
Please ensure all testing is done with the test or dry run flags. If you run
this for your private key outside of your network then your Dynamic DNS may
become inaccurate. This program is only intended to be run in a production
manner on the network which needs the Dynamic DNS pointing towards it.
### Example
```
$ ./update_dns.sh -4
Updated DOMAIN from 1:2:3:4:5:6:7:8 to 1.2.3.4
HTTP200
Status 0 is acceptable.
```
```
$ ./update_dns.sh -6
Updated DOMAIN from 1.2.3.4 to 1:2:3:4:5:6:7:8
HTTP200
Status 0 is acceptable.
```
## Afraid.org Version 1 Instructions
Add one of these to your crontab. Basically what the script does without fancy
options and checks. Please be concious of how often you knock on the servers,
and preferably add a 30-45 second sleep so that you do not hit near :00 seconds.
```
*/4 * * * * sleep 28; curl http://freedns.afraid.org/dynamic/update.php?YOUR_V1_KEY_GOES_HERE
```
```
*/7 * * * * sleep 42; wget -O http://freedns.afraid.org/dynamic/update.php?YOUR_V1_KEY_GOES_HERE
```
## Other Dynamic DNS Hosts
### No-IP.org Instructions
Please see this guide on installing the Dynamic Update Client (DUC).
https://my.noip.com/dynamic-dns/duc

149
Config/DynamicDNS/update_dns.sh Executable file
View File

@ -0,0 +1,149 @@
#!/bin/bash
# 2023-05-18 Hyperling
# Keep afraid.org dynamic DNS synced on ISP connections without static IPs.
## Setup ##
DIR="`dirname $0`"
PROG=`basename $0`
if [[ $DIR == "."* ]]; then
DIR="`pwd`"
fi
DOMAIN="sync.afraid.org"
PROTOCOL="http"
KEYFILE_NAME="private.key"
KEYFILE="$DIR/$KEYFILE_NAME"
## Functions ##
function usage {
# Accepts 1 parameter: The exit code to use.
exit_status=$1
echo "Usage: $PROG [-4] [-6] [-d | -t] [-v] [-h]" 1>&2
cat <<- EOF
Program reads the local $KEYFILE_NAME and syncs with the Dynamic DNS provider.
Current DNS providers are mentioned in the README, but initally only
afraid.org is being supported since that is the maintainer's primary
usage. More may be added eventually or you're welcome to contribute.
Parameters:
-4 : Update IPV4.
-6 : Update IPV6.
* If neither 4 or 6 are provided, 4 is assumed as Yes.
-d : Perform a dry run, echoing the commands rather than doing the update.
-t : Test run. Alias for the dry run option above.
-v : Enable extra output, helpful for debugging.
-h : Print this list of parameters.
EOF
exit $exit_status
}
function check {
# Accepts parameter of status and whether the program should quit.
status=$1
quit=$2
if [[ $status != 0 ]]; then
echo "ERROR: Did not receive a successful return message, got $status." 1>&2
if [[ $quit == "Y" ]]; then
exit $status
fi
fi
echo "Status $status is acceptable."
}
## Validations ##
# Ensure the account key is present and has contents.
if [[ ! -s $KEYFILE ]]; then
echo "ERROR: Key file '$KEYFILE' is empty or does not exist." 1>&2
echo -e "Please see '$DIR/README.md' for instructions.\n"
usage
fi
## Parameters ##
while getopts ":46dtvh" opt; do
case $opt in
4)
v4="Y"
;;
6)
v6="Y"
;;
d | t)
dry_run="Y"
;;
v)
set -x
;;
h)
usage 0
;;
*)
echo "ERROR: Parameter $opt not recognized."
usage 1
;;
esac
done
# Cannot set both 4 and 6, otherwise only the 2nd takes effect.
if [[ -n $v4 && -n $v6 ]]; then
echo "ERROR: Cannot set both v4 and v6, please only choose one." 1>&2
usage 1
fi
# If neither parameter was passed, assume 4 is wanted.
if [[ -z $v4 && -z $v6 ]]; then
v4="Y"
fi
## Main ##
# Use echo instead of cURL if doing a dry/test run.
command="curl -w HTTP%{http_code}\n"
if [[ $dry_run == "Y" ]]; then
command="echo $command"
fi
# Ensure permissions are strict.
chmod -c 600 $KEYFILE
# Get the user's key
if [[ -n $KEYFILE ]]; then
key=`cat $KEYFILE`
else
echo "ERROR: Cannot find '$KEYFILE'. Please set up your account key." 1>&2
usage 1
fi
# Remove any padding like newlines or trailing spaces
key=`echo $key`
# Ensure we got a value
if [[ -z $key ]]; then
echo "ERROR: Key contents were not read, is '$KEYFILE' set up proerly?." 1>&2
usage 1
fi
# Try to ensure the key is not going to cause a malformed link somehow.
if [[ $key == *" "* ]]; then
echo "WARNING: Space character found in key. Is that correct? Converting to %20." 1>&2
key=${key// /%20}
fi
uri="$DOMAIN/u/$key/"
# Connect with the provider.
if [[ $v4 == "Y" ]]; then
$command $PROTOCOL://$uri
check $? Y
fi
if [[ $v6 == "Y" ]]; then
$command $PROTOCOL://v6.$uri
check $? Y
fi
exit 0