blob: fbf6fa65ae3d2c1a918fa70b489993c7067d7116 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
let
hostIp = "192.168.1.10";
in { config, ... }: {
networking = {
# Label lan and wan interfaces
_interfaceLabels = {
enable = true;
interfaces.lan0 = "50:9a:4c:5d:c3:7a";
interfaces.wan0 = "50:9a:4c:5d:c3:7b";
};
# Create bridged lan interface for all containers
bridges.br-lan0.interfaces = [ "lan0" ];
# Disable dhcp on router interfaces
interfaces = {
veth-router-lan.useDHCP = false;
vb-router-lan0.useDHCP = false;
};
# Configure network
defaultGateway = "10.255.255.1"; # Read explaination for veth-router-lan below
nameservers = [ "192.168.1.1" ]; # DNS will only be available from this ip address THROUGH the default gateway
# br-lan0 will be the interface used for networking on poweredge host
interfaces.br-lan0.ipv4.addresses = [{
address = hostIp;
prefixLength = 24;
}];
};
# Wireguard office tunnel secret
sops.secrets.wg0-router.sopsFile = ./resources/secrets/wg0-router.yaml;
# Router container
containers.router = {
autoStart = true;
ephemeral = true;
privateNetwork = true;
# Pass wan0 directly into container since it isn't needed elsewhere
interfaces = [ "wan0" ];
# Setup router lan0
# NOTE: Host/container communication is not possible through a hostBridge interface
extraVeths.vb-router-lan0.hostBridge = "br-lan0";
# Setup virtual host-router bridge interface.
# This is the default gateway for host/container communication since
# communication isn't possible through hostBridge interfaces.
# This is essentially equivalent to connecting the host to the
# container with a virtual ethernet cable on a separate interface.
extraVeths.veth-router-lan = {
hostAddress = "10.255.255.2";
localAddress = "10.255.255.1";
};
# Bind wg0-router secret to container
bindMounts."/run/secrets/wg0" = {
hostPath = config.sops.secrets.wg0-router.path;
isReadOnly = true;
};
config = { lib, config, ... }: {
imports = [
../../nixos/services/router
./router-hosts.nix # Contains dhcp config + static leases + overrides
];
networking = {
# Set ip addresses
enableIPv6 = false;
interfaces = {
vb-router-lan0.ipv4.addresses = [{
address = "192.168.1.1";
prefixLength = 24;
}];
wan0.useDHCP = true;
};
# Setup wireguard
wg-quick.interfaces = {
wg0.configFile = "/run/secrets/wg0";
};
# Firewall (port-forwarding) rules
firewall = {
#interfaces.wan0 = {
# allowedTCPPorts = [ 8333 ]; # bitcoin
# allowedUDPPorts = [ 51820 ]; # wg
#};
};
# Additional advanced rules
# TODO add multi NAT feature to router service (this is just a normal nat rule)
nftables = {
enable = true;
tables = {
# NAT/masquerade wg0 allowing vb-router-lan0 clients to access wg0
wg-nat = {
family = "ip";
content = ''
chain post {
type nat hook postrouting priority srcnat; policy accept;
iifname "vb-router-lan0" oifname "wg0" masquerade comment "vb-router-lan0 => wg0"
iifname "veth-router-lan" oifname "wg0" masquerade comment "veth-router-lan => wg0"
}
'';
};
};
};
};
# Setup router
services._router = {
dnsDhcpConfig.enable = true;
routing = {
enable = true;
interfaces = {
lan = [ "vb-router-lan0" "veth-router-lan" ];
wan = "wan0";
};
};
};
services.unbound._blocklists = {
enable = true;
hageziBlocklists = [ "pro" "nsfw" ];
};
system.stateVersion = "25.11";
};
};
# FIXME the following snippet will cause the router container to fail to start:
# networking.defaultGateway = {
# address = "10.255.255.1";
# interface = "veth-router-lan";
# };
# Journalctl will report:
# poweredge container router: Bring veth-router-lan up
# poweredge container router: RTNETLINK answers: File exists
# poweredge systemd: container@router.service: Control process exited, code=exited, status=2/INVALIDARGUMENT
# So the issue nixos is creating an interface with that same name.
# As a temporary workaround, the following service is deployed (after the container starts):
systemd.services.router-default-route = {
after = [ "container@router.service" ];
wants = [ "container@router.service" ];
serviceConfig.Type = "oneshot";
script = ''
/run/current-system/sw/bin/ip route replace default via 10.255.255.1 dev veth-router-lan
'';
wantedBy = [ "multi-user.target" ];
};
}
|