From 6760d2901e17c1361d0a5db37209e982810a8b67 Mon Sep 17 00:00:00 2001 From: Timotej Lazar Date: Mon, 23 Feb 2026 10:00:50 +0100 Subject: [PATCH] Move firewall role to servers repo --- roles/firewall/files/conntrackd.conf | 2 - roles/firewall/files/sshd_config.friwall | 15 -- roles/firewall/files/update | 41 ----- roles/firewall/handlers/main.yml | 41 ----- roles/firewall/tasks/config.yml | 59 ------ roles/firewall/tasks/conntrackd.yml | 36 ---- roles/firewall/tasks/frr.yml | 48 ----- roles/firewall/tasks/main.yml | 71 -------- roles/firewall/tasks/mgmt.yml | 13 -- roles/firewall/tasks/nftables.yml | 26 --- roles/firewall/tasks/wireguard.yml | 26 --- roles/firewall/templates/conntrackd.conf.j2 | 51 ------ roles/firewall/templates/fabric.intf.j2 | 12 -- roles/firewall/templates/frr.conf.j2 | 141 --------------- roles/firewall/templates/interfaces.j2 | 9 - roles/firewall/templates/interfaces.nft.j2 | 10 -- roles/firewall/templates/mactab.j2 | 3 - roles/firewall/templates/mgmt.intf.j2 | 31 ---- roles/firewall/templates/networks.nft.j2 | 9 - roles/firewall/templates/nftables.nft.j2 | 187 -------------------- roles/firewall/templates/sysctl.conf.j2 | 16 -- roles/firewall/templates/wg.intf.j2 | 12 -- setup.yml | 5 - 23 files changed, 864 deletions(-) delete mode 100644 roles/firewall/files/conntrackd.conf delete mode 100644 roles/firewall/files/sshd_config.friwall delete mode 100644 roles/firewall/files/update delete mode 100644 roles/firewall/handlers/main.yml delete mode 100644 roles/firewall/tasks/config.yml delete mode 100644 roles/firewall/tasks/conntrackd.yml delete mode 100644 roles/firewall/tasks/frr.yml delete mode 100644 roles/firewall/tasks/main.yml delete mode 100644 roles/firewall/tasks/mgmt.yml delete mode 100644 roles/firewall/tasks/nftables.yml delete mode 100644 roles/firewall/tasks/wireguard.yml delete mode 100644 roles/firewall/templates/conntrackd.conf.j2 delete mode 100644 roles/firewall/templates/fabric.intf.j2 delete mode 100644 roles/firewall/templates/frr.conf.j2 delete mode 100644 roles/firewall/templates/interfaces.j2 delete mode 100644 roles/firewall/templates/interfaces.nft.j2 delete mode 100644 roles/firewall/templates/mactab.j2 delete mode 100644 roles/firewall/templates/mgmt.intf.j2 delete mode 100644 roles/firewall/templates/networks.nft.j2 delete mode 100644 roles/firewall/templates/nftables.nft.j2 delete mode 100644 roles/firewall/templates/sysctl.conf.j2 delete mode 100644 roles/firewall/templates/wg.intf.j2 diff --git a/roles/firewall/files/conntrackd.conf b/roles/firewall/files/conntrackd.conf deleted file mode 100644 index 0fa08d9..0000000 --- a/roles/firewall/files/conntrackd.conf +++ /dev/null @@ -1,2 +0,0 @@ -# The init script for conntrackd wants this, not sure about conntrackd itself. -net.netfilter.nf_conntrack_tcp_be_liberal = 1 diff --git a/roles/firewall/files/sshd_config.friwall b/roles/firewall/files/sshd_config.friwall deleted file mode 100644 index 6cdd411..0000000 --- a/roles/firewall/files/sshd_config.friwall +++ /dev/null @@ -1,15 +0,0 @@ -# This is used by sshd in default VRF to receive configuration updates. Lock -# down to only allow executing the update script. - -# Only allow pubkey auth. -KbdInteractiveAuthentication no -PasswordAuthentication no -PermitRootLogin prohibit-password - -# Disable what we can. -AllowTcpForwarding no -GatewayPorts no -X11Forwarding no - -# And then disable everything else. -ForceCommand /usr/local/bin/update diff --git a/roles/firewall/files/update b/roles/firewall/files/update deleted file mode 100644 index f2d5413..0000000 --- a/roles/firewall/files/update +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/sh - -set -e - -apply() { - cp -R /opt/config/etc/nftables.d /etc || return 1 - ip vrf exec mgmt nft -I /etc/nftables.d -f /etc/nftables.nft || return 2 - cp -R /opt/config/etc/wireguard /etc || return 3 - wg syncconf wg /etc/wireguard/wg.conf || return 4 -} - -cleanup() { - rm -fr /opt/config -} - -message() { - logger "${@}" - echo "${@}" -} - -# clean now and on exit -cleanup -trap cleanup EXIT - -mkdir -p /opt/config -tar xz -C /opt/config --warning=no-timestamp - -current="$(cat /opt/version 2>/dev/null || echo -1)" -next="$(cat /opt/config/version 2>/dev/null || echo -1)" -message "Updating config from v${current} to v${next}" -if [ "${next:-0}" -ne "${current:-0}" ] ; then - message "Applying config v${next}" - if apply ; then - echo "${next}" > /opt/version - message "Applied config v${next}" - else - error="$?" - message "Could not apply config v${next}, error ${error}" - exit "${error}" - fi -fi diff --git a/roles/firewall/handlers/main.yml b/roles/firewall/handlers/main.yml deleted file mode 100644 index 47d1eec..0000000 --- a/roles/firewall/handlers/main.yml +++ /dev/null @@ -1,41 +0,0 @@ -- name: enable interfaces - command: ifup --auto - when: "'handler' not in ansible_skip_tags" - -- name: reboot - reboot: - when: "'handler' not in ansible_skip_tags" - -- name: reload frr - command: /usr/lib/frr/frr-reload.py --reload /etc/frr/frr.conf - when: "'handler' not in ansible_skip_tags" - -- name: reload nftables - service: - name: nftables - state: reloaded - when: "'handler' not in ansible_skip_tags" - -- name: restart conntrackd - service: - name: conntrackd - state: restarted - when: "'handler' not in ansible_skip_tags" - -- name: restart frr - service: - name: frr - state: restarted - when: "'handler' not in ansible_skip_tags" - -- name: reload sshd.friwall - service: - name: sshd.friwall - state: reloaded - when: "'handler' not in ansible_skip_tags" - -- name: restart sshd.friwall - service: - name: sshd.friwall - state: restarted - when: "'handler' not in ansible_skip_tags" diff --git a/roles/firewall/tasks/config.yml b/roles/firewall/tasks/config.yml deleted file mode 100644 index 8a0ea1b..0000000 --- a/roles/firewall/tasks/config.yml +++ /dev/null @@ -1,59 +0,0 @@ -- name: Install packages for config updates - package: - name: tar - -- name: Limit SSH for config updates - copy: - dest: /etc/ssh/ - src: sshd_config.friwall - notify: reload sshd.friwall - -- name: Create SSH service for config updates - file: - path: /etc/init.d/sshd.friwall - src: /etc/init.d/sshd - state: link - -- name: Configure SSH service for config updates - copy: - dest: /etc/conf.d/sshd.friwall - content: | - cfgfile="/etc/ssh/sshd_config.friwall" - vrf="default" - notify: restart sshd.friwall - -- name: Enable SSH service for config updates - service: - name: sshd.friwall - enabled: yes - state: started - -- name: Install config updater - copy: - dest: /usr/local/bin/ - src: update - mode: 0700 - -- name: Get master SSH key - delegate_to: '{{ master }}' - command: "cat ~friwall/.ssh/id_ed25519.pub" - register: master_key - changed_when: false - -- name: Deploy master key on node - authorized_key: "user=root key={{ master_key.stdout }}" - -- name: Get my host SSH key - slurp: - src: /etc/ssh/ssh_host_ed25519_key.pub - register: node_key - -- name: Introduce myself to master - delegate_to: '{{ master }}' - become: yes - become_user: friwall - become_method: su - become_flags: "-s /bin/sh" # no login shell for user - known_hosts: - name: "{{ inventory_hostname }}" - key: "{{ inventory_hostname }},{{ interfaces | selectattr('name', '==', 'lo') | map(attribute='ip_addresses') | first | selectattr('role') | selectattr('role.value', '==', 'loopback') | map(attribute='address') | ipv4 | first | ipaddr('address') }} {{ node_key.content | b64decode }}" # TODO make IP retrieval less terrifying diff --git a/roles/firewall/tasks/conntrackd.yml b/roles/firewall/tasks/conntrackd.yml deleted file mode 100644 index 4412574..0000000 --- a/roles/firewall/tasks/conntrackd.yml +++ /dev/null @@ -1,36 +0,0 @@ -- name: Install conntrack-tools - package: - name: conntrack-tools - -# Ensure the module is loaded before setting sysctl values. -- name: Autoload nf_conntrack - lineinfile: - dest: /etc/modules-load.d/netfilter.conf - line: nf_conntrack - create: yes - -# Set required sysctl values. -- name: Set sysctl values for conntrackd - copy: - dest: /etc/sysctl.d/ - src: conntrackd.conf - -- name: Set up conntrackd - template: - dest: /etc/conntrackd/conntrackd.conf - src: conntrackd.conf.j2 - mode: 0644 - notify: restart conntrackd - -- name: Run conntrackd in default VRF - lineinfile: - dest: /etc/conf.d/conntrackd - line: 'vrf="default"' - regexp: '^vrf=' - notify: restart conntrackd - -- name: Enable conntrackd - service: - name: conntrackd - enabled: yes - state: started diff --git a/roles/firewall/tasks/frr.yml b/roles/firewall/tasks/frr.yml deleted file mode 100644 index d7450ec..0000000 --- a/roles/firewall/tasks/frr.yml +++ /dev/null @@ -1,48 +0,0 @@ -- name: Enable sysctl service - service: - name: sysctl - enabled: yes - runlevel: boot - state: started - -- name: Enable community package repo - lineinfile: - path: /etc/apk/repositories - regexp: '^# *(http.*/v[^/]*/community)' - line: '\1' - backrefs: yes - -- name: Install FRR - package: - name: frr,frr-pythontools - state: latest - -- name: Set datacenter defaults - lineinfile: - path: /etc/frr/daemons - regexp: '^frr_profile=' - line: 'frr_profile="datacenter"' - notify: restart frr - -- name: Enable BGP and BFD - lineinfile: - path: /etc/frr/daemons - regexp: "^{{ item }}=" - line: "{{ item }}=yes" - loop: - - bfdd - - bgpd - notify: restart frr - -- name: Enable FRR service - service: - name: frr - enabled: yes - state: started - -- name: Copy FRR config - template: - dest: /etc/frr/frr.conf - src: frr.conf.j2 - mode: 0644 - notify: reload frr diff --git a/roles/firewall/tasks/main.yml b/roles/firewall/tasks/main.yml deleted file mode 100644 index 5220db0..0000000 --- a/roles/firewall/tasks/main.yml +++ /dev/null @@ -1,71 +0,0 @@ -- name: Update package cache - package: - update_cache: yes - -- name: Install packages - package: - name: bash,bonding,iproute2 - state: latest - -- name: Tell ifupdown to also rename network interfaces - copy: - dest: /etc/network/if-pre-up.d/nameif - content: | - #!/bin/sh - nameif -s - mode: 0755 - -- name: Configure interface names - template: - dest: /etc/mactab - src: mactab.j2 - mode: 0644 - -- name: Create /etc/network/interfaces.d - file: - path: /etc/network/interfaces.d - state: directory - mode: 0755 - -- name: Set up interfaces - template: - dest: /etc/network/interfaces - src: interfaces.j2 - mode: 0644 - notify: enable interfaces - -- name: Set up management interfaces - import_tasks: mgmt.yml - -- name: Set up data interfaces - template: - dest: /etc/network/interfaces.d/fabric.intf - src: fabric.intf.j2 - mode: 0644 - notify: enable interfaces - -- name: Set up resolv.conf - template: - dest: /etc/resolv.conf - src: resolv.conf.j2 - mode: 0644 - -- name: Set up sysctls - template: - dest: /etc/sysctl.d/firewall.conf - src: sysctl.conf.j2 - -- name: Set up FRR - import_tasks: frr.yml - -- name: Set up wireguard - import_tasks: wireguard.yml - -- name: Set up nftables - import_tasks: nftables.yml - -- name: Set up conntrackd - import_tasks: conntrackd.yml - -- name: Set up configuration channel - import_tasks: config.yml diff --git a/roles/firewall/tasks/mgmt.yml b/roles/firewall/tasks/mgmt.yml deleted file mode 100644 index a737589..0000000 --- a/roles/firewall/tasks/mgmt.yml +++ /dev/null @@ -1,13 +0,0 @@ -- name: Set up management interfaces - template: - dest: /etc/network/interfaces.d/mgmt.intf - src: mgmt.intf.j2 - mode: 0644 - notify: reboot - -- name: Run SSH in management VRF - lineinfile: - path: /etc/conf.d/sshd - regexp: "#* *vrf=" - line: "vrf=\"mgmt\"" - notify: reboot diff --git a/roles/firewall/tasks/nftables.yml b/roles/firewall/tasks/nftables.yml deleted file mode 100644 index a80ec6f..0000000 --- a/roles/firewall/tasks/nftables.yml +++ /dev/null @@ -1,26 +0,0 @@ -- name: Install nftables - package: - name: nftables - -- name: Copy nftables config - template: - dest: /etc/nftables.nft - src: nftables.nft.j2 - mode: 0644 - notify: reload nftables - -- name: Copy static nftables includes - template: - dest: '/etc/nftables.d/{{ item }}' - src: '{{ item }}.j2' - mode: 0644 - loop: - - interfaces.nft - - networks.nft - notify: reload nftables - -- name: Enable nftables service - service: - name: nftables - enabled: yes - state: started diff --git a/roles/firewall/tasks/wireguard.yml b/roles/firewall/tasks/wireguard.yml deleted file mode 100644 index d49a380..0000000 --- a/roles/firewall/tasks/wireguard.yml +++ /dev/null @@ -1,26 +0,0 @@ -# All firewall nodes share one external IP for wireguard connections. -# Private key and peer configuration is the same for all nodes. Peers -# connected to each node are installed in the routing table and -# distributed into fabric. - -- name: Install wireguard tools - package: - name: wireguard-tools - -- name: Create wireguard directory - file: - path: /etc/wireguard - state: directory - -- name: Touch wireguard config - file: - path: /etc/wireguard/wg.conf - state: touch - access_time: preserve - modification_time: preserve - -- name: Add wireguard interface - template: - dest: /etc/network/interfaces.d/wg.intf - src: wg.intf.j2 - notify: enable interfaces diff --git a/roles/firewall/templates/conntrackd.conf.j2 b/roles/firewall/templates/conntrackd.conf.j2 deleted file mode 100644 index 0894070..0000000 --- a/roles/firewall/templates/conntrackd.conf.j2 +++ /dev/null @@ -1,51 +0,0 @@ -{% set fw = inventory_hostname.split('-')[1]|int -%} - -Sync { - Mode FTFW { - # Add received rules immediately so we don’t need a signal on failover. - DisableExternalCache yes - # Get all connections on startup. - StartupResync yes - } - - UDP { - Interface {{ iface_sync }} - IPv6_address fe80::{{ fw }} - IPv6_Destination_Address fe80::{{ 2 if fw == 1 else 1 }} - Port 3780 - - # Recommended by manual. - Checksum on - RcvSocketBuffer 1249280 - SndSocketBuffer 1249280 - } - - #Options { - # TCPWindowTracking Off - #} -} - -General { - UNIX { - Path /var/run/conntrackd.ctl - } - Syslog on - - # Recommended by manual. - HashLimit 524288 - NetlinkBufferSize 2097152 - NetlinkBufferSizeMaxGrowth 8388608 - - Filter From Kernelspace { - # Don’t replicate rules for traffic from/to firewall. - Address Ignore { - IPv4_address 127.0.0.1/8 - IPv6_address ::1/128 - IPv6_address fe80::/64 # link-local addresses - IPv4_address {{ wg_ip }} -{% for address in interfaces | map(attribute='ip_addresses') | flatten | sort(attribute='address') %} - IPv{{ address.family.value }}_address {{ address.address }} -{% endfor %} - } - } -} diff --git a/roles/firewall/templates/fabric.intf.j2 b/roles/firewall/templates/fabric.intf.j2 deleted file mode 100644 index d0392d5..0000000 --- a/roles/firewall/templates/fabric.intf.j2 +++ /dev/null @@ -1,12 +0,0 @@ -{% for iface in interfaces | selectattr('name', 'match', '^lan') | map(attribute='name') %} -auto {{ iface }} -iface {{ iface }} - mtu 9216 - -auto {{ iface }}.2 -iface {{ iface }}.2 - -auto {{ iface }}.4 -iface {{ iface }}.4 - -{% endfor %} diff --git a/roles/firewall/templates/frr.conf.j2 b/roles/firewall/templates/frr.conf.j2 deleted file mode 100644 index 9078004..0000000 --- a/roles/firewall/templates/frr.conf.j2 +++ /dev/null @@ -1,141 +0,0 @@ -{% set addrs = interfaces | selectattr('name', '==', 'lo') | - map(attribute='ip_addresses') | first | selectattr('role') %} -{% set loopback = addrs | selectattr('role.value', '==', 'loopback') | map(attribute='address') -%} - -frr defaults datacenter -service integrated-vtysh-config -log syslog - -# Without this frr and kernel ECMP routes sometimes get desynced when a link is -# lost and found. Maybe related to https://github.com/FRRouting/frr/issues/12239. -zebra nexthop-group keep 1 - -router-id {{ loopback | ipv4 | first | ipaddr('address') }} - -bfd - profile fast - receive-interval 150 - transmit-interval 150 - -# Default VRF has two connections to each exit, one for inside and one -# for outside networks. The efault route is received from the outside -# peers and distributed back to inside peers. Routes to office -# networks and NAT IPs are distributed to outside peers. -router bgp {{ asn.asn }} - # Allow multipathing through different ASs with equal path length. - bgp bestpath as-path multipath-relax - # NAT IPs are not on any interface so disable checking for it. - no bgp network import-check - -{% for group in ['inside', 'outside'] %} - neighbor {{ group }} peer-group - neighbor {{ group }} remote-as external - neighbor {{ group }} capability extended-nexthop -{% endfor %} - -{% for iface in interfaces | selectattr('name', 'match', '^lan') %} - neighbor {{ iface.name }}.2 interface peer-group inside - neighbor {{ iface.name }}.2 bfd profile fast - neighbor {{ iface.name }}.4 interface peer-group outside - neighbor {{ iface.name }}.4 bfd profile fast -{% endfor %} - -{% for family in ['ipv4', 'ipv6'] %} - address-family {{ family }} unicast -{% if family == 'ipv4' %} -{% for network in nat %} - network {{ network }} -{% endfor %} - -{% endif %} - redistribute connected route-map loopback - maximum-paths 16 - - neighbor outside activate - neighbor outside soft-reconfiguration inbound - neighbor outside route-map outside->default in - neighbor outside route-map default->outside out - - neighbor inside activate - neighbor inside allowas-in origin - neighbor inside default-originate - neighbor inside soft-reconfiguration inbound - neighbor inside route-map inside->default in - neighbor inside route-map default->inside out - exit-address-family - -{% endfor %} - -# Prefix lists. -ip prefix-list default permit 0.0.0.0/0 -ipv6 prefix-list default permit ::/0 - -ip prefix-list fabric permit 10.34.0.0/24 ge 32 - -{% for prefix in vrf_prefixes | rejectattr('vrf.name', '==', 'outside') - | sort(attribute='family.value') %} -{% if prefix.family.value == 4 %} -ip prefix-list office permit {{ prefix.prefix }} -{% elif prefix.family.value == 6 %} -ipv6 prefix-list office permit {{ prefix.prefix }} -{% endif %} -{% endfor %} - -{% if wg_net is defined %} -ip prefix-list vpn permit {{ wg_net | ipaddr('subnet') }} -{% endif %} -{% if wg_net6 is defined %} -ipv6 prefix-list vpn permit {{ wg_net6 | ipaddr('subnet') }} -{% endif %} - -{% for network in nat %} -ip prefix-list nat permit {{ network }} -{% endfor %} -{# TODO WG endpoint should probably be in a separate prefix-list. #} -ip prefix-list nat permit {{ wg_ip }} - -route-map loopback permit 1 - match interface lo -route-map loopback permit 2 - match interface wg - -# Get routes to offices from inside peers. -route-map inside->default permit 10 - match ip address prefix-list fabric -route-map inside->default permit 20 - match ip address prefix-list office -route-map inside->default permit 21 - match ipv6 address prefix-list office - -# Send default route and VPN network to inside peers. -route-map default->inside permit 1 - match interface lo -route-map default->inside permit 20 - match ip address prefix-list default -route-map default->inside permit 21 - match ipv6 address prefix-list default -# I don’t think these /need/ to be announced separately since we are sending the default route anyway. -#route-map default->inside permit 30 -# match ip address prefix-list vpn -#route-map default->inside permit 31 -# match ipv6 address prefix-list vpn - -# Get default route from outside peers. -route-map outside->default permit 10 - match ip address prefix-list default -route-map outside->default permit 11 - match ipv6 address prefix-list default - -# Send inside and NAT addresses to outside peers so inbound packets go through the firewall. -route-map default->outside permit 1 - match interface lo -route-map default->outside permit 20 - match ip address prefix-list office -route-map default->outside permit 21 - match ipv6 address prefix-list office -route-map default->outside permit 30 - match ip address prefix-list nat -route-map default->outside permit 40 - match ip address prefix-list vpn -route-map default->outside permit 41 - match ipv6 address prefix-list vpn diff --git a/roles/firewall/templates/interfaces.j2 b/roles/firewall/templates/interfaces.j2 deleted file mode 100644 index 75980f2..0000000 --- a/roles/firewall/templates/interfaces.j2 +++ /dev/null @@ -1,9 +0,0 @@ -{% set addrs = interfaces | selectattr('name', '==', 'lo') | map(attribute='ip_addresses') | first -%} - -auto lo -iface lo -{% for address in addrs %} - address {{ address.address }} -{% endfor %} - -source-directory /etc/network/interfaces.d diff --git a/roles/firewall/templates/interfaces.nft.j2 b/roles/firewall/templates/interfaces.nft.j2 deleted file mode 100644 index a8b7fda..0000000 --- a/roles/firewall/templates/interfaces.nft.j2 +++ /dev/null @@ -1,10 +0,0 @@ -{% set ifaces_fabric = interfaces | selectattr('name', 'match', '^lan') | map(attribute='name') %} -set inside { - type iface_index - elements = { {{ ifaces_fabric | product(['2']) | map('join', '.') | join(', ') }}, wg } -} - -set outside { - type iface_index - elements = { {{ ifaces_fabric | product(['4']) | map('join', '.') | join(', ') }} } -} diff --git a/roles/firewall/templates/mactab.j2 b/roles/firewall/templates/mactab.j2 deleted file mode 100644 index 9028171..0000000 --- a/roles/firewall/templates/mactab.j2 +++ /dev/null @@ -1,3 +0,0 @@ -{% for iface in interfaces | selectattr('mac_address') %} -{{ iface.name }} {{ iface.mac_address | lower }} -{% endfor %} \ No newline at end of file diff --git a/roles/firewall/templates/mgmt.intf.j2 b/roles/firewall/templates/mgmt.intf.j2 deleted file mode 100644 index a1279dd..0000000 --- a/roles/firewall/templates/mgmt.intf.j2 +++ /dev/null @@ -1,31 +0,0 @@ -auto mgmt -iface mgmt - pre-up ip link add $IFACE type vrf table 100 - up ip link set dev $IFACE up - post-down ip link del $IFACE - -{% for iface in interfaces | selectattr('name', 'match', '^mgmt') %} -auto {{ iface.name }} -iface {{ iface.name }} -{% if iface.vrf %} - requires {{ iface.vrf.name }} - pre-up ip link set $IFACE master {{ iface.vrf.name }} -{% endif %} - pre-up sysctl -w net.ipv4.conf.$IFACE.forwarding=0 - pre-up sysctl -w net.ipv6.conf.$IFACE.forwarding=0 -{% if iface.mtu %} - mtu {{ iface.mtu }} -{% endif %} -{% for addr in iface.ip_addresses %} - address {{ addr.address }} -{% set subnet = addr.address | ipaddr('subnet') %} -{% set prefix_match = prefixes | selectattr('prefix', '==', subnet) %} -{% if prefix_match %} -{% set prefix = prefix_match | first %} -{% if prefix.custom_fields.gateway %} - up ip route add default via {{ prefix.custom_fields.gateway.address | ipaddr('address') }}{% if iface.vrf %} vrf {{ iface.vrf.name }}{% endif %} -{% endif %} -{% endif +%} -{% endfor %} - -{% endfor %} diff --git a/roles/firewall/templates/networks.nft.j2 b/roles/firewall/templates/networks.nft.j2 deleted file mode 100644 index cb74b20..0000000 --- a/roles/firewall/templates/networks.nft.j2 +++ /dev/null @@ -1,9 +0,0 @@ -{% for family, family_prefixes in vrf_prefixes | groupby('family.value') %} -{% for vlan, vlan_prefixes in family_prefixes | groupby('vlan.vid') %} -set {{ vlan_prefixes[0].vlan.name }}{% if family == 6 %}/6{% endif %} { - type ipv{{ family }}_addr; flags interval - elements = { {{ vlan_prefixes | map(attribute='prefix') | join(',') }} } -} -{% endfor %} - -{% endfor %} diff --git a/roles/firewall/templates/nftables.nft.j2 b/roles/firewall/templates/nftables.nft.j2 deleted file mode 100644 index bd37e3a..0000000 --- a/roles/firewall/templates/nftables.nft.j2 +++ /dev/null @@ -1,187 +0,0 @@ -#!/usr/sbin/nft -f -{% set ifaces_fabric = interfaces | selectattr('name', 'match', '^lan') | map(attribute='name') %} - -flush ruleset - -table inet filter { - include "/etc/nftables.d/interfaces.nft" - include "/etc/nftables.d/networks.nft" - include "/etc/nftables.d/sets.nft*" - - set link { - type iface_index - elements = { {{ ifaces_fabric | product(['2', '4']) | map('join', '.') | join(', ') }} } - } - - # convenience port set definitions - set ad-ports { # https://learn.microsoft.com/en-us/troubleshoot/windows-server/active-directory/config-firewall-for-ad-domains-and-trusts - type inet_proto . inet_service - flags interval - elements = { - tcp . 53, - tcp . 88, - tcp . 135, - tcp . 139, - tcp . 389, - tcp . 445, - tcp . 464, - tcp . 636, - tcp . 3268-3269, - #tcp . 3389, # RDP - tcp . 5000-5100, - tcp . 5985, - tcp . 5986, - tcp . 9389, - tcp . 22222-22224, - tcp . 49152-65535, - udp . 53, - udp . 88, - udp . 135, - udp . 137, # netbios, maybe can do without - udp . 138, # netbios, maybe can do without - udp . 389, - udp . 464, - udp . 3269 - } - } - - set ldap-ports { - type inet_proto . inet_service - flags interval - elements = { - tcp . 88, - tcp . 389, - tcp . 636, - tcp . 3268, - tcp . 3269, - udp . 88, - udp . 389 - } - } - - chain input { - type filter hook input priority 0; policy drop - - ct state vmap { established : accept, related : accept, invalid : drop } \ - comment "Accept established streams and drop invalid connections" - - iif lo accept \ - comment "Accept any localhost traffic" - - iif mgmt tcp dport ssh accept \ - comment "Accept SSH from management VRF" - - # allow SSH connections from firewall master’s IPs -{% for iface in hostvars[master].interfaces %} -{% for address in iface.ip_addresses %} - tcp dport ssh {{ 'ip' if address.family.value == 4 else 'ip6' }} saddr {{ address.address | ipaddr('address') }} accept -{% for nat_address in address.nat_outside %} - tcp dport ssh ip saddr {{ nat_address.address | ipaddr('address') }} accept -{% endfor %} -{% endfor %} -{% endfor %} - - iif @link tcp dport bgp ip6 saddr fe80::/10 accept \ - comment "Accept link-local BGP on fabric links" - - iif @link udp dport 3784 ip6 saddr fe80::/10 accept \ - comment "Accept link-local BFD on fabric links" - - udp dport 51820 accept \ - comment "Accept WireGuard from anywhere" - - iif {{ iface_sync }} ip6 saddr fe80::/10 udp dport 3780 accept \ - comment "Accept connection tracking sync data" - - tcp dport auth reject with icmpx type port-unreachable \ - comment "Reject AUTH to make it fail fast" - - # ICMPv4 - ip protocol icmp icmp type { - echo-request, echo-reply, destination-unreachable, - parameter-problem, time-exceeded, - } accept \ - comment "Accept ICMP" - - # ICMPv6 - ip6 nexthdr icmpv6 icmpv6 type { - echo-request, echo-reply, destination-unreachable, - packet-too-big, parameter-problem, time-exceeded, - } accept \ - comment "Accept basic IPv6 functionality" - - ip6 nexthdr icmpv6 icmpv6 type { - nd-neighbor-solicit, nd-neighbor-advert, - nd-router-solicit, nd-router-advert, - } ip6 hoplimit 255 accept \ - comment "Allow IPv6 neighbor discovery" - } - - chain forward { - type filter hook forward priority filter; policy drop - - ct state { established, related } accept \ - comment "Forward all established and related traffic" - - ct status dnat accept \ - comment "Forward DNAT traffic for servers and suchlike" - - ip protocol icmp icmp type { - echo-request, echo-reply, destination-unreachable, - parameter-problem, time-exceeded, - } accept \ - comment "Accept ICMPv4" - - ip6 nexthdr icmpv6 icmpv6 type { - echo-request, echo-reply, destination-unreachable, - packet-too-big, parameter-problem, time-exceeded, - } accept \ - comment "Accept ICMPv6" - - include "/etc/nftables.d/forward.nft*" - } - - chain output { - type filter hook output priority 0; policy accept - } -} - -table inet wireguard { - chain input { - type filter hook prerouting priority raw; policy accept - ip daddr {{ wg_ip | ipaddr('address') }} udp dport 51820 notrack \ - comment "Disable connection tracking for wireguard" - } - chain output { - type route hook output priority raw; policy accept - meta mark 51820 meta nfproto ipv4 ip saddr set {{ wg_ip | ipaddr('address') }} notrack \ - comment "Disable connection tracking and set anycast source IP for wireguard" - } -} - -table ip nat { - include "/etc/nftables.d/interfaces.nft" - include "/etc/nftables.d/networks.nft" - include "/etc/nftables.d/sets.nft*" - include "/etc/nftables.d/netmap.nft*" - - # Ensure these maps exist even if empty. - map netmap-in { type ipv4_addr : interval ipv4_addr; flags interval; } - map netmap-out { type ipv4_addr : interval ipv4_addr; flags interval; } - - chain postrouting { - type nat hook postrouting priority srcnat - - iif @inside oif @outside snat ip prefix to ip saddr map @netmap-out \ - comment "Static source NAT for 1:1 mapped addresses" - - include "/etc/nftables.d/nat.nft*" - } - - chain prerouting { - type nat hook prerouting priority dstnat - - dnat ip prefix to ip daddr map @netmap-in \ - comment "Static destination NAT for 1:1 mapped addresses" - } -} diff --git a/roles/firewall/templates/sysctl.conf.j2 b/roles/firewall/templates/sysctl.conf.j2 deleted file mode 100644 index 1c40f43..0000000 --- a/roles/firewall/templates/sysctl.conf.j2 +++ /dev/null @@ -1,16 +0,0 @@ -# We are router. -net.ipv4.ip_forward = 1 -net.ipv6.conf.all.forwarding = 1 - -# Zebra docs recommend these. -net.ipv6.conf.all.keep_addr_on_down = 1 -net.ipv6.route.skip_notify_on_dev_down = 1 - -# Do not send ICMP redirects. Happens because firewall sees all office -# networks coming from the same routers, and gets confused as to why -# firewall is routing packets between them. -net.ipv4.conf.all.send_redirects = 0 -net.ipv4.conf.default.send_redirects = 0 - -# Increase max connections for netfilter. -net.netfilter.nf_conntrack_max = 1048576 diff --git a/roles/firewall/templates/wg.intf.j2 b/roles/firewall/templates/wg.intf.j2 deleted file mode 100644 index f66ff27..0000000 --- a/roles/firewall/templates/wg.intf.j2 +++ /dev/null @@ -1,12 +0,0 @@ -iface lo - address {{ wg_ip }} - -auto wg -iface wg - use wireguard -{% if wg_net is defined %} - address {{ wg_net }} -{% endif %} -{% if wg_net6 is defined %} - address {{ wg_net6 }} -{% endif %} diff --git a/setup.yml b/setup.yml index c2c9d14..2adf602 100644 --- a/setup.yml +++ b/setup.yml @@ -21,8 +21,3 @@ gather_facts: false roles: - access - -# Set up firewall. -- hosts: fw-* - roles: - - firewall