Jump to content

Multiple rules in effect with iptables when using "--uid-owner" with wireguard server.

Ubuntu 22.04 Cloud VM.

Using iptables persistent.

 

Saved rules file located in:

/etc/iptables/rules.v4

 

Using this command to load changes to iptables. All changes are made by editing the rules.v4 file and restoring:

sudo /sbin/iptables-restore < /etc/iptables/rules.v4

 

Spoiler: Network Information (VNICs, Subnets, etc)

Summary: I have 3 VNICs, along with 2 OpenVPN Servers, 2 Wireguard Servers, 1 Tailscale Client and 2 ZeroTier One subnets.

Spoiler

I have 3 VNICs in this VM that have external IPv4 addresses.

Can refer to them as enp0s3, enp1s0, enp2s0.

 

I have multiple VPN subnets this VM is hosts or is connected to, here are their names and what VNIC they use -

  • Tailscale (Client) - [tailscale0] <-> [enp0s3]
  • ZeroTier One (Client) - [zt0] and [zt1] <-> [enp0s3]
  • OpenVPN Server - [tun0] <-> [enp0s3]
  • OpenVPN Server - [tun2] <-> [enp2s0]
  • Wireguard Server - [wg0] <-> [eth0]
  • Wireguard Server - [wg2] <-> [enp2s0]

Tailscale and Zerotier can use any VNIC they want.

I always notice them using eth0 interface with IPv6 (can check using zerotier-cli peers, tailscale ping mywebserver).

 

Wireguard and OpenVPN can be accessed from anywhere using the ports they are configured to use.

I ensure they are accessed through the specific VNIC by using the cloud firewall.

 

I also have two relay servers that don't have a subnet but do use a VNIC to work -

  • Tailscale (Relay Server - DERP) [enp1s0]
  • ZeroTier One (Relay Server - MOON) [eth0]

I have more than 10 clients that can connect to the VM through either of these VPN subnets from various locations in my country.

 

Here are iptables rules that I think might be important to the problem -

Spoiler

FORWARD and INPUT Rules:

-A FORWARD -d 192.168.88.0/24 -i enp0s3 -o tun0 -m conntrack --ctstate RELATED,ESTABLISHED -m comment --comment openvpn-forward-rule -j ACCEPT
-A FORWARD -s 192.168.88.0/24 -i tun0 -o enp0s3 -m comment --comment openvpn-forward-rule -j ACCEPT
-A FORWARD -d 192.168.111.0/24 -i enp0s3 -o tun222 -m conntrack --ctstate RELATED,ESTABLISHED -m comment --comment openvpn222-forward-rule -j ACCEPT
-A FORWARD -s 192.168.111.0/24 -i tun222 -o enp0s3 -m comment --comment openvpn222-forward-rule -j ACCEPT
-A FORWARD -d 192.168.99.0/24 -i enp0s3 -o wg0 -m conntrack --ctstate RELATED,ESTABLISHED -m comment --comment wireguard-forward-rule -j ACCEPT
-A FORWARD -s 192.168.99.0/24 -i wg0 -o enp0s3 -m comment --comment wireguard-forward-rule -j ACCEPT
-A FORWARD -s 192.168.99.0/24 -i wg0 -o wg0 -m comment --comment wireguard-forwardroute-rule -j ACCEPT
-A FORWARD -d 192.168.99.0/24 -i enp2s0 -o wg2 -m conntrack --ctstate RELATED,ESTABLISHED -m comment --comment wireguard-forward-rule -j ACCEPT
-A FORWARD -s 192.168.99.0/24 -i wg2 -o enp2s0 -m comment --comment wireguard-forward-rule -j ACCEPT
-A FORWARD -s 192.168.99.0/24 -i wg2 -o wg2 -m comment --comment wireguard-forwardroute-rule -j ACCEPT
-I INPUT -i wg0 -j ACCEPT
-I INPUT -i wg2 -j ACCEPT
-I FORWARD -i enp0s3 -o wg0 -j ACCEPT
-I FORWARD -i wg0 -o enp0s3 -j ACCEPT
-I FORWARD -i enp2s0 -o wg2 -j ACCEPT
-I FORWARD -i wg2 -o enp2s0 -j ACCEPT
-I INPUT -i enp0s3 -p udp --dport 51820 -m comment --comment wireguard-incoming-rule-wg0-enp0s3 -j ACCEPT
-I INPUT -i enp1s0 -p udp --dport 51820 -m comment --comment wireguard-incoming-rule-wg0-enp1s0 -j ACCEPT
-I INPUT -i enp0s3 -p udp --dport 51821 -m comment --comment wireguard-incoming-rule-wg1-enp0s3 -j ACCEPT
-I INPUT -i enp1s0 -p udp --dport 51821 -m comment --comment wireguard-incoming-rule-wg1-enp1s0 -j ACCEPT
-I INPUT -i enp2s0 -p udp --dport 51822 -m comment --comment wireguard-incoming-rule-wg2-enp2s0 -j ACCEPT

