我正在运行基于 Debian 的 VPS (Linux vps 2.6.32-042stab092.3 #1 SMP Sun Jul 20 13:27:24 MSK 2014 x86_64 GNU/Linux),它的行为有点奇怪。每当与其建立新连接时,它都会执行 PTR 查找。
我正在端口 80 上运行一些性能测试,其中远程计算机上的 Python 脚本不断获取 VPS 上的页面。对于每个页面请求,都会进行新的 PTR 查找,最终产生数千个活动 DNS 请求。
我正在用 监控这一点tcpdump -n port not 22 and host not MY_REMOTE_IP
。-n
防止查找也是如此。
我还使用 进行监视ntop
,其中还使用了 -n 。
如果我停下ntop
来看看tcpdump
,我就会得到查找。如果我停下来tcpdump
再开始ntop
,我也会得到它们。因此,可以公平地假设它们都没有引起查找。
还有xinetd
在后台运行,显然也使用 PTR 查找。但如果我停止该服务,查找仍然会发生。
然后/usr/sbin/rsyslogd -c5
,当被杀时,也不会改变情况。
rabbitmq-server
和 erlangs也是如此epmd
。authbind
似乎也没有责任,并且screen
通常openvpn
作为服务器运行的 stop 也没有什么区别。
究竟是什么原因导致了这种情况?
这是进程树。
init
`- SCREEN -AmdS py-http authbind python server.py ---scr:py-http
| `- python server.py ---scr:py-http
`- /sbin/getty 38400 tty2
`- /sbin/getty 38400 console
`- /bin/sh /usr/sbin/rabbitmq-server
| `- /usr/lib/erlang/erts-5.9.1/bin/beam.smp -W w -K true -A30 -P 1048576 -- -root /usr/lib/erlang -progname erl -- -home /var/lib/rabbitmq -- -pa /us
t start_sasl -config /etc/rabbitmq/rabbitmq -kernel inet_default_connect_o
| `- inet_gethost 4
| | `- inet_gethost 4
`- /usr/lib/erlang/erts-5.9.1/bin/epmd -daemon
`- /usr/sbin/ntop -d -L -u ntop -P /var/lib/ntop --access-log-file /var/log/ntop/access.log -i venet0:0 -p /etc/ntop/protocol.list -O /var/log/ntop
`- /usr/bin/mongod --config /etc/mongod.conf
`- /usr/sbin/cron
`- /usr/sbin/xinetd -pidfile /var/run/xinetd.pid -stayalive -inetd_compat -inetd_ipv6
`- /usr/sbin/sshd
| `- sshd: user [priv]
| `- sshd: user@pts/0
| `- -bash
| `- htop
`- sendmail: MTA: accepting connections
`- /usr/sbin/openvpn --writepid /var/run/openvpn.server.pid --daemon ovpn-server --cd /etc/openvpn --config /etc/openvpn/server.conf
`- /usr/sbin/saslauthd -a pam -c -m /var/run/saslauthd -n 2
| `- /usr/sbin/saslauthd -a pam -c -m /var/run/saslauthd -n 2
`- /usr/sbin/rsyslogd -c5
`- upstart-socket-bridge --daemon
`- /sbin/udevd --daemon
| `- /sbin/udevd --daemon
| `- /sbin/udevd --daemon
`- upstart-udev-bridge --daemon
更新
此查找发生在每个新连接上,无论是端口 80 还是 22,任何端口,无论是哪个端口。
结果来自斯特雷斯对于一个 HTTP 请求
sendto(10, "C~\1\0\0\1\0\0\0\0\0\0\0016\00270\003168\003192\7in-add"..., 43, MSG_NOSIGNAL, NULL, 0) = 43
print statement in server.py -> request #5 from client 192.168.70.6
sendto(10, "\23\372\1\0\0\1\0\0\0\0\0\0\0016\00270\003168\003192\7in-add"..., 43, MSG_NOSIGNAL, NULL, 0) = 43
sendto(9, "HTTP/1.1 200 OK\r\nDate: Fri, 24 O"..., 146, 0, NULL, 0) = 146
系统挖掘无法使用,因为无法安装在VPS上
iptables日志记录会产生以下条目: 对于新的 ssh 连接:
Oct 24 06:06:11 vps kernel: [6547020.638594] DNS Traffic match:IN= OUT=venet0 SRC=VPS_IP_ADDRESS DST=8.8.8.8 LEN=99 TOS=0x00 PREC=0x00 TTL=64 ID=56490 DF PROTO=UDP SPT=50366 DPT=53 LEN=79 UID=0 GID=0
对于新的 http 连接:
Oct 24 06:06:53 vps kernel: [6547062.417763] DNS Traffic match:IN= OUT=venet0 SRC=VPS_IP_ADDRESS DST=8.8.8.8 LEN=71 TOS=0x00 PREC=0x00 TTL=64 ID=32702 DF PROTO=UDP SPT=59091 DPT=53 LEN=51 UID=1000 GID=1000
SS结果是
ESTAB 0 0 VPS_IP_ADDRESS:42414 8888:53 users:(("python",2375,10))
答案1
首先,我会注意到您共享的进程树中对 ntop 的调用似乎没有该-n
标志:
/usr/sbin/ntop -d -L -u ntop -P /var/lib/ntop --access-log-file /var/log/ntop/access.log -i venet0:0 -p /etc/ntop/protocol.list -O /var/log/ntop
但我认为鉴于您关于即使 ntop 被杀死查询仍在继续的陈述,这不是问题。此外,为了澄清,我假设执行查找的机器与处理端口 80 上的请求是同一台机器。
鉴于此,以下是一些调试思路:
SS
如果相关程序将套接字保留一段时间,您可能可以使用ss
(或 netstat)和该-p
标志来查找您应该在 tcpdump 中看到的源端口的所有者。
斯特雷斯
第一个嫌疑人应该是处理请求的应用程序。我假设屏幕下运行的以下 python 进程是您正在测试的应用程序?
`- SCREEN -AmdS py-http authbind python server.py ---scr:py-http
| `- python server.py ---scr:py-http
您可以考虑在 strace 下运行此进程并查看它是否正在生成 DNS 流量。例如:
strace -e trace=sendmsg,sendto -f YOUR_PROGRAM_HERE
然后仔细查看输出中是否有看起来像是发送到端口 53 的消息:
[pid 3367] sendmsg(20, {msg_name(16)={sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("192.168.1.254")}, msg_iov(1)=[{"\31\322\1\0\0\1\0\0\0\0\0\0\0014\0014\0018\0018\7in-addr\4arp"..., 38}], msg_controllen=0, msg_flags=0}, 0) = 38
ss 循环
如果相关程序快速关闭其套接字,则可能很难从 ss 或 netstat 获取有关它的信息。
然而,我们的一种可能性是编写一个ss
重复轮询命令的脚本。你可以打赌你足够幸运,能够捕获其中一个查找:
while true; do ss -p -n -u | tail -n +2; done
如果您在该计算机上看到大量其他 UDP 流量,可以向 ss 命令添加过滤器来缩小范围。这是否有效取决于你的运气。
系统挖掘
您可以使用相对较新的sysdig
查看所有 sendmsg 或 sendto 系统调用的实用程序:
sudo sysdig evt.type=sendmsg or evt.type=sendto | grep ':53'
输出将包含进程名称(在本例中为 nslookup):
47852 01:15:33.454946732 4 nslookup (3349) > sendmsg fd=20(<4>) size=38 tuple=0.0.0.0:49847->192.168.1.254:53
iptables
iptables 允许您记录生成数据包的进程的用户 ID。如果您的大多数服务都以同一用户身份运行,则这不会有太大帮助,但如果您有特定于服务的用户,则可能会很有帮助。一组iptable规则如下:
iptables -N LOGGING
iptables -A OUTPUT -p udp --dport 53 -j LOGGING
iptables -A LOGGING -j LOG --log-prefix="DNS Traffic match:" --log-uid
将记录具有关联 UID 的所有出站 dns 流量。根据您的日志记录设置,您可以通过 kmesg 或系统日志消息所在的位置找到此信息,输出将类似于:
Oct 24 01:09:53 localhost.localdomain kernel: DNS Traffic match:IN= OUT=enp0s3 SRC=10.0.2.15 DST=192.168.1.254 LEN=66 TOS=0x00 PREC=0x00 TTL=64 ID=35264 PROTO=UDP SPT=51767 DPT=53 LEN=46 UID=1000 GID=1000
从这个输出中我可以看到相关进程的 UID 为 1000,这至少缩小了我的搜索范围。