diff --git a/inventories/chaosknoten/host_vars/router.yaml b/inventories/chaosknoten/host_vars/router.yaml index b181c0a..134d29f 100644 --- a/inventories/chaosknoten/host_vars/router.yaml +++ b/inventories/chaosknoten/host_vars/router.yaml @@ -1 +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 98af847..1d033de 100644 --- a/inventories/chaosknoten/hosts.yaml +++ b/inventories/chaosknoten/hosts.yaml @@ -91,6 +91,9 @@ base_config_hosts: systemd_networkd_hosts: hosts: router: +nftables_hosts: + hosts: + router: docker_compose_hosts: hosts: ccchoir: diff --git a/playbooks/deploy.yaml b/playbooks/deploy.yaml index 69648b2..d971cf4 100644 --- a/playbooks/deploy.yaml +++ b/playbooks/deploy.yaml @@ -9,6 +9,11 @@ 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..6bc6cbe --- /dev/null +++ b/resources/chaosknoten/router/nftables/nftables.conf @@ -0,0 +1,73 @@ +#!/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" + +# 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 } + + +## 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. + meta nfproto ipv6 iifname $lan_ifs oifname $if_net2_v6_wan accept comment "allow v6 internet access" + meta nfproto ipv4 iifname $lan_ifs oifname $if_net1_v4_wan accept comment "allow v4 internet access" + } +} 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 index 880dd1d..c7fd9a7 100644 --- a/resources/chaosknoten/router/systemd_networkd/21-net0.2-v4_nat.network +++ b/resources/chaosknoten/router/systemd_networkd/21-net0.2-v4_nat.network @@ -8,7 +8,7 @@ RequiredForOnline=no [Network] Description=v4-NAT -IPMasquerade=ipv4 +# Masquerading done in nftables (nftables.conf). IPv6SendRA=yes [Address] 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 index 6f73beb..9caca86 100644 --- a/resources/chaosknoten/router/systemd_networkd/21-net0.3-ci_runners.network +++ b/resources/chaosknoten/router/systemd_networkd/21-net0.3-ci_runners.network @@ -8,7 +8,7 @@ RequiredForOnline=no [Network] Description=ci-runners -IPMasquerade=ipv4 +# Masquerading done in nftables (nftables.conf). IPv6SendRA=yes DHCPServer=true 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