POSTROUTING rules:

-A POSTROUTING -s 192.168.88.0/24 -o enp0s3 -m comment --comment openvpn-nat-rule-tun0 -j MASQUERADE
-A POSTROUTING -s 192.168.99.0/24 -o enp0s3 -m comment --comment wireguard-nat-rule-wg0 -j MASQUERADE
-A POSTROUTING -s 192.168.99.0/24 -o enp2s0 -m comment --comment wireguard-nat-rule-wg2 -j MASQUERADE
-A POSTROUTING -s 192.168.111.0/24 -o enp0s3 -m comment --comment openvpn-nat-rule-tun111 -j MASQUERADE
-A POSTROUTING -s 192.168.111.0/24 -o enp1s0 -m comment --comment openvpn-nat-rule-tun111 -j MASQUERADE

 

 

The specific problem I have, only happens with all wireguard servers, with a "limited" user.

 

I have a limited user, named "limited", which should:

  • Have full access / should be fully accessible from any of the VPN subnets
  • Should have no internet access, for security.

All users besides the limited user can access everything normally.

 

To the best of my knowledge, iptables works with "first matching rule wins". I created my rules based on that logic so far.

 

Also to the best of my knowledge, the matching logic below does not work when used with INPUT.

-m owner --uid-owner username_or_uid

 

To limit the "limited" user, here are the rules I created with logic -

First, allow the limited user on all VPN subnets:

-A OUTPUT -o wg0 -m owner --uid-owner limited -j ACCEPT
-A OUTPUT -o wg2 -m owner --uid-owner limited -j ACCEPT
-A OUTPUT -o zt0 -m owner --uid-owner limited -j ACCEPT
-A OUTPUT -o zt1 -m owner --uid-owner limited -j ACCEPT
-A OUTPUT -o tailscale0 -m owner --uid-owner limited -j ACCEPT
-A OUTPUT -o tun0 -m owner --uid-owner limited -j ACCEPT
-A OUTPUT -o tun2 -m owner --uid-owner limited -j ACCEPT

Then, drop all output to either of the VNICs:

-A OUTPUT -o enp0s3 -m owner --uid-owner limited -j DROP
-A OUTPUT -o enp1s0 -m owner --uid-owner limited -j DROP
-A OUTPUT -o enp2s0 -m owner --uid-owner limited -j DROP

 

User "limited" is able to ping any device connected through Tailscale, ZeroTier One and OpenVPN.

 

I can use this command below, to "watch" how many packets matched the rules, by using this command:

sudo watch -n1 -d "(iptables -tfilter -vnxL;iptables -tnat -vnxL;iptables -tmangle -vnxL;iptables -traw -vnxL;iptables -tsecurity -vnxL) | grep -vE 'pkts|Chain' | sort -nk1,1hr | column -t"

 

User "limited" is NOT able to ping any device connected through either of the Wireguard servers.

Two rules get triggered when I try to ping any device on wireguard subnet at the same time.

 

spacer.png

 

Here are other rules I tried to use which would do the same thing, that DID NOT WORK.

The final attempt I made to try and make this work has a very interesting result, which confirms that two rules are matching at the same time.

Spoiler


Tried adding an ACCEPT rule that uses IP instead of interface:

-I OUTPUT -s 192.168.99.0/24 -j ACCEPT

 

Tried each combination of dropping all packets that are not from 192.168.x.x source and/or destination:

-A OUTPUT -m owner --uid-owner limited ! -s 192.168.0.0/16 ! -d 192.168.0.0/16  -j DROP
OR
-A OUTPUT -m owner --uid-owner limited ! -s 192.168.0.0/16 -j DROP
OR
-A OUTPUT -m owner --uid-owner limited ! -d 192.168.0.0/16  -j DROP

 

 

