数週間前、約300ノードの大規模ネットワークでDNSアドレスを変更するという問題がありました。その後、一部のノードは引き続き古いDNSサーバーに問い合わせを続けましたが、resolv.confは問題なく、Host/nslookupは新しいDNSサーバーをクエリしていました。
Tcpdumpを調べ、iptablesロギングでリクエストを記録しようとすると、実際に一部のホストがまだ古いネームサーバーにクエリを送信していることを確認しました。
ホストの1つを本番環境から外し、原因を特定するためにサービスの停止/プロセスの追跡を開始しました。
最後に、それはlldpdデーモンでした。これは明らかに起動時にネームサーバーをキャッシュし、resolv.confの変更にさえ気づきませんでした。
だから、私の質問は-特定の種類のトラフィックを生成しているPIdを見つけるよりインテリジェントな方法はありますか?私はauditctlで試しましたが、あまり成功しませんでした。 CentOS 6は問題ですが、Linuxディストリビューションの解決策がある場合は、それを感謝します。
Auditctlの何が問題になっていますか?
あなたはこのようにします
1)sendmsgおよびsendtoシステムコールを監査するための監査ルールを定義します。これらのシステムコールは、名前解決時に使用されます。
auditctl -a exit,always -F Arch=b64 -S sendmsg -S sendto -k send
2)次に、監査レコードを検索します。ここでリモートDNS IPに基づいてgrepできます
ausearch -k send -i|grep -A2 "serv:53"
以下の例では、システムコールを担当したアプリケーションがDigと呼ばれていることがわかります。
ausearch -k send -i|grep -A2 "serv:53"
type=SOCKADDR msg=audit(10/31/2016 15:24:56.264:176998) : saddr=inet Host:172.16.0.23 serv:53
type=SYSCALL msg=audit(10/31/2016 15:24:56.264:176998) : Arch=x86_64 syscall=sendmsg success=yes exit=29 a0=14 a1=7fa1919f9ac0 a2=0 a3=7fa1919f9780 items=0 ppid=31729 pid=32047 auid=root uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=pts5 ses=52 comm=Dig exe=/usr/bin/Dig subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key=send
comm=Dig exe=/usr/bin/Dig
また、送信先のリモートDNS要求を区別する方法はこちらです。したがって、特定のDNSホストに対してgrepを実行する必要があります。
saddr=inet Host:172.16.0.23 serv:53
またはさらに良い-使用されているDNSホストを確認する(この例では1つしかありません)
ausearch -k send -i|grep "serv:53"|awk '{print $6}'|sort|uniq -c
3 Host:172.16.0.23
次に、これらの特定のホストを使用しているアプリを絞り込みます。
編集1:実際には、ホストへの単純なpingのトレースを行いました。 sendmsgが常に使用されているわけではないようです。これが私が見るものです
socket(PF_INET, SOCK_DGRAM|SOCK_NONBLOCK, IPPROTO_IP) = 4
connect(4, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("172.16.0.23")}, 16) = 0
gettimeofday({1477929832, 712018}, NULL) = 0
poll([{fd=4, events=POLLOUT}], 1, 0) = 1 ([{fd=4, revents=POLLOUT}])
sendto(4, "\3\326\1\0\0\1\0\0\0\0\0\0\tvkontakte\2ru\0\0\1\0\1", 30, MSG_NOSIGNAL, NULL, 0) = 30
poll([{fd=4, events=POLLIN}], 1, 5000) = 1 ([{fd=4, revents=POLLIN}])
ioctl(4, FIONREAD, [62]) = 0
recvfrom(4, "\3\326\201\200\0\1\0\2\0\0\0\0\tvkontakte\2ru\0\0\1\0\1\300\f"..., 1024, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("172.16.0.23")}, [16]) = 62
close(4) = 0
私の前の例はDigアプリに基づいており、システムコールの点で少し異なるルートをとります。
したがって、ほとんどの場合、このルールになるように見えます
auditctl -a exit,always -F Arch=b64 -S connect -k connect
Ausearchが続きます
ausearch -k connect -i|grep saddr|grep "serv:53"|awk '{print $6}'|sort|uniq -c
数日前に同じ問題に取り組み、非常に簡単な方法を思いつきました。これは、送信プロセスが、要求を送信したのと同じポートでDNS応答が来るのを待つという事実に基づいています:
iptables -j LOG
を使用して、発信DNS要求の送信元ポートを見つけます。lsof -i UDP:<source_port>
を使用して、そのポートで応答を待っているプロセスを見つけます。もちろん、応答はミリ秒以内に届くため、手動で行うことはできません。さらに、自動化されている場合でも、DNS応答が到着して送信プロセスが停止する前にシステムにクエリを実行できるとは限りません。そのため、上記の手順を実行する前に、特定のip/portに送信されるパケットをdelay送信するようにカーネルトラフィックコントローラーも構成します(tc
モジュールを使用) netem
)。これにより、手順1で取得したソースUDPポートで、PIDがDNS応答を待機しているシステムを照会する必要がある時間枠を制御できます。
tc
遅延を含む上記の手順を ptrap と呼ばれる小さなスクリプトで自動化しました(これはより一般的なソリューションであり、DNSリクエストに限定されないため、プロセスの検出に適しています) TCP/UDPベースのプロトコルを使用)。その助けを借りて、私の場合、古いDNSサーバーに接続するサービスはsendmailであることがわかりました。
netstat
には、tcp/udp/bothでのリスニング/オープンソケットの組み合わせを示す多くのオプションがあります。何かのようなもの:
$> Sudo netstat -pan
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Addr Foreign Addr State PID/Program name
...
tcp 0 1 192.168.66.1:39219 192.168.66.139:2003 SYN_SENT 2045/logstash-forwa
...多くの出力が得られるはずですが、ソース、宛先、ポート番号、およびそれらのポートを所有するプロセスのPIDが含まれています。
atop
があります。カーネルモジュール(netatop
)とデーモンがあり、atop
がプロセスごとにネットワークの使用状況を追跡します。
最初にatop
をインストールする必要があります
カーネルモジュールのインストール方法を次に示します。これは投稿が書かれたときに有効ですが、古くなる可能性があります:
Sudo apt install linux-headers-$(uname -r) make zlib1g-dev
wget https://www.atoptool.nl/download/netatop-2.0.tar.gz
tar xvf netatop-2.0.tar.gz
cd netatop-2.0
make
Sudo make install
Sudo modprobe -v netatop
Systemdを使用している場合は、netatopd.service
にサービスファイル/etc/systemd/system/
ファイルを作成します。それは含まれます:
[Unit]
Description=NetAtop Daemon
[Service]
Type=forking
ExecStart=/usr/sbin/netatopd
[Install]
WantedBy=multi-user.target
これでデーモンを有効にできます:
Sudo systemctl enable netatopd
プロセスごとのライブネットワーク使用状況を表示するには:
Sudo atop -n
1日を通してネットワーク負荷の高い上位3つを表示するには:
atopsar -N
その他のオプションについては、man atopsar
。
lsof
は、特定のポートを監視し、そのポートでトラフィックを生成しているPIDを特定するための適切なツールです。たとえば、ここではDNS /ドメインTCPポート53のサーバーを監視しているため、DNSルックアップの原因となっているPIDを特定できます。
$ lsof -PniTCP:53 -r 1 | grep :53
ここで、curl
トラフィックをDNSサーバーに送信するとします。
$ curl -v telnet://192.168.3.182:53
* About to connect() to 192.168.3.182 port 53 (#0)
* Trying 192.168.3.182...
* Connected to 192.168.3.182 (192.168.3.182) port 53 (#0)
上記のコマンドからのこのタイプの出力が表示されます。
curl 4953 root 3u IPv4 197807920 0t0 TCP 192.168.23.48:50688->192.168.3.182:53 (ESTABLISHED)
curl 4953 root 3u IPv4 197807920 0t0 TCP 192.168.23.48:50688->192.168.3.182:53 (ESTABLISHED)
curl 4953 root 3u IPv4 197807920 0t0 TCP 192.168.23.48:50688->192.168.3.182:53 (ESTABLISHED)
ポート53トラフィックを監視する上記のコマンドは、lsof
を1秒ごとに実行される繰り返しループ-r 1
に入れることで機能します。次に、lsof
に、ポート53、iTCP:53
を使用するトラフィックのみを報告するように指示します。 -Pn
は、実際の名前ではなく、ホスト名とポートを数字として表示するようにlsof
に指示します。
次に、grep
を使用してlsof
からの出力を読み取り、:53
ポートトラフィックのみが表示されるように出力をフィルター処理します。
トラフィックを送信しているプロセスのPIDは、lsof
によって示されている出力にも含まれています。 2列目はPID 4953を示しています。