1
1
Fork 1
mirror of https://github.com/oddlama/nix-config.git synced 2025-10-10 23:00:39 +02:00
oddlama_nix-config/hosts/ward/net.nix

338 lines
11 KiB
Nix

{
config,
globals,
lib,
...
}:
{
boot.kernel.sysctl."net.ipv4.ip_forward" = 1;
boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = 1;
networking.hostId = config.repo.secrets.local.networking.hostId;
globals.monitoring.ping.ward = {
hostv4 = lib.net.cidr.ip globals.net.home-lan.vlans.services.hosts.ward.cidrv4;
hostv6 = lib.net.cidr.ip globals.net.home-lan.vlans.services.hosts.ward.cidrv6;
network = "home-lan.vlans.services";
};
# Reflect mDNS packets between our networks
services.avahi.reflector = true;
boot.initrd.availableKernelModules = [ "8021q" ];
boot.initrd.systemd.network = {
enable = true;
netdevs."30-vlan-home" = {
netdevConfig = {
Kind = "vlan";
Name = "vlan-home";
};
vlanConfig.Id = globals.net.home-lan.vlans.home.id;
};
networks = {
"10-wan" = {
address = [ globals.net.home-wan.hosts.ward.cidrv4 ];
gateway = [ globals.net.home-wan.hosts.fritzbox.ipv4 ];
matchConfig.Name = "wan";
networkConfig.IPv6PrivacyExtensions = "yes";
linkConfig.RequiredForOnline = "routable";
};
"10-lan" = {
matchConfig.Name = "lan";
# This interface should only be used from attached vlans.
# So don't acquire a link local address and only wait for
# this interface to gain a carrier.
networkConfig.LinkLocalAddressing = "no";
linkConfig.RequiredForOnline = "carrier";
vlan = [ "vlan-home" ];
};
"30-vlan-home" = {
address = [
globals.net.home-lan.vlans.home.hosts.ward.cidrv4
globals.net.home-lan.vlans.home.hosts.ward.cidrv6
];
matchConfig.Name = "vlan-home";
networkConfig = {
IPv4Forwarding = "yes";
IPv6PrivacyExtensions = "yes";
};
linkConfig.RequiredForOnline = "routable";
};
};
};
systemd.network.netdevs = lib.flip lib.concatMapAttrs globals.net.home-lan.vlans (
vlanName: vlanCfg: {
# Add an interface for each VLAN
"30-vlan-${vlanName}" = {
netdevConfig = {
Kind = "vlan";
Name = "vlan-${vlanName}";
};
vlanConfig.Id = vlanCfg.id;
};
# Create a MACVTAP for ourselves too, so that we can communicate with
# our guests on the same interface.
"40-me-${vlanName}" = {
netdevConfig = {
Name = "me-${vlanName}";
Kind = "macvlan";
};
extraConfig = ''
[MACVLAN]
Mode=bridge
'';
};
}
);
systemd.network.networks = {
"10-lan" = {
matchConfig.Name = "lan";
# This interface should only be used from attached vlans.
# So don't acquire a link local address and only wait for
# this interface to gain a carrier.
networkConfig.LinkLocalAddressing = "no";
linkConfig.RequiredForOnline = "carrier";
vlan = map (name: "vlan-${name}") (builtins.attrNames globals.net.home-lan.vlans);
};
"10-wan" = {
#DHCP = "yes";
#dhcpV4Config.UseDNS = false;
#dhcpV6Config.UseDNS = false;
#ipv6AcceptRAConfig.UseDNS = false;
address = [ globals.net.home-wan.hosts.ward.cidrv4 ];
gateway = [ globals.net.home-wan.hosts.fritzbox.ipv4 ];
matchConfig.Name = "wan";
networkConfig.IPv6PrivacyExtensions = "yes";
# dhcpV6Config.PrefixDelegationHint = "::/64";
# FIXME: This should not be needed, but for some reason part of networkd
# isn't seeing the RAs and not triggering DHCPv6. Even though some other
# part of networkd is properly seeing them and logging accordingly.
dhcpV6Config.WithoutRA = "solicit";
linkConfig.RequiredForOnline = "routable";
};
# Remaining macvtap interfaces should not be touched.
"90-macvtap-ignore" = {
matchConfig.Kind = "macvtap";
linkConfig.ActivationPolicy = "manual";
linkConfig.Unmanaged = "yes";
};
}
// lib.flip lib.concatMapAttrs globals.net.home-lan.vlans (
vlanName: vlanCfg: {
"30-vlan-${vlanName}" = {
matchConfig.Name = "vlan-${vlanName}";
# This interface should only be used from attached macvlans.
# So don't acquire a link local address and only wait for
# this interface to gain a carrier.
networkConfig.LinkLocalAddressing = "no";
networkConfig.MACVLAN = "me-${vlanName}";
linkConfig.RequiredForOnline = "carrier";
};
"40-me-${vlanName}" = {
address = [
vlanCfg.hosts.ward.cidrv4
vlanCfg.hosts.ward.cidrv6
];
matchConfig.Name = "me-${vlanName}";
networkConfig = {
IPv4Forwarding = "yes";
IPv6PrivacyExtensions = "yes";
IPv6SendRA = true;
IPv6AcceptRA = false;
# DHCPPrefixDelegation = true;
};
# dhcpPrefixDelegationConfig.UplinkInterface = "wan";
# dhcpPrefixDelegationConfig.Token = "::ff";
# Announce a static prefix
ipv6Prefixes = [
{ Prefix = vlanCfg.cidrv6; }
];
# Delegate prefix
# dhcpPrefixDelegationConfig = {
# SubnetId = vlanCfg.id;
# };
# Provide a DNS resolver
# ipv6SendRAConfig = {
# Managed = true;
# EmitDNS = true;
# FIXME: this is not the true ipv6 of adguardhome DNS = globals.net.home-lan.vlans.services.hosts.ward-adguardhome.ipv6;
# FIXME: todo assign static additional to reservation in kea
# };
linkConfig.RequiredForOnline = "routable";
};
}
);
networking.nftables = {
firewall = {
zones = {
untrusted.interfaces = [ "wan" ];
proxy-home.interfaces = [ "proxy-home" ];
firezone.interfaces = [ "tun-firezone" ];
adguardhome.ipv4Addresses = [ globals.net.home-lan.vlans.services.hosts.ward-adguardhome.ipv4 ];
adguardhome.ipv6Addresses = [ globals.net.home-lan.vlans.services.hosts.ward-adguardhome.ipv6 ];
web-proxy.ipv4Addresses = [ globals.net.home-lan.vlans.services.hosts.ward-web-proxy.ipv4 ];
web-proxy.ipv6Addresses = [ globals.net.home-lan.vlans.services.hosts.ward-web-proxy.ipv6 ];
samba.ipv4Addresses = [ globals.net.home-lan.vlans.services.hosts.sire-samba.ipv4 ];
samba.ipv6Addresses = [ globals.net.home-lan.vlans.services.hosts.sire-samba.ipv6 ];
scanner-ads-4300n.ipv4Addresses = [
globals.net.home-lan.vlans.devices.hosts.scanner-ads-4300n.ipv4
];
scanner-ads-4300n.ipv6Addresses = [
globals.net.home-lan.vlans.devices.hosts.scanner-ads-4300n.ipv6
];
}
// lib.flip lib.concatMapAttrs globals.net.home-lan.vlans (
vlanName: _: {
"vlan-${vlanName}".interfaces = [ "me-${vlanName}" ];
}
);
rules = {
masquerade-internet = {
from = [
"vlan-services"
"vlan-home"
"vlan-devices"
"vlan-guests"
];
to = [ "untrusted" ];
# masquerade = true; NOTE: custom rule below for ip4 + ip6
late = true; # Only accept after any rejects have been processed
verdict = "accept";
};
# masquerade firezone traffic
masquerade-firezone = {
from = [ "firezone" ];
to = [ "vlan-services" ];
# masquerade = true; NOTE: custom rule below for ip4 + ip6
late = true; # Only accept after any rejects have been processed
verdict = "accept";
};
# Allow access to the AdGuardHome DNS server from any VLAN that has internet access
access-adguardhome-dns = {
from = [
"vlan-services"
"vlan-home"
"vlan-devices"
"vlan-guests"
];
to = [ "adguardhome" ];
verdict = "accept";
};
# Allow access to the web proxy from the devices VLAN
access-web-proxy = {
from = [
"vlan-devices"
];
to = [ "web-proxy" ];
allowedTCPPorts = [
80
443
];
allowedUDPPorts = [ 443 ];
verdict = "accept";
};
# Allow the scanner to access samba via SFTP
access-samba-sftp = {
from = [ "scanner-ads-4300n" ];
to = [ "samba" ];
allowedTCPPorts = [ 22 ];
};
# Allow devices in the home VLAN to talk to any of the services or home devices.
access-services = {
from = [ "vlan-home" ];
to = [
"vlan-services"
"vlan-devices"
"vlan-iot"
];
late = true;
verdict = "accept";
};
# Allow the services VLAN to talk to our wireguard server
services-to-local = {
from = [ "vlan-services" ];
to = [ "local" ];
allowedUDPPorts = [ globals.wireguard.proxy-home.port ];
};
# Forward traffic between wireguard participants
forward-proxy-home-vpn-traffic = {
from = [ "proxy-home" ];
to = [ "proxy-home" ];
verdict = "accept";
};
# forward firezone traffic
forward-incoming-firezone-traffic = {
from = [ "firezone" ];
to = [ "vlan-services" ];
verdict = "accept";
};
# FIXME: is this needed? conntrack should take care of it and we want to masquerade anyway
forward-outgoing-firezone-traffic = {
from = [ "vlan-services" ];
to = [ "firezone" ];
verdict = "accept";
};
};
};
chains.postrouting = {
masquerade-firezone = {
after = [ "hook" ];
late = true;
rules =
lib.forEach
[
"firezone"
]
(
zone:
lib.concatStringsSep " " [
"meta protocol { ip, ip6 }"
(lib.head config.networking.nftables.firewall.zones.${zone}.ingressExpression)
(lib.head config.networking.nftables.firewall.zones.vlan-services.egressExpression)
"masquerade random"
]
);
};
masquerade-internet = {
after = [ "hook" ];
late = true;
rules =
lib.forEach
[
"vlan-services"
"vlan-home"
"vlan-devices"
"vlan-guests"
]
(
zone:
lib.concatStringsSep " " [
"meta protocol { ip, ip6 }"
(lib.head config.networking.nftables.firewall.zones.${zone}.ingressExpression)
(lib.head config.networking.nftables.firewall.zones.untrusted.egressExpression)
"masquerade random"
]
);
};
};
};
globals.wireguard.proxy-home = {
openFirewall = false; # Explicitly opened only for lan
hosts.${config.node.name}.server = true;
};
}