阻止进程的网络访问?


73

是否可以阻止单个进程的(传出)网络访问?


6
您打算如何确定流程?PID,名称,路径?
Marco Marco

1
您想阻止什么访问权限?某些程序通过localhost(到同一台计算机)使用网络访问来完成其工作。
vonbrand

Answers:


78

使用Linux 2.6.24+(在2.6.29之前被认为是实验性的),您可以为此使用网络名称空间。您需要CONFIG_NET_NS=y使用该unshare工具在内核()和util-linux中启用“网络名称空间” 。

然后,启动没有网络访问权限的过程非常简单:

unshare -n program ...

这将为该进程创建一个空的网络名称空间。也就是说,它在没有网络接口的情况下运行,包括没有环回。在下面的示例中,仅在将当前有效用户和组ID映射到超级用户ID后,才添加-r以运行程序(避免使用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

4
unshare -n似乎在没有root特权的情况下抛出“不允许操作” ,我对此有何遗漏?
baldrs

1
也许是一个愚蠢的问题...此命名空间是否也适用于未共享应用程序的子进程/被称为进程?
bonanza 2015年

3
是。切换命名空间后,所有子代都继承它。
米哈尔戈尔诺-

2
我看起来像任何我想取消共享的程序都sudo unshare -n继承了根权限。因为我需要sudo来调用unshare,所以我想知道如何确保被调用程序没有root权限。
bonanza

3
一个衬里,将过程限制于用户。只需两次sudo:sudo unshare -n sudo -u dude bash -c 'echo Hello, my name is $USER'@ThorSummoner bbs.archlinux.org/viewtopic.php?id=205240
Jakub Bochenski

21

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规则等)


尽管我需要sudo ip执行ip命令,但是一旦我进入bash,我只是执行su someuser了一个操作,以获取用户'someuser'的无特权外壳。
圣人

10

是的,具有定制的apparmor配置文件,即

/usr/bin/curl {
    ...

    # block ipv4 acces
    deny network inet,
    # ipv6 
    deny network inet6,
    # raw socket
    deny network raw,

}

但是通过这种方式,您还需要生成一个允许访问的文件列表,整个过程可能会有些复杂。并在此处查看帮助文档


10

您可以使用iptables并将该进程移至cgroup中:

mkdir /sys/fs/cgroup/net_cls/block
echo 42 > /sys/fs/cgroup/net_cls/block/net_cls.classid

iptables -A OUTPUT -m cgroup --cgroup 42 -j DROP

echo [pid] > /sys/fs/cgroup/net_cls/block/tasks

1
当我尝试通过root用户通过im从该文件中删除或删除数据时,如何从该任务文件中删除该pid的错误
pkm

@pkm以启用网络连接,您只需要向[pid]回显/sys/fs/cgroup/net_cls/tasks(路径中没有“阻止”)
悲伤

7

您可以使用firejail沙箱(应在具有seccomp功能的内核上运行)。

要使用它就做

firejail --noprofile --net=none <path to executable>

--noprofile禁用默认沙箱, --net=none禁用网络

我确实相信大多数发行版确实已经提供了软件包,但是即使发行版不发行,除构建工具链和启用了名称空间/ seccomp的内核外,firejail实际上也没有任何依赖性。

firejail还有其他一些不错的功能,可以在firejail --help联网方面显示出来(例如仅提供回送接口或阻止ip / dns等),但这应该可以完成工作。另外,它doesn't require root


5

您不能仅凭iptables做到这一点。此功能暂时存在,但无法使其可靠运行并被放弃。

如果您可以使用专用用户ID运行该进程,则iptables可以通过以下owner模块执行该操作:

iptables -A OUTPUT -m owner --uid-owner 1234 -j DROP

请参阅Iptables中的示例:将输出流量与conntrack和owner匹配。使用奇怪的dropsiptables / pf规则仅允许XY应用程序/用户使用?

如果您可以在其自己的容器中运行该进程,则可以独立对该容器进行防火墙保护(甚至使其完全与网络断开连接)。

