nixos-config/machines/fuuko/services/router.nix
Simon Bruder 444aa962b5
fuuko: Add router service
This now mostly replaces ayu, which has been sitting between upstream
and the switch the last 6 months.

It now also configures routing over Mullvad, which also finally enables
IPv6 (I don’t understand how people get away with not providing it
natively in 2023).

Once I get a WLAN card, it will also host its own access point, which
currently still relies on ayu as “dumb AP” (as OpenWRT calls it).
2023-04-02 01:14:01 +02:00

216 lines
5.7 KiB
Nix
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Home network configuration
#
# +----------+ +---------------+
# | | | +-+-+---+ |
# | +|-|-|-|-|+ | |
# +---+----+ |5 4 3 2 1| | +--+--+
# |upstream| |TL-SG105 | | |fuuko|
# +--------+ +---------+ | +-----+
# |
# ( clients )
#
# 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 dont control.
#
# The VLANs are configured as follows:
# Port | VLAN | ID(s)
# 5 | untagged | 2
# 4 | tagged | 2,3
# 1-3 | untagged | 3
#
# Wireless currently still is done by a separate GL.iNet GL-MT300N-V2 running OpenWRT,
# but this will be changed to a Intel Wireless-AC 9260 in fuuko at a later date.
{ config, lib, ... }:
let
domain = "home.sbruder.de";
in
{
sops.secrets.wg-mullvad-private-key = {
owner = config.users.users.systemd-network.name;
sopsFile = ../secrets.yaml;
};
boot.kernel.sysctl = {
"net.ipv4.conf.all.forwarding" = true;
};
networking = {
# networkd handles this
useDHCP = false;
# networkd didnt work that well for this
nat = {
enable = true;
enableIPv6 = true;
externalInterface = "wg-mullvad";
internalInterfaces = [ "lan" ];
internalIPv6s = [ "fd00:80:1::/64" ];
};
};
systemd.network = {
enable = true;
netdevs = {
wan = {
netdevConfig = {
Kind = "vlan";
Name = "wan";
};
vlanConfig = {
Id = 2;
};
};
lan = {
netdevConfig = {
Kind = "vlan";
Name = "lan";
};
vlanConfig = {
Id = 3;
};
};
wg-mullvad = {
netdevConfig = {
Kind = "wireguard";
Name = "wg-mullvad";
};
wireguardConfig = {
PrivateKeyFile = config.sops.secrets.wg-mullvad-private-key.path;
FirewallMark = 51820;
};
wireguardPeers = lib.singleton {
wireguardPeerConfig = {
Endpoint = "146.70.117.194:51820";
PublicKey = "ydXFN45/kROELJrF6id+uIrnS5DvTKSCkZDjfL9De2Q=";
AllowedIPs = [ "0.0.0.0/0" "::0/0" ];
PersistentKeepalive = 25;
};
};
};
};
networks = {
physical = {
name = "enp8s0";
vlan = [ "wan" "lan" ];
# no autoconfiguration needed, only tagged VLAN
networkConfig = {
LinkLocalAddressing = "no";
LLDP = "no";
EmitLLDP = "no";
IPv6AcceptRA = "no";
IPv6SendRA = "no";
};
};
wan = {
name = "wan";
matchConfig = {
Type = "vlan";
};
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 = {
name = "lan";
matchConfig = {
Type = "vlan";
};
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; # cant be used here (forwarding does not work with it)
};
}
# FIXME: those two shouldnt 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
interface=lan # only respond to queries from lan
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
interface-name=${config.networking.hostName}.${domain},lan
interface-name=${config.networking.hostName},lan
# 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
'';
servers = [
"10.64.0.1" # mullvad DNS, should be fastest overall
#"9.9.9.9" # dns.quad9.net
#"2620:fe::fe"
];
};
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 ];
}