是否可以阻止单个进程的(传出)网络访问?
答案1
对于 Linux 2.6.24+(在 2.6.29 之前被认为是实验性的),您可以为此使用网络命名空间。您需要在内核 ( CONFIG_NET_NS=y
) 和 util-linux 中启用“网络命名空间”,并使用unshare
工具。
然后,在没有网络访问的情况下启动进程非常简单:
unshare -n program ...
这会为进程创建一个空的网络命名空间。也就是说,它在没有网络接口的情况下运行,包括无环回。在下面的示例中,我们添加 -r 仅在当前有效用户和组 ID 映射到超级用户 ID 后才运行程序(避免 sudo):
$ unshare -r -n ping 127.0.0.1
connect: Network is unreachable
如果您的应用程序需要网络接口,您可以设置一个新的网络接口:
$ unshare -n -- sh -c 'ip link set dev lo up; ping 127.0.0.1'
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=32 time=0.066 ms
请注意,这将创建一个新的,当地的环回。也就是说,生成的进程将无法访问主机的开放端口127.0.0.1
。
如果您需要访问命名空间内的原始网络,您可以使用nsenter
进入另一个命名空间。
以下示例ping
使用 PID 1 使用的网络命名空间运行(通过 指定-t 1
):
$ nsenter -n -t 1 -- ping -c4 example.com
PING example.com (93.184.216.119) 56(84) bytes of data.
64 bytes from 93.184.216.119: icmp_seq=1 ttl=50 time=134 ms
64 bytes from 93.184.216.119: icmp_seq=2 ttl=50 time=134 ms
64 bytes from 93.184.216.119: icmp_seq=3 ttl=50 time=134 ms
64 bytes from 93.184.216.119: icmp_seq=4 ttl=50 time=139 ms
--- example.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 134.621/136.028/139.848/2.252 ms
答案2
Linux有一个功能叫做网络命名空间它本质上允许您在同一台计算机上拥有多个网络堆栈,并在运行程序时将其分配给一个程序。这是通常用于容器的功能,但您也可以使用它来完成您想要的任务。
这ip netns
子命令管理它。创建一个无法访问任何内容的新网络命名空间很容易,这是新命名空间的默认状态:
root@host:~# ip netns add jail
现在,如果您切换到该名称空间,则可以相当轻松地配置它。你可能会想在其中提到 lo,就是这样:
root@host:~# ip netns exec jail /bin/bash
root@host:~# ip addr add 127.0.0.1/8 dev lo
root@host:~# ip link set dev lo up
root@host:~# exit
现在,当您想在没有网络的情况下运行命令时,只需在该监狱中运行它即可:
root@host:~# ip netns exec jail su user -c 'ping 8.8.8.8'
connect: Network is unreachable
根据需要,网络无法访问。 (您可以做各种有趣的事情,因为单独的网络堆栈包含iptables
规则等)
答案3
解决方案 1:取消共享
取消分享来自 util-linux 包可以在没有网络的情况下在不同的命名空间上启动应用程序,但这需要 root firejail 的解决方案做几乎完全相同的事情,但不需要 root
unshare -r -n app-command
解决方案2:Firejail:
火狱可用于阻止应用程序的网络访问,这不需要 root 任何用户都可以从中受益
firejail --noprofile --net=none app-command
解决方案3:Systemd
自从系统 v235还有另一个非常简单的选择:
systemd-run --scope -p IPAddressDeny=any -p IPAddressAllow=localhost app-command
解决方案 4:防火墙:
我们可以使用防火墙,例如杜安或者开放式告密者但这些应用程序并不是 100% 高效或处于开发的早期阶段(截至 2019 年有很多错误等)
解决方案 5:内核 MAC:
内核 MAC 可用作防火墙,最著名的是智代,塞林克斯和阿帕莫尔 就稳定性和效率(防火墙解决方案)而言,此解决方案是最好的解决方案,但大多数时候设置此解决方案有点复杂。
解决方案 6:代理:
一种解决方案是将应用程序代理到空/假代理人。我们可以用tsocks或者代理绑定。这是一些有关设置的详细信息
解决方案7:iptables:
另一个简单的解决方案是 iptables,它可以设置为阻止应用程序
- 创建、验证新组;将所需的用户添加到该组:
- 创造:
groupadd no-internet
- 证实:
grep no-internet /etc/group
- 添加用户:
useradd -g no-internet username
注意:如果您要修改现有用户,您应该运行:usermod -a -G no-internet userName
检查:sudo groups userName
- 创造:
- 创建一个脚本在您的路径中并使其可执行:
- 创造:
nano /home/username/.local/bin/no-internet
- 可执行文件:
chmod 755 /home/username/.local/bin/no-internet
- 内容:
#!/bin/bash
sg no-internet "$@"
- 添加iptables规则用于删除组的网络活动没有互联网:
iptables -I OUTPUT 1 -m owner --gid-owner no-internet -j DROP
注意:不要忘记使更改永久生效,这样就可以了重启后自动应用。是否执行此操作取决于您的 Linux 发行版。
4. 检查它,例如在 Firefox 上运行: * `no-internet "firefox"`
5. 如果您想破例并允许程序访问本地网络:
iptables -A OUTPUT -m owner --gid-owner no-internet -d 192.168.1.0/24 -j ACCEPT
iptables -A OUTPUT -m owner --gid-owner no-internet -d 127.0.0.0/8 -j ACCEPT
iptables -A OUTPUT -m owner --gid-owner no-internet -j DROP
6. 使其永久化
在启动时应用 iptables 规则的一种方法是使用 systemd 将规则添加为服务
cat /usr/lib/systemd/system/nonet.service
[Unit]
Description=Nonet group iptable update
After=network.target
After=xsession.target
After=iptables.service
After=shorewall.service
[Service]
Type=oneshot
RemainAfterExit=true
StandardOutput=journal
ExecStart=/bin/bash /home/user/Scripts/Nonet.iptables.sh
答案4
是的,具有定制的 apparmor 配置文件,即
/usr/bin/curl {
...
# block ipv4 acces
deny network inet,
# ipv6
deny network inet6,
# raw socket
deny network raw,
}
但这样,您还需要生成允许访问的文件列表,整个过程可能有点复杂。和请参阅此处的帮助文档