Move bridge setup to iproute2

This commit is contained in:
Wojciech Kozlowski 2023-08-10 17:34:04 +03:00
parent 476bd0f13e
commit 8eb4bc0f44
16 changed files with 271 additions and 133 deletions

View File

@ -13,6 +13,47 @@
sysctl_file: "/etc/sysctl.d/local.conf" sysctl_file: "/etc/sysctl.d/local.conf"
reload: true reload: true
- name: "keep ipv6 addresses on link down"
ansible.posix.sysctl:
name: "net.ipv6.conf.all.keep_addr_on_down"
value: "1"
sysctl_file: "/etc/sysctl.d/local.conf"
reload: true
- name: "create network directory hierarchy"
ansible.builtin.file:
path: "{{ system_etc_root_directory }}/{{ item }}"
state: "directory"
mode: 0755
loop:
- "network"
- "network/utils"
- "network/interfaces"
- name: "ifupdown script"
ansible.builtin.template:
src: "./ifupdown.sh"
dest: "{{ system_etc_root_directory }}/network/utils/ifupdown.sh"
mode: 0755
- name: "symlink ifupdown script to /etc/network"
ansible.builtin.file:
src: "{{ system_etc_root_directory }}/network/utils/ifupdown.sh"
dest: "/etc/network/{{ item }}/the-nine-worlds"
state: "link"
loop:
- "if-pre-up.d"
- "if-up.d"
- "if-down.d"
- "if-post-down.d"
- name: "ensure bridge-utils is not installed"
ansible.builtin.apt:
name: "bridge-utils"
state: "absent"
purge: true
# TODO: remove once all interfaces have been moved.
- name: "script for creating virtual interfaces" - name: "script for creating virtual interfaces"
ansible.builtin.copy: ansible.builtin.copy:
src: "./ip-link-add.sh" src: "./ip-link-add.sh"

21
vpn/base/templates/ifupdown.sh Executable file
View File

@ -0,0 +1,21 @@
#!/usr/bin/env bash
# Do not run if the deprecated bridge scripts are present.
if [ -f "$(dirname ${0})/bridge" ]
then
echo "$(basename ${0}):"\
"ifupdown scripts from bridge-utils interfere with the-nine-worlds scripts" 1>&2
exit 1
fi
IFDIR={{ system_etc_root_directory }}/network/interfaces/${IFACE}
IFUPDIR=${IFDIR}/ifup.d
IFDOWNDIR=${IFDIR}/ifdown.d
if [ "${MODE}" == "start" ] && [ -d ${IFUPDIR} ]
then
/bin/run-parts --exit-on-error ${IFUPDIR}
elif [ "${MODE}" == "stop" ] && [ -d ${IFDOWNDIR} ]
then
/bin/run-parts --reverse ${IFDOWNDIR}
fi

2
vpn/bridge/files/br0 Normal file
View File

@ -0,0 +1,2 @@
auto br0
iface br0 inet6 manual

View File

@ -1,4 +0,0 @@
#!/usr/bin/env -S nft -f
flush table inet br0_inet
delete table inet br0_inet

View File

@ -1,4 +0,0 @@
#!/usr/bin/env -S nft -f
flush table ip br0_ipv4
delete table ip br0_ipv4

View File

@ -1,4 +0,0 @@
#!/usr/bin/env -S nft -f
flush table ip6 br0_ipv6
delete table ip6 br0_ipv6

View File

