#!/bin/bash
-source ~/.bashrc
+# I, Ian Kelling, follow the GNU license recommendations at
+# https://www.gnu.org/licenses/license-recommendations.en.html. They
+# recommend that small programs, < 300 lines, be licensed under the
+# Apache License 2.0. This file contains or is part of one or more small
+# programs. If a small program grows beyond 300 lines, I plan to switch
+# its license to GPL.
+# Copyright 2024 Ian Kelling
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+set -e; . /usr/local/lib/bash-bear; set +e
+[[ $EUID == 0 ]] || exec sudo -E "${BASH_SOURCE[0]}" "$@"
+
+this_file="$(readlink -f -- "${BASH_SOURCE[0]}")"
+readonly this_file
+this_dir="${this_file%/*}"
+readonly this_dir
+cd "$this_dir"
+
+usage() {
+ cat <<EOF
+Usage: ${0##*/} [-f]
+Update ip in remote nameserver.
+
+-f Force update even if ip hasn't changed.
+-h|--help Print help and exit.
+
+Note: Uses util-linux getopt option parsing: spaces between args and
+options, short options can be combined, options before args.
+EOF
+ exit $1
+}
+
+##### begin command line parsing ########
+
+# ensure we can handle args with spaces or empty.
+ret=0; getopt -T || ret=$?
+[[ $ret == 4 ]] || { echo "Install util-linux for enhanced getopt" >&2; exit 1; }
+
+force=false # default
+temp=$(getopt -l help hf "$@") || usage 1
+eval set -- "$temp"
+while true; do
+ case $1 in
+ -f) force=true ;;
+ --) shift; break ;;
+ *) echo "$0: unexpected args: $*" >&2 ; usage 1 ;;
+ esac
+ shift
+done
+
+##### end command line parsing ########
main() {
up4=false
- if ! read -r _ _ gateway _ ifdev _ < <(ip -4 route get 85.119.83.50 2>/dev/null); then
- # if our internet is down, just give up, no need to have an error
- if [[ ! $INVOCATION_ID ]]; then
+ if ! tmp=$(ip -4 route get 85.119.83.50 2>/dev/null); then
+ # our internet is down
+ if [[ $PPID == 1 ]]; then
+ return 0
+ else
echo $0: failed to get route, giving up
+ exit 0
fi
- exit 0
fi
+ read -r _ _ gateway _ ifdev _ <<<"$tmp"
case $gateway in
10.2.0.1)
- dynhost=i.b8.nz
+ dyndomain=b8.nz
+ # This domain is for any case where we want some different
+ # configuration based on lan vs wan. For right now, the only use
+ # is for ssh config to use port forwarding ports on the wan
+ # domain.
+ dyndomain_internet=i.b8.nz
;;
*)
return 0
;;
esac
+ # We check if we are at home by testing gateway ssh
+ # fingerprint. However, if we found in the past that we are, I dont
+ # like to spam its logs with ssh login attempts, so just check if our
+ # gateway interface has an increasing amount of packets sent +
+ # received from last time.
athome=false
if [[ -s /dev/shm/dynamic-ip-update-state ]]; then
oldbytes=$(cat /dev/shm/dynamic-ip-update-state)
if $athome; then
- cur4="$(dig +short $dynhost @iankelling.org | tail -1)"
- if ip4=$(curl -s4 https://iankelling.org/cgi/pubip); then
- if [[ $cur4 && $ip4 && $cur4 != $ip4 ]]; then
+ if ! cur4="$(dig +short $dyndomain @iankelling.org | tail -1)"; then
+ if [[ $PPID != 1 ]]; then
+ echo "$0: dig failed. internet looks down. giving up"
+ fi
+ return 0
+ fi
+ if ip4=$(curl --connect-timeout 10 -s4 https://iankelling.org/cgi/pubip); then
+ if $force || [[ $cur4 && $ip4 && $cur4 != "$ip4" ]]; then
up4=true # update ipv4
fi
fi
up6=false
- out6=$(curl -s6 https://iankelling.org/cgi/pubip) ||: # failure allowed if we have no ipv6
+ out6=$(curl --connect-timeout 10 -s6 https://iankelling.org/cgi/pubip) ||: # failure allowed if we have no ipv6
if [[ $out6 ]]; then
dev=$(ip -o a show to $out6 | awk '{print $2}')
# we use slaac with privacy extension, so get our less private more permanent address
mac=$(cat /sys/class/net/$dev/address)
- IFS=: read -a f <<<$mac; set -- ${f[@]}
+ IFS=: read -ra f <<<$mac; set -- ${f[@]}
ip6=${out6%:*:*:*:*}:$(printf %x $((0x$1 + 2)))$2:$3'ff:fe'$4:$5$6
# in case we aren't using slaac
if ! ip a | grep "^ *inet6 $ip6/" &>/dev/null; then
fi
fi
- if [[ $cur6 != $ip6 ]]; then
+ if $force || [[ $cur6 != "$ip6" ]]; then
up6=true
fi
+ # if we failed to get our ipv6 addr, we probably have ipv6
+ # connectivity problem.
+ if [[ ! $ip6 ]]; then
+ ip_arg=-4
+ fi
+
if ! $up4 && ! $up6; then
return 0
fi
# "${SSH_CLIENT%% *}
# to update bind if needed.
- f=$(mktemp)
- cat >>$f <<EOF
+ tmpf=$(mktemp)
+ cat >>$tmpf <<EOF
server iankelling.org
zone b8.nz
EOF
if $up4; then
- cat >>$f <<EOF
-update delete $dynhost. A
-update add $dynhost. 300 A $ip4
+ cat >>$tmpf <<EOF
+update delete $dyndomain. A
+update add $dyndomain. 300 A $ip4
+update delete $dyndomain_internet. A
+update add $dyndomain_internet. 300 A $ip4
EOF
fi
if $up6; then
if [[ $ip6 ]]; then
- cat >>$f <<EOF
+ cat >>$tmpf <<EOF
update delete $fqdn. AAAA
update add $fqdn. 60 AAAA $ip6
EOF
else
- cat >>$f <<EOF
+ cat >>$tmpf <<EOF
update delete $fqdn. AAAA
EOF
fi
fi
- cat >>$f <<EOF
+ cat >>$tmpf <<EOF
show
send
answer
quit
EOF
- nsupdate -k /p/c/machine_specific/vps/filesystem/etc/bind/Kb8.nz.*.private <$f
- sed -i 's/^server .*/server bk.b8.nz/' $f
- nsupdate -k /p/c/machine_specific/vps/filesystem/etc/bind/Kb8.nz.*.private <$f
-
-
+ chronic nsupdate $ip_arg -k /p/c/machine_specific/vps/filesystem/etc/bind/Kb8.nz.*.private <$tmpf || nsupdate_fails=$((nsupdate_fails + 1))
+ sed -i 's/^server .*/server bk.b8.nz/' $tmpf
+ chronic nsupdate $ip_arg -k /p/c/machine_specific/vps/filesystem/etc/bind/Kb8.nz.*.private <$tmpf || nsupdate_fails=$((nsupdate_fails + 1))
+ if (( nsupdate_fails > nsupdate_fail_limit )); then
+ echo error: nsupdate is persistently failing >&2
+ exit 1
+ fi
+ rm -f $tmpf
}
loop-main() {
done
}
-
-if [[ $INVOCATION_ID ]]; then
+nsupdate_fails=0
+if [[ $PPID == 1 ]]; then
+ nsupdate_fail_limit=10
loop-main
else
+ nsupdate_fail_limit=0
main
fi
# f=key.b8.nz
-# cat >$f <<EOF
+# cat >$tmpf <<EOF
# key b8.nz. {
# algorithm HMAC-SHA512;
# secret "$(awk '$1 == "Key:" {print $2}' Kb8.nz.*.private)";
# # push here?
# #myunison -ob li
# #ssh li conflink
-# ssh li.b8.nz systemctl reload bind9
+# ssh li.b8.nz systemctl reload named
# # b8.nz has address 65.96.178.16