{ config, pkgs, lib, ... }: let iface = "hurricane"; remote = "216.218.221.42"; clinet = "2001:470:35:72a::2"; server = "2001:470:35:72a::1"; prefix64 = "2001:470:36:72a::/64"; prefix48 = "2001:470:ee65::/48"; makeAddr = prefix: host: let split = lib.strings.splitString "/" prefix; in { address = "${lib.head split}${host}"; prefixLength = lib.toInt (lib.last split); }; in { networking = { sits.${iface} = { inherit remote; ttl = 225; }; interfaces.${iface} = { mtu = 1472; # 1492(ppp0) - 20 ipv6.addresses = [ { address = clinet; prefixLength = 64; } (makeAddr prefix64 "1") (makeAddr prefix48 "1") (makeAddr prefix48 "1337") ]; }; iproute2 = { enable = true; rttablesExtraConfig = "200 hurricane"; }; firewall.extraCommands = "iptables -A INPUT --proto 41 --source ${remote} --jump ACCEPT"; }; sops.secrets = { "hurricane/username" = {}; "hurricane/update_key" = {}; "hurricane/tunnel_id" = {}; }; systemd.services."network-route-${iface}" = { description = "Routing configuration of ${iface}"; wantedBy = [ "network-setup.service" "network.target" ]; before = [ "network-setup.service" ]; bindsTo = [ "network-addresses-hurricane.service" ]; after = [ "network-pre.target" "network-addresses-hurricane.service" ]; # restart rather than stop+start this unit to prevent the # network from dying during switch-to-configuration. stopIfChanged = false; serviceConfig = { Type = "oneshot"; RemainAfterExit = true; }; path = [ pkgs.iproute2 ]; script = '' echo -n "adding route" ip -6 rule add from ${clinet}/64 table hurricane || exit 1 ip -6 rule add from ${prefix64} table hurricane || exit 1 ip -6 rule add from ${prefix48} table hurricane || exit 1 ip -6 route add default via ${server} dev hurricane table hurricane || exit 1 ''; preStop = '' echo -n "deleting route" ip -6 route del default via ${server} dev hurricane table hurricane || exit 1 ip -6 rule del from ${prefix48} table hurricane || exit 1 ip -6 rule del from ${prefix64} table hurricane || exit 1 ip -6 rule del from ${clinet}/64 table hurricane || exit 1 ''; }; services.pppd.script."01-${iface}" = { runtimeInputs = with pkgs; [ curl coreutils iproute2 iputils ]; text = '' wan_ip="$4" username="$(cat ${config.sops.secrets."hurricane/username".path})" update_key="$(cat ${config.sops.secrets."hurricane/update_key".path})" tunnel_id="$(cat ${config.sops.secrets."hurricane/tunnel_id".path})" auth_url="https://$username:$update_key@ipv4.tunnelbroker.net/nic/update?hostname=$tunnel_id" until curl --silent "$auth_url"; do sleep 1 done while [ ! -e /sys/class/net/${iface} ]; do sleep 1 # make sure ${iface} is up done ip tunnel change ${iface} local "$wan_ip" mode sit ''; }; }