From 1a8ff1ba380458672f4ee89f77374e3759edd1ea Mon Sep 17 00:00:00 2001 From: Akemi Izuko Date: Wed, 6 Nov 2024 12:04:08 -0700 Subject: [PATCH] Unix: update a-record script --- src/content/unix/reverse-proxy.md | 120 +++++++++++++++--------------- 1 file changed, 58 insertions(+), 62 deletions(-) diff --git a/src/content/unix/reverse-proxy.md b/src/content/unix/reverse-proxy.md index d1e51f0..7842270 100644 --- a/src/content/unix/reverse-proxy.md +++ b/src/content/unix/reverse-proxy.md @@ -206,16 +206,15 @@ domain! Of course, make sure your router's ports are forwarding to your computer. We now need to make your computer update Cloudflare's DNS, whenever the IP -changes. I use the script below to do this. Fill in the `HOST`, `DOMAIN`, +changes. I use the script below to do this. Fill in the `HOST4`, `HOST6`, `TOKEN`, `ZONE_ID`. The `TOKEN` is your Cloudflare application token: ```bash #!/usr/bin/env bash declare wan_ip_record wan_ip cf_records host_record cf_host_ip cf_rec_id -declare -r HOST4='mycomputer' -declare -r HOST6='mycomputer6' -declare -r DOMAIN='example.com' +declare -r HOST4='mycomputer.example.com' +declare -r HOST6='mycomputer6.example.com' declare -r TOKEN='CLOUDFLARE_TOKEN_HERE' declare -r ZONE_ID='CLOUDFLARE_ZONEID_HERE' @@ -223,17 +222,47 @@ utc_date() { date -u +'%Y-%m-%d_%H-%M-%S_UTC' } -#╔─────────────────────────────────────────────────────────────────────────────╗ -#│ Gετ WΛN IP | -#╚─────────────────────────────────────────────────────────────────────────────╝ -# Comment out as needed. Many home networks don't have ipv6 support -if ! wan_ipv4="$(curl -s https://api4.ipify.org)"; then - echo "Request for ipv4 WAN timed out" >&2 - exit 1 -elif ! wan_ipv6="$(curl -s https://api6.ipify.org)"; then - echo "Request for ipv6 WAN timed out" >&2 - exit 1 -fi +cf_update_ip() { + local -r my_ip="$1" + local -r cf_ip="$2" + local -r cf_id="$3" + local -r host="$4" + + if [[ -z "$my_ip" || "$my_ip" == null ]]; then + echo "Failed to find local WAN ip: $my_ip" >&2 + return 1 + elif [[ -z "$cf_ip" || "$cf_ip" == null ]]; then + echo "Failed to find content of A record for $host" >&2 + return 1 + elif [[ -z "$cf_id" || "$cf_id" == null ]]; then + echo "Failed to find A record ID for $host" >&2 + return 1 + elif [[ "$my_ip" == "$cf_ip" ]]; then + echo "Cloudflare for $host is up to date @ $(utc_date)" >&2 + else + echo "Updating Cloudflare's for $host from $cf_ip to $my_ip" >&2 + + patch_response="$(curl -s --request PATCH \ + --url "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records/${cf_id}" \ + --header 'Content-Type: application/json' \ + --header "Authorization: Bearer $TOKEN" \ + --data '{ + "comment": "'"${host} @ $(utc_date)"'", + "content": "'"$my_ip"'", + "name": "'"$host"'", + "proxied": false, + "ttl": 1 + }')" + + if [[ "$(echo "$patch_response" | jq -r '.success')" == true ]]; then + echo "Update to $my_ip for $host succeeded @ $(utc_date)" >&2 + else + echo "Failed to update $host. DUMP:" + echo "$patch_response" + return 1 + fi + fi +} #╔─────────────────────────────────────────────────────────────────────────────╗ #│ Gετ Λ rεcδrd δη Clδμdflαrε | @@ -248,64 +277,31 @@ then fi declare -r cf_ipv4_record="$(echo "$cf_records" | - jq '.result[] | select(.name == "'"${HOST4}.${DOMAIN}"'")')" + jq '.result[] | select(.name == "'"$HOST4"'")')" declare -r cf_ipv4_ip="$(echo "$cf_ipv4_record" | jq --raw-output '.content')" declare -r cf_ipv4_id="$(echo "$cf_ipv4_record" | jq --raw-output '.id')" declare -r cf_ipv6_record="$(echo $cf_records | - jq --raw-output '.result[] | select(.name == "'"${HOST6}.${DOMAIN}"'")')" + jq --raw-output '.result[] | select(.name == "'"$HOST6"'")')" declare -r cf_ipv6_ip="$(echo "$cf_ipv6_record" | jq --raw-output '.content')" declare -r cf_ipv6_id="$(echo "$cf_ipv6_record" | jq --raw-output '.id')" #╔─────────────────────────────────────────────────────────────────────────────╗ #│ Sετ Λ rεcδrd τδ cμrrεητ WΛN | #╚─────────────────────────────────────────────────────────────────────────────╝ -cf_update_ip() { - local -r my_ip="$1" - local -r cf_ip="$2" - local -r cf_id="$3" - local -r host="$4" - local -r domain="$5" - local -r url="${host}.${domain}" +if wan_ipv4="$(curl -s https://api4.ipify.org)"; then + echo "ipv4 record: $wan_ipv4" + cf_update_ip "$wan_ipv4" "$cf_ipv4_ip" "$cf_ipv4_id" "$HOST4" +else + echo "Hosts timed out on ipv4. Not updating ipv4 A record" >&2 +fi - if [[ -z "$my_ip" || "$my_ip" == null ]]; then - echo "Failed to find local WAN ip: $my_ip" >&2 - return 1 - elif [[ -z "$cf_ip" || "$cf_ip" == null ]]; then - echo "Failed to find content of A record for $url" >&2 - return 1 - elif [[ -z "$cf_id" || "$cf_id" == null ]]; then - echo "Failed to find A record ID for $url" >&2 - return 1 - elif [[ "$my_ip" == "$cf_ip" ]]; then - echo "Cloudflare for $url is up to date @ $(utc_date)" >&2 - else - echo "Updating Cloudflare's for $url from $cf_ip to $my_ip" >&2 - - patch_response="$(curl -s --request PATCH \ - --url "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records/${cf_id}" \ - --header 'Content-Type: application/json' \ - --header "Authorization: Bearer $TOKEN" \ - --data '{ - "comment": "'"${host} @ $(utc_date)"'", - "content": "'"$my_ip"'", - "name": "'"$url"'", - "proxied": false, - "ttl": 1 - }')" - - if [[ "$(echo "$patch_response" | jq -r '.success')" == true ]]; then - echo "Update to $my_ip for $url succeeded @ $(utc_date)" >&2 - else - echo "Failed to update $url. DUMP:" - echo "$patch_response" - exit 1 - fi - fi -} - -cf_update_ip "$wan_ipv4" "$cf_ipv4_ip" "$cf_ipv4_id" "$HOST4" "$DOMAIN" -cf_update_ip "$wan_ipv6" "$cf_ipv6_ip" "$cf_ipv6_id" "$HOST6" "$DOMAIN" +if wan_ipv6="$(curl -s https://api6.ipify.org)"; then + echo "ipv6 record: $wan_ipv6" + cf_update_ip "$wan_ipv6" "$cf_ipv6_ip" "$cf_ipv6_id" "$HOST6" +else + echo "Hosts timed out on ipv6. Not updating ipv6 AAAA record" >&2 +fi ``` Now we need a systemd-timer to run this script. I run it once every 15 minutes.