iptables规则配置异常:仅允许特定组启动的程序访问网络的规则不生效
我来帮你捋清楚问题出在哪,以及怎么解决~
你踩的核心坑是iptables的owner模块默认匹配的是进程的「真实GID」,而非你用sudo -g临时切换的「有效GID」。
咱们拆解下你的测试场景:
当你执行sudo -g has-internet ping somesite.xyz时,这个ping进程的「真实GID」还是你当前用户的主组(比如你的个人用户组),只是「有效GID」被临时改成了has-internet。而你写的规则-m owner ! --gid-owner has-internet是基于「真实GID」做判断的,所以这个ping进程会被判定为“不属于has-internet组”,直接被DROP掉。
反过来,当你设置-m owner --gid-owner has-internet -j DROP时,规则能匹配到sudo -g启动的ping,是因为这条规则找的是“属于has-internet组的进程”,而此时ping的有效GID刚好符合,所以触发了DROP——这也侧面验证了owner模块对有效GID是能识别的,只是默认的--gid-owner参数不优先用它。
解决办法
直接让iptables匹配「有效GID」就好了,owner模块提供了专门的参数--egid-owner来做这件事。修改你的规则如下:
# 替换原有的iptables规则 sudo iptables -A OUTPUT -m owner ! --egid-owner has-internet -j DROP sudo ip6tables -A OUTPUT -m owner ! --egid-owner has-internet -j DROP
修改后再测试sudo -g has-internet ping somesite.xyz,应该就能正常连接了——因为这条规则会识别到ping进程的有效GID是has-internet,不会触发DROP动作。
另外,如果你不想改iptables参数,也可以先切换到has-internet组再启动程序,这样进程的真实GID会变成该组,原规则也能生效:
sudo newgrp has-internet ping somesite.xyz
不过这种方式需要先切换组,不如第一种方法灵活。
额外提醒
注意iptables规则是按顺序匹配的,如果你的OUTPUT链之前已经有其他允许流量的规则,可能会影响结果。但从你的测试来看,普通ping和sudo ping都被成功DROP,说明你的规则顺序是没问题的,主要就是GID匹配的逻辑问题。
备注:内容来源于stack exchange,提问作者codeispoetry

