On my ubuntu 16.04 laptop, I'm trying to setup the iptables rules so that internet access is denied to all applications by default, and allowed to only one group called internet. I won't add that group to my own login, but use sudo -g or sg to access internet whenever I want. For example:

sudo -g internet firefox


sg internet -c "firefox"

However, this approach isn't working. Following is the iptables rule that I've added:

/sbin/iptables -A OUTPUT -p tcp --dport 80  -m owner --gid-owner internet   -j ACCEPT
/sbin/iptables -A OUTPUT -p tcp --dport 443  -m owner --gid-owner internet   -j ACCEPT
/sbin/iptables -A OUTPUT -p udp --dport 53  -m owner --gid-owner internet   -j ACCEPT

I've tested the above rules, when I remove the owner module, it works perfectly and internet is allowed to all applications. But when I add the owner module and gid-owner filter, no app is able to access the internet (even using the mentioned sg and sudo -g commands).

What am I doing wrong?

  • Have you tried adding iptables -A OUTPUT -j LOG to log any dropped packet and compare it with your rule? You may also try using nc or telnet (i.e. "telnet 53") to check if it works. – user996142 Jun 27 '17 at 16:34
  • I've tried both telnet and ping - neither works with the gid filter set, but after removing that, both work. Don't think logging would be of any use as I already know its out right rejecting the packages. – Prahlad Yeri Jun 27 '17 at 17:17
  • Logging may help you to investigate this issue. Your scenario worked for me (I just checked) so I think that logs along with iptables -L may help. – user996142 Jun 27 '17 at 17:30
  • btw, here is my scenario on virtualbox. I denied for anyone but root, and it works: pastebin.com/TVQTV2gP – user996142 Jun 27 '17 at 17:33
  • Did you try with ubuntu 16.04? – Prahlad Yeri Jun 27 '17 at 19:13

After much trial and error, I was able to find the answer to my own question. The issue wasn't with iptables or with Ubuntu/Linux version I was using, but rather, the issue was with this third rule:

/sbin/iptables -A OUTPUT -p udp --dport 53  -m owner --gid-owner internet   -j ACCEPT

Since udp/53 port is used for DNS name resolution, background services like dnsmasq could be using them, hence name resolution wasn't happening when I tried to run a program with the internet group as these other services weren't in that group. However, ideally those services should still have had access to the port since they are running under root account (and root can do anything!), but the design of iptables owner module seems not to respect such root privileges.

As soon as I removed the owner module check from this last rule, the internet started working:

/sbin/iptables -A OUTPUT -p udp --dport 53 -j ACCEPT


Another, not directly linked, but related issue is using the owner module for root group. We are inclined to assign the root group access to the internet (in addition to or instead of the internet group) like this:

/sbin/iptables -A OUTPUT -p tcp --dport 80  -m owner --gid-owner root   -j ACCEPT

However, this doesn't work in practice because a lot many apps don't use the root user to connect to the internet for security reasons. For example, the following command won't work even after doing the above:

sudo apt-get update

That's because apt program internally uses the _apt user to download packages for security reasons.

  • that's why I asked you to telnet to by IP, not by name;) – user996142 Jun 28 '17 at 0:01

Already marked solved, but for the sanity of anyone else running into this issue, I thought I'd elaborate here and explain the actual cause of the problem you discovered. The issue is with iptables. Specifically, it does not handle group ID filtering as us humans expect it to. I'm not sure if it's WAD or a bug. IMHO, it's a bug in the iptables -m owner extension code.

The issue is with the handling of --gid-owner. It appears the iptables extensions code does not filter the group id literally (i.e. is user in this group, yes or no?). It's apparent from the module's behavior that it digs deeper and examines the username settings, and then makes a decision based on primary group membership of the user. That is versus a literal examination of the list of group members (expected by myself and others who've had this problem). This behavior is not documented in any of the relevant man pages.

To wit, Ubuntu's implementation of iptables only examines the primary group of the owner of the current network packet. Let's say you wish to create a split VPN, where a specific user group vpn will have its traffic forced to the VPN interface.

If you were to specify each owner, the --uid-owner parameter under the -m owner extension will work as expected. Then let's say you have multiple usernames that you want to branch, and the user list may change over time. So, you decide it would be more efficient to use group id filtering instead (--gid-owner). You place all your VPN traffic users into a single group called vpn and change the iptables parameter to --gid-owner vpn. As you've seen, in many cases the filter fails to perform as expected. Why?

Only the primary/default group of the owner of the packet will be compared. Therefore, any username you added to your vpn group after the user was created will be in the vpn group as a secondary user, and they won't be branched even though they are a member of the group!

The reason the 'root' user didn't work for you is because its primary/default group is 'root'.

Illustrated Example

Say you have username vpn in primary group vpn and username testdummy in primary group test but testdummy is also a member of the vpn group. To testdummy, vpn is a secondary group.

This iptables rule will mark packets belonging to the vpn user but not the testdummy user, even though instinctively one would think packets from both users would be marked because they both belong to group vpn:

iptables -t mangle -A OUTPUT ! -d -m owner --gid-owner vpn -j MARK --set-mark 0x1

To solve the problem, you will have to create another rule, such as this solution:

iptables -t mangle -A OUTPUT ! -d -m owner --gid-owner vpn -j MARK --set-mark 0x1
iptables -t mangle -A OUTPUT ! -d -m owner --uid-owner testdummy -j MARK --set-mark 0x1
/sbin/iptables -A OUTPUT -p tcp --dport 80  -m owner ! --gid-owner root -j DROP
  • welcome to U&L, can you please elaborate your answer ? like meaning of flags, etc .. – Archemar Dec 19 '17 at 5:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.