389 lines
9.6 KiB
Nix
389 lines
9.6 KiB
Nix
{
|
|
lib,
|
|
# outputs,
|
|
# config,
|
|
# pkgs,
|
|
...
|
|
}: let
|
|
# NOTE: I could turn this into a cool NixOS module?
|
|
# TODO: review https://francis.begyn.be/blog/nixos-home-router
|
|
ip = "192.168.0.1";
|
|
cidr = "${ip}/16";
|
|
netmask = "255.255.0.0"; # see cidr
|
|
dhcp_lease_space = {
|
|
min = "192.168.0.5";
|
|
max = "192.168.0.250";
|
|
};
|
|
wan_if = "wan0";
|
|
lan_if = "lan0";
|
|
hosts = {
|
|
dragon = {
|
|
identifier = "dragon";
|
|
host = "dragon";
|
|
ip = "192.168.0.10";
|
|
};
|
|
beefcake = {
|
|
identifier = "beefcake";
|
|
host = "beefcake";
|
|
ip = "192.168.0.9";
|
|
};
|
|
};
|
|
in {
|
|
imports = [
|
|
{
|
|
# hardware
|
|
boot = {
|
|
loader = {
|
|
efi.canTouchEfiVariables = true;
|
|
systemd-boot.enable = true;
|
|
};
|
|
initrd.availableKernelModules = ["xhci_pci"];
|
|
initrd.kernelModules = [];
|
|
kernelModules = ["kvm-intel"];
|
|
extraModulePackages = [];
|
|
};
|
|
|
|
nixpkgs.hostPlatform = "x86_64-linux";
|
|
powerManagement.cpuFreqGovernor = "performance";
|
|
hardware.cpu.intel.updateMicrocode = true;
|
|
}
|
|
];
|
|
|
|
boot = {
|
|
kernel = {
|
|
sysctl = {
|
|
"net.ipv4.conf.all.forwarding" = true;
|
|
"net.ipv6.conf.all.forwarding" = true;
|
|
|
|
# TODO: may want to disable this once it's working
|
|
# "net.ipv6.conf.all.accept_ra" = 0;
|
|
# "net.ipv6.conf.all.autoconf" = 0;
|
|
# "net.ipv6.conf.all.use_tempaddr" = 0;
|
|
|
|
"net.ipv6.conf.wan0.accept_ra" = 2;
|
|
"net.ipv6.conf.wan0.autoconf" = 1;
|
|
};
|
|
};
|
|
};
|
|
|
|
# services.fail2ban.enable = true;
|
|
services.radvd = {
|
|
enable = false;
|
|
# NOTE: this config is just the default arch linux config I think and may
|
|
# need tweaking? this is what I had on the arch linux router, though :shrug:
|
|
# config = ''
|
|
# interface lo
|
|
# {
|
|
# AdvSendAdvert on;
|
|
# MinRtrAdvInterval 3;
|
|
# MaxRtrAdvInterval 10;
|
|
# AdvDefaultPreference low;
|
|
# AdvHomeAgentFlag off;
|
|
|
|
# prefix 2001:db8:1:0::/64
|
|
# {
|
|
# AdvOnLink on;
|
|
# AdvAutonomous on;
|
|
# AdvRouterAddr off;
|
|
# };
|
|
|
|
# prefix 0:0:0:1234::/64
|
|
# {
|
|
# AdvOnLink on;
|
|
# AdvAutonomous on;
|
|
# AdvRouterAddr off;
|
|
# Base6to4Interface ppp0;
|
|
# AdvPreferredLifetime 120;
|
|
# AdvValidLifetime 300;
|
|
# };
|
|
|
|
# route 2001:db0:fff::/48
|
|
# {
|
|
# AdvRoutePreference high;
|
|
# AdvRouteLifetime 3600;
|
|
# };
|
|
|
|
# RDNSS 2001:db8::1 2001:db8::2
|
|
# {
|
|
# AdvRDNSSLifetime 30;
|
|
# };
|
|
|
|
# DNSSL branch.example.com example.com
|
|
# {
|
|
# AdvDNSSLLifetime 30;
|
|
# };
|
|
# };
|
|
# '';
|
|
};
|
|
|
|
# services.resolved = {
|
|
# enable = true;
|
|
# extraConfig = ''
|
|
# [Resolve]
|
|
# DNSStubListener=no
|
|
# '';
|
|
# };
|
|
|
|
services.dnsmasq = {
|
|
enable = false;
|
|
settings = {
|
|
# server endpoints
|
|
listen-address = "::1,127.0.0.1,${ip}";
|
|
port = "53";
|
|
|
|
# DNS cache entries
|
|
cache-size = "10000";
|
|
|
|
# local domain entries
|
|
local = "/lan/";
|
|
domain = "lan";
|
|
expand-hosts = true;
|
|
|
|
dhcp-authoritative = true;
|
|
|
|
conf-file = "/usr/share/dnsmasq/trust-anchors.conf";
|
|
dnssec = true;
|
|
|
|
except-interface = "${wan_if}";
|
|
interface = "${lan_if}";
|
|
|
|
enable-ra = true;
|
|
|
|
# dhcp-option = "121,${cidr},${ip}";
|
|
|
|
dhcp-range = [
|
|
"lan,${dhcp_lease_space.min},${dhcp_lease_space.max},${netmask},10m"
|
|
"tag:${lan_if},::1,constructor:${lan_if},ra-names,12h"
|
|
];
|
|
|
|
dhcp-host = [
|
|
"${hosts.dragon.host},${hosts.dragon.ip},12h"
|
|
"${hosts.beefcake.host},${hosts.beefcake.ip},12h"
|
|
];
|
|
|
|
# may need to go in /etc/hosts (networking.extraHosts), too?
|
|
address = [
|
|
"/video.lyte.dev/192.168.0.9"
|
|
"/git.lyte.dev/192.168.0.9"
|
|
"/bw.lyte.dev/192.168.0.9"
|
|
"/files.lyte.dev/192.168.0.9"
|
|
"/vpn.h.lyte.dev/192.168.0.9"
|
|
"/.h.lyte.dev/192.168.0.9"
|
|
];
|
|
|
|
server = [
|
|
"${ip}"
|
|
"8.8.8.8"
|
|
"8.8.4.4"
|
|
"1.1.1.1"
|
|
"1.0.0.1"
|
|
];
|
|
};
|
|
};
|
|
|
|
networking = {
|
|
hostName = "router";
|
|
domain = "h.lyte.dev";
|
|
useDHCP = false;
|
|
|
|
# useDHCP = true;
|
|
# nat.enable = true; # TODO: maybe replace some of the nftables stuff with this module?
|
|
|
|
extraHosts = ''
|
|
127.0.0.1 localhost
|
|
${ip} router.h.lyte.dev router
|
|
|
|
::1 localhost ip6-localhost ip6-loopback
|
|
ff02::1 ip6-allnodes
|
|
ff02::2 ip6-allrouters
|
|
'';
|
|
|
|
firewall.enable = false;
|
|
firewall.allowedTCPPorts = [
|
|
2201
|
|
22
|
|
];
|
|
|
|
nftables = {
|
|
enable = false;
|
|
flushRuleset = true;
|
|
|
|
tables = {
|
|
filter = {
|
|
family = "inet";
|
|
content = ''
|
|
chain input {
|
|
# type filter hook input priority filter; policy accept;
|
|
type filter hook input priority 0;
|
|
|
|
# anything from loopback interface
|
|
iifname "lo" accept
|
|
|
|
# accept traffic we originated
|
|
ct state { established, related } counter accept
|
|
ct state invalid counter drop
|
|
|
|
# ICMP
|
|
ip6 nexthdr icmpv6 icmpv6 type { echo-request, nd-neighbor-solicit, nd-neighbor-advert, nd-router-solicit, nd-router-advert, mld-listener-query, destination-unreachable, packet-too-big, time-exceeded, parameter-problem } counter accept
|
|
ip protocol icmp icmp type { echo-request, destination-unreachable, router-advertisement, time-exceeded, parameter-problem } counter accept
|
|
ip protocol icmpv6 counter accept
|
|
ip protocol icmp counter accept
|
|
meta l4proto ipv6-icmp counter accept
|
|
|
|
udp dport dhcpv6-client counter accept
|
|
|
|
tcp dport { 64022, 22, 53, 67, 25565 } counter accept
|
|
udp dport { 64020, 22, 53, 67 } counter accept
|
|
|
|
# iifname "iot" ip saddr $iot-ip tcp dport { llmnr } counter accept
|
|
# iifname "iot" ip saddr $iot-ip udp dport { mdns, llmnr } counter accept
|
|
iifname "${lan_if}" tcp dport { llmnr } counter accept
|
|
iifname "${lan_if}" udp dport { mdns, llmnr } counter accept
|
|
|
|
counter drop
|
|
}
|
|
|
|
# allow all outgoing
|
|
chain output {
|
|
type filter hook output priority 0;
|
|
accept
|
|
}
|
|
|
|
chain forward {
|
|
type filter hook forward priority 0;
|
|
accept
|
|
}
|
|
'';
|
|
};
|
|
|
|
nat = {
|
|
family = "ip";
|
|
content = ''
|
|
set masq_saddr {
|
|
type ipv4_addr
|
|
flags interval
|
|
elements = { ${cidr} }
|
|
}
|
|
|
|
map map_port_ipport {
|
|
type inet_proto . inet_service : ipv4_addr . inet_service
|
|
}
|
|
|
|
chain prerouting {
|
|
iifname ${lan_if} accept
|
|
|
|
type nat hook prerouting priority dstnat + 1; policy accept;
|
|
fib daddr type local dnat ip addr . port to meta l4proto . th dport map @map_port_ipport
|
|
|
|
iifname ${wan_if} tcp dport { 22, 80, 443, 25565, 64022 } dnat to ${hosts.beefcake.ip}
|
|
iifname ${wan_if} udp dport { 64020 } dnat to ${hosts.beefcake.ip}
|
|
|
|
# iifname ${wan_if} tcp dport { 25565 } dnat to 192.168.0.244
|
|
# iifname ${wan_if} udp dport { 25565 } dnat to 192.168.0.244
|
|
|
|
# router
|
|
iifname ${wan_if} tcp dport { 2201 } dnat to ${ip}
|
|
}
|
|
|
|
chain output {
|
|
type nat hook output priority -99; policy accept;
|
|
ip daddr != 127.0.0.0/8 oif "lo" dnat ip addr . port to meta l4proto . th dport map @map_port_ipport
|
|
}
|
|
|
|
chain postrouting {
|
|
type nat hook postrouting priority srcnat + 1; policy accept;
|
|
oifname ${lan_if} masquerade
|
|
ip saddr @masq_saddr masquerade
|
|
}
|
|
'';
|
|
};
|
|
};
|
|
};
|
|
|
|
dhcpcd = {
|
|
enable = false;
|
|
extraConfig = ''
|
|
duid
|
|
|
|
# No way.... https://github.com/NetworkConfiguration/dhcpcd/issues/36#issuecomment-954777644
|
|
# issues caused by guests with oneplus devices
|
|
noarp
|
|
|
|
persistent
|
|
vendorclassid
|
|
|
|
option domain_name_servers, domain_name, domain_search
|
|
option classless_static_routes
|
|
option interface_mtu
|
|
option host_name
|
|
#option ntp_servers
|
|
|
|
require dhcp_server_identifier
|
|
slaac private
|
|
noipv4ll
|
|
noipv6rs
|
|
|
|
static domain_name_servers=${ip}
|
|
|
|
interface ${wan_if}
|
|
gateway
|
|
ipv6rs
|
|
iaid 1
|
|
# option rapid_commit
|
|
# ia_na 1
|
|
ia_pd 1 ${lan_if}
|
|
|
|
interface ${lan_if}
|
|
static ip_address=${cidr}
|
|
static routers=${ip}
|
|
static domain_name_servers=${ip}
|
|
'';
|
|
};
|
|
};
|
|
|
|
systemd.services.systemd-networkd-wait-online.enable = lib.mkForce false;
|
|
|
|
services.openssh.listenAddresses = [
|
|
{
|
|
addr = "0.0.0.0";
|
|
port = 2201;
|
|
}
|
|
{
|
|
addr = "[::]";
|
|
port = 2201;
|
|
}
|
|
];
|
|
|
|
systemd.network = {
|
|
enable = true;
|
|
links = {
|
|
"10-${wan_if}" = {
|
|
enable = true;
|
|
matchConfig = {
|
|
MACAddress = "00:01:2e:82:73:59";
|
|
};
|
|
linkConfig = {
|
|
Name = wan_if;
|
|
};
|
|
};
|
|
"10-${lan_if}" = {
|
|
enable = true;
|
|
matchConfig = {
|
|
MACAddress = "00:01:2e:82:73:5a";
|
|
};
|
|
linkConfig = {
|
|
Name = lan_if;
|
|
};
|
|
};
|
|
};
|
|
};
|
|
|
|
services.avahi = {
|
|
enable = true;
|
|
reflector = true;
|
|
allowInterfaces = [lan_if];
|
|
};
|
|
|
|
system.stateVersion = "24.05";
|
|
}
|