summaryrefslogtreecommitdiff
path: root/inventory/host_vars/ch-router.yml
blob: a5bac5f3e3184eace292363bbfa076f9b203ed31 (plain) (blame)
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: '142000'
        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