Compare commits
4 commits
a0681ee841
...
683555e4eb
Author | SHA1 | Date | |
---|---|---|---|
|
683555e4eb | ||
|
2555b97680 | ||
|
fa0ce6b7ef | ||
|
1a6f9ffb8f |
7 changed files with 492 additions and 335 deletions
|
@ -1,326 +1,14 @@
|
||||||
{ config, pkgs, lib, ... }:
|
{ config, pkgs, lib, ... }:
|
||||||
let
|
|
||||||
inherit (lib) mkOption types;
|
|
||||||
mkVLAN = name: id: {
|
|
||||||
netdevConfig = {
|
|
||||||
Kind = "vlan";
|
|
||||||
Name = name;
|
|
||||||
};
|
|
||||||
vlanConfig.Id = id;
|
|
||||||
};
|
|
||||||
mkTunnel = kind: name: { local, remote, mtu ? 1480 }: {
|
|
||||||
netdevConfig = {
|
|
||||||
Kind = kind;
|
|
||||||
Name = name;
|
|
||||||
MTUBytes = toString mtu;
|
|
||||||
};
|
|
||||||
tunnelConfig = {
|
|
||||||
Local = local;
|
|
||||||
Remote = remote;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
vip = config.router.wan.vip;
|
|
||||||
rip = config.router.wan.rip;
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
options.router = {
|
krz-router = {
|
||||||
wan = {
|
enable = true;
|
||||||
vip = mkOption {
|
enablePrimary = true;
|
||||||
type = types.str;
|
routerId = 1;
|
||||||
description = "Highly-available virtual IP address of the router";
|
virtualRouterId = 1;
|
||||||
|
vip = "129.199.146.230";
|
||||||
|
rip = "129.199.146.231";
|
||||||
|
trunkPort.macAddress = "92:E3:9C:CE:EF:14";
|
||||||
};
|
};
|
||||||
rip = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
description = "Real IP address of the router";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
config = {
|
|
||||||
router.wan.vip = "129.199.146.230";
|
|
||||||
router.wan.rip = "129.199.146.231";
|
|
||||||
networking.firewall.allowedUDPPorts = [ 25351 ];
|
|
||||||
systemd.network.enable = true;
|
|
||||||
networking.dhcpcd.enable = false;
|
|
||||||
systemd.network.links."10-swp" = {
|
|
||||||
matchConfig.MACAddress = "92:E3:9C:CE:EF:14";
|
|
||||||
linkConfig.Name = "swp";
|
|
||||||
};
|
|
||||||
systemd.network = {
|
|
||||||
config.routeTables = {
|
|
||||||
he = 100;
|
|
||||||
mwan = 110;
|
|
||||||
};
|
|
||||||
netdevs = {
|
|
||||||
"05-admin-vpn" = {
|
|
||||||
netdevConfig = {
|
|
||||||
Kind = "wireguard";
|
|
||||||
Name = "wgadmin";
|
|
||||||
MTUBytes = "1420";
|
|
||||||
};
|
|
||||||
wireguardConfig = {
|
|
||||||
PrivateKeyFile = "/etc/secrets/wireguard/wgadmin";
|
|
||||||
ListenPort = 25351;
|
|
||||||
};
|
|
||||||
wireguardPeers = [
|
|
||||||
{
|
|
||||||
wireguardPeerConfig = {
|
|
||||||
PublicKey = "obsUPq4Y1XGbl3yPUytPKkVcSP+eECpaQX+bV+ocwXg=";
|
|
||||||
AllowedIPs = [ "fd81:fb3a:50cc::100/128" ];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
"10-tun-mwan" = mkTunnel "gre" "gre-mwan" {
|
|
||||||
remote = "80.67.167.30";
|
|
||||||
local = vip;
|
|
||||||
};
|
|
||||||
"10-tun-he" = mkTunnel "sit" "sit-he" {
|
|
||||||
remote = "216.66.84.42";
|
|
||||||
local = vip;
|
|
||||||
};
|
|
||||||
# VLANs
|
|
||||||
# 401: uplink ENS
|
|
||||||
# 3500: intranet club réseau, proxy ARP et proxy arp pvlan / 10.1.1.1/22
|
|
||||||
# 3510: mgmt club réseau (administration network) / fd81:fb3a:50cc::/64
|
|
||||||
# 3605: MWAN V6 DMZ / 2a0e:e701:1120:b00c::1/64
|
|
||||||
# 3606: MWAN V4 DMZ / 45.13.104.25/29
|
|
||||||
# 3607: Club Réseau v6 DMZ (en ASN propre)
|
|
||||||
# 3608: DN42 DMZ
|
|
||||||
# 3609: HE V6 DMZ / 2001:470:1f13:187::1/64
|
|
||||||
# 3610: Free V6 DMZ
|
|
||||||
# 3620: HE.net IPv6 /48 -> DHCP-PD /60
|
|
||||||
# 3621: MWAN DMZ /48 PD delivery / 2a0e:e701:1120::1/48
|
|
||||||
# 3622: Router VRRP link / $to_be_determined.
|
|
||||||
# "10-uplink-ens" = mkVLAN "uplink-ens" 401; dysfunctional?
|
|
||||||
"10-intranet-krz" = mkVLAN "intranet-krz" 3500;
|
|
||||||
"10-admin" = mkVLAN "admin" 3510;
|
|
||||||
"10-mwan-v6" = mkVLAN "mwan-v6" 3605;
|
|
||||||
"10-mwan-dual" = mkVLAN "mwan-dual" 3606;
|
|
||||||
"10-krz-v6" = mkVLAN "krz-v6" 3607;
|
|
||||||
"10-dn42-dmz" = mkVLAN "dn42-dmz" 3608;
|
|
||||||
"10-he-dmz" = mkVLAN "he-dmz" 3609;
|
|
||||||
"10-free-dmz" = mkVLAN "free-dmz" 3610;
|
|
||||||
"10-he-pd" = mkVLAN "he-v6-pd" 3620;
|
|
||||||
"10-mwan-pd" = mkVLAN "mwan-v6-pd" 3621;
|
|
||||||
"10-vrrp-router" = mkVLAN "vrrp-router" 3622;
|
|
||||||
};
|
|
||||||
networks = {
|
|
||||||
"10-admin-vpn" = {
|
|
||||||
matchConfig.Name = "wgadmin";
|
|
||||||
networkConfig = {
|
|
||||||
Description = "VPN d'administration système de l'infrastructure";
|
|
||||||
Address = [ "fd81:fb3a:50cc::1/64" ];
|
|
||||||
# Give access to the rest of the network.
|
|
||||||
IPForward = "ipv6";
|
|
||||||
ConfigureWithoutCarrier = true;
|
|
||||||
};
|
|
||||||
linkConfig.RequiredForOnline = "routable";
|
|
||||||
};
|
|
||||||
"15-admin-vlan" = {
|
|
||||||
matchConfig.Name = "admin";
|
|
||||||
networkConfig = {
|
|
||||||
Description = "VLAN d'administration système de l'infrastructure";
|
|
||||||
Address = [ "fd81:fb3a:50cc:1::1/48" ];
|
|
||||||
# Give access to the rest of the network.
|
|
||||||
IPForward = "ipv6";
|
|
||||||
IPv6ProxyNDP = true;
|
|
||||||
ConfigureWithoutCarrier = true;
|
|
||||||
};
|
|
||||||
linkConfig.RequiredForOnline = "routable";
|
|
||||||
};
|
|
||||||
"20-tun-mwan" = {
|
|
||||||
matchConfig.Name = "gre-mwan";
|
|
||||||
networkConfig = {
|
|
||||||
Description = "Tunnel de livraison GRE IPv4/IPv6 de MilkyWAN";
|
|
||||||
Address = [ "10.1.1.50/30" "2a0b:cbc0:1::216/126" ];
|
|
||||||
ConfigureWithoutCarrier = true;
|
|
||||||
};
|
|
||||||
routes = [
|
|
||||||
{
|
|
||||||
routeConfig = {
|
|
||||||
Gateway = "10.1.1.49";
|
|
||||||
Table = "mwan";
|
|
||||||
Scope = "global";
|
|
||||||
# FIXME(raito): Has no effect? Upstream bug?
|
|
||||||
Source = "45.13.104.25/29";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
{
|
|
||||||
routeConfig = {
|
|
||||||
Destination = "::/0";
|
|
||||||
Gateway = "2a0b:cbc0:1::215";
|
|
||||||
Table = "mwan";
|
|
||||||
Scope = "global";
|
|
||||||
Source = "2a0e:e701:1120::/48";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
routingPolicyRules = [
|
|
||||||
{
|
|
||||||
routingPolicyRuleConfig = {
|
|
||||||
From = "2a0e:e701:1120::/48";
|
|
||||||
Table = "mwan";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
{
|
|
||||||
routingPolicyRuleConfig = {
|
|
||||||
From = "45.13.104.25/29";
|
|
||||||
Table = "mwan";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
{
|
|
||||||
routingPolicyRuleConfig = {
|
|
||||||
To = "45.13.104.25/29";
|
|
||||||
Table = "mwan";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
"20-tun-he" = {
|
|
||||||
matchConfig.Name = "sit-he";
|
|
||||||
networkConfig = {
|
|
||||||
Description = "HE.NET IPv6 Tunnel (owned by gdd)";
|
|
||||||
Address = [ "2001:470:1f12:187::2/64" ];
|
|
||||||
ConfigureWithoutCarrier = true;
|
|
||||||
};
|
|
||||||
routes = [
|
|
||||||
{
|
|
||||||
routeConfig = {
|
|
||||||
Destination = "::/0";
|
|
||||||
Table = "he";
|
|
||||||
Scope = "global";
|
|
||||||
Source = "2001:470:1f13::/48";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
routingPolicyRules = [
|
|
||||||
{
|
|
||||||
routingPolicyRuleConfig = {
|
|
||||||
From = "2001:470:1f13::/48";
|
|
||||||
Table = "he";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
"10-swp" = {
|
|
||||||
matchConfig.Name = "swp";
|
|
||||||
networkConfig = {
|
|
||||||
Description = "VLAN-aware switch port";
|
|
||||||
Address = [ "${rip}/24" ];
|
|
||||||
Gateway = "129.199.146.254";
|
|
||||||
LLDP = true;
|
|
||||||
# Only to the switch we are connected to directly, e.g. the hypervisor or the switch.
|
|
||||||
EmitLLDP = "nearest-bridge";
|
|
||||||
# For VRRP.
|
|
||||||
KeepConfiguration = true;
|
|
||||||
};
|
|
||||||
routingPolicyRules = [
|
|
||||||
{
|
|
||||||
routingPolicyRuleConfig = {
|
|
||||||
From = "45.13.104.25/29";
|
|
||||||
Type = "prohibit";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
tunnel = [
|
|
||||||
"gre-mwan"
|
|
||||||
"sit-he"
|
|
||||||
];
|
|
||||||
vlan = [
|
|
||||||
# "intranet-krz" - we don't want to keep this.
|
|
||||||
"admin"
|
|
||||||
# FIXME: "mwan-v6" - do we want to keep this?
|
|
||||||
# We can achieve v6-only by enforcing MAC address isolation for IPv4.
|
|
||||||
"mwan-dual"
|
|
||||||
# FIXME: legacy-nat-zone.
|
|
||||||
# FIXME: "krz-v6" - not ready yet.
|
|
||||||
# FIXME: "dn42-dmz" - revive this if you want.
|
|
||||||
"he-dmz"
|
|
||||||
# FIXME: "free-dmz" - not ready yet, abandoned?
|
|
||||||
# FIXME: "he-v6-pd" - require rework
|
|
||||||
# FIXME: "mwan-v6-pd" - require rework
|
|
||||||
];
|
|
||||||
};
|
|
||||||
# TODO: SIIT/NAT64/DNS64 component to avoid IPv4 dependency.
|
|
||||||
"20-mwan-dual" = {
|
|
||||||
matchConfig.Name = "mwan-dual";
|
|
||||||
addresses = [
|
|
||||||
{
|
|
||||||
addressConfig = {
|
|
||||||
Address = "2a0e:e701:1120:b00c::1/64";
|
|
||||||
AddPrefixRoute = false;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
{
|
|
||||||
addressConfig = {
|
|
||||||
Address = "45.13.104.25/29";
|
|
||||||
AddPrefixRoute = false;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
routes = [
|
|
||||||
{
|
|
||||||
routeConfig = {
|
|
||||||
Destination = "2a0e:e701:1120:b00c::/64";
|
|
||||||
Metric = 256;
|
|
||||||
Table = "mwan";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
{
|
|
||||||
routeConfig = {
|
|
||||||
Destination = "45.13.104.25/29";
|
|
||||||
Metric = 256;
|
|
||||||
Table = "mwan";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
networkConfig = {
|
|
||||||
Description = "MilkyWAN dual stack public interface";
|
|
||||||
DHCPServer = true;
|
|
||||||
IPv6SendRA = true;
|
|
||||||
IPForward = true;
|
|
||||||
ConfigureWithoutCarrier = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
"20-he-dmz" = {
|
|
||||||
matchConfig.Name = "he-dmz";
|
|
||||||
addresses = [
|
|
||||||
{
|
|
||||||
addressConfig = {
|
|
||||||
Address = "2001:470:1f13:187::1/64";
|
|
||||||
# This will add it in the wrong table.
|
|
||||||
# TODO: add to systemd a `Table` option here.
|
|
||||||
AddPrefixRoute = false;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
routes = [
|
|
||||||
{
|
|
||||||
routeConfig = {
|
|
||||||
Destination = "2001:470:1f13:187::/64";
|
|
||||||
Metric = 256;
|
|
||||||
Table = "he";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
networkConfig = {
|
|
||||||
Description = "Hurricane Electrical's 187 /64 unfirewalled zone";
|
|
||||||
IPv6SendRA = true;
|
|
||||||
ConfigureWithoutCarrier = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# services.keepalived.enable = true;
|
|
||||||
# services.keepalived.vrrpInstances.wan = {
|
|
||||||
# interface = "swp";
|
|
||||||
# state = "MASTER";
|
|
||||||
# priority = 50;
|
|
||||||
# virtualIps = [{ addr = "129.199.146.230"; }];
|
|
||||||
# virtualRouterId = 1;
|
|
||||||
# };
|
|
||||||
|
|
||||||
|
|
||||||
# systemd.services."systemd-networkd".environment.SYSTEMD_LOG_LEVEL = "debug";
|
# systemd.services."systemd-networkd".environment.SYSTEMD_LOG_LEVEL = "debug";
|
||||||
environment.systemPackages = [ pkgs.tcpdump pkgs.wireguard-tools ];
|
environment.systemPackages = [ pkgs.tcpdump pkgs.wireguard-tools ];
|
||||||
|
@ -337,5 +25,4 @@ in
|
||||||
# settings = {
|
# settings = {
|
||||||
# };
|
# };
|
||||||
# };
|
# };
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
28
machines/router04/_configuration.nix
Normal file
28
machines/router04/_configuration.nix
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
# Edit this configuration file to define what should be installed on
|
||||||
|
# your system. Help is available in the configuration.nix(5) man page
|
||||||
|
# and in the NixOS manual (accessible by running ‘nixos-help’).
|
||||||
|
|
||||||
|
{ config, pkgs, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
imports =
|
||||||
|
[
|
||||||
|
./router.nix
|
||||||
|
];
|
||||||
|
|
||||||
|
# Use the systemd-boot EFI boot loader.
|
||||||
|
boot.loader.systemd-boot.enable = true;
|
||||||
|
boot.loader.efi.canTouchEfiVariables = true;
|
||||||
|
|
||||||
|
# Set your time zone.
|
||||||
|
# time.timeZone = "Europe/Amsterdam";
|
||||||
|
|
||||||
|
networking.hostName = "router04";
|
||||||
|
networking.domain = "internal.rz.ens.wtf";
|
||||||
|
|
||||||
|
services.getty.autologinUser = "root";
|
||||||
|
services.openssh.enable = true;
|
||||||
|
|
||||||
|
system.stateVersion = "24.05"; # Did you read the comment?
|
||||||
|
}
|
||||||
|
|
40
machines/router04/_hardware-configuration.nix
Normal file
40
machines/router04/_hardware-configuration.nix
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
# Do not modify this file! It was generated by ‘nixos-generate-config’
|
||||||
|
# and may be overwritten by future invocations. Please make changes
|
||||||
|
# to /etc/nixos/configuration.nix instead.
|
||||||
|
{ config, lib, pkgs, modulesPath, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
imports =
|
||||||
|
[ (modulesPath + "/profiles/qemu-guest.nix")
|
||||||
|
];
|
||||||
|
|
||||||
|
boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "virtio_pci" "virtio_scsi" "sd_mod" "sr_mod" ];
|
||||||
|
boot.initrd.kernelModules = [ ];
|
||||||
|
boot.kernelModules = [ ];
|
||||||
|
boot.extraModulePackages = [ ];
|
||||||
|
boot.initrd.luks.devices.c-disk = {
|
||||||
|
device = "/dev/disk/by-uuid/9c57dd15-b6e4-4496-84ca-6ffe41a9dd42";
|
||||||
|
|
||||||
|
keyFile = "/dev/zero";
|
||||||
|
keyFileSize = 1;
|
||||||
|
|
||||||
|
fallbackToPassword = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
fileSystems."/" =
|
||||||
|
{ device = "/dev/disk/by-uuid/a48770a7-87f0-4f95-9458-50f022d20472";
|
||||||
|
fsType = "ext4";
|
||||||
|
};
|
||||||
|
|
||||||
|
fileSystems."/boot" =
|
||||||
|
{ device = "/dev/disk/by-uuid/1FD5-AB3E";
|
||||||
|
fsType = "vfat";
|
||||||
|
};
|
||||||
|
|
||||||
|
swapDevices =
|
||||||
|
[ { device = "/dev/disk/by-uuid/050ed1a8-60be-47e8-9f96-146362ea5e46"; }
|
||||||
|
];
|
||||||
|
|
||||||
|
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
|
||||||
|
}
|
28
machines/router04/router.nix
Normal file
28
machines/router04/router.nix
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
{ config, pkgs, lib, ... }:
|
||||||
|
{
|
||||||
|
krz-router = {
|
||||||
|
enable = true;
|
||||||
|
enablePrimary = false;
|
||||||
|
routerId = 2;
|
||||||
|
virtualRouterId = 1;
|
||||||
|
vip = "129.199.146.230";
|
||||||
|
rip = "129.199.146.232";
|
||||||
|
trunkPort.macAddress = "92:E3:9C:CE:EF:15";
|
||||||
|
};
|
||||||
|
|
||||||
|
# systemd.services."systemd-networkd".environment.SYSTEMD_LOG_LEVEL = "debug";
|
||||||
|
environment.systemPackages = [ pkgs.tcpdump pkgs.wireguard-tools ];
|
||||||
|
|
||||||
|
# Zone based firewall
|
||||||
|
|
||||||
|
# Flow accounting in PostgreSQL.
|
||||||
|
services.postgresql = {
|
||||||
|
enable = true;
|
||||||
|
ensureUsers = [];
|
||||||
|
};
|
||||||
|
# services.ulogd = {
|
||||||
|
# enable = true;
|
||||||
|
# settings = {
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
}
|
|
@ -57,8 +57,22 @@ builtins.mapAttrs mkNode {
|
||||||
"sinavir"
|
"sinavir"
|
||||||
];
|
];
|
||||||
|
|
||||||
deployment.targetHost = "router03.internal.rz.ens.wtf";
|
deployment.targetHost = "129.199.146.231";
|
||||||
|
|
||||||
stateVersion = "24.05";
|
stateVersion = "24.05";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
router04 = {
|
||||||
|
admins = [
|
||||||
|
"gdd"
|
||||||
|
"hubrecht"
|
||||||
|
"raito"
|
||||||
|
"sinavir"
|
||||||
|
];
|
||||||
|
|
||||||
|
deployment.targetHost = "129.199.146.232";
|
||||||
|
|
||||||
|
stateVersion = "24.05";
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
imports = (lib.extra.mkImports ./. [
|
imports = (lib.extra.mkImports ./. [
|
||||||
"krz-access-control"
|
"krz-access-control"
|
||||||
"krz-ssh"
|
"krz-ssh"
|
||||||
|
"krz-router"
|
||||||
]) ++ [
|
]) ++ [
|
||||||
# TODO: Switch to global version of agenix via npins
|
# TODO: Switch to global version of agenix via npins
|
||||||
# "${sources.agenix}/modules/age.nix"
|
# "${sources.agenix}/modules/age.nix"
|
||||||
|
|
359
modules/krz-router.nix
Normal file
359
modules/krz-router.nix
Normal file
|
@ -0,0 +1,359 @@
|
||||||
|
{ config, lib, ... }:
|
||||||
|
let
|
||||||
|
inherit (lib)
|
||||||
|
mkIf mkEnableOption mkOption types;
|
||||||
|
cfg = config.krz-router;
|
||||||
|
mkVLAN = name: id: {
|
||||||
|
netdevConfig = {
|
||||||
|
Kind = "vlan";
|
||||||
|
Name = name;
|
||||||
|
};
|
||||||
|
vlanConfig.Id = id;
|
||||||
|
};
|
||||||
|
mkTunnel = kind: name: { local, remote, mtu ? 1480 }: {
|
||||||
|
netdevConfig = {
|
||||||
|
Kind = kind;
|
||||||
|
Name = name;
|
||||||
|
MTUBytes = toString mtu;
|
||||||
|
};
|
||||||
|
tunnelConfig = {
|
||||||
|
Local = local;
|
||||||
|
Remote = remote;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.krz-router = {
|
||||||
|
enable = mkEnableOption "KlubRZ router";
|
||||||
|
enablePrimary = mkEnableOption ''primary mode for this router.
|
||||||
|
This means that this router will assume the primary role by default.
|
||||||
|
Do not run on the same L2 segment the same router as primary.
|
||||||
|
'';
|
||||||
|
enableDebug = mkEnableOption "debug mode for the various subsystems";
|
||||||
|
trunkPort.macAddress = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = "MAC address of the trunk port connected to a (virtual) switch";
|
||||||
|
};
|
||||||
|
vip = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = "Highly-available virtual IP address of the router";
|
||||||
|
};
|
||||||
|
rip = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = "Real IP address of the router";
|
||||||
|
};
|
||||||
|
routerId = mkOption {
|
||||||
|
type = types.int;
|
||||||
|
description = "Router ID for computing automatic IPs";
|
||||||
|
};
|
||||||
|
virtualRouterId = mkOption {
|
||||||
|
type = types.int;
|
||||||
|
description = "Virtual router ID for VRRP";
|
||||||
|
};
|
||||||
|
virtualPriority = mkOption {
|
||||||
|
type = types.int;
|
||||||
|
description = "Virtual router priority in the election";
|
||||||
|
# As recommended per RFC.
|
||||||
|
default = if cfg.enablePrimary then 100 else 50;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
systemd.network.links."10-swp" = {
|
||||||
|
matchConfig.MACAddress = cfg.trunkPort.macAddress;
|
||||||
|
linkConfig.Name = "swp";
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.firewall.allowedUDPPorts = [ 25351 ];
|
||||||
|
systemd.network.enable = true;
|
||||||
|
networking.dhcpcd.enable = false;
|
||||||
|
systemd.network = {
|
||||||
|
config.routeTables = {
|
||||||
|
he = 100;
|
||||||
|
mwan = 110;
|
||||||
|
};
|
||||||
|
netdevs = {
|
||||||
|
"05-admin-vpn" = {
|
||||||
|
netdevConfig = {
|
||||||
|
Kind = "wireguard";
|
||||||
|
Name = "wgadmin";
|
||||||
|
MTUBytes = "1420";
|
||||||
|
};
|
||||||
|
wireguardConfig = {
|
||||||
|
PrivateKeyFile = "/etc/secrets/wireguard/wgadmin";
|
||||||
|
ListenPort = 25351;
|
||||||
|
};
|
||||||
|
wireguardPeers = [
|
||||||
|
{
|
||||||
|
wireguardPeerConfig = {
|
||||||
|
PublicKey = "obsUPq4Y1XGbl3yPUytPKkVcSP+eECpaQX+bV+ocwXg=";
|
||||||
|
AllowedIPs = [ "fd81:fb3a:50cc::100/128" ];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
"10-tun-mwan" = mkTunnel "gre" "gre-mwan" {
|
||||||
|
remote = "80.67.167.30";
|
||||||
|
local = cfg.vip;
|
||||||
|
};
|
||||||
|
"10-tun-he" = mkTunnel "sit" "sit-he" {
|
||||||
|
remote = "216.66.84.42";
|
||||||
|
local = cfg.vip;
|
||||||
|
};
|
||||||
|
# VLANs
|
||||||
|
# 401: uplink ENS
|
||||||
|
# 3500: intranet club réseau, proxy ARP et proxy arp pvlan / 10.1.1.1/22
|
||||||
|
# 3510: mgmt club réseau (administration network) / fd81:fb3a:50cc::/64
|
||||||
|
# 3605: MWAN V6 DMZ / 2a0e:e701:1120:b00c::1/64
|
||||||
|
# 3606: MWAN V4 DMZ / 45.13.104.25/29
|
||||||
|
# 3607: Club Réseau v6 DMZ (en ASN propre)
|
||||||
|
# 3608: DN42 DMZ
|
||||||
|
# 3609: HE V6 DMZ / 2001:470:1f13:187::1/64
|
||||||
|
# 3610: Free V6 DMZ
|
||||||
|
# 3620: HE.net IPv6 /48 -> DHCP-PD /60
|
||||||
|
# 3621: MWAN DMZ /48 PD delivery / 2a0e:e701:1120::1/48
|
||||||
|
# 3622: Router VRRP link / $to_be_determined.
|
||||||
|
# "10-uplink-ens" = mkVLAN "uplink-ens" 401; dysfunctional?
|
||||||
|
"10-intranet-krz" = mkVLAN "intranet-krz" 3500;
|
||||||
|
"10-admin" = mkVLAN "admin" 3510;
|
||||||
|
"10-mwan-v6" = mkVLAN "mwan-v6" 3605;
|
||||||
|
"10-mwan-dual" = mkVLAN "mwan-dual" 3606;
|
||||||
|
"10-krz-v6" = mkVLAN "krz-v6" 3607;
|
||||||
|
"10-dn42-dmz" = mkVLAN "dn42-dmz" 3608;
|
||||||
|
"10-he-dmz" = mkVLAN "he-dmz" 3609;
|
||||||
|
"10-free-dmz" = mkVLAN "free-dmz" 3610;
|
||||||
|
"10-he-pd" = mkVLAN "he-v6-pd" 3620;
|
||||||
|
"10-mwan-pd" = mkVLAN "mwan-v6-pd" 3621;
|
||||||
|
"10-vrrp-router" = mkVLAN "vrrp-router" 3622;
|
||||||
|
};
|
||||||
|
networks = {
|
||||||
|
"10-admin-vpn" = {
|
||||||
|
matchConfig.Name = "wgadmin";
|
||||||
|
networkConfig = {
|
||||||
|
Description = "VPN d'administration système de l'infrastructure";
|
||||||
|
Address = [ "fd81:fb3a:50cc::${toString cfg.routerId}/64" ];
|
||||||
|
# Give access to the rest of the network.
|
||||||
|
IPForward = "ipv6";
|
||||||
|
ConfigureWithoutCarrier = true;
|
||||||
|
};
|
||||||
|
linkConfig.RequiredForOnline = "routable";
|
||||||
|
};
|
||||||
|
"15-admin-vlan" = {
|
||||||
|
matchConfig.Name = "admin";
|
||||||
|
networkConfig = {
|
||||||
|
Description = "VLAN d'administration système de l'infrastructure";
|
||||||
|
Address = [ "fd81:fb3a:50cc:1::${toString cfg.routerId}/48" ];
|
||||||
|
# Give access to the rest of the network.
|
||||||
|
IPForward = "ipv6";
|
||||||
|
IPv6ProxyNDP = true;
|
||||||
|
ConfigureWithoutCarrier = true;
|
||||||
|
};
|
||||||
|
linkConfig.RequiredForOnline = "routable";
|
||||||
|
};
|
||||||
|
"20-tun-mwan" = {
|
||||||
|
matchConfig.Name = "gre-mwan";
|
||||||
|
networkConfig = {
|
||||||
|
Description = "Tunnel de livraison GRE IPv4/IPv6 de MilkyWAN";
|
||||||
|
Address = [ "10.1.1.50/30" "2a0b:cbc0:1::216/126" ];
|
||||||
|
ConfigureWithoutCarrier = true;
|
||||||
|
};
|
||||||
|
routes = [
|
||||||
|
{
|
||||||
|
routeConfig = {
|
||||||
|
Gateway = "10.1.1.49";
|
||||||
|
Table = "mwan";
|
||||||
|
Scope = "global";
|
||||||
|
# FIXME(raito): Has no effect? Upstream bug?
|
||||||
|
Source = "45.13.104.25/29";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
{
|
||||||
|
routeConfig = {
|
||||||
|
Destination = "::/0";
|
||||||
|
Gateway = "2a0b:cbc0:1::215";
|
||||||
|
Table = "mwan";
|
||||||
|
Scope = "global";
|
||||||
|
Source = "2a0e:e701:1120::/48";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
routingPolicyRules = [
|
||||||
|
{
|
||||||
|
routingPolicyRuleConfig = {
|
||||||
|
From = "2a0e:e701:1120::/48";
|
||||||
|
Table = "mwan";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
{
|
||||||
|
routingPolicyRuleConfig = {
|
||||||
|
From = "45.13.104.25/29";
|
||||||
|
Table = "mwan";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
{
|
||||||
|
routingPolicyRuleConfig = {
|
||||||
|
To = "45.13.104.25/29";
|
||||||
|
Table = "mwan";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
"20-tun-he" = {
|
||||||
|
matchConfig.Name = "sit-he";
|
||||||
|
networkConfig = {
|
||||||
|
Description = "HE.NET IPv6 Tunnel (owned by gdd)";
|
||||||
|
Address = [ "2001:470:1f12:187::2/64" ];
|
||||||
|
ConfigureWithoutCarrier = true;
|
||||||
|
};
|
||||||
|
routes = [
|
||||||
|
{
|
||||||
|
routeConfig = {
|
||||||
|
Destination = "::/0";
|
||||||
|
Table = "he";
|
||||||
|
Scope = "global";
|
||||||
|
Source = "2001:470:1f13::/48";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
routingPolicyRules = [
|
||||||
|
{
|
||||||
|
routingPolicyRuleConfig = {
|
||||||
|
From = "2001:470:1f13::/48";
|
||||||
|
Table = "he";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
"10-swp" = {
|
||||||
|
matchConfig.Name = "swp";
|
||||||
|
networkConfig = {
|
||||||
|
Description = "VLAN-aware switch port";
|
||||||
|
Address = [ "${cfg.rip}/24" ];
|
||||||
|
Gateway = "129.199.146.254";
|
||||||
|
LLDP = true;
|
||||||
|
# Only to the switch we are connected to directly, e.g. the hypervisor or the switch.
|
||||||
|
EmitLLDP = "nearest-bridge";
|
||||||
|
# For VRRP.
|
||||||
|
KeepConfiguration = true;
|
||||||
|
};
|
||||||
|
routingPolicyRules = [
|
||||||
|
{
|
||||||
|
routingPolicyRuleConfig = {
|
||||||
|
From = "45.13.104.25/29";
|
||||||
|
Type = "prohibit";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
tunnel = [
|
||||||
|
"gre-mwan"
|
||||||
|
"sit-he"
|
||||||
|
];
|
||||||
|
vlan = [
|
||||||
|
# "intranet-krz" - we don't want to keep this.
|
||||||
|
"admin"
|
||||||
|
# FIXME: "mwan-v6" - do we want to keep this?
|
||||||
|
# We can achieve v6-only by enforcing MAC address isolation for IPv4.
|
||||||
|
"mwan-dual"
|
||||||
|
# FIXME: legacy-nat-zone.
|
||||||
|
# FIXME: "krz-v6" - not ready yet.
|
||||||
|
# FIXME: "dn42-dmz" - revive this if you want.
|
||||||
|
"he-dmz"
|
||||||
|
# FIXME: "free-dmz" - not ready yet, abandoned?
|
||||||
|
# FIXME: "he-v6-pd" - require rework
|
||||||
|
# FIXME: "mwan-v6-pd" - require rework
|
||||||
|
"vrrp-router"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
# TODO: SIIT/NAT64/DNS64 component to avoid IPv4 dependency.
|
||||||
|
"20-mwan-dual" = {
|
||||||
|
matchConfig.Name = "mwan-dual";
|
||||||
|
addresses = [
|
||||||
|
{
|
||||||
|
addressConfig = {
|
||||||
|
Address = "2a0e:e701:1120:b00c::1/64";
|
||||||
|
AddPrefixRoute = false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
{
|
||||||
|
addressConfig = {
|
||||||
|
Address = "45.13.104.25/29";
|
||||||
|
AddPrefixRoute = false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
routes = [
|
||||||
|
{
|
||||||
|
routeConfig = {
|
||||||
|
Destination = "2a0e:e701:1120:b00c::/64";
|
||||||
|
Metric = 256;
|
||||||
|
Table = "mwan";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
{
|
||||||
|
routeConfig = {
|
||||||
|
Destination = "45.13.104.25/29";
|
||||||
|
Metric = 256;
|
||||||
|
Table = "mwan";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
networkConfig = {
|
||||||
|
Description = "MilkyWAN dual stack public interface";
|
||||||
|
DHCPServer = true;
|
||||||
|
IPv6SendRA = true;
|
||||||
|
IPForward = true;
|
||||||
|
ConfigureWithoutCarrier = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
"20-he-dmz" = {
|
||||||
|
matchConfig.Name = "he-dmz";
|
||||||
|
addresses = [
|
||||||
|
{
|
||||||
|
addressConfig = {
|
||||||
|
Address = "2001:470:1f13:187::1/64";
|
||||||
|
# This will add it in the wrong table.
|
||||||
|
# TODO: add to systemd a `Table` option here.
|
||||||
|
AddPrefixRoute = false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
routes = [
|
||||||
|
{
|
||||||
|
routeConfig = {
|
||||||
|
Destination = "2001:470:1f13:187::/64";
|
||||||
|
Metric = 256;
|
||||||
|
Table = "he";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
networkConfig = {
|
||||||
|
Description = "Hurricane Electrical's 187 /64 unfirewalled zone";
|
||||||
|
IPv6SendRA = true;
|
||||||
|
ConfigureWithoutCarrier = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
"20-vrrp-router" = {
|
||||||
|
matchConfig.Name = "vrrp-router";
|
||||||
|
networkConfig = {
|
||||||
|
Description = "VRRP router health network";
|
||||||
|
Address = [ "10.0.0.${toString cfg.routerId}/24" ];
|
||||||
|
KeepConfiguration = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services.keepalived = {
|
||||||
|
enable = true;
|
||||||
|
vrrpInstances.wan = {
|
||||||
|
interface = "vrrp-router";
|
||||||
|
state = if cfg.enablePrimary then "MASTER" else "BACKUP";
|
||||||
|
# We want to start in a stable state.
|
||||||
|
priority = cfg.virtualPriority;
|
||||||
|
virtualIps = [{ addr = "${cfg.vip}/24"; dev = "swp"; scope = "global"; }];
|
||||||
|
inherit (cfg) virtualRouterId;
|
||||||
|
noPreempt = !cfg.enablePrimary;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in a new issue