diff options
| author | Mel <mel@rnrd.eu> | 2026-04-24 03:10:11 +0200 |
|---|---|---|
| committer | Mel <mel@rnrd.eu> | 2026-04-24 03:18:05 +0200 |
| commit | fa38ea010957a98e778c32b23a8f133b14afdef1 (patch) | |
| tree | 2548538141908ceafa25c5f8ac7371d054b7bd87 /modules/vpn/ingress.nix | |
| parent | 97e935e0ff718cbec86605bf584a5660812bdce9 (diff) | |
| download | network-fa38ea010957a98e778c32b23a8f133b14afdef1.tar.zst network-fa38ea010957a98e778c32b23a8f133b14afdef1.zip | |
Give the VPN its final name 'Tunnel'
Signed-off-by: Mel <mel@rnrd.eu>
Diffstat (limited to 'modules/vpn/ingress.nix')
| -rw-r--r-- | modules/vpn/ingress.nix | 201 |
1 files changed, 0 insertions, 201 deletions
diff --git a/modules/vpn/ingress.nix b/modules/vpn/ingress.nix deleted file mode 100644 index 6c6a78e..0000000 --- a/modules/vpn/ingress.nix +++ /dev/null @@ -1,201 +0,0 @@ -{ - config, - lib, - ... -}: - -let - inherit (lib) - imap0 - attrValues - mergeAttrsList - replaceString - concatImapStringsSep - ; - - definition = import ./definition.nix; - - inherit (definition) paths users mask; - - ownAddress = "10.123.X.1"; # ip of host running the ingress vpn (per-interface) - - addressFromTemplate = - index: template: prefix: - "${replaceString "X" (toString (index + 1)) template}/${toString prefix}"; - - ingressName = index: "vpn-ingress${toString index}"; - egressName = "vpn-egress0"; - egressAddress = "10.123.255.1/16"; # /16 encompasses all possible subnet addresses - egressMTU = 1400; - - egressHost = name: "${name}.rnrd.eu"; -in -{ - boot.kernel.sysctl = { - "net.ipv4.ip_forward" = 1; # allow ipv4 forwarding - }; - - networking.firewall = { - allowedUDPPorts = map (x: x.port) paths; - allowedTCPPorts = map (x: x.port) paths; - checkReversePath = "loose"; - }; - - age.secrets.ingress-key = { - file = ../../secrets/vpn/ingress-key.age; - owner = "systemd-network"; - }; - - systemd.network = - let - mkNetdev = index: path: { - "10-${ingressName index}" = { - netdevConfig = { - Kind = "wireguard"; - Name = ingressName index; - }; - wireguardConfig = { - PrivateKeyFile = config.age.secrets.ingress-key.path; - ListenPort = path.port; - }; - wireguardPeers = map (user: { - PublicKey = user.key; - AllowedIPs = [ (addressFromTemplate index user.ip 32) ]; - }) (attrValues users); - }; - }; - - mkNetwork = index: path: { - "10-${ingressName index}" = { - name = ingressName index; - address = [ (addressFromTemplate index ownAddress 24) ]; - routingPolicyRules = [ - { - IncomingInterface = ingressName index; - Table = 100; - } - ]; - }; - }; - - ingressNetdevs = imap0 mkNetdev paths; - - ingressNetworks = imap0 mkNetwork paths; - egressNetworks = [ - { - "20-${egressName}" = { - name = egressName; - address = [ egressAddress ]; - networkConfig = { - IPv4ReversePathFilter = "loose"; - }; - linkConfig = { - ActivationPolicy = "up"; - RequiredForOnline = "no"; # does not count as online - MTUBytes = toString egressMTU; - }; - routes = [ - { - Destination = "0.0.0.0/0"; - Table = 100; - Scope = "link"; - } - ]; - }; - } - ]; - in - { - netdevs = mergeAttrsList ingressNetdevs; - networks = mergeAttrsList (ingressNetworks ++ egressNetworks); - }; - - # allow forwarding packets between egress and ingress, but avoid any snat, - # ip should always keep it's origin form, for correct egress routing. - # also adapt mss to outgoing mss value, so that we don't shatter packets. - networking.nftables.ruleset = - let - ingressInterfaces = concatImapStringsSep "\", \"" (i: _: ingressName (i - 1)) paths; - in - '' - table inet filter { - chain forward { - type filter hook forward priority 0; policy drop; - - tcp flags syn tcp option maxseg size set rt mtu - - iifname { "${ingressInterfaces}" } oifname "${egressName}" accept - iifname "${egressName}" oifname { "${ingressInterfaces}" } accept - } - } - ''; - - # sing-box is a vpn client supporting various protocols which will allow us - # to configure it in whichever way we want to avoid russian dpi. - # in this case, our communications crossing the borders are relying on vless. - services.sing-box = - let - inboundName = "vpn-in"; - outboundName = egress: "vpn-out-${egress}"; - in - { - enable = true; - settings = { - inbounds = [ - { - type = "tun"; - tag = inboundName; - interface_name = egressName; - address = [ egressAddress ]; - mtu = egressMTU; - stack = "gvisor"; - auto_route = false; # we route manually - strict_route = false; - endpoint_independent_nat = true; - } - ]; - - outbounds = map (path: { - type = "vless"; - flow = "xtls-rprx-vision"; - - server = egressHost path.egress; - server_port = 443; - - tag = outboundName path.egress; - uuid = path.info.uuid; - - tls = { - enabled = true; - server_name = "www.${mask}"; - - utls = { - enabled = true; - fingerprint = "chrome"; - }; - - reality = { - enabled = true; - public_key = path.info.public; - short_id = path.info.short; - }; - }; - }) paths; - - route = { - rules = imap0 (index: path: { - inbound = inboundName; - source_ip_cidr = [ (addressFromTemplate index "10.123.X.0" 24) ]; - outbound = outboundName path.egress; - }) paths; - - auto_detect_interface = true; - }; - - log = { - level = "debug"; - timestamp = true; - }; - }; - }; -} |
