# SPDX-FileCopyrightText: 2023-2024 Simon Bruder # # 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) }; routingPolicyRules = lib.singleton { routingPolicyRuleConfig = { Family = "ipv6"; FirewallMark = 31092; # 0x7974 Table = 31092; # 0x7974 }; }; routes = lib.singleton { routeConfig = { Gateway = "_ipv6ra"; Table = 31092; # 0x7974 }; }; }; 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; }