现象

工作中遇到这样一个问题,想查一下本机的某个进程偶尔会请求一个已知的目标IP和端口,但是由于流量很小,连接时间很短,使用netstat命令最多只能抓到处于TIME_WAIT状态的连接,看不到这个连接属于哪个进程。

思路

在这种很少量、连接时间很短的场景下,netstat、ss这类命令很难起到作用。可以借助auditd系统服务来抓取connect的系统调用,从而定位到对应的进程。

解决

  1. 首先确保auditd服务在运行,使用ps aux | grep auditd查看进程存在,没有运行的话就用service auditd start等系统工具启动起来。
  2. 执行以下命令设置一条audit规则,用来抓取connect系统调用的信息并记录到audit日志:
    auditctl -a exit,always -F arch=b64 -S connect -k MYCONNECT

    其中arch=b64表示是64位系统,如果是32位可以换成arch=b32,不设置这个参数会报WARNING,但貌似不影响规则设置成功。

  3. 上述规则设置成功后,/var/log/audit/audit.log中就会出现记录connect系统调用的日志,同时会有对应的PID、进程命令、对端IP、端口等信息,但是IP和端口都是16进制表示的,不易看懂。
    这里建议同时使用tcpdump抓包,只要抓到包,就说明有连接建立,然后可以使用ausearch工具搜索到对应的audit日志。比如要查对端IP是10.69.0.35的连接,就可以执行:

    ausearch -hn 10.69.0.35

    可以看到类似以下的结果:

    time->Wed May 16 15:32:01 2018
    type=SOCKADDR msg=audit(1526455921.178:3910574): saddr=02001F900A4500230000000000000000
    type=SYSCALL msg=audit(1526455921.178:3910574): arch=c000003e syscall=42 success=no exit=-115 a0=30 a1=c4523e860c a2=10 a3=0 items=0 ppid=1 pid=18782 auid=0 uid=500 gid=500 euid=500 suid=500 fsuid=500 egid=500 sgid=500 fsgid=500 tty=(none) ses=3377 comm="" exe="/opt/work/bin/ssagent" key="MYCONNECT"

    其中saddr=02001F900A4500230000000000000000中包含了目的端口8080(16进制是1F90),目的地址10.69.0.35(16进制是0A450023)。另一行中则包含了发起连接的PID是18782,进程命令是exe="/opt/work/bin/ssagent"

  4. 确定了是哪个进程,接下来就是业务层面的事情了。排查完后不要忘了清除刚才的规则,把添加规则的命令的-a换成-d即可:
    auditctl -d exit,always -F arch=b64 -S connect -k MYCONNECT

注意事项

开启规则后,如果机器本身网络很繁忙,有频繁的网络连接建立,可能会导致audit日志增长很快,而audit默认配置的日志文件比较小,可能会导致自己想要抓的连接日志很快就被覆盖删除了,可以通过/etc/audit/auditd.conf适当增大设置。当然也要注意磁盘空间,不宜太大。并且测试完后记得改回配置。

参考链接

本文基本上是参考下面的链接,经过实际测试写成,链接里也提供了IP地址的16进制转换网址:
https://serverfault.com/questions/352259/finding-short-lived-tcp-connections-owner-process?answertab=active#tab-top