This repository has been archived on 2026-09-17. You can view files and clone it, but you cannot make any changes to its state, such as pushing and creating new issues, pull requests or comments.
nixos-config/scripts/configure-mango-ipv6-web.sh
pijukka b1441d0913 host(pinix): autoritatives BIND als Kandidat, parallel zu Cloudflare
BIND laeuft auf pinix und beantwortet 0ff.space autoritativ, ohne
Rekursion, ohne Zonenuebertragung und ohne dynamische Updates. Die
Delegation bleibt unveraendert bei Cloudflare; diese Stufe aendert an
der oeffentlichen Aufloesung nichts.

`networking.resolvconf.useLocalResolver = false` ist zwingend: das
BIND-Modul setzt sonst localhost als Resolver, und pinix' Uplink ist
IPv6-only ueber Mangos DNS64 -- ein autoritativer Server ohne Rekursion
kann den nicht ersetzen. Nach dem switch geprueft, resolv.conf und
ausgehende Aufloesung sind unveraendert.

Dazu die dynamische Nachfuehrung der oeffentlichen IPv6: mango-dns
aktualisiert per Timer ausschliesslich den bestehenden AAAA von
ipv6-test.0ff.space bei Cloudflare, ueber das schon vorhandene
verschluesselte Token. Die Zonendatei ist dagegen ein Snapshot und wird
noch nicht nachgefuehrt -- vor einer Delegation zu loesen, zusammen mit
Glue, Redundanz und RFC2136 fuer ACME.

Die Mango-DNAT-Regel fuer Port 53 ist als Skript abgelegt, aber noch
nicht angewandt; BIND ist bislang nur im LAN und im Tailnet erreichbar.
Web- und SSH-Weiterleitungen tragen jetzt die Form ohne src_dip und
ueberleben damit einen Praefixwechsel.

Aktiviert auf pinix als
074z8vkzdldf98hvnsyacws21cbbrpkr-nixos-system-pinix.
Details und Pruefungen: docs/pinix-bind.md.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Aw4viUJyXGP8ANocHiF15q
2026-09-12 17:02:27 +02:00

109 lines
4.3 KiB
Bash
Executable file

