在我的 ubuntu 16.04 笔记本电脑上,我尝试设置规则,iptables
以便默认情况下拒绝所有应用程序的互联网访问,并且只允许一个名为internet
.我不会将该组添加到我自己的登录中,而是在需要时使用sudo -g
或sg
访问互联网。例如:
sudo -g internet firefox
或者
sg internet -c "firefox"
然而,这种方法并不奏效。以下是iptables
我添加的规则:
/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
我已经测试了上述规则,当我删除所有者模块时,它工作正常并且所有应用程序都允许互联网。但是当我添加所有者模块和gid-owner
过滤器时,没有应用程序能够访问互联网(即使使用提到的sg
和sudo -g
命令)。
我究竟做错了什么?
答案1
已经标记为已解决,但为了其他遇到此问题的人的理智,我想我应该在这里详细说明并解释您发现的问题的实际原因。问题在于iptables。具体来说,它并不像我们人类期望的那样处理组 ID 过滤。我不确定这是 WAD 还是 bug。恕我直言,这是一个错误iptables -m owner
扩展代码。
问题在于 的处理--gid-owner
。看来iptables 扩展代码不会按字面过滤组ID(即用户是否在该组中,是还是否?)。从该模块的行为可以明显看出,它会更深入地挖掘并检查用户名设置,然后根据用户的主要组成员身份做出决定。这与对小组成员列表的字面检查(我自己和其他遇到此问题的人所期望的)不同。此行为未记录在任何相关手册页中。
也就是说,Ubuntu 的 iptables 实现只检查主要群体当前网络数据包的所有者。假设您希望创建一个拆分 VPN,其中特定用户组VPN将其流量强制发送到 VPN 接口。
如果您要指定每个所有者,则扩展--uid-owner
下的参数-m owner
将按预期工作。然后,假设您有多个要分支的用户名,并且用户列表可能会随着时间的推移而改变。因此,您认为使用组 ID 过滤会更有效 ( --gid-owner
)。您将所有 VPN 流量用户放入一个名为VPN并将 iptables 参数更改为--gid-owner vpn
。正如您所看到的,在许多情况下,过滤器无法按预期运行。为什么?
仅比较数据包所有者的主要/默认组。因此,您添加到的任何用户名VPN创建用户后的组将在VPN组作为辅助用户,并且即使他们是该团体的成员,他们也不会被分支!
“root”用户对您不起作用的原因是它的主要/默认组是“root”。
举例说明
假设您有用户名VPN在初级组VPN和用户名测试假人在初级组测试但测试假人也是该组织的成员VPN团体。到测试假人,VPN是一个次要群体。
该 iptables 规则将标记属于VPN用户但不是测试假人用户,即使本能地认为来自两个用户的数据包都会被标记,因为它们都属于组VPN:
iptables -t mangle -A OUTPUT ! -d 192.168.1.1 -m owner --gid-owner vpn -j MARK --set-mark 0x1
要解决该问题,您必须创建另一个规则,例如以下解决方案:
iptables -t mangle -A OUTPUT ! -d 192.168.1.1 -m owner --gid-owner vpn -j MARK --set-mark 0x1
iptables -t mangle -A OUTPUT ! -d 192.168.1.1 -m owner --uid-owner testdummy -j MARK --set-mark 0x1
答案2
经过多次尝试和错误,我找到了自己问题的答案。问题不在于 iptables 或我使用的 Ubuntu/Linux 版本,而在于第三条规则:
/sbin/iptables -A OUTPUT -p udp --dport 53 -m owner --gid-owner internet -j ACCEPT
由于udp/53
端口用于 DNS 名称解析,因此后台服务dnsmasq
可能会使用它们,因此当我尝试在该组中运行程序时,不会发生名称解析,internet
因为这些其他服务不在该组中。然而,理想情况下,这些服务仍然应该有权访问该端口,因为它们在 root 帐户下运行(并且 root 可以做任何事情!),但 iptables 所有者模块的设计似乎不尊重这种 root 权限。
当我从最后一条规则中删除所有者模块检查后,互联网就开始工作:
/sbin/iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
编辑
另一个不直接链接但相关的问题是使用根组的所有者模块。我们倾向于分配根组对互联网的访问权限(除了internet
组之外或代替组),如下所示:
/sbin/iptables -A OUTPUT -p tcp --dport 80 -m owner --gid-owner root -j ACCEPT
然而,这在实践中行不通,因为出于安全原因,很多应用程序不使用 root 用户连接到互联网。例如,即使执行了上述操作,以下命令也将不起作用:
sudo apt-get update
这是因为出于安全原因apt
,程序内部使用_apt
用户下载包。
答案3
您可以--suppl-groups
为此使用,添加在EA6CC2FD。从iptables-extensions(8)
:
--suppl-groups
Causes group(s) specified with --gid-owner to be also checked in
the supplementary groups of a process.
也可以看看iptables组匹配:修改用户的主要组
答案4
/sbin/iptables -A OUTPUT -p tcp --dport 80 -m owner ! --gid-owner root -j DROP