Simon Bruder
959f7be3d0
It adds a bit of latency (and is definitely not the best solution in theory), but finally allows dropping IPv6 NAT and it works within the constraits my home network has to live in.
146 lines
4 KiB
Nix
146 lines
4 KiB
Nix
# SPDX-FileCopyrightText: 2023-2024 Simon Bruder <simon@sbruder.de>
|
||
#
|
||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||
|
||
# Home network configuration
|
||
#
|
||
# +----------+ +------------+
|
||
# | | | | (clients)# (guests)
|
||
# | | | +--|--|--|--|-#+-|--|--|-|-unused|
|
||
# +---+----+ +-+-+-+-+-+ | 01 02 …… 12 # 13 …… 24 | 25 26 |
|
||
# |upstream| | 1 2 3 4 | | aruba Instant On 1830 | (SFP) |
|
||
# +--------+ | shinobu | +------------------------+-------+
|
||
# +---------+
|
||
#
|
||
# It consists of shinobu as a router (this configuration),
|
||
# connected to a aruba (HPE) Instant ON 1830 24-port 1GbE switch.
|
||
# The upstream comes (for now) from a PŸUR “WLAN-Kabelbox” (Compal CH7467CE).
|
||
# Sadly, I could not enable bridge mode on it, so the packets now go through (at least) three layers of NAT:
|
||
# device → NAT on shinobu → NAT on plastic router → PŸUR CGNAT
|
||
#
|
||
# Because of issues with the NICs operating at 2.5GbE,
|
||
# all clients are connected to the switch,
|
||
# even if they have a 2.5GbE NIC.
|
||
#
|
||
# 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, ... }:
|
||
let
|
||
cfg = pkgs.callPackage ./common.nix { };
|
||
in
|
||
{
|
||
imports = [
|
||
./dnsmasq.nix
|
||
./nft.nix
|
||
./tc.nix
|
||
];
|
||
|
||
sbruder.wireguard.he.enable = true;
|
||
|
||
boot.kernel.sysctl = {
|
||
"net.ipv4.conf.all.forwarding" = true;
|
||
"net.ipv6.conf.all.forwarding" = true;
|
||
};
|
||
|
||
environment.systemPackages = with pkgs; [
|
||
ethtool
|
||
];
|
||
|
||
networking.useDHCP = false;
|
||
|
||
systemd.network = {
|
||
enable = true;
|
||
# not all interfaces need to be up
|
||
wait-online.extraArgs = [ "--any" ];
|
||
netdevs = lib.mkMerge [
|
||
(lib.mapAttrs
|
||
(name: config: {
|
||
netdevConfig = {
|
||
Kind = "vlan";
|
||
Name = name;
|
||
};
|
||
vlanConfig = {
|
||
Id = config.id;
|
||
};
|
||
})
|
||
cfg.vlan)
|
||
(lib.mapAttrs'
|
||
(name: config: lib.nameValuePair "br-${name}" {
|
||
netdevConfig = {
|
||
Name = "br-${name}";
|
||
Kind = "bridge";
|
||
};
|
||
})
|
||
cfg.vlan)
|
||
];
|
||
networks = lib.mkMerge [
|
||
(lib.mapAttrs
|
||
(name: config: {
|
||
inherit name;
|
||
matchConfig = {
|
||
Type = "vlan";
|
||
};
|
||
bridge = [ "br-${name}" ];
|
||
})
|
||
cfg.vlan)
|
||
(lib.mapAttrs'
|
||
(name: config: lib.nameValuePair "br-${name}" {
|
||
name = "br-${name}";
|
||
domains = [ config.domain ];
|
||
address = lib.mapAttrsToList (family: familyConfig: familyConfig.gatewayCidr) config.subnet;
|
||
networkConfig = {
|
||
IPv6AcceptRA = false;
|
||
};
|
||
})
|
||
cfg.vlan)
|
||
{
|
||
wan = {
|
||
name = "enp1s0";
|
||
DHCP = "ipv4";
|
||
networkConfig = {
|
||
IPv6AcceptRA = "yes";
|
||
};
|
||
dhcpV4Config = {
|
||
UseDNS = "no";
|
||
};
|
||
ipv6AcceptRAConfig = {
|
||
# Only use RA
|
||
DHCPv6Client = false;
|
||
UseDNS = "no";
|
||
UseGateway = false; # should not be used by default for routing (wg-he takes precendence)
|
||
};
|
||
};
|
||
physical-lan = {
|
||
name = "enp2s0";
|
||
vlan = lib.attrNames cfg.vlan;
|
||
# no autoconfiguration needed, only tagged VLAN
|
||
networkConfig = {
|
||
LinkLocalAddressing = "no";
|
||
LLDP = "no";
|
||
EmitLLDP = "no";
|
||
IPv6AcceptRA = "no";
|
||
IPv6SendRA = "no";
|
||
};
|
||
};
|
||
lan2 = {
|
||
name = "enp3s0";
|
||
bridge = [ "br-lan" ];
|
||
};
|
||
lan3 = {
|
||
name = "enp4s0";
|
||
bridge = [ "br-lan" ];
|
||
};
|
||
# extended from common config
|
||
wg-he = {
|
||
address = lib.singleton "2001:470:73b9::1";
|
||
routes = lib.singleton {
|
||
routeConfig.Gateway = "::"; # on link
|
||
};
|
||
};
|
||
}
|
||
];
|
||
};
|
||
services.resolved.enable = false;
|
||
}
|