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