@ -1,27 +1,39 @@
--- ---
- name: "post-up nftables scripts" - name: "create interface directory hierarchy"
ansible.builtin.template: ansible.builtin.file:
src: "./{{ item }}" path: "{{ system_etc_root_directory }}/network/interfaces/{{ item }}"
dest: "/usr/local/sbin/{{ item }}" state: "directory"
mode: 0755 mode: 0755
loop: loop:
- "post-up-br0-inet.nft" - "br0"
- "post-up-br0-ipv4.nft" - "br0/ifup.d"
- "post-up-br0-ipv6.nft" - "br0/ifdown.d"
register: vpn_bridge_post_up_nft - "br0/nftables"
- name: "nftables up script"
ansible.builtin.template:
src: "./nftables/up.nft"
dest: "{{ system_etc_root_directory }}/network/interfaces/br0/nftables/up.nft"
mode: 0644
register: vpn_bridge_nftables_up
- name: "interface up scripts"
ansible.builtin.template:
src: "./ifupdown.d/{{ item }}"
dest: "{{ system_etc_root_directory }}/network/interfaces/br0/ifup.d/{{ item }}"
mode: 0755
loop:
- "00-interface"
- "10-nftables"
- "20-routes"
register: vpn_bridge_interface_up
- name: "configure interface" - name: "configure interface"
ansible.builtin.template: ansible.builtin.copy:
src: "./br0" src: "./br0"
dest: "/etc/network/interfaces.d/br0" dest: "/etc/network/interfaces.d/br0"
mode: 0644 mode: 0644
validate: > register: vpn_bridge_interface_file
bash -c
'if ! diff %s /etc/network/interfaces.d/br0 && ip link show dev br0 ;
then
ifdown br0 ;
fi'
register: vpn_bridge_intf
- name: "restart interface" - name: "restart interface"
ansible.builtin.shell: | ansible.builtin.shell: |
@ -32,15 +44,22 @@
ifup br0 ifup br0
fi fi
when: when:
vpn_bridge_post_up_nft.changed or vpn_bridge_nftables_up.changed or
vpn_bridge_intf.changed vpn_bridge_interface_up.changed or
vpn_bridge_interface_file.changed
- name: "pre-down nftables scripts" - name: "nftables down script"
ansible.builtin.copy: ansible.builtin.template:
src: "./{{ item }}" src: "./nftables/down.nft"
dest: "/usr/local/sbin/{{ item }}" dest: "{{ system_etc_root_directory }}/network/interfaces/br0/nftables/down.nft"
mode: 0644
- name: "interface down scripts"
ansible.builtin.template:
src: "./ifupdown.d/{{ item }}"
dest: "{{ system_etc_root_directory }}/network/interfaces/br0/ifdown.d/{{ item }}"
mode: 0755 mode: 0755
loop: loop:
- "pre-down-br0-inet.nft" - "00-interface"
- "pre-down-br0-ipv4.nft" - "10-nftables"
- "pre-down-br0-ipv6.nft" - "20-routes"

View File

@ -1,40 +0,0 @@
auto br0
iface br0 inet6 static
pre-up /usr/local/sbin/ip-link-add.sh $IFACE type bridge
post-up /usr/local/sbin/post-up-$IFACE-inet.nft
post-up /usr/local/sbin/post-up-$IFACE-ipv6.nft
{% if vpn_bridge_routing_table is defined %}
post-up ip -6 rule add dev $IFACE table {{ vpn_bridge_routing_table }}
post-up ip -6 rule add dev $IFACE to {{ local_inet6_network }} table main priority 1
{% endif %}
{% if vpn_bridge_routing_table is defined %}
pre-down ip -6 rule del dev $IFACE to {{ local_inet6_network }} table main priority 1
pre-down ip -6 rule del dev $IFACE table {{ vpn_bridge_routing_table }}
{% endif %}
pre-down /usr/local/sbin/pre-down-$IFACE-ipv6.nft
pre-down /usr/local/sbin/pre-down-$IFACE-inet.nft
bridge_stp off
bridge_waitport 0
bridge_fd 0
bridge_ports none
address {{ vpn_bridge_inet6_address }}/{{ vpn_bridge_inet6_prefixlen }}
dad-attempts 0
iface br0 inet static
post-up /usr/local/sbin/post-up-$IFACE-ipv4.nft
{% if vpn_bridge_routing_table is defined %}
post-up ip rule add dev $IFACE table {{ vpn_bridge_routing_table }}
post-up ip rule add dev $IFACE to {{ local_inet_network }} table main priority 1
{% endif %}
{% if vpn_bridge_routing_table is defined %}
pre-down ip rule del dev $IFACE to {{ local_inet_network }} table main priority 1
pre-down ip rule del dev $IFACE table {{ vpn_bridge_routing_table }}
{% endif %}
pre-down /usr/local/sbin/pre-down-$IFACE-ipv4.nft
address {{ vpn_bridge_inet_address }}/{{ vpn_bridge_inet_prefixlen }}

View File

@ -0,0 +1,34 @@
#!/usr/bin/env bash
if [ ${MODE} == "start" ]
then
set -ue
elif [ ${MODE} == "stop" ]
then
set -u
else
echo "$(basename ${0}): mode must be one of either 'start' or 'stop'" 1>&2
exit 1
fi
case ${PHASE} in
"pre-up")
/usr/sbin/ip link add ${IFACE} type bridge
/usr/sbin/ip link set ${IFACE} type bridge forward_delay 0
/usr/sbin/sysctl -q -w net.ipv6.conf.br0.autoconf=0
/usr/sbin/ip -4 address add {{ vpn_bridge_inet_address }}/{{ vpn_bridge_inet_prefixlen }} dev ${IFACE}
/usr/sbin/ip -6 address add {{ vpn_bridge_inet6_address }}/{{ vpn_bridge_inet6_prefixlen }} dev ${IFACE} nodad
;;
"post-up")
;;
"pre-down")
;;
"post-down")
/usr/sbin/ip -6 address flush dev ${IFACE}
/usr/sbin/ip -4 address flush dev ${IFACE}
/usr/sbin/ip link delete ${IFACE}
;;
esac

View File

@ -0,0 +1,27 @@
#!/usr/bin/env bash
if [ ${MODE} == "start" ]
then
set -ue
elif [ ${MODE} == "stop" ]
then
set -u
else
echo "$(basename ${0}): mode must be one of either 'start' or 'stop'" 1>&2
exit 1
fi
IFDIR={{ system_etc_root_directory }}/network/interfaces/${IFACE}
case ${PHASE} in
"pre-up")
/usr/bin/envsubst '${IFACE}' < ${IFDIR}/nftables/up.nft | /usr/sbin/nft -f /dev/stdin
;;
"post-up")
;;
"pre-down")
;;
"post-down")
/usr/bin/envsubst '${IFACE}' < ${IFDIR}/nftables/down.nft | /usr/sbin/nft -f /dev/stdin
;;
esac

View File

@ -0,0 +1,37 @@
#!/usr/bin/env bash
if [ ${MODE} == "start" ]
then
set -ue
elif [ ${MODE} == "stop" ]
then
set -u
else
echo "$(basename ${0}): mode must be one of either 'start' or 'stop'" 1>&2
exit 1
fi
case ${PHASE} in
"pre-up")
{% if vpn_bridge_routing_table is defined %}
/usr/sbin/ip -4 rule add dev $IFACE table {{ vpn_bridge_routing_table }}
/usr/sbin/ip -6 rule add dev $IFACE table {{ vpn_bridge_routing_table }}
/usr/sbin/ip -4 rule add dev $IFACE to {{ local_inet_network }} table main priority 1
/usr/sbin/ip -6 rule add dev $IFACE to {{ local_inet6_network }} table main priority 1
{% endif %}
;;
"post-up")
;;
"pre-down")
;;
"post-down")
{% if vpn_bridge_routing_table is defined %}
/usr/sbin/ip -6 rule del dev $IFACE to {{ local_inet6_network }} table main priority 1
/usr/sbin/ip -4 rule del dev $IFACE to {{ local_inet_network }} table main priority 1
/usr/sbin/ip -6 rule del dev $IFACE table {{ vpn_bridge_routing_table }}
/usr/sbin/ip -4 rule del dev $IFACE table {{ vpn_bridge_routing_table }}
{% endif %}
;;
esac

View File

@ -0,0 +1,8 @@
flush table ip6 ${IFACE}_ipv6
delete table ip6 ${IFACE}_ipv6
flush table ip ${IFACE}_ipv4
delete table ip ${IFACE}_ipv4
flush table inet ${IFACE}_inet
delete table inet ${IFACE}_inet

View File

@ -0,0 +1,57 @@
#!/usr/bin/env -S nft -f
table inet ${IFACE}_inet {
chain postrouting {
type nat hook postrouting priority 100;
iif ${IFACE} oif { {{ [
ansible_default_ipv4.interface | default(ansible_default_ipv6.interface),
ansible_default_ipv6.interface | default(ansible_default_ipv4.interface)
] | unique | join(", ") }} } masquerade;
}
}
table ip ${IFACE}_ipv4 {
chain prerouting {
type nat hook prerouting priority -100;
{% for forward in vpn_bridge_dnat %}
iif {{ ansible_default_ipv4.interface | default(ansible_default_ipv6.interface) }} tcp dport { {{ forward.ports | join(", ") }} } dnat to {{ forward.inet_address }};
{% endfor %}
}
chain forward {
type filter hook forward priority 0;
{% if local_inet_network is defined %}
ct state established,related accept;
iif ${IFACE} ip daddr {{ local_inet_network }} drop;
{% endif %}
{% if vpn_bridge_local_only_inet_daddr %}
# Drop all external traffic for these addresses.
ip saddr != {{ vpn_bridge_inet_subnet }} ip daddr { {{ vpn_bridge_local_only_inet_daddr | join(", ") }} } drop;
{% endif %}
}
}
table ip6 ${IFACE}_ipv6 {
chain prerouting {
type nat hook prerouting priority -100;
{% for forward in vpn_bridge_dnat %}
iif {{ ansible_default_ipv6.interface | default(ansible_default_ipv4.interface) }} tcp dport { {{ forward.ports | join(", ") }} } dnat to {{ forward.inet6_address }};
{% endfor %}
}
chain forward {
type filter hook forward priority 0;
{% if local_inet6_network is defined %}
ct state established,related accept;
iif ${IFACE} ip6 daddr {{ local_inet6_network }} drop;
{% endif %}
{% if vpn_bridge_local_only_inet6_daddr %}
# Drop all external traffic for these addresses.
ip6 saddr != {{ vpn_bridge_inet6_subnet }} ip6 daddr { {{ vpn_bridge_local_only_inet6_daddr | join(", ") }} } drop;
{% endif %}
}
}

View File

@ -1,8 +0,0 @@
#!/usr/bin/env -S nft -f
table inet br0_inet {
chain postrouting {
type nat hook postrouting priority 100;
iif br0 oif { {{ [ansible_default_ipv4.interface, ansible_default_ipv6.interface] | unique | join(", ") }} } masquerade;
}
}

View File

@ -1,24 +0,0 @@
#!/usr/bin/env -S nft -f
table ip br0_ipv4 {
chain prerouting {
type nat hook prerouting priority -100;
{% for forward in vpn_bridge_dnat %}
iif {{ ansible_default_ipv4.interface }} tcp dport { {{ forward.ports | join(", ") }} } dnat to {{ forward.inet_address }};
{% endfor %}
}
chain forward {
type filter hook forward priority 0;
{% if local_inet_network is defined %}
ct state established,related accept;
iif br0 ip daddr {{ local_inet_network }} drop;
{% endif %}
{% if vpn_bridge_local_only_inet_daddr %}
# Drop all external traffic for these addresses.
ip saddr != {{ vpn_bridge_inet_subnet }} ip daddr { {{ vpn_bridge_local_only_inet_daddr | join(", ") }} } drop;
{% endif %}
}
}

View File

@ -1,24 +0,0 @@
#!/usr/bin/env -S nft -f
table ip6 br0_ipv6 {
chain prerouting {
type nat hook prerouting priority -100;
{% for forward in vpn_bridge_dnat %}
iif {{ ansible_default_ipv6.interface }} tcp dport { {{ forward.ports | join(", ") }} } dnat to {{ forward.inet6_address }};
{% endfor %}
}
chain forward {
type filter hook forward priority 0;
{% if local_inet6_network is defined %}
ct state established,related accept;
iif br0 ip6 daddr {{ local_inet6_network }} drop;
{% endif %}
{% if vpn_bridge_local_only_inet6_daddr %}
# Drop all external traffic for these addresses.
ip6 saddr != {{ vpn_bridge_inet6_subnet }} ip6 daddr { {{ vpn_bridge_local_only_inet6_daddr | join(", ") }} } drop;
{% endif %}
}
}