diff --git a/inventories/chaosknoten/host_vars/router.yaml b/inventories/chaosknoten/host_vars/router.yaml new file mode 100644 index 0000000..134d29f --- /dev/null +++ b/inventories/chaosknoten/host_vars/router.yaml @@ -0,0 +1,2 @@ +systemd_networkd__config_dir: 'resources/chaosknoten/router/systemd_networkd/' +nftables__config: "{{ lookup('ansible.builtin.file', 'resources/chaosknoten/router/nftables/nftables.conf') }}" diff --git a/inventories/chaosknoten/hosts.yaml b/inventories/chaosknoten/hosts.yaml index cae283d..1d033de 100644 --- a/inventories/chaosknoten/hosts.yaml +++ b/inventories/chaosknoten/hosts.yaml @@ -55,6 +55,9 @@ all: public-reverse-proxy: ansible_host: public-reverse-proxy.hamburg.ccc.de ansible_user: chaos + router: + ansible_host: router.hamburg.ccc.de + ansible_user: chaos wiki: ansible_host: wiki-intern.hamburg.ccc.de ansible_user: chaos @@ -81,9 +84,16 @@ base_config_hosts: pad: pretalx: public-reverse-proxy: + router: tickets: wiki: zammad: +systemd_networkd_hosts: + hosts: + router: +nftables_hosts: + hosts: + router: docker_compose_hosts: hosts: ccchoir: @@ -161,6 +171,7 @@ infrastructure_authorized_keys_hosts: pad: pretalx: public-reverse-proxy: + router: wiki: zammad: wiki_hosts: diff --git a/playbooks/deploy.yaml b/playbooks/deploy.yaml index d7dcdac..d971cf4 100644 --- a/playbooks/deploy.yaml +++ b/playbooks/deploy.yaml @@ -4,6 +4,16 @@ roles: - base_config +- name: Ensure systemd-networkd config deployment on systemd_networkd_hosts + hosts: systemd_networkd_hosts + roles: + - systemd_networkd + +- name: Ensure nftables deployment on nftables_hosts + hosts: nftables_hosts + roles: + - nftables + - name: Ensure deployment of infrastructure authorized keys hosts: infrastructure_authorized_keys_hosts roles: diff --git a/resources/chaosknoten/router/nftables/nftables.conf b/resources/chaosknoten/router/nftables/nftables.conf new file mode 100644 index 0000000..8d30852 --- /dev/null +++ b/resources/chaosknoten/router/nftables/nftables.conf @@ -0,0 +1,84 @@ +#!/usr/sbin/nft -f + +## Variables + +# Interfaces +define if_net1_v4_wan = "net1" +define if_net2_v6_wan = "net2" +define if_net0_2_v4_nat = "net0.2" +define if_net0_3_ci_runner = "net0.3" +define if_net0_4_v4_nat_legacy = "net0.4" +define if_net0_5_public = "net0.5" + +# Interface Groups +define wan_ifs = { $if_net1_v4_wan, + $if_net2_v6_wan } +define lan_ifs = { $if_net0_2_v4_nat, + $if_net0_3_ci_runner, + $if_net0_4_v4_nat_legacy, + $if_net0_5_public } +define v4_exposed_ifs = { $if_net0_5_public } +define v6_exposed_ifs = { $if_net0_2_v4_nat, + $if_net0_4_v4_nat_legacy, + $if_net0_5_public } + + +## Rules + +table inet reverse-path-forwarding { + chain rpf-filter { + type filter hook prerouting priority mangle + 10; policy drop; + + # Only allow packets if their source address is routed via their incoming interface. + # https://github.com/NixOS/nixpkgs/blob/d9d87c51960050e89c79e4025082ed965e770d68/nixos/modules/services/networking/firewall-nftables.nix#L100 + fib saddr . mark . iif oif exists accept + } +} + +table inet host { + chain input { + type filter hook input priority filter; policy drop; + + iifname "lo" accept comment "allow loopback" + + ct state invalid drop + ct state established,related accept + + ip protocol icmp accept + ip6 nexthdr icmpv6 accept + + # Allow SSH access. + tcp dport 22 accept comment "allow ssh access" + + # Allow DHCP server access. + iifname $if_net0_3_ci_runner udp dport 67 accept comment "allow dhcp server access" + } +} + +table ip v4nat { + chain prerouting { + type nat hook prerouting priority dstnat; policy accept; + } + + chain postrouting { + type nat hook postrouting priority srcnat; policy accept; + + oifname $if_net1_v4_wan masquerade + } +} + +table inet forward { + chain forward { + type filter hook forward priority filter; policy drop; + + ct state invalid drop + ct state established,related accept + + # Allow internet access. + iifname $lan_ifs oifname $wan_ifs accept comment "allow internet access" + + # Allow access to exposed networks from internet. + meta nfproto ipv4 oifname $v4_exposed_ifs accept comment "allow v4 exposed network access" + meta nfproto ipv6 oifname $v6_exposed_ifs accept comment "allow v6 exposed network access" + } +} diff --git a/resources/chaosknoten/router/systemd_networkd/00-net0.link b/resources/chaosknoten/router/systemd_networkd/00-net0.link new file mode 100644 index 0000000..0c55d13 --- /dev/null +++ b/resources/chaosknoten/router/systemd_networkd/00-net0.link @@ -0,0 +1,6 @@ +[Match] +MACAddress=BC:24:11:54:11:15 +Type=ether + +[Link] +Name=net0 diff --git a/resources/chaosknoten/router/systemd_networkd/00-net1.link b/resources/chaosknoten/router/systemd_networkd/00-net1.link new file mode 100644 index 0000000..9489f17 --- /dev/null +++ b/resources/chaosknoten/router/systemd_networkd/00-net1.link @@ -0,0 +1,7 @@ +[Match] +# Stolen from turing to make 212.12.48.122 work. +MACAddress=0E:A4:E3:97:16:92 +Type=ether + +[Link] +Name=net1 diff --git a/resources/chaosknoten/router/systemd_networkd/00-net2.link b/resources/chaosknoten/router/systemd_networkd/00-net2.link new file mode 100644 index 0000000..2a56f72 --- /dev/null +++ b/resources/chaosknoten/router/systemd_networkd/00-net2.link @@ -0,0 +1,6 @@ +[Match] +MACAddress=BC:24:11:AE:C7:04 +Type=ether + +[Link] +Name=net2 diff --git a/resources/chaosknoten/router/systemd_networkd/10-net0.2-v4_nat.netdev b/resources/chaosknoten/router/systemd_networkd/10-net0.2-v4_nat.netdev new file mode 100644 index 0000000..a46afb4 --- /dev/null +++ b/resources/chaosknoten/router/systemd_networkd/10-net0.2-v4_nat.netdev @@ -0,0 +1,7 @@ +[NetDev] +Name=net0.2 +Kind=vlan + +[VLAN] +Id=2 + diff --git a/resources/chaosknoten/router/systemd_networkd/10-net0.3-ci_runner.netdev b/resources/chaosknoten/router/systemd_networkd/10-net0.3-ci_runner.netdev new file mode 100644 index 0000000..0cd60db --- /dev/null +++ b/resources/chaosknoten/router/systemd_networkd/10-net0.3-ci_runner.netdev @@ -0,0 +1,7 @@ +[NetDev] +Name=net0.3 +Kind=vlan + +[VLAN] +Id=3 + diff --git a/resources/chaosknoten/router/systemd_networkd/10-net0.4-v4_nat_legacy.netdev b/resources/chaosknoten/router/systemd_networkd/10-net0.4-v4_nat_legacy.netdev new file mode 100644 index 0000000..5cb68ed --- /dev/null +++ b/resources/chaosknoten/router/systemd_networkd/10-net0.4-v4_nat_legacy.netdev @@ -0,0 +1,6 @@ +[NetDev] +Name=net0.4 +Kind=vlan + +[VLAN] +Id=4 diff --git a/resources/chaosknoten/router/systemd_networkd/10-net0.5-public.netdev b/resources/chaosknoten/router/systemd_networkd/10-net0.5-public.netdev new file mode 100644 index 0000000..be3c9d9 --- /dev/null +++ b/resources/chaosknoten/router/systemd_networkd/10-net0.5-public.netdev @@ -0,0 +1,6 @@ +[NetDev] +Name=net0.5 +Kind=vlan + +[VLAN] +Id=5 diff --git a/resources/chaosknoten/router/systemd_networkd/20-net0.network b/resources/chaosknoten/router/systemd_networkd/20-net0.network new file mode 100644 index 0000000..59897cf --- /dev/null +++ b/resources/chaosknoten/router/systemd_networkd/20-net0.network @@ -0,0 +1,13 @@ +[Match] +Name=net0 + +[Link] +RequiredForOnline=no + +[Network] +VLAN=net0.2 +VLAN=net0.3 +VLAN=net0.4 +VLAN=net0.5 + +LinkLocalAddressing=no diff --git a/resources/chaosknoten/router/systemd_networkd/20-net1.network b/resources/chaosknoten/router/systemd_networkd/20-net1.network new file mode 100644 index 0000000..5789ef6 --- /dev/null +++ b/resources/chaosknoten/router/systemd_networkd/20-net1.network @@ -0,0 +1,15 @@ +[Match] +Name=net1 + +[Network] +DNS=212.12.50.158 +IPForward=ipv4 +IPv6AcceptRA=no +# v4 taken from turing for routing public v4 range and turing-compat for v4-NAT-legacy network. +# Also just the v4 for other purposes as well. +Address=212.12.48.122/24 +Address=212.12.48.123/24 +# v6 for turing-compat for v4-NAT-legacy network routed v6. +Address=2a00:14b0:4200:3000:122::1 +Gateway=212.12.48.55 +Gateway=2a00:14b0:4200:3000::1 diff --git a/resources/chaosknoten/router/systemd_networkd/20-net2.network b/resources/chaosknoten/router/systemd_networkd/20-net2.network new file mode 100644 index 0000000..b3f497d --- /dev/null +++ b/resources/chaosknoten/router/systemd_networkd/20-net2.network @@ -0,0 +1,14 @@ +[Match] +Name=net2 + +[Network] +#DNS=212.12.50.158 +IPForward=ipv6 +IPv6AcceptRA=no + +[Address] +Address=2a00:14b0:4200:3500::130:2/112 + +[Route] +Gateway=2a00:14b0:4200:3500::130:1 + diff --git a/resources/chaosknoten/router/systemd_networkd/21-net0.2-v4_nat.network b/resources/chaosknoten/router/systemd_networkd/21-net0.2-v4_nat.network new file mode 100644 index 0000000..c7fd9a7 --- /dev/null +++ b/resources/chaosknoten/router/systemd_networkd/21-net0.2-v4_nat.network @@ -0,0 +1,23 @@ +[Match] +Name=net0.2 +Type=vlan + +[Link] +RequiredForOnline=no + +[Network] +Description=v4-NAT + +# Masquerading done in nftables (nftables.conf). +IPv6SendRA=yes + +[Address] +Address=10.32.2.1/24 + +[IPv6SendRA] +UplinkInterface=net2 + +[IPv6Prefix] +Prefix=2a00:14b0:42:102::/64 +Assign=true +Token=static:::1 diff --git a/resources/chaosknoten/router/systemd_networkd/21-net0.3-ci_runners.network b/resources/chaosknoten/router/systemd_networkd/21-net0.3-ci_runners.network new file mode 100644 index 0000000..9caca86 --- /dev/null +++ b/resources/chaosknoten/router/systemd_networkd/21-net0.3-ci_runners.network @@ -0,0 +1,29 @@ +[Match] +Name=net0.3 +Type=vlan + +[Link] +RequiredForOnline=no + +[Network] +Description=ci-runners + +# Masquerading done in nftables (nftables.conf). +IPv6SendRA=yes + +DHCPServer=true + +[DHCPServer] +PoolOffset=100 +PoolSize=150 + +[Address] +Address=10.32.3.1/24 + +[IPv6SendRA] +UplinkInterface=net2 + +[IPv6Prefix] +Prefix=2a00:14b0:42:103::/64 +Assign=true +Token=static:::1 diff --git a/resources/chaosknoten/router/systemd_networkd/21-net0.4-v4_nat_legacy.network b/resources/chaosknoten/router/systemd_networkd/21-net0.4-v4_nat_legacy.network new file mode 100644 index 0000000..dd63a73 --- /dev/null +++ b/resources/chaosknoten/router/systemd_networkd/21-net0.4-v4_nat_legacy.network @@ -0,0 +1,23 @@ +[Match] +Name=net0.4 +Type=vlan + +[Link] +RequiredForOnline=no + +[Network] +Description=v4-NAT-legacy + +# Masquerading done in nftables (nftables.conf). +IPv6SendRA=yes + +[Address] +Address=172.31.17.129/25 + +[IPv6SendRA] +UplinkInterface=net1 + +[IPv6Prefix] +Prefix=2a00:14b0:f000:23::/64 +Assign=true +Token=static:::1 diff --git a/resources/chaosknoten/router/systemd_networkd/21-net0.5-public.network b/resources/chaosknoten/router/systemd_networkd/21-net0.5-public.network new file mode 100644 index 0000000..d49eb60 --- /dev/null +++ b/resources/chaosknoten/router/systemd_networkd/21-net0.5-public.network @@ -0,0 +1,22 @@ +[Match] +Name=net0.5 +Type=vlan + +[Link] +RequiredForOnline=no + +[Network] +Description=public + +IPv6SendRA=yes + +[Address] +Address=212.12.50.209/29 + +[IPv6SendRA] +UplinkInterface=net2 + +[IPv6Prefix] +Prefix=2a00:14b0:42:105::/64 +Assign=true +Token=static:::1 diff --git a/roles/nftables/README.md b/roles/nftables/README.md new file mode 100644 index 0000000..81d8871 --- /dev/null +++ b/roles/nftables/README.md @@ -0,0 +1,11 @@ +# Role `nftables` + +Deploys nftables. + +## Support Distributions + +Should work on Debian-based distributions. + +## Required Arguments + +- `nftables__config`: nftables configuration to deploy. diff --git a/roles/nftables/handlers/main.yaml b/roles/nftables/handlers/main.yaml new file mode 100644 index 0000000..3b72c54 --- /dev/null +++ b/roles/nftables/handlers/main.yaml @@ -0,0 +1,5 @@ +- name: Restart nftables service + ansible.builtin.systemd_service: + name: nftables + state: restarted + become: true diff --git a/roles/nftables/meta/argument_specs.yaml b/roles/nftables/meta/argument_specs.yaml new file mode 100644 index 0000000..aa56223 --- /dev/null +++ b/roles/nftables/meta/argument_specs.yaml @@ -0,0 +1,6 @@ +argument_specs: + main: + options: + nftables__config: + type: str + required: true diff --git a/roles/nftables/tasks/main.yaml b/roles/nftables/tasks/main.yaml new file mode 100644 index 0000000..46ea18d --- /dev/null +++ b/roles/nftables/tasks/main.yaml @@ -0,0 +1,15 @@ +- name: ensure nftables is installed + ansible.builtin.apt: + name: nftables + state: present + become: true + +- name: deploy nftables configuration + ansible.builtin.copy: + content: "{{ nftables__config }}" + dest: "/etc/nftables.conf" + mode: "0644" + owner: root + group: root + become: true + notify: Restart nftables service diff --git a/roles/systemd_networkd/README.md b/roles/systemd_networkd/README.md new file mode 100644 index 0000000..3297c47 --- /dev/null +++ b/roles/systemd_networkd/README.md @@ -0,0 +1,11 @@ +# Role `systemd_networkd` + +Deploys the given systemd-networkd configuration files. + +## Support Distributions + +Should work on Debian-based distributions. + +## Required Arguments + +- `systemd_networkd__config_dir`: Directory with systemd-networkd configs to deploy. diff --git a/roles/systemd_networkd/meta/argument_specs.yaml b/roles/systemd_networkd/meta/argument_specs.yaml new file mode 100644 index 0000000..81b046a --- /dev/null +++ b/roles/systemd_networkd/meta/argument_specs.yaml @@ -0,0 +1,6 @@ +argument_specs: + main: + options: + systemd_networkd__config_dir: + type: path + required: true diff --git a/roles/systemd_networkd/tasks/main.yaml b/roles/systemd_networkd/tasks/main.yaml new file mode 100644 index 0000000..f88ed14 --- /dev/null +++ b/roles/systemd_networkd/tasks/main.yaml @@ -0,0 +1,14 @@ +- name: ensure rsync is installed + ansible.builtin.apt: + name: rsync + state: present + become: true + +- name: synchronize systemd-networkd configs + ansible.posix.synchronize: + src: "{{ systemd_networkd__config_dir }}" + dest: "/etc/systemd/network" + archive: false + recursive: true + delete: true + become: true