安全模块可以过滤进程对网络功能的访问。warl0ck的答案给出了AppArmor的示例。


3

解决方案1:防火墙:

我们可以使用防火墙等DouaneOpensnitch但这些应用程序是不是100%有效的或处于发展的早期阶段(有很多的bug等,2019年的)

解决方案2:内核MAC:

内核MAC可以用作防火墙,其中最著名的是TomoyoSelinuxApparmor。 这种解决方案在稳定性和效率方面是最好的解决方案(防火墙解决方案),但是大多数情况下设置起来有些复杂。

解决方案3:Firejail:

Firejail可用于阻止不需要root用户的应用程序的网络访问,任何用户都可以从中受益

firejail --noprofile --net=none command-application

解决方案4:取消共享

Unshare可以在没有网络的情况下以不同的名称启动应用程序,但这需要root firejail的解决方案可以做几乎完全相同的事情,但不需要root

unshare -r -n application-comand

解决方案5:代理:

一种解决方案是将应用程序代理为空/伪代理。我们可以使用tsocksproxybound。这是有关设置的一些详细信息

解决方案6:Iptables:

iptables是另一个简单的解决方案,可以将其设置为阻止应用程序

  1. 创建,验证新组;将所需的用户添加到该组:
    • 创造: groupadd no-internet
    • 验证: grep no-internet /etc/group
    • 添加用户:useradd -g no-internet username

      注意:如果要修改现有用户,则应运行:用进行usermod -a -G no-internet userName 检查:sudo groups userName

  2. 在路径中创建一个脚本并将其可执行:
    • 创造: nano /home/username/.local/bin/no-internet
    • 可执行文件: chmod 755 /home/username/.local/bin/no-internet
    • 内容: #!/bin/bash
                    sg no-internet "$@"

  3. 添加iptables规则以删除组no-internet的网络活动:
    • 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

1
这是一个非常出色的指南。谢谢。尽管对我来说,我的无互联网命令似乎从未传递过该参数,所以我现在使用sg no-internet
Zach Bloomquist

@Zach我更新了我的答案,您可能对firejail感兴趣;)
intika

2

这取决于您使用的发行版,但这是操作系统的MAC系统通常包含的功能。如前所述,Ubuntu或SuSE的AppArmor可以做到这一点。如果您使用的是RHEL,则可以根据执行进程的标签将SELinux配置为允许或拒绝对特定端口号的访问。是所有后一些快速google搜索我能找到,但可能更加有深入的在线资源,如果你更努力,它给你的总体思路。


2

您可以使用seccomp-bpf阻止某些系统调用。例如,可能想阻止socket系统调用,以防止进程创建套接字FD。

我写了一个此方法的示例,该示例阻止socket使用libseccomp 进行系统调用。摘要为(不检查错误):

scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_ALLOW);
seccomp_arch_add(ctx, SCMP_ARCH_NATIVE);
seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EACCES), SCMP_SYS(socket), 1, SCMP_CMP(0, SCMP_CMP_EQ, pf));
seccomp_load(ctx);
execvp(argv[1], argv+1);

这不需要root特权。

但是,完整的沙箱要复杂得多,因此您不应使用此un命令来阻止非合作/恶意程序。


您能举一个如何使用它的例子吗?它需要root特权才能工作吗?
bonanza

-4

您可以使用称为“ proxychains”的命令行程序并尝试以下可能性之一:

设置它使用...

  • ...不存在的代理?(我不知道它是否将使用“无效”代理运行它)
  • ...限制访问互联网的本地代理(例如“ tinyproxy”,“ squid”,“ privoxy”等)?(仅使用ACL)

我自己还没有测试过,所以不知道它是否有效...


发布未经测试的解决方案通常不是一个好主意。
Twirrim

使用不存在的代理服务器(例如localhost:1234之类的代理服务器)的代理链实际上可能是一种可靠的方法,但是
phil294,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.