2023-04-02 01:14:01 +02:00
|
|
|
|
# Home network configuration
|
|
|
|
|
#
|
2023-04-15 18:08:46 +02:00
|
|
|
|
# +----------+ +------+
|
|
|
|
|
# | | | | ( clients )
|
|
|
|
|
# | | | +|-|-|-|-|+
|
|
|
|
|
# +---+----+ +-+-+-+ |5 4 3 2 1|
|
|
|
|
|
# |upstream| |fuuko| |TL-SG105 |
|
|
|
|
|
# +--------+ +-----+ +---------+
|
2023-04-02 01:14:01 +02:00
|
|
|
|
#
|
|
|
|
|
# It consists of fuuko as a router (this configuration),
|
|
|
|
|
# connected to a TP-LINK TL-SG105E “smart managed” (i.e., it can do VLANs) 5-port switch.
|
|
|
|
|
# The upstream comes from some plasic Huawei router/AP I don’t control.
|
|
|
|
|
#
|
2023-04-15 18:08:46 +02:00
|
|
|
|
# fuuko has two physical network interfaces,
|
|
|
|
|
# because remote unlocking (which requires network in initrd) is hard with VLANs.
|
2023-04-02 01:14:01 +02:00
|
|
|
|
#
|
2023-04-05 10:09:34 +02:00
|
|
|
|
# Wireless is configured by providing the whole hostapd configuration file as a secret.
|
|
|
|
|
# Once nixpkgs PR 222536 is merged, I will migrate to using the NixOS module.
|
|
|
|
|
# Thanks to Intel’s wisdom, it’s not possible to use 5GHz in AP mode.
|
|
|
|
|
{ config, lib, pkgs, ... }:
|
2023-04-02 01:14:01 +02:00
|
|
|
|
let
|
|
|
|
|
domain = "home.sbruder.de";
|
|
|
|
|
in
|
|
|
|
|
{
|
|
|
|
|
sops.secrets.wg-mullvad-private-key = {
|
|
|
|
|
owner = config.users.users.systemd-network.name;
|
|
|
|
|
sopsFile = ../secrets.yaml;
|
|
|
|
|
};
|
2023-04-05 10:09:34 +02:00
|
|
|
|
sops.secrets.hostapd-config = {
|
|
|
|
|
sopsFile = ../secrets.yaml;
|
|
|
|
|
};
|
2023-04-02 01:14:01 +02:00
|
|
|
|
|
|
|
|
|
boot.kernel.sysctl = {
|
|
|
|
|
"net.ipv4.conf.all.forwarding" = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
networking = {
|
|
|
|
|
# networkd handles this
|
|
|
|
|
useDHCP = false;
|
|
|
|
|
# networkd didn’t work that well for this
|
|
|
|
|
nat = {
|
|
|
|
|
enable = true;
|
|
|
|
|
enableIPv6 = true;
|
|
|
|
|
externalInterface = "wg-mullvad";
|
2023-04-05 10:09:14 +02:00
|
|
|
|
internalInterfaces = [ "br-lan" ];
|
2023-04-02 01:14:01 +02:00
|
|
|
|
internalIPv6s = [ "fd00:80:1::/64" ];
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
systemd.network = {
|
|
|
|
|
enable = true;
|
|
|
|
|
netdevs = {
|
2023-04-05 10:09:14 +02:00
|
|
|
|
br-lan = {
|
|
|
|
|
netdevConfig = {
|
|
|
|
|
Name = "br-lan";
|
|
|
|
|
Kind = "bridge";
|
|
|
|
|
};
|
|
|
|
|
};
|
2023-04-02 01:14:01 +02:00
|
|
|
|
wg-mullvad = {
|
|
|
|
|
netdevConfig = {
|
|
|
|
|
Kind = "wireguard";
|
|
|
|
|
Name = "wg-mullvad";
|
|
|
|
|
};
|
|
|
|
|
wireguardConfig = {
|
|
|
|
|
PrivateKeyFile = config.sops.secrets.wg-mullvad-private-key.path;
|
|
|
|
|
FirewallMark = 51820;
|
|
|
|
|
};
|
|
|
|
|
wireguardPeers = lib.singleton {
|
|
|
|
|
wireguardPeerConfig = {
|
2023-05-25 20:08:04 +02:00
|
|
|
|
Endpoint = "193.32.127.70:51820";
|
|
|
|
|
PublicKey = "dV/aHhwG0fmp0XuvSvrdWjCtdyhPDDFiE/nuv/1xnRM=";
|
2023-04-02 01:14:01 +02:00
|
|
|
|
AllowedIPs = [ "0.0.0.0/0" "::0/0" ];
|
|
|
|
|
PersistentKeepalive = 25;
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
networks = {
|
|
|
|
|
wan = {
|
2023-04-15 18:08:46 +02:00
|
|
|
|
name = "enp8s0";
|
2023-04-02 01:14:01 +02:00
|
|
|
|
networkConfig = {
|
|
|
|
|
# Upstream provides no IPv6 :(
|
|
|
|
|
# If this is not set, it waits and fails systemd-networkd-wait-online
|
|
|
|
|
LinkLocalAddressing = "no";
|
|
|
|
|
IPv6AcceptRA = "no";
|
|
|
|
|
};
|
|
|
|
|
DHCP = "ipv4";
|
|
|
|
|
dhcpV4Config = {
|
|
|
|
|
UseDNS = "no";
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
lan = {
|
2023-04-15 18:08:46 +02:00
|
|
|
|
name = "enp9s0";
|
2023-04-05 10:09:14 +02:00
|
|
|
|
bridge = [ "br-lan" ];
|
|
|
|
|
};
|
|
|
|
|
br-lan = {
|
|
|
|
|
name = "br-lan";
|
2023-04-02 01:14:01 +02:00
|
|
|
|
domains = [ domain ];
|
|
|
|
|
address = [ "10.80.1.1/24" "fd00:80:1::1/64" ];
|
|
|
|
|
};
|
|
|
|
|
wg-mullvad = {
|
|
|
|
|
name = "wg-mullvad";
|
|
|
|
|
address = [ "10.66.208.88/32" "fc00:bbbb:bbbb:bb01::3:d057/128" ];
|
|
|
|
|
dns = [ "10.64.0.1" ];
|
|
|
|
|
routingPolicyRules = [
|
|
|
|
|
{
|
|
|
|
|
routingPolicyRuleConfig = {
|
|
|
|
|
FirewallMark = 51820;
|
|
|
|
|
InvertRule = "yes";
|
|
|
|
|
Table = 51820;
|
|
|
|
|
Priority = 10;
|
|
|
|
|
#SuppressPrefixLength = 0; # can’t be used here (forwarding does not work with it)
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
# FIXME: those two shouldn’t be necessary
|
|
|
|
|
# It should automatically detect those routes existing and prioritise them
|
|
|
|
|
{
|
|
|
|
|
routingPolicyRuleConfig = {
|
|
|
|
|
To = "10.80.0.0/24";
|
|
|
|
|
Priority = 9;
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
routingPolicyRuleConfig = {
|
|
|
|
|
To = "10.80.1.0/24";
|
|
|
|
|
Priority = 9;
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
];
|
|
|
|
|
routes = [
|
|
|
|
|
{
|
|
|
|
|
routeConfig = {
|
|
|
|
|
Gateway = "0.0.0.0"; # point-to-point connection
|
|
|
|
|
Table = 51820;
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
routeConfig = {
|
|
|
|
|
Gateway = "::";
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
];
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
services.resolved.enable = false;
|
|
|
|
|
|
|
|
|
|
services.dnsmasq = {
|
|
|
|
|
enable = true;
|
|
|
|
|
|
|
|
|
|
extraConfig = ''
|
|
|
|
|
bogus-priv # do not forward revese lookups of internal addresses
|
|
|
|
|
domain-needed # do not forward names without domain
|
2023-04-05 10:09:14 +02:00
|
|
|
|
interface=br-lan # only respond to queries from lan
|
2023-04-02 01:14:01 +02:00
|
|
|
|
no-hosts # do not resolve hosts from /etc/hosts
|
|
|
|
|
no-resolv # only use explicitly configured resolvers
|
|
|
|
|
|
|
|
|
|
cache-size=10000
|
|
|
|
|
|
|
|
|
|
domain=${domain}
|
|
|
|
|
# Allow resolving the router
|
2023-04-05 10:09:14 +02:00
|
|
|
|
interface-name=${config.networking.hostName}.${domain},br-lan
|
|
|
|
|
interface-name=${config.networking.hostName},br-lan
|
2023-04-02 01:14:01 +02:00
|
|
|
|
|
|
|
|
|
# DHCPv4
|
|
|
|
|
dhcp-range=10.80.1.20,10.80.1.150,12h
|
|
|
|
|
dhcp-option=option:router,10.80.1.1
|
|
|
|
|
|
|
|
|
|
# SLAAC (for addresses) / DHCPv6 (for DNS)
|
|
|
|
|
dhcp-range=fd00:80:1::,ra-stateless,ra-names
|
|
|
|
|
dhcp-option=option6:dns-server,fd00:80:1::1
|
2023-04-02 12:00:19 +02:00
|
|
|
|
|
|
|
|
|
# Despite its name, the switch does not have a “smart” configuration,
|
|
|
|
|
# that would allow me to tell it not to get DHCP from wan,
|
|
|
|
|
# but from lan instead.
|
|
|
|
|
# So it has to use static configuration.
|
|
|
|
|
host-record=switchviech,switchviech.${domain},10.80.1.19
|
2023-04-02 01:14:01 +02:00
|
|
|
|
'';
|
|
|
|
|
servers = [
|
|
|
|
|
"10.64.0.1" # mullvad DNS, should be fastest overall
|
|
|
|
|
#"9.9.9.9" # dns.quad9.net
|
|
|
|
|
#"2620:fe::fe"
|
|
|
|
|
];
|
|
|
|
|
};
|
2023-04-05 10:09:14 +02:00
|
|
|
|
systemd.services.dnsmasq.after = [ "systemd-networkd.service" ];
|
2023-04-02 01:14:01 +02:00
|
|
|
|
|
|
|
|
|
services.prometheus.exporters.dnsmasq = {
|
|
|
|
|
enable = true;
|
|
|
|
|
listenAddress = config.sbruder.wireguard.home.address;
|
|
|
|
|
leasesPath = "/var/lib/dnsmasq/dnsmasq.leases";
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
networking.firewall.allowedUDPPorts = [ 53 67 ];
|
|
|
|
|
networking.firewall.allowedTCPPorts = [ 53 ];
|
2023-04-05 10:09:34 +02:00
|
|
|
|
|
|
|
|
|
# Wireless
|
|
|
|
|
boot.kernelModules = [ "nl80211" ];
|
|
|
|
|
|
|
|
|
|
environment.systemPackages = with pkgs; [
|
|
|
|
|
iw
|
|
|
|
|
wirelesstools
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
# The service is mostly taken from nixpkgs pr 222536.
|
|
|
|
|
systemd.services.hostapd = {
|
|
|
|
|
path = with pkgs; [ hostapd ];
|
|
|
|
|
after = [ "sys-subsystem-net-devices-wlp7s0.device" ];
|
|
|
|
|
bindsTo = [ "sys-subsystem-net-devices-wlp7s0.device" ];
|
|
|
|
|
wantedBy = [ "multi-user.target" ];
|
|
|
|
|
|
|
|
|
|
serviceConfig = {
|
|
|
|
|
ExecStart = "${pkgs.hostapd}/bin/hostapd ${config.sops.secrets.hostapd-config.path}";
|
|
|
|
|
Restart = "always";
|
|
|
|
|
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
|
|
|
|
|
RuntimeDirectory = "hostapd";
|
|
|
|
|
|
|
|
|
|
# Hardening
|
|
|
|
|
LockPersonality = true;
|
|
|
|
|
MemoryDenyWriteExecute = true;
|
|
|
|
|
DevicePolicy = "closed";
|
|
|
|
|
DeviceAllow = "/dev/rfkill rw";
|
|
|
|
|
NoNewPrivileges = true;
|
|
|
|
|
PrivateUsers = false; # hostapd requires true root access.
|
|
|
|
|
PrivateTmp = true;
|
|
|
|
|
ProtectClock = true;
|
|
|
|
|
ProtectControlGroups = true;
|
|
|
|
|
ProtectHome = true;
|
|
|
|
|
ProtectHostname = true;
|
|
|
|
|
ProtectKernelLogs = true;
|
|
|
|
|
ProtectKernelModules = true;
|
|
|
|
|
ProtectKernelTunables = true;
|
|
|
|
|
ProtectProc = "invisible";
|
|
|
|
|
ProcSubset = "pid";
|
|
|
|
|
ProtectSystem = "strict";
|
|
|
|
|
RestrictAddressFamilies = [
|
|
|
|
|
"AF_INET"
|
|
|
|
|
"AF_INET6"
|
|
|
|
|
"AF_NETLINK"
|
|
|
|
|
"AF_UNIX"
|
|
|
|
|
];
|
|
|
|
|
RestrictNamespaces = true;
|
|
|
|
|
RestrictRealtime = true;
|
|
|
|
|
RestrictSUIDSGID = true;
|
|
|
|
|
SystemCallArchitectures = "native";
|
|
|
|
|
SystemCallFilter = [
|
|
|
|
|
"@system-service"
|
|
|
|
|
"~@privileged"
|
|
|
|
|
"@chown"
|
|
|
|
|
];
|
|
|
|
|
UMask = "0077";
|
|
|
|
|
};
|
|
|
|
|
};
|
2023-04-02 01:14:01 +02:00
|
|
|
|
}
|