Tried blocking all ports on both tcp and udp, using multiport, besides the 2 ports I need for testing. Used minecraft server for testing (port 25565) and voice chat server (24454):

First accept rule to match ports:

-A OUTPUT -p tcp -m tcp --dport 25565 -m owner --uid-owner limited -j ACCEPT
-A OUTPUT -p tcp -m tcp --dport 24454 -m owner --uid-owner limited -j ACCEPT

Then drop rule to drop all ports besides the two accepted above:

-A OUTPUT -o enp0s3 -p tcp -m multiport --dports 0:24453 -m owner --uid-owner limited -j REJECT
-A OUTPUT -o enp1s0 -p tcp -m multiport --dports 0:24453 -m owner --uid-owner limited -j REJECT
-A OUTPUT -o enp2s0 -p tcp -m multiport --dports 0:24453 -m owner --uid-owner limited -j REJECT
-A OUTPUT -o enp0s3 -p tcp -m multiport --dports 24455:25564 -m owner --uid-owner limited -j REJECT
-A OUTPUT -o enp1s0 -p tcp -m multiport --dports 24455:25564 -m owner --uid-owner limited -j REJECT
-A OUTPUT -o enp2s0 -p tcp -m multiport --dports 24455:25564 -m owner --uid-owner limited -j REJECT
-A OUTPUT -o enp0s3 -p tcp -m multiport --dports 25566:65535 -m owner --uid-owner limited -j REJECT
-A OUTPUT -o enp1s0 -p tcp -m multiport --dports 25566:65535 -m owner --uid-owner limited -j REJECT
-A OUTPUT -o enp2s0 -p tcp -m multiport --dports 25566:65535 -m owner --uid-owner limited -j REJECT
-A OUTPUT -o enp0s3 -p udp -m multiport --dports 0:24453 -m owner --uid-owner limited -j REJECT
-A OUTPUT -o enp1s0 -p udp -m multiport --dports 0:24453 -m owner --uid-owner limited -j REJECT
-A OUTPUT -o enp2s0 -p udp -m multiport --dports 0:24453 -m owner --uid-owner limited -j REJECT
-A OUTPUT -o enp0s3 -p udp -m multiport --dports 24455:25564 -m owner --uid-owner limited -j REJECT
-A OUTPUT -o enp1s0 -p udp -m multiport --dports 24455:25564 -m owner --uid-owner limited -j REJECT
-A OUTPUT -o enp2s0 -p udp -m multiport --dports 24455:25564 -m owner --uid-owner limited -j REJECT
-A OUTPUT -o enp0s3 -p udp -m multiport --dports 25566:65535 -m owner --uid-owner limited -j REJECT
-A OUTPUT -o enp1s0 -p udp -m multiport --dports 25566:65535 -m owner --uid-owner limited -j REJECT
-A OUTPUT -o enp2s0 -p udp -m multiport --dports 25566:65535 -m owner --uid-owner limited -j REJECT

This last attempt created a rather strange result in the watch command. Take a look at this -

Here is the important parts to note (lines highlighted in white):

spacer.png

 

The total of all REJECT packets is the same as the total of all ACCEPT packets matching the wg0 rule FIRST. Still packets get rejected!

spacer.png

 

If I add a rule that accepts all packets from the internal ipv4 address of enp0s3 (default vnic) -

-A OUTPUT -m owner --uid-owner limited -s 10.0.0.175 -j ACCEPT

Everything works and nothing is blocked for the "limited" user. (the ipv4 address 10.0.0.195 is the internal ipv4 of the VM for interface enp0s3)

Indicating that iptables knows that packets coming to "limited" user from either wg0 or wg2 interface, are actually from an external source that is not in 192.168.x.x range and matches enp0s3 or enp2s0 output interfaces.

 

1. How are two rules getting matched at the same time, and why is DROP rule winning?

2. How does iptables know that packets coming to wireguard are from an external source?

3. Why does this happen only with wireguard and not with any other VPNs I have set up?

4. Is there any other way I could block all internet access from "limited" user and still be able to connect to devices on VPN subnets?

 

I could not find answers to this problem anywhere and I have no idea why this is happening.

Any help, suggestions and explanations would be nice.

Thanks in advance! 🙂

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×