#!/bin/sh
# Persistente IPv6-Weiterleitung auf dem Mango (GL.iNet, OpenWrt/fw4).
#
# Aufruf von einem Host im LAN des Mango:
# ssh root@192.168.8.1 'sh -s' < scripts/configure-mango-ipv6-web.sh
#
# Parameter als Umgebungsvariablen, alle mit Vorgabewert -- ein anderes
# Ziel braucht keine Aenderung an diesem Skript:
# ssh root@192.168.8.1 "TARGET_IP='fdee:...:1234' sh -s" < scripts/...
#
# TARGET_IP LAN-Adresse, die die Weiterleitung bekommt.
# Vorgabe: pinix (hosts/pinix/localServices/traefik.nix).
# PUBLIC_IP Optional: Eingang auf genau diese Adresse beschraenken.
# Vorgabe: alle Adressen der WAN6-Zone, damit ein neues
# Mobilfunkpraefix ohne Firewall-Aenderung funktioniert.
# WAN_DEV WAN-Interface. Vorgabe usb0 (Nokia-Tethering).
# PORT_MAP aussen:innen, leerzeichengetrennt. Vorgabe leitet 8080 auf
# 80 um, weil auf dem Ziel nur Traefik mit 80/443 lauscht --
# der alte 8080-Link bleibt so gueltig und landet ueber die
# HTTPS-Weiterleitung des Proxys richtig.
# RULE_PREFIX Namenspraefix der erzeugten uci-Sektionen.
# STALE_PREFIXES Praefixe frueherer Ziele, die entfernt werden.
#
# Es gibt bewusst keine SNAT-Rueckwegregeln mehr. Die frueheren
# tnix_web_return_* waren noetig, weil tnix seine Default-Route auf dem
# iPhone-Hotspot behielt und Antwortpakete sonst am Mango vorbeiliefen.
# pinix' Default-Route zeigt ohnehin auf den Mango. Ohne SNAT steht die
# echte Client-Adresse im Traefik-Log statt der Router-Adresse.
#
# Bestehende, nicht zugehoerige Firewall-Einstellungen bleiben unberuehrt.
# Kein Netzwerk-Neustart, nur ein Firewall-Reload.
set -eu
TARGET_IP="${TARGET_IP:-fdee:3c40:44f0:0:dea6:32ff:fe48:c6c8}"
WAN_DEV="${WAN_DEV:-usb0}"
PORT_MAP="${PORT_MAP:-80:80 443:443 8080:80}"
RULE_PREFIX="${RULE_PREFIX:-pinix_web}"
STALE_PREFIXES="${STALE_PREFIXES:-tnix_web}"
echo "Weiterleitung: [${PUBLIC_IP:-WAN6}] -> [$TARGET_IP] ($PORT_MAP)"
[ "$(uci -q get firewall.@zone[1].name)" = wan ]
[ "$(uci -q get firewall.wan6.name)" = wan6 ]
[ -z "$(uci changes firewall)" ] || {
echo 'Unsaved firewall changes exist; refusing to overwrite them.' >&2
exit 1
}
backup_dir=$(mktemp -d /root/ipv6-web-firewall-backup.XXXXXX)
cp /etc/config/firewall "$backup_dir/firewall"
echo "Firewall backup: $backup_dir/firewall"
trap 'uci revert firewall' EXIT
# GL.iNet creates wan6 separately but leaves wan matching both families.
# Restrict wan to IPv4 so IPv6 can reach its own zone, including after reload.
uci set 'firewall.@zone[1].family=ipv4'
uci set firewall.wan6.masq_src='fdee:3c40:44f0::/48'
uci set firewall.ipv6_lan_wan=forwarding
uci set firewall.ipv6_lan_wan.src=lan
uci set firewall.ipv6_lan_wan.dest=wan6
uci set firewall.ipv6_lan_wan.family=ipv6
# Preserve the existing WAN IPv6 control-traffic policy in the correct zone.
for index in 2 3 4 5; do
[ "$(uci -q get "firewall.@rule[$index].family")" = ipv6 ]
uci set "firewall.@rule[$index].src=wan6"
# Remove only named copies created by the initial migration attempt.
uci -q delete "firewall.ipv6_control_$index" || true
done
# Alte Weiterleitungen samt ihrer SNAT-Rueckwege entfernen, bevor die neuen
# entstehen: zwei DNAT-Regeln auf dieselbe Adresse und denselben Port waeren
# ein Wettlauf um den ersten Treffer.
for prefix in $STALE_PREFIXES "$RULE_PREFIX"; do
for section in $(uci show firewall \
| sed -n "s/^firewall\.\($prefix[A-Za-z0-9_]*\)=.*/\1/p" | sort -u); do
echo " entferne alte Regel firewall.$section"
uci -q delete "firewall.$section" || true
done
done
for mapping in $PORT_MAP; do
outer="${mapping%%:*}"
inner="${mapping##*:}"
rule="firewall.${RULE_PREFIX}_$outer"
uci set "$rule=redirect"
uci set "$rule.name=IPv6 web $outer -> $inner"
uci set "$rule.family=ipv6"
uci set "$rule.src=wan6"
if [ -n "${PUBLIC_IP:-}" ]; then
uci set "$rule.src_dip=$PUBLIC_IP"
fi
uci set "$rule.src_dport=$outer"
uci set "$rule.dest=lan"
uci set "$rule.dest_ip=$TARGET_IP"
uci set "$rule.dest_port=$inner"
uci set "$rule.proto=tcp"
uci set "$rule.target=DNAT"
uci set "$rule.reflection=0"
done
if ! fw4 check; then
uci revert firewall
echo 'Firewall validation failed; staged changes reverted.' >&2
exit 1
fi
uci commit firewall
trap - EXIT
/etc/init.d/firewall reload
echo 'Persistent IPv6 web forwarding installed.'