diff --git a/homelab/vyos/cfddns.sh b/homelab/vyos/cfddns.sh new file mode 100644 index 00000000..f5b0474c --- /dev/null +++ b/homelab/vyos/cfddns.sh @@ -0,0 +1,50 @@ +#!/bin/bash +# Takes two positional arguments: +# $1 is the name of the zone to update +# E.g. jafner.net +# $2 is an auth token for Cloudflare; +# Must have the following permissions +# for the given zone: +# - Zone: Read +# - DNS: Read +# - DNS: Edit +function cfddns () { + ZONE=$1 + TOKEN=$2 + + # 1. Get the zone ID from the zone name + ZONE_ID=$( + curl -s \ + -X GET "https://api.cloudflare.com/client/v4/zones" \ + --header "Authorization: Bearer $TOKEN" \ + --header "Content-Type:application/json" |\ + jq -r --arg NAME "$ZONE" '.[] | .[]? | select(.name?==$NAME) | .id' 2>/dev/null |\ + xargs + ); echo $ZONE_ID + + # 2. Get the record ID of the root A record + RECORD_ID=$( + curl -s \ + -X GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \ + --header "Authorization: Bearer $TOKEN" \ + --header 'Content-Type:application/json' |\ + jq -r --arg NAME "$ZONE" '.[] | .[]? | select(.type=="A") | select(.name?==$NAME) | .id' 2>/dev/null |\ + xargs + ); echo $RECORD_ID + + # 3. Compose the json payload for the record to push + DATA=$(jq --null-input \ + --arg CONTENT "$(curl -s ipinfo.io/ip)" \ + --arg NAME "$ZONE" \ + '{"content": $CONTENT, "name": $NAME, "type": "A"}' + ); echo $DATA + + # 4. Finally submit the updated record to Cloudflare + curl --request PUT \ + --url https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$RECORD_ID \ + --header "Authorization: Bearer $TOKEN" \ + --header 'Content-Type:application/json' \ + --data "$DATA" > /dev/null 2>&1 +} + +cfddns $1 $2 \ No newline at end of file diff --git a/homelab/vyos/cloudflare.token b/homelab/vyos/cloudflare.token new file mode 100644 index 00000000..6c6e4ec0 --- /dev/null +++ b/homelab/vyos/cloudflare.token @@ -0,0 +1,58 @@ +{ + "data": "ENC[AES256_GCM,data:60TE1dxBU0Yz4EFLYJKXwzDLazyhKPYldxN8o0uBJOZh94aPaheQ8w==,iv:GwDtrXV3F3zyrVpDRc8lp97CQr8VNWWZTgJmLLnVE50=,tag:yY/JOzl5vNLLKMynJOz9pA==,type:str]", + "sops": { + "shamir_threshold": 2, + "key_groups": [ + { + "hc_vault": null, + "age": [ + { + "recipient": "age1zswcq6t5wl8spr3g2wpxhxukjklngcav0vw8py0jnfkqd2jm2ypq53ga00", + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBnOGY0bU5nYTF5b2hFQlhs\nRlM3QmRaOGhCOWdIc2MzSzcvaUVoU2pEbGd3CnZBbkgrWFFoUmxvYXMxNWRGNnVl\nTE5wRm81NnlKUk1YUGlCU0p0cGYwWW8KLS0tIGZtN1pDRCtMVldObEVNR0lsQUNa\nRzVEcTZCR0o3NEp1YmNEd1JCcDRhWDAKNdM2sZWMqmiUHQNVb7EWsL1sch5W+TIE\nj6n65AxGTLUkVVg+elWuSu6l6WcD2p47Z8SqjequzaGzyU+lEPpPPzI=\n-----END AGE ENCRYPTED FILE-----\n" + } + ] + }, + { + "hc_vault": null, + "age": [ + { + "recipient": "age1zswcq6t5wl8spr3g2wpxhxukjklngcav0vw8py0jnfkqd2jm2ypq53ga00", + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBhbVhiUEo5ZXE2cVhuTDNp\nTFNvMjFQU2cxMkVPdzNId0FHR1Y5dWF3OWk4ClZJNVZ2aXBlTERCdlNOYlhpblV0\nQ2V2MDZQTW9NRmpyTzZoaHpRLy9oa1kKLS0tIG94RDQyY3JKR3NId1d1WDc5WG1P\nM3lsVS9aY3g3SUlnVSt1VWhEU1ZHaWsKaZJ9zqHEx1r/NBmsc4oNIb6QQInjCa/e\n8KRMfQdku4sasGdIB10cCbBhVzJbePKhF8bytWO7YgWv+ifRkjePUIc=\n-----END AGE ENCRYPTED FILE-----\n" + } + ] + }, + { + "hc_vault": null, + "age": [ + { + "recipient": "age193t908fjxl8ekl77p5xqnpj4xmw3y0khvyzlrw22hdzjduk6l53q05spq3", + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBTb2VLNkhzNnY0UTFiRk0w\nVTYrcW9aMS9ad01DZFhXcVZ1NFVJd1VDbUF3CjVMNGo3NUdrWWx5ZnpxeVFKSTAz\nM01GdkptR05rTHlSd2d0aDBsU0N3dWsKLS0tIGNXRGlQNTdYSzZxS1RJajFPWUhs\nNVZydnV5bXhhTnZCTUhhWDV0Smo4TVUKYkIujoeIUXwrl9XqP+O1rtmQWNZwHVF+\nVruG1izI5LDxDJ3kv3xyGRDqYjR7nuiIe8z3jbfjVB/RL9ITX7fRLJs=\n-----END AGE ENCRYPTED FILE-----\n" + } + ] + }, + { + "hc_vault": null, + "age": [ + { + "recipient": "age13prhyye2jy3ysa6ltnjgkrqtxrxgs0035d86jyn4ltgk3wxtqgrqgav855", + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBZZ3lEbkFWbHI4WHJGclFr\nWDVxS2NzNUQvZWtnVnprVHRVOVVRYmtpQ25JCmNwSVl4czRSNTk3QThySG5iWEFP\nL1BINVdHQUI3N05ta1dVVytyK1ppWUkKLS0tIHRpS2o0eEVmYTRjTTA5VkVuQ2h1\nNzV3a0I1dFFPa2ZmRWUvZkRIT1ZBKzQKWiBY7vOp3eJ43KrnI9nrfmSMLGaUr3U0\nYgZ1JYS9pypDmSFfwhOxSglEcJ5OaZrNn60L71zci7Z0blHfYyDVVCI=\n-----END AGE ENCRYPTED FILE-----\n" + }, + { + "recipient": "age1n20krynrj75jqfy2muvhrygvzd4ee8ngamljqavsrk033zwx0ses2tdtfe", + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB3L3pCL2NMOTRVeFFxWXFx\nUVA4TVg2MGNHdGZJS3RrbDg0YnBqZys0S2w0CndkVERGOU4zYjVqS3ZqS2Y4MWQv\ncnJHbXQvUTBudE5vV0VxYTRJZG9KbkEKLS0tIGVEZSt5L1BYVm04TXVoWmQ1eXFu\nM2pjSjhpL001cnJxTXhPamNwOEkrY2cK7eX/WDVth1S9GLs1LBrEvTxsGJv+RHIj\nzFifUBbkthHs+bFY9CWeEVMKDkHwhUhRFMo6lTa+hT51zKJAo+HnRlA=\n-----END AGE ENCRYPTED FILE-----\n" + } + ] + } + ], + "kms": null, + "gcp_kms": null, + "azure_kv": null, + "hc_vault": null, + "age": null, + "lastmodified": "2024-10-17T04:42:04Z", + "mac": "ENC[AES256_GCM,data:oqPIlCZpe8EzLVI1bjVSB8tDwfkdF/s5lBJpfZq3Zo1RURe1hxJHj7ESDuhwsTfeR9hhUuUdlKV/F5VKE63TeOMyzMO+70D6I22zafRow7kP3TvbbDx4zc6BGtxJEHBy8K7BntQgWGB4WxjlH6mBYFJq5hyZFVTj8CqlbjY47ig=,iv:H44Y8TLXw0mlDwRtOKlSV4NeDl7Gwn8MLYYvB+AQfMM=,tag:6DhcS584OSAQKyJ7qIj2eA==,type:str]", + "pgp": null, + "unencrypted_suffix": "_unencrypted", + "version": "3.9.0" + } +} \ No newline at end of file diff --git a/homelab/vyos/update_public_ip.sh b/homelab/vyos/update_public_ip.sh new file mode 100755 index 00000000..9b4a5159 --- /dev/null +++ b/homelab/vyos/update_public_ip.sh @@ -0,0 +1,39 @@ +#!/bin/vbash +source /opt/vyatta/etc/functions/script-template +unalias exit + +SCRIPT_PATH="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" + +echo "SCRIPT_PATH: $SCRIPT_PATH" + +echo "Checking for updates to NAT rules." + +PUBLIC_IP="$(curl -s ipinfo.io/ip)" +echo "" > /tmp/commands +while IFS= read -r rule; do + echo -n "Checking rule: $rule: " + if [[ "$(echo $rule | cut -d' ' -f8 | xargs)" != "$(echo $PUBLIC_IP)" ]]; then + echo "mismatched. Updating." + echo " $(echo $rule | cut -d' ' -f8 | xargs) != $(echo $PUBLIC_IP)" + echo "$(echo "$rule" | cut -d' ' -f-7) $PUBLIC_IP" >> /tmp/commands + echo " New rule: $(echo "$rule" | cut -d' ' -f-7) $PUBLIC_IP" + else + echo "matched. Nothing to do." + fi +done <<< "$(run show configuration commands | grep 'set nat destination' | grep 'destination address')" + +if [[ "$(cat /tmp/commands | wc -l)" == "1" ]]; then # if our /tmp/commands file is empty, it will have 1 line. + echo "Nothing to do. Exiting." + exit 0 + echo "exiting did not work as expected..." +fi + +echo "Entering configuration mode and sourcing commands list." +configure +source /tmp/commands +rm /tmp/commands + +source /opt/vyatta/etc/functions/script-template +commit || exit discard +save || exit discard +exit diff --git a/homelab/vyos/vyos.sh b/homelab/vyos/vyos.sh index 7d34683e..ce6d6f35 100755 --- a/homelab/vyos/vyos.sh +++ b/homelab/vyos/vyos.sh @@ -36,6 +36,23 @@ function get_dhcp_leases () { ssh $VYOS_TARGET 'chmod +x /home/vyos/op.sh; /home/vyos/op.sh "show dhcp server leases"; rm /home/vyos/op.sh' } +function update_public_ip () { + scp -q ./update_public_ip.sh $VYOS_TARGET:/home/vyos/update_public_ip.sh + ssh $VYOS_TARGET 'chmod +x /home/vyos/update_public_ip.sh; /home/vyos/update_public_ip.sh; rm /home/vyos/update_public_ip.sh' +} + +function cfddns () { + scp -q ./cfddns.sh $VYOS_TARGET:/home/vyos/cfddns.sh + scp -q ./cloudflare.token $VYOS_TARGET:/home/vyos/cloudflare.token + ssh $VYOS_TARGET 'chmod +x /home/vyos/cfddns.sh; /home/vyos/cfddns.sh "jafner.net" "$(cat /home/vyos/cloudflare.token)"; rm /home/vyos/cfddns.sh /home/vyos/cloudflare.token' +} + +function run_script () { + SCRIPT="$1" + scp -q $SCRIPT $VYOS_TARGET:/home/vyos/$SCRIPT + ssh $VYOS_TARGET "chmod +x /home/vyos/$SCRIPT; /home/vyos/$SCRIPT; rm /home/vyos/$SCRIPT" +} + function op () { command="$@" scp -q ./op.sh $VYOS_TARGET:/home/vyos/op.sh @@ -60,4 +77,4 @@ function edit () { "$@" -# Fair warning, this script is trash. \ No newline at end of file +# Fair warning, this script is trash.