Move firewall role to servers repo
This commit is contained in:
parent
0889d24c35
commit
6760d2901e
23 changed files with 0 additions and 864 deletions
|
|
@ -1,2 +0,0 @@
|
||||||
# The init script for conntrackd wants this, not sure about conntrackd itself.
|
|
||||||
net.netfilter.nf_conntrack_tcp_be_liberal = 1
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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"
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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 %}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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 %}
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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(', ') }} }
|
|
||||||
}
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
{% for iface in interfaces | selectattr('mac_address') %}
|
|
||||||
{{ iface.name }} {{ iface.mac_address | lower }}
|
|
||||||
{% endfor %}
|
|
||||||
|
|
@ -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 %}
|
|
||||||
|
|
@ -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 %}
|
|
||||||
|
|
@ -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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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 %}
|
|
||||||
|
|
@ -21,8 +21,3 @@
|
||||||
gather_facts: false
|
gather_facts: false
|
||||||
roles:
|
roles:
|
||||||
- access
|
- access
|
||||||
|
|
||||||
# Set up firewall.
|
|
||||||
- hosts: fw-*
|
|
||||||
roles:
|
|
||||||
- firewall
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue