Add IPv6 support to bridges

This commit is contained in:
Wojciech Kozlowski 2023-07-27 23:07:45 +02:00
parent f944dae2fe
commit 18ee9c7a24
8 changed files with 82 additions and 47 deletions

View File

@ -1,2 +1,3 @@
--- ---
vpn_bridge_local_only_daddr: [] vpn_bridge_local_only_inet_daddr: []
vpn_bridge_local_only_inet6_daddr: []

View File

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

View File

@ -6,29 +6,36 @@ argument_specs:
interface: interface:
type: "str" type: "str"
required: true required: true
local_network: local_inet_network:
type: "str"
required: false
local_inet6_network:
type: "str" type: "str"
required: false required: false
vpn_bridge_dnat: vpn_bridge_dnat:
type: "list" type: "list"
elements: "dict" elements: "dict"
required: true required: true
vpn_bridge_address: vpn_bridge_inet_address:
type: "str" type: "str"
required: true required: true
vpn_bridge_broadcast: vpn_bridge_inet6_prefixlen:
type: "str" type: "str"
required: true required: true
vpn_bridge_prefixlen: vpn_bridge_inet_subnet:
type: "str" type: "str"
required: true required: true
vpn_bridge_subnet: vpn_bridge_inet6_subnet:
type: "str" type: "str"
required: true required: true
vpn_bridge_routing_table: vpn_bridge_routing_table:
type: "int" type: "int"
required: false required: false
vpn_bridge_local_only_daddr: vpn_bridge_local_only_inet_daddr:
type: "list"
elements: "str"
required: true
vpn_bridge_local_only_inet6_daddr:
type: "list" type: "list"
elements: "str" elements: "str"
required: true required: true

View File

@ -1,17 +1,14 @@
--- ---
- name: "post-up nftables inet script" - name: "post-up nftables scripts"
ansible.builtin.template: ansible.builtin.template:
src: "./post-up-br0-inet.nft" src: "./{{ item }}"
dest: "/usr/local/sbin/post-up-br0-inet.nft" dest: "/usr/local/sbin/{{ item }}"
mode: 0755 mode: 0755
register: vpn_bridge_post_up_br0_inet_nft loop:
- "post-up-br0-inet.nft"
- name: "post-up nftables ipv4 script" - "post-up-br0-ipv4.nft"
ansible.builtin.template: - "post-up-br0-ipv6.nft"
src: "./post-up-br0-ipv4.nft" register: vpn_bridge_post_up_nft
dest: "/usr/local/sbin/post-up-br0-ipv4.nft"
mode: 0755
register: vpn_bridge_post_up_br0_ipv4_nft
- name: "configure interface" - name: "configure interface"
ansible.builtin.template: ansible.builtin.template:
@ -35,18 +32,15 @@
ifup br0 ifup br0
fi fi
when: when:
vpn_bridge_post_up_br0_inet_nft.changed or vpn_bridge_post_up_nft.changed or
vpn_bridge_post_up_br0_ipv4_nft.changed or
vpn_bridge_intf.changed vpn_bridge_intf.changed
- name: "pre-down nftables inet script" - name: "pre-down nftables scripts"
ansible.builtin.copy: ansible.builtin.copy:
src: "./pre-down-br0-inet.nft" src: "./{{ item }}"
dest: "/usr/local/sbin/pre-down-br0-inet.nft" dest: "/usr/local/sbin/{{ item }}"
mode: 0755
- name: "pre-down nftables ipv4 script"
ansible.builtin.copy:
src: "./pre-down-br0-ipv4.nft"
dest: "/usr/local/sbin/pre-down-br0-ipv4.nft"
mode: 0755 mode: 0755
loop:
- "pre-down-br0-inet.nft"
- "pre-down-br0-ipv4.nft"
- "pre-down-br0-ipv6.nft"

View File

@ -4,15 +4,21 @@ iface br0 inet static
post-up /usr/local/sbin/post-up-$IFACE-inet.nft post-up /usr/local/sbin/post-up-$IFACE-inet.nft
post-up /usr/local/sbin/post-up-$IFACE-ipv4.nft post-up /usr/local/sbin/post-up-$IFACE-ipv4.nft
post-up /usr/local/sbin/post-up-$IFACE-ipv6.nft
{% if vpn_bridge_routing_table is defined %} {% 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 table {{ vpn_bridge_routing_table }}
post-up ip rule add dev $IFACE to {{ local_network }} table main priority 1 post-up ip rule add dev $IFACE to {{ local_inet_network }} table main priority 1
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 %} {% endif %}
{% if vpn_bridge_routing_table is defined %} {% if vpn_bridge_routing_table is defined %}
pre-down ip rule del dev $IFACE to {{ local_network }} table main priority 1 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 }}
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 }} pre-down ip rule del dev $IFACE table {{ vpn_bridge_routing_table }}
{% endif %} {% endif %}
pre-down /usr/local/sbin/pre-down-$IFACE-ipv6.nft
pre-down /usr/local/sbin/pre-down-$IFACE-ipv4.nft pre-down /usr/local/sbin/pre-down-$IFACE-ipv4.nft
pre-down /usr/local/sbin/pre-down-$IFACE-inet.nft pre-down /usr/local/sbin/pre-down-$IFACE-inet.nft
@ -21,6 +27,8 @@ iface br0 inet static
bridge_fd 0 bridge_fd 0
bridge_ports none bridge_ports none
address {{ vpn_bridge_address }} address {{ vpn_bridge_inet_address }}/{{ vpn_bridge_inet_prefixlen }}
broadcast {{ vpn_bridge_broadcast }}
netmask {{ vpn_bridge_prefixlen }} iface br0 inet6 static
address {{ vpn_bridge_inet6_address }}/{{ vpn_bridge_inet6_prefixlen }}
dad-attempts 0

View File

@ -1,5 +1,8 @@
#!/usr/bin/env -S nft -f #!/usr/bin/env -S nft -f
table inet br0_inet { 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

@ -4,27 +4,21 @@ table ip br0_ipv4 {
chain prerouting { chain prerouting {
type nat hook prerouting priority -100; type nat hook prerouting priority -100;
{% for forward in vpn_bridge_dnat %} {% for forward in vpn_bridge_dnat %}
iif {{ ansible_default_ipv4.interface }} tcp dport { {{ forward.ports | join(", ") }} } dnat to {{ forward.address }}; iif {{ ansible_default_ipv4.interface }} tcp dport { {{ forward.ports | join(", ") }} } dnat to {{ forward.inet_address }};
{% endfor %} {% endfor %}
} }
chain forward { chain forward {
type filter hook forward priority 0; type filter hook forward priority 0;
{% if local_inet_network is defined %}
{% if local_network is defined %}
ct state established,related accept; ct state established,related accept;
iif br0 ip daddr {{ local_network }} drop; iif br0 ip daddr {{ local_inet_network }} drop;
{% endif %} {% endif %}
{% if vpn_bridge_local_only_daddr %} {% if vpn_bridge_local_only_inet_daddr %}
# Drop all external traffic for these addresses. # Drop all external traffic for these addresses.
ip saddr != {{ vpn_bridge_subnet }} ip daddr { {{ vpn_bridge_local_only_daddr | join(", ") }} } drop; ip saddr != {{ vpn_bridge_inet_subnet }} ip daddr { {{ vpn_bridge_local_only_inet_daddr | join(", ") }} } drop;
{% endif %} {% endif %}
} }
chain postrouting {
type nat hook postrouting priority 100;
iif br0 oif {{ ansible_default_ipv4.interface }} masquerade;
}
} }

View File

@ -0,0 +1,24 @@
#!/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 %}
}
}