#!/usr/bin/env bash # Runs ON a private node VM (no public address) as root, through the gateway jump: # private-node.sh # Hetzner's DHCP on the private interface pushes the network's 0.0.0.0/0 route (option 121) once the route exists # on the network; this adds it if it is missing (and keeps adding it on every lease through a dhclient hook), sets # the resolvers (Hetzner's recursive resolvers, reached through the NAT), then proves the uplink with a TCP connect # to deb.debian.org:443 and a DNS lookup. set -euo pipefail router="$1" privif=$(ip -4 -o addr show | awk -v p="${router%.*}." '$4 ~ "^" p { print $2; exit }') [ -n "$privif" ] || { echo "no private interface for $router"; exit 1; } ip -4 route show default | grep -q . || ip route add default via "$router" dev "$privif" cat > /etc/dhcp/dhclient-exit-hooks.d/igneum-private </dev/null; then if [ -d /etc/resolvconf/resolv.conf.d ]; then printf 'nameserver 185.12.64.1\nnameserver 185.12.64.2\n' > /etc/resolvconf/resolv.conf.d/base; resolvconf -u 2>/dev/null || true; fi grep -qE '^nameserver 185\.12\.64\.' /etc/resolv.conf 2>/dev/null || printf 'nameserver 185.12.64.1\nnameserver 185.12.64.2\n' > /etc/resolv.conf fi ok=1 timeout 8 bash -c 'getent hosts deb.debian.org >/dev/null' || { echo "DNS failed"; ok=0; } timeout 8 bash -c 'exec 3<>/dev/tcp/deb.debian.org/443' 2>/dev/null || { echo "TCP to deb.debian.org:443 failed"; ok=0; } echo "private node: default via $(ip -4 route show default | awk '{ print $3 }' | head -1) dev $privif, resolvers $(awk '/^nameserver/ { printf "%s ", $2 }' /etc/resolv.conf), uplink $([ $ok = 1 ] && echo ok || echo BROKEN)" [ "$ok" = 1 ]