{ config, lib, pkgs, ... }: let wan-dev = "bond0.10"; lan-dev = "bond0"; # config.orbekk.nycmesh.listenPort wireguardPorts = [ config.orbekk.mullvad.listenPort config.orbekk.vpn.listenPort ]; mullvadMark = 30; # nycmeshMark = 32; aliases = import ../data/aliases.nix; in { orbekk.mullvad.enable = true; orbekk.nycmesh.enable = false; services.tftpd.enable = true; services.openntpd.enable = true; networking.useDHCP = false; networking.networkmanager.enable = lib.mkForce false; networking.nameservers = [ "1.1.1.1" "1.0.0.1" "2606:4700:4700::1111" "2606:4700:4700::1001" ]; networking.vlans = builtins.listToAttrs (map (id: { name = "${lan-dev}.${toString id}"; value = { inherit id; interface = lan-dev; }; }) [ 10 30 32 100 255 ]); networking.bonds.bond0 = { interfaces = [ "eno1" "eno2" ]; driverOptions = { miimon = "1000"; mode = "balance-rr"; }; }; systemd.services.update-dynamic-dns = { description = "Update dynamic dns records"; path = with pkgs; [ bash dnsutils nettools gawk iproute curl ]; startLimitIntervalSec = 5; script = toString ../tools/update-dns.sh; }; networking.dhcpcd.runHook = '' systemctl restart update-dynamic-dns.service ''; networking.firewall = { enable = lib.mkForce false; allowedTCPPorts = lib.mkForce [ ]; allowedUDPPorts = lib.mkForce [ ]; allowPing = true; logRefusedConnections = false; checkReversePath = false; }; services.ddclient = { enable = true; configFile = "/opt/secret/he-ddclient.conf"; }; # FIXME: Workaround for ddclient.conf not being available to ddclient. systemd.services.ddclient.serviceConfig.DynamicUser = lib.mkForce false; services.ferm = { enable = true; config = '' @def $DEV_UNTRUSTED_LAN = (${lan-dev}.30 ${lan-dev}.32); @def $DEV_LAN = (${lan-dev}.100 vpn); @def $DEV_ADMIN = (${lan-dev}.255); @def $DEV_WAN = (${wan-dev} he0 mullvad); @def $NET_LAN = (172.20.0.0/16); # Forward dns queries to dnsmasq on LAN interfaces. domain (ip ip6) table nat chain PREROUTING { interface ($DEV_LAN $DEV_UNTRUSTED_LAN) daddr $NET_LAN proto (tcp udp) dport 53 REDIRECT to-ports 2053; } domain (ip ip6) table filter { chain INPUT { policy DROP; mod state state INVALID DROP; mod state state (ESTABLISHED RELATED) ACCEPT; interface lo ACCEPT; proto icmp ACCEPT; proto (udp udp) dport dhcpv6-client ACCEPT; proto 41 ACCEPT; # IPv6 sit tunnel interface ($DEV_WAN $DEV_LAN $DEV_UNTRUSTED_LAN) @subchain "wan_services" { # Valheim proto udp dport (3400 3401 3402) ACCEPT; proto (tcp udp) dport 2053 ACCEPT; proto (tcp udp) dport (bootpc bootps) ACCEPT; proto tcp dport ssh ACCEPT; proto (tcp udp) dport domain ACCEPT; proto tcp dport (http https) ACCEPT; proto udp dport (${lib.concatStringsSep " " (map toString wireguardPorts)}) ACCEPT; } interface ($DEV_LAN $DEV_ADMIN) @subchain "lan_services" { proto (tcp udp) dport 5000 ACCEPT; # random debugging proto (tcp udp) dport (ssh domain bootpc bootps ntp) ACCEPT; # prometheus temp rule proto tcp dport 11112 ACCEPT; proto (tcp udp) dport tftp ACCEPT; # RTMP streaming proto (tcp udp) dport 1935 ACCEPT; # Chromecast # proto udp dport 32768:61000 ACCEPT; # proto udp dport (5353 1900) ACCEPT; # proto tcp dport (8008 8009) ACCEPT; interface $DEV_LAN jump logdrop; } } chain OUTPUT policy ACCEPT; chain FORWARD { policy DROP; mod state state INVALID DROP; mod state state (ESTABLISHED RELATED) ACCEPT; interface $DEV_UNTRUSTED_LAN outerface $DEV_WAN ACCEPT; interface $DEV_LAN ACCEPT; jump logdrop; } } domain ip6 table filter chain INPUT { proto ipv6-icmp ACCEPT; } domain (ip ip6) table filter chain logdrop { LOG log-level warning log-prefix "dropped "; DROP; } domain (ip ip6) table filter chain INPUT { interface $DEV_WAN DROP; jump logdrop; } domain ip table nat { chain POSTROUTING { saddr $NET_LAN outerface $DEV_WAN MASQUERADE; } } domain (ip ip6) table mangle { chain PREROUTING { interface ${lan-dev}.30 MARK set-mark ${toString mullvadMark}; } } ''; }; services = { openssh.enable = lib.mkDefault true; openssh.passwordAuthentication = false; }; boot.kernel.sysctl = { "net.ipv4.conf.all.forwarding" = true; "net.ipv4.conf.default.forwarding" = true; "net.ipv6.conf.all.forwarding" = true; "net.ipv6.conf.default.forwarding" = true; }; #services.hostapd = { # enable = true; # # driver = "iwlwifi"; # ssid = "2c"; # wpaPassphrase = "mintchip"; # interface = "${lan-dev}"; # hwMode = "g"; # channel = 11; # extraConfig = '' # country_code=US # wpa_key_mgmt=WPA-PSK # rsn_pairwise=CCMP # ''; #}; networking.dhcpcd = { # Wait for v4 and v6 addresses. # wait = "both"; extraConfig = '' debug noipv6rs interface ${wan-dev} dhcp ipv6rs ia_na 0 # ia_pd 1/::/64 ${lan-dev}.100/0/64 ''; }; systemd.services.dhcpcd = { after = [ "network-addresses-${wan-dev}.service" ]; preStart = lib.mkAfter '' ${pkgs.iproute}/bin/ip link set dev ${wan-dev} address ${ config.networking.interfaces.${wan-dev}.macAddress }; ''; }; services.dnsmasq = { enable = true; servers = [ "1.1.1.1" "8.8.8.8" "8.8.4.4" ]; resolveLocalQueries = false; extraConfig = '' port=2053 no-resolv address=/test-dns.orbekk.com/::1 enable-ra dhcp-authoritative # Null AAAA response on these domains server=/netflix.com/# address=/netflix.com/:: server=/netflix.net/# address=/netflix.net/:: server=/nflxext.com/# address=/nflxext.com/:: server=/nflximg.net/# address=/nflximg.net/:: server=/nflxvideo.net/# address=/nflxvideo.net/:: server=/nflxso.net/# address=/nflxso.net/:: dhcp-range=vlan30,172.20.30.50,172.20.30.254,5m dhcp-option=net:vlan30,option:router,172.20.30.1 dhcp-option=net:vlan30,option:dns-server,172.20.30.1 dhcp-range=vlan100,172.20.100.50,172.20.100.254,5m dhcp-host=vlan100,d8:3b:bf:59:22:de,172.20.100.10 dhcp-range=vlan100,::100,::500,constructor:bond0.100,ra-only dhcp-option=net:vlan100,option:router,172.20.100.1 dhcp-option=net:vlan100,option:dns-server,172.20.100.1 dhcp-range=vlan32,172.20.32.50,172.20.32.254,5m dhcp-range=vlan32,::100,::500,constructor:bond0.32,ra-only dhcp-option=net:vlan32,option:router,172.20.32.1 dhcp-option=net:vlan32,option:dns-server,172.20.32.1 ''; }; networking.sits.he0 = { dev = wan-dev; remote = "209.51.161.14"; }; networking.iproute2.enable = true; # ${toString nycmeshMark} nycmesh networking.iproute2.rttablesExtraConfig = '' ${toString mullvadMark} mullvad 200 he ''; systemd.services.network-route-setup = { description = "HE tunnel route setup"; requires = [ "network-online.target" ]; after = [ "network.target" "network-online.target" ]; wantedBy = [ "multi-user.target" ]; path = [ pkgs.iproute ]; script = '' # ip -6 rule add from 2001:470:8e2e::/48 lookup he prio 0 || true # ip -6 route replace default dev he0 src 2001:470:8e2e:20::d table he # ip -6 route flush cache ''; }; networking.wireguard.interfaces.mullvad.postSetup = '' ip rule add fwmark ${toString mullvadMark} table mullvad ip route replace default dev mullvad table mullvad ip route flush cache ''; # networking.wireguard.interfaces.nycmesh.postSetup = '' # ip rule add fwmark ${toString nycmeshMark} table nycmesh # ip route replace default via 10.70.73.1 onlink dev nycmesh table nycmesh # ip route flush cache # ''; # boot.kernel.sysctl."net.ipv6.conf.${wan-dev}.disable_ipv6" = true; networking.interfaces.${wan-dev} = { macAddress = "3c:97:0e:19:7e:5c"; useDHCP = true; }; networking.interfaces.he0.ipv6 = { addresses = [ { address = "2001:470:1f06:1194::2"; prefixLength = 64; } { address = "2001:470:8e2e:20::d"; prefixLength = 64; } ]; routes = [{ address = "::"; prefixLength = 0; }]; }; networking.interfaces."${lan-dev}".useDHCP = false; networking.interfaces."${lan-dev}.255" = { ipv4.addresses = [{ address = "10.10.255.3"; prefixLength = 24; }]; ipv6.addresses = [{ address = "2001:470:8e2e:ffff::3"; prefixLength = 64; }]; useDHCP = false; }; networking.interfaces."${lan-dev}.100" = { ipv4.addresses = [{ address = "172.20.100.1"; prefixLength = 24; }]; ipv6.addresses = [{ address = "2001:470:8e2e:100::1"; prefixLength = 64; }]; useDHCP = false; }; networking.interfaces."${lan-dev}.30" = { ipv4.addresses = [{ address = "172.20.30.1"; prefixLength = 24; }]; useDHCP = false; }; networking.interfaces."${lan-dev}.32" = { ipv4.addresses = [{ address = "172.20.32.1"; prefixLength = 23; }]; ipv6.addresses = [{ address = "2001:470:8e2e:32::1"; prefixLength = 64; }]; useDHCP = false; }; }