2 # I, Ian Kelling, follow the GNU license recommendations at
3 # https://www.gnu.org/licenses/license-recommendations.en.html. They
4 # recommend that small programs, < 300 lines, be licensed under the
5 # Apache License 2.0. This file contains or is part of one or more small
6 # programs. If a small program grows beyond 300 lines, I plan to switch
9 # Copyright 2024 Ian Kelling
11 # Licensed under the Apache License, Version 2.0 (the "License");
12 # you may not use this file except in compliance with the License.
13 # You may obtain a copy of the License at
15 # http://www.apache.org/licenses/LICENSE-2.0
17 # Unless required by applicable law or agreed to in writing, software
18 # distributed under the License is distributed on an "AS IS" BASIS,
19 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 # See the License for the specific language governing permissions and
21 # limitations under the License.
24 set -e; .
/usr
/local
/lib
/bash-bear
; set +e
25 [[ $EUID == 0 ]] ||
exec sudo
-E "${BASH_SOURCE[0]}" "$@"
27 this_file
="$(readlink -f -- "${BASH_SOURCE[0]}")"
29 this_dir
="${this_file%/*}"
36 Update ip in remote nameserver.
38 -f Force update even if ip hasn't changed.
39 -h|--help Print help and exit.
41 Note: Uses util-linux getopt option parsing: spaces between args and
42 options, short options can be combined, options before args.
47 ##### begin command line parsing ########
49 # ensure we can handle args with spaces or empty.
50 ret
=0; getopt
-T || ret
=$?
51 [[ $ret == 4 ]] ||
{ echo "Install util-linux for enhanced getopt" >&2; exit 1; }
54 temp
=$
(getopt
-l help hf
"$@") || usage
1
60 *) echo "$0: unexpected args: $*" >&2 ; usage
1 ;;
65 ##### end command line parsing ########
71 hostnametmp
=${fqdn%%.*}
73 fqdn
=${hostnametmp}i.
${domaintmp}
77 if ! tmp
=$
(ip
-4 route get
85.119.83.50 2>/dev
/null
); then
78 # our internet is down
79 if [[ $INVOCATION_ID ]]; then
82 echo $0: failed to get route
, giving up
86 read -r _ _ gateway _ ifdev _
<<<"$tmp"
97 # We check if we are at home by testing gateway ssh
98 # fingerprint. However, if we found in the past that we are, I dont
99 # like to spam its logs with ssh login attempts, so just check if our
100 # gateway interface has an increasing amount of packets sent +
101 # received from last time.
103 if [[ -s /dev
/shm
/dynamic-ip-update-state
]]; then
104 oldbytes
=$
(cat /dev
/shm
/dynamic-ip-update-state
)
105 newbytes
=$
(awk '$1 == "'$ifdev':" {print $2 + $10}' /proc
/net
/dev
)
106 if [[ $oldbytes == [1-9]* ]] && (( newbytes
>= oldbytes
)); then
108 printf "%s\n" "$newbytes" >/dev
/shm
/dynamic-ip-update-state
111 if ! $athome && timeout
-s 9 5 ssh-keyscan
-p 2220 -t rsa
$gateway 2>/dev
/null |
grep -qFx "[$gateway]:2220 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCH+/h1dGEfKEusBblndU2e6QT4wLCm5+yqr/sqh/0X9YfjR7BfWWm8nNmuP55cYc+Wuf5ljB1H1acXEcsl1y8e0j3agHfF0V74FE1N1zz5nn2Ep8NHnmqgEhza38ZxMPh+4p3X7zklEKU7+3SzybKBi8sg0wLzlS2LM0JaUN80zR2sK11Kye3dURUXPk78u5wodOkgcEYRwSYaDMJlUzWP+poRXIDJwFaMQnwmxbl/c84yOyaU0x/d6hFwoRscWecihX+vvBNeSyxR4xr2HDOyUWwJkctyAgt2p7w3tfkXOKcCRzTAjGVIMQLTvo0sG/yJbcyHoEFdFybCsgDvfyYn"; then
113 awk '$1 == "'$ifdev':" {print $2 + $10}' /proc
/net
/dev
> /dev
/shm
/dynamic-ip-update-state
118 if ! cur4
="$(dig +short $dyndomain @iankelling.org | tail -1)"; then
119 if [[ ! $INVOCATION_ID ]]; then
120 echo "$0: dig failed. internet looks down. giving up"
124 if ip4
=$
(curl
--connect-timeout 10 -s4 https
://iankelling.org
/cgi
/pubip
); then
125 if $force ||
[[ $cur4 && $ip4 && $cur4 != "$ip4" ]]; then
126 up4
=true
# update ipv4
131 # may not be set yet so allow fail
132 cur6
="$(host -4 -t aaaa $fqdn iankelling.org | sed -rn 's/.*has IPv6 address (.*)/\1/p;T;q')" ||
:
136 out6
=$
(curl
--connect-timeout 10 -s6 https
://iankelling.org
/cgi
/pubip
) ||
: # failure allowed if we have no ipv6
139 dev
=$
(ip
-o a show to
$out6 |
awk '{print $2}')
140 # we use slaac with privacy extension, so get our less private more permanent address
141 mac
=$
(cat /sys
/class
/net
/$dev/address
)
143 IFS
=: read -ra f
<<<$mac; set -- ${f[@]}
144 ip6
=${out6%:*:*:*:*}:$
(printf %x $
((0x
$1 + 2)))$2:$3'ff:fe'$4:$5$6
145 # in case we aren't using slaac
146 if ! ip a |
grep "^ *inet6 $ip6/" &>/dev
/null
; then
151 if $force ||
[[ $cur6 != "$ip6" ]]; then
155 # if we failed to get our ipv6 addr, we probably have ipv6
156 # connectivity problem.
157 if [[ ! $ip6 ]]; then
161 if ! $up4 && ! $up6; then
165 # note, a simpler way to do this would be to ssh and use
167 # to update bind if needed.
171 server iankelling.org
177 update delete $dyndomain. A
178 update add $dyndomain. 300 A $ip4
185 update delete $fqdn. AAAA
186 update add $fqdn. 60 AAAA $ip6
190 update delete $fqdn. AAAA
202 chronic nsupdate
$ip_arg -k /p
/c
/machine_specific
/vps
/filesystem
/etc
/bind
/Kb8.nz.
*.private
<$tmpf || nsupdate_fails
=$
((nsupdate_fails
+ 1))
203 sed -i 's/^server .*/server bk.b8.nz/' $tmpf
204 chronic nsupdate
$ip_arg -k /p
/c
/machine_specific
/vps
/filesystem
/etc
/bind
/Kb8.nz.
*.private
<$tmpf || nsupdate_fails
=$
((nsupdate_fails
+ 1))
205 if (( nsupdate_fails
> nsupdate_fail_limit
)); then
206 echo error
: nsupdate is persistently failing
>&2
220 if [[ $INVOCATION_ID ]]; then
221 nsupdate_fail_limit
=10
224 nsupdate_fail_limit
=0
231 # # # persistent initial setup for this:
232 # # # create files in /a/c/machine_specific/vps/filesystem/etc/bind
233 # # # note, conflink also does some group ownership stuff.
234 # mkc /p/c/machine_specific/vps/filesystem/etc/bind
235 # sudo dnssec-keygen -a HMAC-SHA512 -b 512 -n HOST b8.nz
237 # sudo chown $user:$user *
243 # algorithm HMAC-SHA512;
244 # secret "$(awk '$1 == "Key:" {print $2}' Kb8.nz.*.private)";
253 # ssh li.b8.nz systemctl reload named
256 # # b8.nz has address 65.96.178.16
257 # # b8.nz has IPv6 address 2601:197:600:6efb:82fa:5bff:fe1c:6ecf