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

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

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

iptables -A OUTPUT -m state --state NEW -j LOG --log-uid

这会记录发起连接的 uid/gid,但不会记录进程/命令名称,甚至不会记录 pid。如果我能获取 pid,我可能会编写一个脚本,在写入日志时提取进程名称,但这似乎根本不可能。

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

有什么想法可以在 Linux 机器上使用 iptables [或其他任何东西] 来实现这一点吗?

答案1

你可以编写一个程序来监视/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

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

obi-wan ~ # readlink /proc/28850/fd/3
socket:[4847458]

在此处看到 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

当监控程序注意到 /proc/net/tcp 中的变化时,解析数据并确定变化是否是新打开的套接字。然后,您可以枚举 /proc 中列出的每个进程的所有文件描述符,对每个进程执行 readlink 以找到匹配的 inode。一旦找到,您就有了所属的 pid,您可以从中获得您可能需要的任何其他信息,特别是如果您启用了进程记帐。

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

答案2

您需要所有者匹配模块,它仅在 OUTPUT 链上起作用(也许是 PREROUTING……?)。阅读文档,但它的工作方式如下:

iptables --append OUTPUT -m owner --cmd-owner "$app" \
--jump LOG --log-level DEBUG --log-prefix "OUTPUT $app packet died: "

答案3

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

http://sourceforge.net/projects/nethogs

“NetHogs 是一款小型‘网络流量统计’工具。它不像大多数工具那样按协议或子网细分流量,而是按进程分组带宽。NetHogs 不依赖于加载特殊内核模块。”

答案4

您可以ss在 Linux 上使用命令执行此操作。我在 Debian 10 和 Ubuntu 20.04 上使用了它。

命令如下:

ss --extended --processes --ipv4 -o state all '( dport = :ssh )'

该命令列表处理从机器启动到端口 22 的连接。

就是这样。请阅读 ss man 了解详细信息。

相关内容