1

I have a wireguard interface configured in a dedicated namespace vpn. It is configured first creating the interface in the main namespace (that has access to the physical interface routing to the Internet eno1), then moving the Wireguard interface wg0 to the vpn namespace (Reference).

Now, this is my ruleset in the main namespace:

sudo nft -a list table inet filter
table inet filter { # handle 15
        set blackhole { # handle 4
                type ipv4_addr
                elements = { 224.0.0.1, 224.0.0.251,
                             255.255.255.255 }
        }

        set in_tcp_accept { # handle 5
                type inet_service
                flags interval
                elements = { 22 }
        }

        set ip6blackhole { # handle 6
                type ipv6_addr
                elements = { ff02::16 }
        }

        set out_tcp_accept { # handle 7
                type inet_service
                flags interval
                elements = { 80, 443, 11371 }
        }

        set out_udp_accept { # handle 8
                type inet_service
                flags interval
                elements = { 53, 67, 123 }
        }

        chain global { # handle 1
                ct state established,related accept # handle 12
                ct state invalid drop # handle 13
        }

        chain input { # handle 2
                type filter hook input priority filter; policy drop;
                jump global # handle 14
                ip daddr @blackhole counter packets 0 bytes 0 drop # handle 15
                ip6 daddr @ip6blackhole counter packets 0 bytes 0 drop # handle 16
                iif "lo" accept # handle 17
                meta l4proto { icmp, ipv6-icmp } accept # handle 18
                tcp dport @in_tcp_accept ct state new accept # handle 19
                tcp dport { 80, 443 } ct state new accept # handle 20
                udp dport 51821 accept # handle 21
        }

        chain output { # handle 3
                type filter hook output priority filter; policy drop;
                jump global # handle 22
                oif "lo" accept # handle 23
                ip protocol icmp accept # handle 24
                ip6 nexthdr ipv6-icmp counter packets 3 bytes 192 accept # handle 25
                udp dport @out_udp_accept ct state new accept # handle 26
                tcp dport @out_tcp_accept ct state new accept # handle 27
                tcp sport 22 tcp flags { rst, psh | ack } counter packets 44 bytes 6052 accept # handle 28

and this blocks output traffic from wg0 in the vpn namespace.

How do I allow traffic to come from vpn namespace and go through eno1 to the Internet?

rdbisme
  • 420
  • 5
  • 17

1 Answers1

1

I will assume that WireGuard wg0 interface is configured to use main host's port 51821 since there's a rule about this port in the inet filter input chain, and the value is near the usual reference port 51820.

Just add the reverse of this input rule:

        udp dport 51821 accept # handle 21

in the inet filter output chain:

    udp sport 51821 accept

or else add this port in the out_udp_accept set.

With the several restrictions used compared to simpler setups, these are the two places allowing a new outgoing flow from UDP port 51821.

With the current rules, the same flow could be instead allowed as (new) incoming to 51821, allowing later through the global chain the whole flow in both directions as long as a peer reaches the system first, but this might never work for IPv4 in the incoming direction first if the system is hidden behind IPv4 NAT and the NAT gateway is not configured to forward UDP port 51821 to this system (or simply for example if the system is behind CG-NAT ...). If that's the case, PersistentKeepalive should be used in WireGuard's configuration.


Note: ICMPv6 in the output chain should be handled like it was in the input chain. Instead of:

ip protocol icmp accept # handle 24
ip6 nexthdr ipv6-icmp counter packets 3 bytes 192 accept # handle 25

this should be used:

meta l4proto { icmp, ipv6-icmp } counter accept

The reason, as documented, is that one should almost never use ip6 nexthdr which isn't the exact equivalent of ip protocol: it might match an intermediate header rather than the final ICMPv6 header, and thus fail to allow traffic.

A.B
  • 5,338
  • 1
  • 17
  • 20
  • Thanks! This works. Only problem I have is that the output port might change (I'm using random VPN peers). Is there a way to allow udp output traffic without specifying a port? Maybe tagging the traffic using nftables in the `vpn` namespace, then allowing those marked packets in the root namespace? – rdbisme Oct 22 '22 at 18:08
  • No the output *source* port when defined in the local WireGuard configuration will not change unless you change the WireGuard configuration. If for some reason (that I didn't see explained nor find needed) you need to use a mark, then WireGuard has options to mark the outgoing envelope packets for this. See this documentation: https://www.wireguard.com/netns/#improved-rule-based-routing for the marking part (not the routing part of the documentation, you don't appear to need it since you're using an alternate namespace instead). – A.B Oct 22 '22 at 19:46
  • You are right. The source port won't change and thanks for the effort to understand my questions. Thanks for the additional link. – rdbisme Oct 22 '22 at 20:05