This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

superconfig / 2configs / container-bridge.nix
5.2 kB 142 lines
1{ config, lib, pkgs, ... }: 2{ 3 # Local DNS64 resolver for containers 4 # Synthesizes AAAA records with 64:ff9b::/96 prefix for IPv4-only hosts 5 services.unbound = { 6 enable = true; 7 settings = { 8 server = { 9 interface = [ "fd00:c700::1" "127.0.0.1" ]; 10 access-control = [ 11 "fd00:c700::/64 allow" 12 "127.0.0.0/8 allow" 13 ]; 14 # DNS64: synthesize AAAA with NAT64 prefix 15 module-config = ''"dns64 validator iterator"''; 16 dns64-prefix = "64:ff9b::/96"; 17 # Always synthesize, even if real AAAA exists (needed when host has no IPv6) 18 dns64-synthall = "yes"; 19 # Handle reverse DNS for NAT64 prefix locally (return NXDOMAIN immediately) 20 # Without this, PTR lookups for 64:ff9b::* timeout waiting for upstream 21 local-zone = ''"0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.b.9.f.f.4.6.0.0.ip6.arpa." static''; 22 }; 23 forward-zone = [ 24 { 25 name = "."; 26 forward-addr = [ 27 "1.1.1.1" # Cloudflare (IPv4 - always works) 28 "8.8.8.8" # Google (IPv4) 29 "2606:4700:4700::1111" # Cloudflare (IPv6 - when available) 30 ]; 31 } 32 ]; 33 }; 34 }; 35 36 # Bridge interface for containers 37 systemd.network.netdevs."10-ctr0" = { 38 netdevConfig = { 39 Kind = "bridge"; 40 Name = "ctr0"; 41 }; 42 }; 43 44 systemd.network.networks."10-ctr0" = { 45 matchConfig.Name = "ctr0"; 46 address = [ "fd00:c700::1/64" ]; 47 networkConfig = { 48 ConfigureWithoutCarrier = true; 49 IPv6SendRA = true; # Enable Router Advertisements 50 }; 51 52 # Router Advertisement configuration 53 ipv6SendRAConfig = { 54 Managed = false; # No DHCPv6 for addresses (use SLAAC) 55 OtherInformation = false; # No DHCPv6 for DNS (use RDNSS) 56 RouterLifetimeSec = 1800; 57 DNS = [ "fd00:c700::1" ]; # RDNSS: advertise DNS64 resolver 58 }; 59 ipv6Prefixes = [ 60 { Prefix = "fd00:c700::/64"; } 61 ]; 62 # Advertise NAT64 prefix via PREF64 option (RFC 8781) 63 ipv6PREF64Prefixes = [ 64 { Prefix = "64:ff9b::/96"; } 65 ]; 66 }; 67 68 # Exclude from NetworkManager 69 networking.networkmanager.unmanaged = [ "ctr0" ]; 70 71 # IP forwarding 72 boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = 1; 73 boot.kernel.sysctl."net.ipv4.ip_forward" = 1; 74 75 # Jool NAT64 kernel module 76 boot.extraModulePackages = [ config.boot.kernelPackages.jool ]; 77 boot.kernelModules = [ "jool" ]; 78 79 systemd.services.jool = { 80 description = "Jool NAT64"; 81 after = [ "network.target" ]; 82 wantedBy = [ "multi-user.target" ]; 83 serviceConfig = { 84 Type = "oneshot"; 85 RemainAfterExit = true; 86 ExecStart = "${pkgs.jool-cli}/bin/jool instance add --netfilter --pool6 64:ff9b::/96"; 87 ExecStop = "${pkgs.jool-cli}/bin/jool instance remove"; 88 }; 89 }; 90 91 # Update Jool pool4 with current IPv4 address (needed for NAT64 on dynamic IPs) 92 systemd.services.jool-pool4-update = { 93 description = "Update Jool NAT64 pool4 with current IPv4"; 94 after = [ "jool.service" "network-online.target" ]; 95 wants = [ "network-online.target" ]; 96 wantedBy = [ "multi-user.target" ]; 97 path = [ pkgs.iproute2 pkgs.gawk pkgs.jool-cli ]; 98 serviceConfig = { 99 Type = "oneshot"; 100 RemainAfterExit = true; 101 }; 102 script = '' 103 # Get default route's source IP 104 IP=$(ip -4 route get 1.1.1.1 2>/dev/null | awk '/src/ {print $7}') 105 if [ -n "$IP" ]; then 106 # Flush old pool and add new 107 jool pool4 flush --tcp 2>/dev/null || true 108 jool pool4 flush --udp 2>/dev/null || true 109 jool pool4 flush --icmp 2>/dev/null || true 110 jool pool4 add "$IP" 1-65535 --tcp 111 jool pool4 add "$IP" 1-65535 --udp 112 jool pool4 add "$IP" 1-65535 --icmp 113 echo "Jool pool4 updated to $IP" 114 else 115 echo "No IPv4 address found, skipping pool4 update" 116 fi 117 ''; 118 }; 119 120 # Firewall rules for container bridge 121 krebs.iptables.tables.filter.FORWARD.rules = [ 122 # IPv6 forwarding for containers 123 { v4 = false; v6 = true; predicate = "-i ctr0"; target = "ACCEPT"; } 124 { v4 = false; v6 = true; predicate = "-o ctr0 -m conntrack --ctstate RELATED,ESTABLISHED"; target = "ACCEPT"; } 125 # IPv4 forwarding for NAT64 translated packets 126 { v4 = true; v6 = false; predicate = "-m conntrack --ctstate RELATED,ESTABLISHED"; target = "ACCEPT"; } 127 { v4 = true; v6 = false; predicate = ""; target = "ACCEPT"; } 128 ]; 129 130 # NAT66 - masquerade container IPv6 to reach public IPv6 (when host has IPv6) 131 # NAT44 - masquerade NAT64 translated IPv4 packets (exclude localhost!) 132 krebs.iptables.tables.nat.POSTROUTING.rules = [ 133 { v4 = false; v6 = true; predicate = "-s fd00:c700::/64 ! -d fd00:c700::/64"; target = "MASQUERADE"; } 134 { v4 = true; v6 = false; predicate = "! -d 127.0.0.0/8 ! -o lo"; target = "MASQUERADE"; } # Don't masquerade localhost 135 ]; 136 137 # Allow containers to reach host's DNS64 resolver (IPv6 only) 138 krebs.iptables.tables.filter.INPUT.rules = [ 139 { v4 = false; v6 = true; predicate = "-s fd00:c700::/64 -p udp --dport 53"; target = "ACCEPT"; } 140 { v4 = false; v6 = true; predicate = "-s fd00:c700::/64 -p tcp --dport 53"; target = "ACCEPT"; } 141 ]; 142}