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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
|
---
install:
vm:
memory: 128M
numcpus: 2
autostart: true
disks:
primary: /dev/sda
scsi:
sda:
type: image
path: "/srv/nvme/{{ inventory_hostname }}/root.img"
interfaces:
- bridge: br-svc
- bridge: br-magenta
- bridge: br-mgmt
openwrt_arch: x86
openwrt_target: 64
openwrt_profile: generic
openwrt_output_image_suffixes:
- "{{ openwrt_profile }}-ext4-combined.img.gz"
openwrt_packages_remove:
- ppp
- ppp-mod-pppoe
- dnsmasq
- firewall
- firewall4
- odhcpd
- odhcpd-ipv6only
openwrt_packages_add:
- nftables
- kmod-nft-nat
- sqm-scripts
- rng-tools
- htop
- ip
- less
- nano
- tcpdump-mini
- iperf
- iperf3
- mtr
- usbutils
- openvpn-openssl
- kmod-wireguard
- wireguard-tools
- iptraf-ng
- prometheus-node-exporter-lua
- prometheus-node-exporter-lua-nat_traffic
- prometheus-node-exporter-lua-netstat
- prometheus-node-exporter-lua-openwrt
openwrt_mixin:
/etc/openvpn/ca.crt:
content: "{{ openvpn_ca_certificate }}"
/etc/openvpn/dhparams:
mode: "0600"
content: "{{ openvpn_dhparams }}"
/etc/openvpn/ta.key:
mode: "0600"
content: "{{ openvpn_ta_key }}"
/etc/openvpn/server.crt:
content: |
-----BEGIN CERTIFICATE-----
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
8ucdxgsmNPJk/dyj/4vqxQ==
-----END CERTIFICATE-----
/etc/openvpn/server.key:
mode: "0600"
content: "{{ vault_openvpn_key }}"
/etc/openvpn/ipp.txt:
mode: "0444"
content: |
pan,192.168.8.4
mimas,192.168.8.8
/etc/dropbear/authorized_keys:
content: "{{ ssh_keys_root | join('\n') }}\n"
/etc/htoprc:
file: "{{ global_files_dir }}/common/htoprc"
/etc/rc.d/S21nftables:
link: "../init.d/nftables"
/etc/rc.d/K89nftables:
link: "../init.d/nftables"
/etc/init.d/nftables:
mode: "0755"
content: |
#!/bin/sh /etc/rc.common
START=21
STOP=89
start() {
nft -f /etc/nftables.conf
}
stop() {
nft flush ruleset
}
/etc/nftables.conf:
content: |
flush ruleset
define nic_magenta = eth1
define ip_magenta = {{ network_zones.magenta.prefix | ansible.utils.ipaddr(network_zones.magenta.offsets[inventory_hostname]) | ansible.utils.ipaddr('address') }}
define nic_mgmt = eth2
define nic_internal = eth0
define nic_openvpn = extern0
define nic_remote = remote
define prefix_mgmt = {{ network_zones.mgmt.prefix }}
define prefix_openvpn = 192.168.8.0/24
define prefix_remote = 192.168.51.0/24
define prefix_svc = {{ network_zones.svc.prefix }}
define prefixes_internal = { {{ network_zones.svc.prefix }}, {{ network_zones.lan.prefix }} }
define prefixes_natonly = { {{ network_zones.c3voc.prefix }} }
define ip_prometheus_legacy = {{ network_zones.lan.prefix | ansible.utils.ipaddr(network_zones.lan.offsets['ch-prometheus-legacy']) | ansible.utils.ipaddr('address') }}
table inet global {
## INPUT
chain input_mgmt {
ip saddr $prefix_mgmt accept
}
chain input_internal {
ip saddr != $prefixes_internal drop
ip protocol icmp accept
ip6 nexthdr ipv6-icmp accept
tcp dport { {{ ansible_port }} } accept
}
chain input_magenta {
ip daddr != $ip_magenta drop
ip protocol icmp accept
ip6 nexthdr ipv6-icmp accept
tcp dport { {{ ansible_port }} } accept
udp dport { openvpn, 51820 } accept
}
chain input_openvpn {
ip saddr != $prefix_openvpn drop
ip protocol icmp accept
tcp dport { {{ ansible_port }} } accept
}
chain input_remote {
ip saddr != $prefix_remote drop
ip protocol icmp accept
tcp dport { {{ ansible_port }} } accept
}
chain input {
type filter hook input priority filter; policy drop;
ct state vmap { established: accept, related: accept, invalid: drop }
iifname vmap { lo: accept, $nic_mgmt: jump input_mgmt, $nic_internal: jump input_internal, $nic_magenta: jump input_magenta, $nic_openvpn: jump input_openvpn, $nic_remote: jump input_remote }
}
## FORWARD
chain forward {
type filter hook forward priority filter; policy drop;
ct state vmap { established: accept, related: accept, invalid: drop }
iif $nic_internal ip saddr $prefixes_internal oif $nic_magenta accept
iif $nic_internal ip saddr $prefixes_natonly oif $nic_magenta accept
iif $nic_internal ip saddr $prefixes_internal oifname $nic_openvpn ip daddr $prefix_openvpn accept
iifname $nic_openvpn ip saddr $prefix_openvpn oif $nic_internal ip daddr $prefixes_internal accept
iif $nic_internal ip saddr { $prefix_svc, $ip_prometheus_legacy } oifname $nic_remote ip daddr $prefix_remote accept
iifname $nic_remote ip saddr $prefix_remote oif $nic_internal ip daddr { $prefix_svc, $ip_prometheus_legacy } accept
{% for name, svc in network_services.items() %}
iif $nic_magenta oif $nic_internal ip daddr {{ svc.addr }} tcp dport { {{ svc.ports | join(', ') }} } accept comment "Service: {{ name }}"
{% endfor %}
}
chain prerouting {
type nat hook prerouting priority dstnat; policy accept;
{% for name, svc in network_services.items() %}
iif $nic_magenta ip daddr $ip_magenta tcp dport { {{ svc.ports | join(', ') }} } dnat to {{ svc.addr }} comment "Service: {{ name }}"
{% endfor %}
}
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
ip saddr $prefixes_internal oif $nic_magenta snat to $ip_magenta
ip saddr $prefixes_natonly oif $nic_magenta snat to $ip_magenta
}
}
openwrt_uci:
system:
- name: system
options:
hostname: '{{ host_name }}'
timezone: 'CET-1CEST,M3.5.0,M10.5.0/3'
ttylogin: '0'
log_size: '64'
urandom_seed: '0'
- name: timeserver 'ntp'
options:
enabled: '1'
enable_server: '1'
interface: 'mgmt'
server:
- '0.at.pool.ntp.org'
- '1.at.pool.ntp.org'
- '2.at.pool.ntp.org'
- '3.at.pool.ntp.org'
- name: rngd
options:
enabled: '1'
device: '/dev/hwrng'
dropbear:
- name: dropbear
options:
PasswordAuth: 'off'
RootPasswordAuth: 'off'
Port: '{{ ansible_port | default(22) }}'
uhttpd:
- name: uhttpd main
options:
enabled: '0'
prometheus-node-exporter-lua:
- name: prometheus-node-exporter-lua 'main'
options:
listen_interface: 'mgmt'
listen_port: '9100'
openvpn:
- name: openvpn 'extern'
options:
enabled: '1'
port: '1194'
proto: 'udp'
dev_type: 'tun'
dev: 'extern0'
server: '192.168.8.0 255.255.255.0'
client_to_client: '1'
ifconfig_pool_persist: '/etc/openvpn/ipp.txt'
push:
- 'route 192.168.28.0 255.255.255.0'
- 'route 192.168.32.0 255.255.255.0'
tls_auth: '/etc/openvpn/ta.key 0'
ca: '/etc/openvpn/ca.crt'
cert: '/etc/openvpn/server.crt'
key: '/etc/openvpn/server.key'
dh: '/etc/openvpn/dhparams'
tls_cipher: 'DHE-RSA-AES256-SHA'
cipher: 'AES-256-CBC'
auth: 'SHA256'
comp_lzo: 'yes'
keepalive: '10 120'
persist_key: '1'
persist_tun: '1'
user: 'nobody'
verb: '3'
network:
- name: globals 'globals'
options:
ula_prefix: "fc{{ '%02x:%04x:%04x' | format((255 | random(seed=inventory_hostname + '0')), (65535 | random(seed=inventory_hostname + '1')), (65535 | random(seed=inventory_hostname + '2'))) }}::/48"
- name: interface 'loopback'
options:
device: lo
proto: static
ipaddr: 127.0.0.1
netmask: 255.0.0.0
- name: interface 'svc'
options:
device: eth0
proto: static
ipaddr: "{{ network_zones.svc.prefix | ansible.utils.ipaddr(network_zones.svc.offsets[inventory_hostname]) | ansible.utils.ipaddr('address') }}"
netmask: "{{ network_zones.svc.prefix | ansible.utils.ipaddr('netmask') }}"
- name: interface 'magenta'
options:
device: eth1
proto: static
ipaddr: "{{ network_zones.magenta.prefix | ansible.utils.ipaddr(network_zones.magenta.offsets[inventory_hostname]) | ansible.utils.ipaddr('address') }}"
netmask: "{{ network_zones.magenta.prefix | ansible.utils.ipaddr('netmask') }}"
gateway: "{{ network_zones.magenta.gateway }}"
dns: "{{ network_zones.magenta.dns }}"
- name: interface 'mgmt'
options:
device: eth2
proto: static
ipaddr: "{{ network_zones.mgmt.prefix | ansible.utils.ipaddr(network_zones.mgmt.offsets[inventory_hostname]) | ansible.utils.ipaddr('address') }}"
netmask: "{{ network_zones.mgmt.prefix | ansible.utils.ipaddr('netmask') }}"
- name: route 'lan'
options:
interface: svc
target: "{{ network_zones.lan.prefix | ansible.utils.ipaddr('network') }}"
netmask: "{{ network_zones.lan.prefix | ansible.utils.ipaddr('netmask') }}"
gateway: "{{ network_zones.svc.prefix | ansible.utils.ipaddr(network_zones.svc.offsets['ch-gw-lan']) | ansible.utils.ipaddr('address') }}"
- name: route 'c3voc'
options:
interface: svc
target: "{{ network_zones.c3voc.prefix | ansible.utils.ipaddr('network') }}"
netmask: "{{ network_zones.c3voc.prefix | ansible.utils.ipaddr('netmask') }}"
gateway: "{{ network_zones.svc.prefix | ansible.utils.ipaddr(network_zones.svc.offsets['ch-gw-c3voc']) | ansible.utils.ipaddr('address') }}"
- name: interface 'remote'
options:
proto: wireguard
private_key: "{{ vault_wireguard_remote_private_key }}"
listen_port: 51820
addresses:
- "{{ network_zones.remote.prefix | ansible.utils.ipaddr(network_zones.remote.offsets[inventory_hostname]) }}"
nohostroute: 1
- name: wireguard_remote 'pan'
options:
public_key: "sd/OqiO0hktuJ3FvIBnM8RJpqG0lkN7wWJjdKbU1TSw="
# preshared_key: ""
endpoint_host: "{{ hostvars['ch-pan'].network.primary.address | ansible.utils.ipaddr('address') }}"
endpoint_port: 51820
allowed_ips:
- "{{ network_zones.remote.prefix | ansible.utils.ipaddr(network_zones.remote.offsets['ch-pan']) | ansible.utils.ipaddr('address') }}"
persistent_keepalive: 60
- name: wireguard_remote 'mimas'
options:
public_key: "ZpvJ3Myn/FSJTqsEkNB5AQaVAuTqfFFCAqLomkeZV3g="
# preshared_key: ""
endpoint_host: "{{ hostvars['ch-mimas'].external_ip }}"
endpoint_port: 51820
allowed_ips:
- "{{ network_zones.remote.prefix | ansible.utils.ipaddr(network_zones.remote.offsets['ch-mimas']) | ansible.utils.ipaddr('address') }}"
persistent_keepalive: 60
- name: wireguard_remote 'fp4'
options:
public_key: "m0CoYVrdTQirEnM86ReGJvsabnJKLM6Rph2hnVQllnU="
allowed_ips:
- "{{ network_zones.remote.prefix | ansible.utils.ipaddr(network_zones.remote.offsets['ch-equinox-fp4']) | ansible.utils.ipaddr('address') }}"
sqm:
- name: queue 'magenta'
options:
enabled: '1'
interface: 'eth1'
download: '147000'
upload: '20000'
qdisc: 'cake'
script: 'piece_of_cake.qos'
qdisc_advanced: '0'
ingress_ecn: 'ECN'
egress_ecn: 'ECN'
qdisc_really_really_advanced: '0'
itarget: 'auto'
etarget: 'auto'
linklayer: 'ethernet'
overhead: '18 mpu 64 noatm'
prometheus_scrape_endpoint: "{{ network_zones.mgmt.prefix | ansible.utils.ipaddr(network_zones.mgmt.offsets[inventory_hostname]) | ansible.utils.ipaddr('address') }}:9100"
prometheus_exporters_default:
- openwrt
|