summaryrefslogtreecommitdiff
path: root/config/networking
diff options
context:
space:
mode:
authorquentin@aristote.fr <quentin@aristote.fr>2023-05-18 13:39:06 +0200
committerquentin@aristote.fr <quentin@aristote.fr>2023-05-20 20:13:45 +0200
commit925fc182e5ea9b87c3a62e80f5a20be4e827cd3b (patch)
treedc3772ee2a298fd6f39b8ab355aaecd8d5da593e /config/networking
parent001f53d081b78c5145cd7449f08f783bb56f35e3 (diff)
config: networking: hostapd: disable low-level bridging
Diffstat (limited to 'config/networking')
-rw-r--r--config/networking/bridges.nix22
-rw-r--r--config/networking/default.nix16
-rw-r--r--config/networking/services/ap.nix23
-rw-r--r--config/networking/services/default.nix2
-rw-r--r--config/networking/services/firewall.nix165
-rw-r--r--config/networking/services/firewall/default.nix31
-rw-r--r--config/networking/services/firewall/ruleset.nix160
7 files changed, 241 insertions, 178 deletions
diff --git a/config/networking/bridges.nix b/config/networking/bridges.nix
new file mode 100644
index 0000000..95f163e
--- /dev/null
+++ b/config/networking/bridges.nix
@@ -0,0 +1,22 @@
+{ config, lib, utils, pkgs, ... }:
+
+let cfg = config.personal.networking;
+in {
+ config = lib.mkMerge (builtins.map (network:
+ let
+ bridge = network.interface;
+ device = network.device;
+ in {
+ networking.bridges."${bridge}".interfaces = [ ];
+
+ systemd.services."${bridge}-netdev".script = ''
+ echo Setting forward delay to 0 for ${bridge}...
+ ip link set ${bridge} type bridge forward_delay 0
+ '';
+
+ systemd.services.hostapd.postStart = ''
+ sleep 3
+ ${pkgs.iproute2}/bin/bridge link set dev ${device} hairpin on
+ '';
+ }) [ cfg.networks.wan cfg.networks.iot ]);
+}
diff --git a/config/networking/default.nix b/config/networking/default.nix
index ea7e17e..eb189eb 100644
--- a/config/networking/default.nix
+++ b/config/networking/default.nix
@@ -4,13 +4,19 @@
let cfg = config.personal.networking;
in {
- imports = [ ./services ];
+ imports = [ ./bridges.nix ./services ];
options.personal.networking = {
networks = lib.mkOption {
type = with lib.types;
attrsOf (submodule {
options = {
+ device = lib.mkOption {
+ type = with lib.types; nullOr str;
+ default = null;
+ description = "Name of the network device.";
+ example = "wlp1s0";
+ };
interface = lib.mkOption {
type = lib.types.str;
description = "Name of the network interface.";
@@ -54,12 +60,14 @@ in {
};
};
wan = {
- interface = "wlp1s0";
+ device = "wlp1s0";
+ interface = "wan";
subnet = "192.168.2";
machines = { self.address = "192.168.2.1"; };
};
iot = {
- interface = "wlp5s0";
+ device = "wlp5s0";
+ interface = "iot";
subnet = "192.168.3";
machines = { self.address = "192.168.3.1"; };
};
@@ -76,6 +84,7 @@ in {
inherit (machines.livebox) address;
};
+ useDHCP = false;
dhcpcd.enable = false;
interfaces = lib.concatMapAttrs (name: value: {
"${value.interface}" = {
@@ -86,6 +95,7 @@ in {
};
};
}) cfg.networks;
+
};
};
}
diff --git a/config/networking/services/ap.nix b/config/networking/services/ap.nix
index 202cff5..d93e053 100644
--- a/config/networking/services/ap.nix
+++ b/config/networking/services/ap.nix
@@ -2,12 +2,12 @@
let
cfg = config.services.hostapd;
- makeHostapdConf = { name, interface ? cfg.interface, driver ? cfg.driver, ssid
+ makeHostapdConf = { name, device, interface, driver ? cfg.driver, ssid
, hwMode ? cfg.hwMode, channel ? cfg.channel, countryCode ? cfg.countryCode
, passphrase ? secrets.wifi."${name}".passphrase, logLevel ? cfg.logLevel
, extraConfig ? "" }:
builtins.toFile "hostapd.${name}.conf" (''
- interface=${interface}
+ interface=${device}
driver=${driver}
# IEEE 802.11
@@ -23,6 +23,9 @@ let
ieee80211d=1
country_code=${countryCode}
+ # disable low-level bridging of frames
+ ap_isolate=1
+ bridge=${interface}
# WPA/IEEE 802.11i
wpa=2
@@ -80,7 +83,7 @@ let
'' + extraConfig);
hostapdIotConf = makeHostapdConf {
name = "iot";
- interface = config.personal.networking.networks.iot.interface;
+ inherit (config.personal.networking.networks.iot) device interface;
ssid = "Quentinternet of Things";
hwMode = "g";
channel = 0;
@@ -93,7 +96,7 @@ let
};
hostapdWanConf = makeHostapdConf {
name = "wan";
- interface = config.personal.networking.networks.wan.interface;
+ inherit (config.personal.networking.networks.wan) device interface;
ssid = "Quentintranet";
hwMode = "a";
channel = 36;
@@ -119,15 +122,17 @@ in {
};
systemd.services.hostapd = let
- interfaces = with config.personal.networking.networks; [
+ devices = with config.personal.networking.networks; [
+ wan.device
wan.interface
+ iot.device
iot.interface
];
- netDevices = builtins.map (interface:
- "sys-subsystem-net-devices-${utils.escapeSystemdPath interface}.device")
- interfaces;
+ netDevices = builtins.map (device:
+ "sys-subsystem-net-devices-${utils.escapeSystemdPath device}.device")
+ devices;
networkLinkServices =
- builtins.map (interface: "network-link-${interface}.service") interfaces;
+ builtins.map (device: "network-link-${device}.service") devices;
in {
serviceConfig.ExecStart = lib.mkForce
"${pkgs.hostapd}/bin/hostapd ${hostapdIotConf} ${hostapdWanConf}";
diff --git a/config/networking/services/default.nix b/config/networking/services/default.nix
index e51aa5a..454a9e1 100644
--- a/config/networking/services/default.nix
+++ b/config/networking/services/default.nix
@@ -1,5 +1,5 @@
{ ... }:
{
- imports = [ ./ap.nix ./dhcp.nix ./dns.nix ./firewall.nix ];
+ imports = [ ./ap.nix ./dhcp.nix ./dns.nix ./firewall ];
}
diff --git a/config/networking/services/firewall.nix b/config/networking/services/firewall.nix
deleted file mode 100644
index a0aa281..0000000
--- a/config/networking/services/firewall.nix
+++ /dev/null
@@ -1,165 +0,0 @@
-{ config, lib, ... }:
-
-let nets = config.personal.networking.networks;
-in {
- boot.kernel.sysctl = { "net.ipv4.conf.all.forwarding" = true; };
-
- networking = {
- nftables = {
- enable = true;
- ruleset = with nets; ''
- table ip filter {
- chain conntrack {
- ct state vmap { established : accept \
- , related : accept \
- , invalid : drop }
- }
- chain dhcp {
- # https://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol#Operation
- ip protocol udp \
- udp sport 68 \
- udp dport 67 \
- accept comment "dhcp"
- }
- chain dns {
- # https://en.wikipedia.org/wiki/Domain_Name_System#Transport_protocols
- ip protocol { tcp, udp } \
- th sport 53 \
- th dport 53 \
- accept comment "dns"
- }
- chain kdeconnect {
- # https://userbase.kde.org/KDEConnect#I_have_two_devices_running_KDE_Connect_on_the_same_network,_but_they_can't_see_each_other
- ip protocol { tcp, udp } \
- th sport 1714-1764 \
- th dport 1714-1764 \
- accept comment "kdeconnect"
- }
- chain sonos_app {
- # https://support.sonos.com/en-us/article/configure-your-firewall-to-work-with-sonos
- # https://en.community.sonos.com/advanced-setups-229000/changed-udp-tcp-ports-for-sonos-app-needed-after-update-to-s2-6842454
- ip protocol tcp \
- tcp sport { 1400, 3400, 3401, 3500 } \
- tcp dport { 1400, 3400, 3401, 3500 } \
- accept comment "sonos: app control"
- ip protocol udp \
- udp sport 1900-1901 \
- udp dport 1900-1901 \
- accept comment "sonos: app control"
- }
- chain sonos {
- # https://support.sonos.com/en-us/article/configure-your-firewall-to-work-with-sonos
- # https://en.community.sonos.com/advanced-setups-229000/changed-udp-tcp-ports-for-sonos-app-needed-after-update-to-s2-6842454
- ip protocol tcp \
- tcp sport 4444 \
- tcp dport 4444 \
- accept comment "sonos: system updates"
- ip protocol udp \
- udp sport 6969 \
- udp dport 6969 \
- accept comment "sonos: setup"
- ip protocol udp \
- udp sport { 32413, 32414 } \
- udp dport { 32412, 32414 } \
- accept comment "sonos"
- }
- chain ssh {
- ip protocol tcp \
- tcp dport 22 \
- accept comment "ssh"
- }
- chain steam {
- # https://help.steampowered.com/en/faqs/view/2EA8-4D75-DA21-31EB
- ip protocol { udp, tcp } \
- th dport 27015-27050 \
- accept comment "steam: login, download"
- ip protocol udp \
- udp dport 27000-27100 \
- accept comment "steam: client: game traffic"
- ip protocol . th sport \
- { udp . 27031-27036, tcp . 27036 } \
- accept comment "steam: client: remote play"
- ip protocol udp \
- udp dport 4380 \
- accept comment "steam: client"
- ip protocol tcp \
- tcp sport 27015 \
- accept comment "steam: servers: SRCDS Rcon port"
- ip protocol udp \
- udp sport 27015 \
- accept comment "steam: servers: gameplay traffic"
- ip protocol udp \
- udp dport { 3478, 4379, 4380, 27014-27030 } \
- accept comment "steam: p2p, voice chat"
- }
- chain syncthing {
- # https://docs.syncthing.net/users/firewall.html
- ip protocol { tcp, udp } \
- th sport 22000 \
- th dport 22000 \
- accept comment "syncthing"
- ip protocol udp \
- udp sport 21027 \
- udp dport 21027 \
- accept comment "syncthing: discovery broadcasts"
- }
-
- chain in_wan {
- jump dns
- jump dhcp
- jump ssh
- }
- chain in_iot {
- jump dns
- jump dhcp
- }
- chain inbound {
- type filter hook input priority 0; policy drop;
- icmp type echo-request limit rate 5/second accept
- jump conntrack
- meta iifname vmap \
- { lo : accept \
- , ${lan.interface} : drop \
- , ${wan.interface} : goto in_wan \
- , ${iot.interface} : goto in_iot }
- }
-
- chain wan_wan {
- jump kdeconnect
- jump syncthing
- }
- chain iot_wan {
- jump sonos_app
- }
- chain forward {
- type filter hook forward priority 0; policy drop;
- jump conntrack
- meta oifname ${lan.interface} accept
- meta iifname ${wan.interface} meta oifname ${wan.interface} \
- goto wan_wan
- meta iifname ${iot.interface} meta oifname ${wan.interface} \
- goto iot_wan
- }
- }
-
- table ip nat {
- chain postrouting {
- type nat hook postrouting priority 100; policy accept;
- meta oifname ${lan.interface} snat to ${lan.machines.self.address}
- }
- }
-
- table ip6 global6 {
- chain input {
- type filter hook input priority 0; policy drop;
- }
- chain forward {
- type filter hook forward priority 0; policy drop;
- }
- }
- '';
- };
-
- firewall.enable = lib.mkForce false;
- };
-}
diff --git a/config/networking/services/firewall/default.nix b/config/networking/services/firewall/default.nix
new file mode 100644
index 0000000..878e7cc
--- /dev/null
+++ b/config/networking/services/firewall/default.nix
@@ -0,0 +1,31 @@
+{ config, lib, ... }:
+
+let
+ # { any } -> (string -> any -> [ string ]) -> string
+ mapAttrsStrings = attrs: f: lib.concatStrings (lib.mapAttrsToList f attrs);
+ bracket = title: content:
+ ''
+ ${title} {
+ '' + content + ''
+ }
+ '';
+in {
+ boot.kernel.sysctl = { "net.ipv4.conf.all.forwarding" = true; };
+
+ networking = {
+ nftables = {
+ enable = true;
+ ruleset = mapAttrsStrings
+ (import ./ruleset.nix config.personal.networking.networks)
+ (family: tables:
+ mapAttrsStrings tables (tableName: chains:
+ bracket "table ${family} ${tableName}" (mapAttrsStrings chains
+ (chainName: chain:
+ bracket "chain ${chainName}" (lib.optionalString (chain ? base)
+ (with chain.base; ''
+ type ${type} hook ${hook} priority ${priority}; policy ${policy};
+ '') + chain.rules)))));
+ };
+ firewall.enable = lib.mkForce false;
+ };
+}
diff --git a/config/networking/services/firewall/ruleset.nix b/config/networking/services/firewall/ruleset.nix
new file mode 100644
index 0000000..b3e75c7
--- /dev/null
+++ b/config/networking/services/firewall/ruleset.nix
@@ -0,0 +1,160 @@
+{ lan, wan, iot, ... }:
+
+let
+ makeBaseChain = type: hook:
+ { priority ? type, policy ? "drop", rules ? "" }: {
+ base = { inherit type hook priority policy; };
+ inherit rules;
+ };
+ rulesCommon = {
+ conntrack = ''
+ ct state vmap { established : accept \
+ , related : accept \
+ , invalid : drop }
+ '';
+ # https://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol#Operation
+ dhcp = ''
+ ip protocol udp \
+ udp sport 68 \
+ udp dport 67 \
+ accept comment dhcp
+ '';
+ # https://en.wikipedia.org/wiki/Domain_Name_System#Transport_protocols
+ dns = ''
+ ip protocol { tcp, udp } \
+ th sport 53 \
+ th dport 53 \
+ accept comment dns
+ '';
+ # https://userbase.kde.org/KDEConnect#I_have_two_devices_running_KDE_Connect_on_the_same_network,_but_they_can't_see_each_other
+ kdeconnect = ''
+ ip protocol { tcp, udp } \
+ th dport 1714-1764 \
+ accept comment kdeconnect
+ '';
+ ping = ''
+ icmp type echo-request limit rate 5/second accept
+ '';
+ ssh = ''
+ ip protocol tcp \
+ tcp dport 22 \
+ accept comment ssh
+ '';
+ # # https://docs.syncthing.net/users/firewall.html
+ syncthing = ''
+ ip protocol tcp \
+ tcp sport 22000 \
+ tcp dport 22000 \
+ accept comment syncthing
+ ip protocol udp \
+ udp dport 21027 \
+ accept comment "syncthing: discovery broadcast"
+ '';
+ };
+in {
+ ip = {
+ filter = {
+ wan_in.rules = with rulesCommon; dns + dhcp + ssh;
+ iot_in.rules = with rulesCommon; dns + dhcp;
+ input = makeBaseChain "filter" "input" {
+ rules = with rulesCommon;
+ conntrack + ping + ''
+ meta iifname vmap { lo : accept \
+ , ${lan.interface} : drop \
+ , ${wan.interface} : goto wan_in \
+ , ${iot.interface} : goto iot_in }
+ '';
+ };
+ forward = makeBaseChain "filter" "forward" {
+ rules = with rulesCommon;
+ conntrack + ''
+ meta oifname ${lan.interface} accept
+ '';
+ };
+ };
+ nat = {
+ postrouting = makeBaseChain "nat" "postrouting" {
+ priority = "srcnat";
+ policy = "accept";
+ rules = ''
+ meta oifname ${lan.interface} snat to ${lan.machines.self.address}
+ '';
+ };
+ };
+ };
+
+ ip6 = {
+ global6 = {
+ input = makeBaseChain "filter" "input" { };
+ forward = makeBaseChain "filter" "forward" { };
+ };
+ };
+
+ bridge = {
+ filter = {
+ wan_wan.rules = with rulesCommon; syncthing + kdeconnect;
+ forward = makeBaseChain "filter" "forward" {
+ rules = with rulesCommon;
+ conntrack + ''
+ ether type vmap { ip6 : drop, arp : accept }
+ '' + ping + ''
+ meta ibrname . meta obrname vmap \
+ { ${wan.interface} . ${wan.interface} : goto wan_wan }
+ '';
+ };
+ };
+ };
+}
+
+# chain sonos_app {
+# # https://support.sonos.com/en-us/article/configure-your-firewall-to-work-with-sonos
+# # https://en.community.sonos.com/advanced-setups-229000/changed-udp-tcp-ports-for-sonos-app-needed-after-update-to-s2-6842454
+# ip protocol tcp \
+# tcp sport { 1400, 3400, 3401, 3500 } \
+# tcp dport { 1400, 3400, 3401, 3500 } \
+# accept comment "sonos: app control"
+# ip protocol udp \
+# udp sport 1900-1901 \
+# udp dport 1900-1901 \
+# accept comment "sonos: app control"
+# }
+# chain sonos {
+# # https://support.sonos.com/en-us/article/configure-your-firewall-to-work-with-sonos
+# # https://en.community.sonos.com/advanced-setups-229000/changed-udp-tcp-ports-for-sonos-app-needed-after-update-to-s2-6842454
+# ip protocol tcp \
+# tcp sport 4444 \
+# tcp dport 4444 \
+# accept comment "sonos: system updates"
+# ip protocol udp \
+# udp sport 6969 \
+# udp dport 6969 \
+# accept comment "sonos: setup"
+# ip protocol udp \
+# udp sport { 32413, 32414 } \
+# udp dport { 32412, 32414 } \
+# accept comment "sonos"
+# }
+# chain steam {
+# # https://help.steampowered.com/en/faqs/view/2EA8-4D75-DA21-31EB
+# ip protocol { udp, tcp } \
+# th dport 27015-27050 \
+# accept comment "steam: login, download"
+# ip protocol udp \
+# udp dport 27000-27100 \
+# accept comment "steam: client: game traffic"
+# ip protocol . th sport \
+# { udp . 27031-27036, tcp . 27036 } \
+# accept comment "steam: client: remote play"
+# ip protocol udp \
+# udp dport 4380 \
+# accept comment "steam: client"
+# ip protocol tcp \
+# tcp sport 27015 \
+# accept comment "steam: servers: SRCDS Rcon port"
+# ip protocol udp \
+# udp sport 27015 \
+# accept comment "steam: servers: gameplay traffic"
+# ip protocol udp \
+# udp dport { 3478, 4379, 4380, 27014-27030 } \
+# accept comment "steam: p2p, voice chat"
+# }