chore: wip router firewall options
Some checks failed
/ check (push) Failing after 10s

This commit is contained in:
Daniel Flanagan 2025-02-18 22:37:45 -06:00
parent 48caa98989
commit f0c5293adf
3 changed files with 479 additions and 448 deletions

View file

@ -18,6 +18,7 @@ in
};
config = lib.mkIf cfg.enable {
services.xserver.desktopManager.gnome.enable = true;
environment.systemPackages = [ pkgs.wl-clipboard ];
fonts.packages = [
(

View file

@ -22,45 +22,8 @@ in
example = "lan";
};
/*
hosts = {
dragon = {
ip = "192.168.0.10";
};
bald = {
ip = "192.168.0.11";
additionalHosts = [
"ourcraft.lyte.dev"
];
};
beefcake = {
ip = "192.168.0.9";
additionalHosts = [
".beefcake.lan"
"a.lyte.dev"
"atuin.h.lyte.dev"
"audio.lyte.dev"
"bw.lyte.dev"
"files.lyte.dev"
"finances.h.lyte.dev"
"git.lyte.dev"
"grafana.h.lyte.dev"
"idm.h.lyte.dev"
"matrix.lyte.dev"
"nextcloud.h.lyte.dev"
"nix.h.lyte.dev"
"onlyoffice.h.lyte.dev"
"paperless.h.lyte.dev"
"prometheus.h.lyte.dev"
"video.lyte.dev"
"vpn.h.lyte.dev"
];
};
};
*/
hosts = lib.mkOption {
};
openPorts = lib.mkOption { };
hosts = lib.mkOption { };
interfaces = {
wan = {
@ -164,30 +127,75 @@ in
ff02::2 ip6-allrouters
'';
nftables = {
# tcp dport 2201 accept comment "Accept SSH on port 2201"
# tcp dport 53 accept comment "Accept DNS"
# udp dport 53 accept comment "Accept DNS"
# tcp dport { 80, 443 } accept comment "Allow HTTP/HTTPS to server (see nat prerouting)"
# udp dport { 80, 443 } accept comment "Allow QUIC to server (see nat prerouting)"
nftables =
let
mkOpenPortRule =
protocol: rules:
builtins.concatStringsSep "\n " (
lib.attrsets.mapAttrsToList (
name: ports:
let
nfports = builtins.concatStringsSep ", " (lib.lists.toList (builtins.toString ports));
in
''${protocol} dport {${nfports}} accept comment "${name}"''
) rules
);
tcpRulesString = mkOpenPortRule "tcp" cfg.openPorts.tcp;
udpRulesString = mkOpenPortRule "udp" cfg.openPorts.udp;
tcpHostRulesString = mkOpenPortRule "tcp" cfg.hosts.all.nat;
udpHostRulesString = mkOpenPortRule "udp" cfg.hosts.all.nat;
builtins.mapAttrs (name: { nat ? {} }: nat) cfg.hosts
acceptPorts = builtins.concatStringsSep "\n " [
tcpRulesString
udpRulesString
tcpHostRulesString
udpHostRulesString
];
in
{
enable = true;
checkRuleset = true;
flushRuleset = true;
/*
set LANv4 {
type ipv4_addr
flags interval
elements = { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16 }
}
set LANv6 {
type ipv6_addr
flags interval
elements = { fd00::/8, fe80::/10 }
}
TODO: maybe tailnet?
chain my_input_lan {
udp sport 1900 udp dport >= 1024 meta pkttype unicast limit rate 4/second burst 20 packets accept comment "Accept UPnP IGD port mapping reply"
udp sport netbios-ns udp dport >= 1024 meta pkttype unicast accept comment "Accept Samba Workgroup browsing replies"
}
chain forward {
type filter hook forward priority filter; policy drop;
iifname { "${lan}" } oifname { "${wan}" } accept comment "Allow trusted LAN to WAN"
iifname { "tailscale0" } oifname { "${wan}" } accept comment "Allow trusted LAN to WAN"
iifname { "${wan}" } oifname { "${lan}" } ct state { established, related } accept comment "Allow established back to LAN"
}
*/
ruleset = ''
table inet filter {
## set LANv4 {
## type ipv4_addr
## flags interval
## elements = { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16 }
## }
## set LANv6 {
## type ipv6_addr
## flags interval
## elements = { fd00::/8, fe80::/10 }
## }
## TODO: maybe tailnet?
## chain my_input_lan {
## udp sport 1900 udp dport >= 1024 meta pkttype unicast limit rate 4/second burst 20 packets accept comment "Accept UPnP IGD port mapping reply"
## udp sport netbios-ns udp dport >= 1024 meta pkttype unicast accept comment "Accept Samba Workgroup browsing replies"
## }
chain input {
type filter hook input priority 0; policy drop;
@ -213,6 +221,8 @@ in
udp dport mdns ip6 daddr ff02::fb accept comment "Accept mDNS"
udp dport mdns ip daddr 224.0.0.251 accept comment "Accept mDNS"
${acceptPorts}
tcp dport 2201 accept comment "Accept SSH on port 2201"
tcp dport 53 accept comment "Accept DNS"
udp dport 53 accept comment "Accept DNS"
@ -241,14 +251,6 @@ in
type filter hook forward priority 0;
accept
}
## chain forward {
## type filter hook forward priority filter; policy drop;
## iifname { "${lan}" } oifname { "${wan}" } accept comment "Allow trusted LAN to WAN"
## iifname { "tailscale0" } oifname { "${wan}" } accept comment "Allow trusted LAN to WAN"
## iifname { "${wan}" } oifname { "${lan}" } ct state { established, related } accept comment "Allow established back to LAN"
## }
}
table ip nat {
@ -426,8 +428,9 @@ in
{
ip,
additionalHosts ? [ ],
identifier ? name,
time ? "12h",
# identifier ? name,
# time ? "12h",
...
}:
[
"/${name}.${cfg.domain}/${ip}"
@ -447,4 +450,319 @@ in
};
}
);
# NOTE: see flake.nix 'nnf.nixosModules.default'
/*
nftables.firewall = let
me = config.networking.nftables.firewall.localZoneName;
in {
enable = true;
snippets.nnf-common.enable = true;
zones = {
${interfaces.wan.name} = {
interfaces = [interfaces.wan.name interfaces.lan.name];
};
${interfaces.lan.name} = {
parent = interfaces.wan.name;
ipv4Addresses = [cidr];
};
## banned = {
## ingressExpression = [
## "ip saddr @banlist"
## "ip6 saddr @banlist6"
## ];
## egressExpression = [
## "ip daddr @banlist"
## "ip6 daddr @banlist6"
## ];
## };
};
rules = {
dhcp = {
from = "all";
to = [hosts.beefcake.ip];
allowedTCPPorts = [67];
allowedUDPPorts = [67];
};
http = {
from = "all";
to = [me];
allowedTCPPorts = [80 443];
};
router-ssh = {
from = "all";
to = [me];
allowedTCPPorts = [2201];
};
server-ssh = {
from = "all";
to = [hosts.beefcake.ip];
allowedTCPPorts = [22];
};
};
};
*/
/*
dnsmasq serves as our DHCP and DNS server
almost all the configuration should be derived from the values at the top of
this file
*/
/*
since the home network reserves port 22 for ssh to the big server and to
gitea, the router uses port 2201 for ssh
*/
/*
NOTE: everything from here on is deprecated or old stuff
TODO: may not be strictly necessary for IPv6?
TODO: also may not even be the best implementation?
services.radvd = {
enable = false;
## NOTE: this config is just the default arch linux config I think and may
## need tweaking? this is what I had on the arch linux router, though :shrug:
config = ''
interface lo
{
AdvSendAdvert on;
MinRtrAdvInterval 3;
MaxRtrAdvInterval 10;
AdvDefaultPreference low;
AdvHomeAgentFlag off;
prefix 2001:db8:1:0::/64
{
AdvOnLink on;
AdvAutonomous on;
AdvRouterAddr off;
};
prefix 0:0:0:1234::/64
{
AdvOnLink on;
AdvAutonomous on;
AdvRouterAddr off;
Base6to4Interface ppp0;
AdvPreferredLifetime 120;
AdvValidLifetime 300;
};
route 2001:db0:fff::/48
{
AdvRoutePreference high;
AdvRouteLifetime 3600;
};
RDNSS 2001:db8::1 2001:db8::2
{
AdvRDNSSLifetime 30;
};
DNSSL branch.example.com example.com
{
AdvDNSSLLifetime 30;
};
};
'';
};
TODO: old config, should be deleted ASAP
services.dnsmasq = {
enable = false;
settings = {
# server endpoints
listen-address = "::1,127.0.0.1,${ip}";
port = "53";
# DNS cache entries
cache-size = "10000";
# local domain entries
local = "/lan/";
domain = "lan";
expand-hosts = true;
dhcp-authoritative = true;
conf-file = "/usr/share/dnsmasq/trust-anchors.conf";
dnssec = true;
except-interface = "${wan_if}";
interface = "${lan_if}";
enable-ra = true;
# dhcp-option = "121,${cidr},${ip}";
dhcp-range = [
"lan,${dhcp_lease_space.min},${dhcp_lease_space.max},${netmask},10m"
"tag:${lan_if},::1,constructor:${lan_if},ra-names,12h"
];
dhcp-host = [
"${hosts.dragon.host},${hosts.dragon.ip},12h"
"${hosts.beefcake.host},${hosts.beefcake.ip},12h"
];
# may need to go in /etc/hosts (networking.extraHosts), too?
address = [
"/video.lyte.dev/192.168.0.9"
"/git.lyte.dev/192.168.0.9"
"/bw.lyte.dev/192.168.0.9"
"/files.lyte.dev/192.168.0.9"
"/vpn.h.lyte.dev/192.168.0.9"
"/.h.lyte.dev/192.168.0.9"
];
server = [
"${ip}"
"8.8.8.8"
"8.8.4.4"
"1.1.1.1"
"1.0.0.1"
];
};
};
TODO: old config, should be deleted ASAP
nftables = {
enable = false;
flushRuleset = true;
tables = {
filter = {
family = "inet";
content = ''
chain input {
# type filter hook input priority filter; policy accept;
type filter hook input priority 0;
# anything from loopback interface
iifname "lo" accept
# accept traffic we originated
ct state { established, related } counter accept
ct state invalid counter drop
# ICMP
ip6 nexthdr icmpv6 icmpv6 type { echo-request, nd-neighbor-solicit, nd-neighbor-advert, nd-router-solicit, nd-router-advert, mld-listener-query, destination-unreachable, packet-too-big, time-exceeded, parameter-problem } counter accept
ip protocol icmp icmp type { echo-request, destination-unreachable, router-advertisement, time-exceeded, parameter-problem } counter accept
ip protocol icmpv6 counter accept
ip protocol icmp counter accept
meta l4proto ipv6-icmp counter accept
udp dport dhcpv6-client counter accept
tcp dport { 64022, 22, 53, 67, 25565 } counter accept
udp dport { 64020, 22, 53, 67 } counter accept
## iifname "iot" ip saddr $iot-ip tcp dport { llmnr } counter accept
## iifname "iot" ip saddr $iot-ip udp dport { mdns, llmnr } counter accept
iifname "${lan_if}" tcp dport { llmnr } counter accept
iifname "${lan_if}" udp dport { mdns, llmnr } counter accept
counter drop
}
# allow all outgoing
chain output {
type filter hook output priority 0;
accept
}
chain forward {
type filter hook forward priority 0;
accept
}
'';
};
nat = {
family = "ip";
content = ''
set masq_saddr {
type ipv4_addr
flags interval
elements = { ${cidr} }
}
map map_port_ipport {
type inet_proto . inet_service : ipv4_addr . inet_service
}
chain prerouting {
iifname ${lan_if} accept
type nat hook prerouting priority dstnat + 1; policy accept;
fib daddr type local dnat ip addr . port to meta l4proto . th dport map @map_port_ipport
iifname ${wan_if} tcp dport { 22, 80, 443, 25565, 64022 } dnat to ${hosts.beefcake.ip}
iifname ${wan_if} udp dport { 64020 } dnat to ${hosts.beefcake.ip}
## iifname ${wan_if} tcp dport { 25565 } dnat to 192.168.0.244
## iifname ${wan_if} udp dport { 25565 } dnat to 192.168.0.244
## router
iifname ${wan_if} tcp dport { 2201 } dnat to ${ip}
}
chain output {
type nat hook output priority -99; policy accept;
ip daddr != 127.0.0.0/8 oif "lo" dnat ip addr . port to meta l4proto . th dport map @map_port_ipport
}
chain postrouting {
type nat hook postrouting priority srcnat + 1; policy accept;
oifname ${lan_if} masquerade
ip saddr @masq_saddr masquerade
}
'';
};
};
};
TODO: also want to try to avoid using dhcpcd for IPv6 since systemd-networkd
should be sufficient?
dhcpcd = {
enable = false;
extraConfig = ''
duid
## No way.... https://github.com/NetworkConfiguration/dhcpcd/issues/36#issuecomment-954777644
## issues caused by guests with oneplus devices
noarp
persistent
vendorclassid
option domain_name_servers, domain_name, domain_search
option classless_static_routes
option interface_mtu
option host_name
#option ntp_servers
require dhcp_server_identifier
slaac private
noipv4ll
noipv6rs
static domain_name_servers=${ip}
interface ${wan_if}
gateway
ipv6rs
iaid 1
## option rapid_commit
## ia_na 1
ia_pd 1 ${lan_if}
interface ${lan_if}
static ip_address=${cidr}
static routers=${ip}
static domain_name_servers=${ip}
'';
};
*/
}

View file

@ -113,18 +113,45 @@ in
lan.mac = "00:01:2e:82:73:5a";
};
openPorts = {
tcp = {
"Accept SSH to router" = 2201;
};
udp = {
"Accept DNS" = 53;
};
};
# TODO: nftables
hosts = {
dragon = {
ip = "192.168.0.10";
};
bald = {
ip = "192.168.0.11";
nat.tcp.minecraft = 25565;
additionalHosts = [
"ourcraft.lyte.dev"
];
};
beefcake = {
ip = "192.168.0.9";
nat = {
tcp = {
"SSH" = 22;
"HTTP" = 80;
"HTTPS" = 443;
"Minecraft Flanilla" = 26966;
};
udp = {
"QUIC" = [
80
443
];
"Factorio" = 34197;
};
};
additionalHosts = [
".beefcake.lan"
"a.lyte.dev"
@ -147,321 +174,6 @@ in
];
};
};
# NOTE: see flake.nix 'nnf.nixosModules.default'
/*
nftables.firewall = let
me = config.networking.nftables.firewall.localZoneName;
in {
enable = true;
snippets.nnf-common.enable = true;
zones = {
${interfaces.wan.name} = {
interfaces = [interfaces.wan.name interfaces.lan.name];
};
${interfaces.lan.name} = {
parent = interfaces.wan.name;
ipv4Addresses = [cidr];
};
## banned = {
## ingressExpression = [
## "ip saddr @banlist"
## "ip6 saddr @banlist6"
## ];
## egressExpression = [
## "ip daddr @banlist"
## "ip6 daddr @banlist6"
## ];
## };
};
rules = {
dhcp = {
from = "all";
to = [hosts.beefcake.ip];
allowedTCPPorts = [67];
allowedUDPPorts = [67];
};
http = {
from = "all";
to = [me];
allowedTCPPorts = [80 443];
};
router-ssh = {
from = "all";
to = [me];
allowedTCPPorts = [2201];
};
server-ssh = {
from = "all";
to = [hosts.beefcake.ip];
allowedTCPPorts = [22];
};
};
};
*/
};
/*
dnsmasq serves as our DHCP and DNS server
almost all the configuration should be derived from the values at the top of
this file
*/
/*
since the home network reserves port 22 for ssh to the big server and to
gitea, the router uses port 2201 for ssh
*/
/*
NOTE: everything from here on is deprecated or old stuff
TODO: may not be strictly necessary for IPv6?
TODO: also may not even be the best implementation?
services.radvd = {
enable = false;
## NOTE: this config is just the default arch linux config I think and may
## need tweaking? this is what I had on the arch linux router, though :shrug:
config = ''
interface lo
{
AdvSendAdvert on;
MinRtrAdvInterval 3;
MaxRtrAdvInterval 10;
AdvDefaultPreference low;
AdvHomeAgentFlag off;
prefix 2001:db8:1:0::/64
{
AdvOnLink on;
AdvAutonomous on;
AdvRouterAddr off;
};
prefix 0:0:0:1234::/64
{
AdvOnLink on;
AdvAutonomous on;
AdvRouterAddr off;
Base6to4Interface ppp0;
AdvPreferredLifetime 120;
AdvValidLifetime 300;
};
route 2001:db0:fff::/48
{
AdvRoutePreference high;
AdvRouteLifetime 3600;
};
RDNSS 2001:db8::1 2001:db8::2
{
AdvRDNSSLifetime 30;
};
DNSSL branch.example.com example.com
{
AdvDNSSLLifetime 30;
};
};
'';
};
TODO: old config, should be deleted ASAP
services.dnsmasq = {
enable = false;
settings = {
# server endpoints
listen-address = "::1,127.0.0.1,${ip}";
port = "53";
# DNS cache entries
cache-size = "10000";
# local domain entries
local = "/lan/";
domain = "lan";
expand-hosts = true;
dhcp-authoritative = true;
conf-file = "/usr/share/dnsmasq/trust-anchors.conf";
dnssec = true;
except-interface = "${wan_if}";
interface = "${lan_if}";
enable-ra = true;
# dhcp-option = "121,${cidr},${ip}";
dhcp-range = [
"lan,${dhcp_lease_space.min},${dhcp_lease_space.max},${netmask},10m"
"tag:${lan_if},::1,constructor:${lan_if},ra-names,12h"
];
dhcp-host = [
"${hosts.dragon.host},${hosts.dragon.ip},12h"
"${hosts.beefcake.host},${hosts.beefcake.ip},12h"
];
# may need to go in /etc/hosts (networking.extraHosts), too?
address = [
"/video.lyte.dev/192.168.0.9"
"/git.lyte.dev/192.168.0.9"
"/bw.lyte.dev/192.168.0.9"
"/files.lyte.dev/192.168.0.9"
"/vpn.h.lyte.dev/192.168.0.9"
"/.h.lyte.dev/192.168.0.9"
];
server = [
"${ip}"
"8.8.8.8"
"8.8.4.4"
"1.1.1.1"
"1.0.0.1"
];
};
};
TODO: old config, should be deleted ASAP
nftables = {
enable = false;
flushRuleset = true;
tables = {
filter = {
family = "inet";
content = ''
chain input {
# type filter hook input priority filter; policy accept;
type filter hook input priority 0;
# anything from loopback interface
iifname "lo" accept
# accept traffic we originated
ct state { established, related } counter accept
ct state invalid counter drop
# ICMP
ip6 nexthdr icmpv6 icmpv6 type { echo-request, nd-neighbor-solicit, nd-neighbor-advert, nd-router-solicit, nd-router-advert, mld-listener-query, destination-unreachable, packet-too-big, time-exceeded, parameter-problem } counter accept
ip protocol icmp icmp type { echo-request, destination-unreachable, router-advertisement, time-exceeded, parameter-problem } counter accept
ip protocol icmpv6 counter accept
ip protocol icmp counter accept
meta l4proto ipv6-icmp counter accept
udp dport dhcpv6-client counter accept
tcp dport { 64022, 22, 53, 67, 25565 } counter accept
udp dport { 64020, 22, 53, 67 } counter accept
## iifname "iot" ip saddr $iot-ip tcp dport { llmnr } counter accept
## iifname "iot" ip saddr $iot-ip udp dport { mdns, llmnr } counter accept
iifname "${lan_if}" tcp dport { llmnr } counter accept
iifname "${lan_if}" udp dport { mdns, llmnr } counter accept
counter drop
}
# allow all outgoing
chain output {
type filter hook output priority 0;
accept
}
chain forward {
type filter hook forward priority 0;
accept
}
'';
};
nat = {
family = "ip";
content = ''
set masq_saddr {
type ipv4_addr
flags interval
elements = { ${cidr} }
}
map map_port_ipport {
type inet_proto . inet_service : ipv4_addr . inet_service
}
chain prerouting {
iifname ${lan_if} accept
type nat hook prerouting priority dstnat + 1; policy accept;
fib daddr type local dnat ip addr . port to meta l4proto . th dport map @map_port_ipport
iifname ${wan_if} tcp dport { 22, 80, 443, 25565, 64022 } dnat to ${hosts.beefcake.ip}
iifname ${wan_if} udp dport { 64020 } dnat to ${hosts.beefcake.ip}
## iifname ${wan_if} tcp dport { 25565 } dnat to 192.168.0.244
## iifname ${wan_if} udp dport { 25565 } dnat to 192.168.0.244
## router
iifname ${wan_if} tcp dport { 2201 } dnat to ${ip}
}
chain output {
type nat hook output priority -99; policy accept;
ip daddr != 127.0.0.0/8 oif "lo" dnat ip addr . port to meta l4proto . th dport map @map_port_ipport
}
chain postrouting {
type nat hook postrouting priority srcnat + 1; policy accept;
oifname ${lan_if} masquerade
ip saddr @masq_saddr masquerade
}
'';
};
};
};
TODO: also want to try to avoid using dhcpcd for IPv6 since systemd-networkd
should be sufficient?
dhcpcd = {
enable = false;
extraConfig = ''
duid
## No way.... https://github.com/NetworkConfiguration/dhcpcd/issues/36#issuecomment-954777644
## issues caused by guests with oneplus devices
noarp
persistent
vendorclassid
option domain_name_servers, domain_name, domain_search
option classless_static_routes
option interface_mtu
option host_name
#option ntp_servers
require dhcp_server_identifier
slaac private
noipv4ll
noipv6rs
static domain_name_servers=${ip}
interface ${wan_if}
gateway
ipv6rs
iaid 1
## option rapid_commit
## ia_na 1
ia_pd 1 ${lan_if}
interface ${lan_if}
static ip_address=${cidr}
static routers=${ip}
static domain_name_servers=${ip}
'';
};
*/
};
}