Personal Nix setup
at main 6.3 kB view raw
1{ lib, config, ... } @ inputs: 2 3with lib; 4let 5 inherit (import ../../lib/ipv4.nix inputs) ipv4; 6 7 cfg = config.modules.router; 8 9 leaseType = types.submodule { 10 options = { 11 macAddress = mkOption { 12 type = types.str; 13 example = "00:00:00:00:00:00"; 14 }; 15 ipAddress = mkOption { 16 type = types.str; 17 example = "10.0.0.10"; 18 }; 19 }; 20 }; 21 22 interfaceType = types.submodule { 23 options = { 24 name = mkOption { 25 type = types.str; 26 example = "eth0"; 27 }; 28 macAddress = mkOption { 29 type = types.str; 30 example = "00:00:00:00:00:00"; 31 }; 32 adoptMacAddress = mkOption { 33 type = types.nullOr types.str; 34 example = "00:00:00:00:00:00"; 35 }; 36 cidr = mkOption { 37 type = types.str; 38 default = "0.0.0.0/0"; 39 example = "10.0.0.1/24"; 40 }; 41 }; 42 }; 43 44 extern = cfg.interfaces.external; 45 intern = cfg.interfaces.internal; 46in { 47 options.modules.router = let 48 defaultAddress = if intern != null 49 then ipv4.prettyIp (ipv4.cidrToIpAddress intern.cidr) 50 else "127.0.0.1"; 51 in { 52 address = mkOption { 53 type = types.str; 54 default = defaultAddress; 55 example = "127.0.0.1"; 56 }; 57 mdns = mkOption { 58 type = types.bool; 59 default = !config.services.avahi.enable; 60 }; 61 ipv6 = mkOption { 62 type = types.bool; 63 default = false; 64 }; 65 interfaces = { 66 external = mkOption { 67 type = interfaceType; 68 }; 69 internal = mkOption { 70 type = types.nullOr interfaceType; 71 default = null; 72 }; 73 }; 74 leases = mkOption { 75 default = []; 76 type = types.listOf leaseType; 77 description = "List of reserved IP address leases"; 78 }; 79 }; 80 81 config = let 82 links = { 83 "10-${extern.name}" = { 84 matchConfig.PermanentMACAddress = extern.macAddress; 85 linkConfig = { 86 Description = "External Network Interface"; 87 Name = extern.name; 88 MACAddress = extern.adoptMacAddress; 89 MTUBytes = "1500"; 90 }; 91 }; 92 } // (optionalAttrs (intern != null) { 93 "11-${intern.name}" = { 94 matchConfig.PermanentMACAddress = intern.macAddress; 95 linkConfig = { 96 Description = "Internal Network Interface"; 97 Name = intern.name; 98 MTUBytes = "1500"; 99 }; 100 }; 101 }); 102 in mkIf cfg.enable { 103 networking = { 104 useNetworkd = true; 105 hosts."127.0.0.2" = mkForce []; 106 networkmanager.enable = mkForce false; 107 firewall = mkIf (intern != null) { 108 trustedInterfaces = [ "lo" intern.name ]; 109 }; 110 nameservers = [ 111 "1.1.1.1#cloudflare-dns.com" 112 "9.9.9.9#dns.quad9.net" 113 "8.8.8.8#dns.google" 114 ] ++ (optionals cfg.ipv6 [ 115 "2606:4700:4700::1111#cloudflare-dns.com" 116 "2620:fe::9#dns.quad9.net" 117 "2001:4860:4860::8888#dns.google" 118 ]); 119 }; 120 121 boot.initrd.systemd.network = { 122 enable = true; 123 inherit links; 124 }; 125 126 systemd.network = { 127 enable = true; 128 inherit links; 129 networks = let 130 gatewayAddress = ipv4.prettyIp (ipv4.cidrToIpAddress intern.cidr); 131 in { 132 "10-${extern.name}" = { 133 name = extern.name; 134 networkConfig = { 135 DHCP = if cfg.ipv6 then "yes" else "ipv4"; 136 IPv4Forwarding = true; 137 IPv6Forwarding = true; 138 IPv6AcceptRA = mkIf cfg.ipv6 true; 139 }; 140 cakeConfig = { 141 Parent = "root"; 142 }; 143 dhcpV4Config = { 144 UseDNS = false; 145 UseDomains = false; 146 UseNTP = !cfg.timeserver.enable; 147 }; 148 dhcpV6Config = mkIf cfg.ipv6 { 149 WithoutRA = "solicit"; 150 UseDNS = false; 151 UseDomains = false; 152 UseAddress = false; 153 DUIDType = "link-layer"; 154 DUIDRawData = mkIf (extern.adoptMacAddress != null) "00:01:${extern.adoptMacAddress}"; 155 }; 156 dhcpPrefixDelegationConfig = mkIf cfg.ipv6 { 157 UplinkInterface = ":self"; 158 Announce = false; 159 }; 160 ipv6AcceptRAConfig = mkIf cfg.ipv6 { 161 UseDNS = false; 162 UseDomains = false; 163 DHCPv6Client = "always"; 164 Token = mkIf (extern.adoptMacAddress != null) "static:::${extern.adoptMacAddress}"; 165 }; 166 }; 167 } // (optionalAttrs (intern != null) { 168 "11-${intern.name}" = { 169 name = intern.name; 170 networkConfig = { 171 Address = intern.cidr; 172 DHCPServer = true; 173 IPv4Forwarding = true; 174 IPv6Forwarding = cfg.ipv6; 175 IPMasquerade = "ipv4"; 176 ConfigureWithoutCarrier = true; 177 MulticastDNS = cfg.mdns; 178 DHCPPrefixDelegation = cfg.ipv6; 179 IPv6SendRA = cfg.ipv6; 180 IPv6AcceptRA = mkIf cfg.ipv6 false; 181 }; 182 fairQueueingControlledDelayConfig = { 183 Parent = "root"; 184 }; 185 dhcpServerStaticLeases = builtins.map (lease: { 186 Address = lease.ipAddress; 187 MACAddress = lease.macAddress; 188 }) cfg.leases; 189 dhcpServerConfig = { 190 EmitDNS = true; 191 EmitNTP = true; 192 DNS = gatewayAddress; 193 NTP = gatewayAddress; 194 DefaultLeaseTimeSec = 43200; 195 MaxLeaseTimeSec = 86400; 196 }; 197 dhcpPrefixDelegationConfig = mkIf cfg.ipv6 { 198 UplinkInterface = extern.name; 199 Token = "static:::1"; 200 Announce = true; 201 }; 202 }; 203 }); 204 }; 205 206 services.resolved = { 207 enable = true; 208 llmnr = "false"; 209 domains = [ "~." ]; 210 fallbackDns = [ 211 "1.0.0.1" 212 "8.8.4.4" 213 ] ++ (optionals cfg.ipv6 [ 214 "2606:4700:4700::1001" 215 "2001:4860:4860::8844" 216 ]); 217 dnsovertls = "opportunistic"; 218 extraConfig = strings.concatStringsSep "\n" [ 219 "[Resolve]" 220 (optionalString cfg.mdns '' 221 MulticastDNS=yes 222 '') 223 (optionalString (intern != null) '' 224 DNSStubListener=yes 225 DNSStubListenerExtra=${ipv4.prettyIp (ipv4.cidrToIpAddress intern.cidr)} 226 '') 227 ]; 228 }; 229 }; 230}