使用 Linux iptables,是否可以记录启动出站连接的进程/命令名称?

Nac*_*ack 28 linux firewall iptables

我想跟踪在 Linux 桌面上启动出站连接的进程。我能想到的最好的是:

iptables -A OUTPUT -m state --state NEW -j LOG --log-uid
Run Code Online (Sandbox Code Playgroud)

这会记录启动连接的 uid/gid,但不会记录进程/命令名称甚至 pid。如果我能得到 pid,我可能会创建一个脚本,在写入日志时提取进程名称,但这似乎是不可能的。

理想情况下,我也想记录接受传入连接的进程。

任何想法如何在 Linux 机器上使用 iptables [或其他任何东西]?

小智 9

您需要所有者匹配模块,该模块仅适用于 OUTPUT 链(可能还有 PREROUTING...?)。阅读文档,但它会像这样工作:

iptables --append OUTPUT -m owner --cmd-owner "$app" \
--jump LOG --log-level DEBUG --log-prefix "OUTPUT $app packet died: "
Run Code Online (Sandbox Code Playgroud)

  • 是的,--cmd-owner 已被删除:“无法修复的损坏” (4认同)
  • 感谢您提供的信息,@guettli。http://permalink.gmane.org/gmane.comp.security.firewalls.netfilter.general/41273 有更多细节,其中引用了更多变更日志:*“[NETFILTER]:删除 ipt{,6} 中的 tasklist_lock 滥用所有者;删除 cmd/sid/pid 匹配,因为它无法修复,并且妨碍了对 tasklist_lock 的锁定更改。”* 但我仍然想要更多背景知识或更好的替代方案。 (2认同)

Ben*_*ins 7

您可以编写一个程序来监视 /proc/net/tcp,其输出如下所示:

obi-wan ~ # cat /proc/net/tcp
  sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode
   0: 00000000:0050 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 4847458 1 e6060560 300 0 0 2 -1
   1: 00000000:04D2 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 4847477 1 f2e64da0 300 0 0 2 -1
   2: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 7109 1 f2e65ac0 300 0 0 2 -1
   3: 0100007F:177A 00000000:0000 0A 00000000:00000000 00:00000000 00000000  1000        0 4864457 1 d2726540 300 0 0 2 -1
   4: 00000000:01BB 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 4847462 1 e60609c0 300 0 0 2 -1
   5: 6B00A8C0:0016 30F4B5CA:C3AB 01 00000044:00000000 01:00000031 00000000     0        0 4982752 3 f2e64940 55 4 0 2 -1
   6: 0100007F:B143 0100007F:BC5E 01 00000000:00000000 00:00000000 00000000  1000        0 2130283 1 d59cce40 21 4 1 2 -1
   7: 0100007F:BC5E 0100007F:B143 01 00000000:00000000 00:00000000 00000000  1000        0 2130285 1 d59cd2a0 21 4 0 2 -1
   8: 6B00A8C0:0016 3276C35B:8E11 01 00000000:00000000 02:000ADAB1 00000000     0        0 4982629 2 d2727260 40 4 8 2 2
   9: 6B00A8C0:0016 6500A8C0:DD5D 01 00000538:00000000 01:00000029 00000000     0        0 4864416 5 e6061b40 42 12 27 3 -1
Run Code Online (Sandbox Code Playgroud)

然后,您可以将打开的端口与 inode 相关联,通过对为每个进程列出的文件描述符执行 readlink,可以将这些端口与进程和文件描述符相关联:

obi-wan ~ # readlink /proc/28850/fd/3
socket:[4847458]
Run Code Online (Sandbox Code Playgroud)

在这里看到 inode 4847458 对应于上面列表中的第一个 tcp 套接字。netstat -tapn 的输出为我验证了这一点(还记得 0x50 == 80):

obi-wan ~ # netstat -tapn
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN     28850/cherokee-work
Run Code Online (Sandbox Code Playgroud)

当监控程序注意到 /proc/net/tcp 发生变化时,解析数据并确定变化是否是新打开的套接字。然后,您可以枚举 /proc 中列出的每个进程的所有文件描述符,对每个进程执行 readlink 以找到匹配的 inode。一旦你找到了,你就有了自己的 pid,你可以从中得到任何你想要的东西,特别是如果你有进程会计。

如果您不需要即时通知,那么您的监控程序可以使用慢速轮询(可能是 50 毫秒或 100 毫秒,甚至 1000 毫秒)。

  • 感谢您提供一个选项!但是每次都需要轮询和查询每个打开的文件描述符不是很健壮,而且效率很低。我仍然希望有人能找到更好的解决方案,或者澄清为什么这不再是 iptables 的一部分,以及为什么 --cmd-owner 被认为是不可修复的。 (2认同)

小智 5

与 iptables 或日志记录无关;但这里有一个类似于“顶部”的界面,它轮询 /proc/ 目录并显示每个程序/pid 的带宽:

http://sourceforge.net/projects/nethogs

“NetHogs 是一个小型的 'net top' 工具。它不像大多数工具那样按协议或每个子网分解流量,而是按进程对带宽进行分组。NetHogs 不依赖于要加载的特殊内核模块。“