web-dev-qa-db-ja.com

LinuxでUDPトラフィックを発生させているプロセスを特定するにはどうすればよいですか?

私のマシンは継続的にudp dnsトラフィック要求を行っています。私が知る必要があるのは、このトラフィックを生成するプロセスのPIDです。

TCP接続の通常の方法は、netstat/lsofを使用して、pidで関連付けられたプロセスを取得することです。

UDPは接続がステートレスであるため、netastat/lsofを呼び出すと、UDPソケットが開いていてトラフィックを送信している場合にのみ接続を確認できます。

lsof -i UDPおよびnestat -anpue、しかし、udpデータグラムが送信される前/後にlsof/netstatを呼び出すと、 UDPソケットを開きました。

3/4 udpパケットが送信されるときに正確にnetstat/lsofを呼び出します。これは不可能です。

悪名高いプロセスを特定するにはどうすればよいですか?送信されたPIDをパケットの内容から識別しようとするためにトラフィックをすでに検査していますが、トラフィックの接続から識別することはできません。

誰でも手伝ってくれる?

私はこのマシンのルートですFedora 12 Linux noise.company.lan 2.6.32.16-141.fc12.x86_64#1 SMP Wed Jul 7 04:49:59 UTC 2010 x86_64 x86_64 x86_64 GNU/Linux

39
boos

Linux監査が役立ちます。データグラムネットワーク接続を行うユーザーとプロセスを少なくとも特定します。 UDPパケットはデータグラムです。

最初に、プラットフォームにauditdフレームワークをインストールし、ルールが定義されていないと表示されていても、_auditctl -l_が何かを返すことを確認します。

次に、システムコールsocket()を監視するルールを追加し、後で簡単に見つけられるようにタグを付けます(_-k_)。 64ビットアーキテクチャを使用していると想定する必要がありますが、そうでない場合は、_b32_の代わりに_b64_を使用できます。

_auditctl -a exit,always -F Arch=b64 -F a0=2 -F a1\&=2 -S socket -k SOCKET
_

これをビルドするには、manページとヘッダーファイルを選択する必要がありますが、キャプチャするのは、基本的には次のシステムコールです:socket(PF_INET, SOCK_DGRAM|X, Y)。3番目のパラメーターは未指定ですが、多くの場合ゼロです。 _PF_INET_は2で、_SOCK_DGRAM_は2です。TCP接続は_SOCK_STREAM_を使用し、_a1=1_を設定します。(_SOCK_DGRAM_ in 2番目のパラメータは_SOCK_NONBLOCK_または_SOCK_CLOEXEC_とORで結合される可能性があるため、_&=_の比較です。)_-k SOCKET_は、監査証跡を後で検索するときに使用するキーワードです。何でもいいが、私はそれをシンプルに保つのが好きだ。

しばらくしてから、監査証跡を確認してください。必要に応じて、ネット上でホストにpingを送信することにより、いくつかのパケットを強制することができます。これにより、DNSルックアップが発生し、UDPを使用して監査アラートをトリップします。

_ausearch -i -ts today -k SOCKET
_

以下のセクションのような出力が表示されます。重要な部分を強調するために省略しています

_type=SYSCALL ... Arch=x86_64 syscall=socket success=yes exit=1 a0=2 a1=2 ... pid=14510 ... auid=zlagtime uid=zlagtime ... euid=zlagtime ... comm=ping exe=/usr/bin/ping key=SOCKET
_

上記の出力では、pingコマンドによってソケットが開かれたことがわかります。その後、まだ実行されている場合は、プロセスで_strace -p 14510_を実行できます。 ppid(親プロセスID)も、問題の子を大量に生成するスクリプトの場合に表示されます。

UDPトラフィックが多い場合、これでは十分ではなく、 OProfile または SystemTap に頼る必要があります。どちらも現在私の専門知識を超えています。

これは、一般的なケースで物事を絞り込むのに役立ちます。

完了したら、作成に使用したのと同じ行を使用して監査ルールを削除し、_-a_を_-d_に置き換えます。

_auditctl -d exit,always -F Arch=b64 -F a0=2 -F a1\&=2 -S socket -k SOCKET
_
50
zerolagtime

Netstatを使用できますが、正しいフラグが必要であり、データを送信しているプロセスがまだ生きている場合にのみ機能します。一時的に活気づき、UDPトラフィックを送信してから消えてしまったものの痕跡は見つかりません。また、ローカルのroot権限も必要です。それは言った:

ローカルホストでncatを開始し、UDPトラフィックを(存在しない)マシン10.11.12.13のポート2345に送信します。

[madhatta@risby]$ ncat -u 10.11.12.13 2345 < /dev/urandom

以下は、トラフィックが進んでいることを証明するtcpdump出力です。

[root@risby ~]# tcpdump -n -n port 2345
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
12:41:32.391750 IP 192.168.3.11.57550 > 10.11.12.13.2345: UDP, length 8192
12:41:32.399723 IP 192.168.3.11.57550 > 10.11.12.13.2345: UDP, length 8192
12:41:32.401817 IP 192.168.3.11.57550 > 10.11.12.13.2345: UDP, length 8192
12:41:32.407051 IP 192.168.3.11.57550 > 10.11.12.13.2345: UDP, length 8192
12:41:32.413492 IP 192.168.3.11.57550 > 10.11.12.13.2345: UDP, length 8192
12:41:32.417417 IP 192.168.3.11.57550 > 10.11.12.13.2345: UDP, length 8192

これが便利なビットです、-aフラグ(ポートの詳細を表示)と-pフラグを指定してnetstatを使用し、プロセスIDの詳細を表示します。 root権限が必要なのは-pフラグです。

[root@risby ~]# netstat -apn|grep -w 2345
udp        0      0 192.168.3.11:57550          10.11.12.13:2345            ESTABLISHED 9152/ncat     

ご覧のように、pid 9152は、指定されたリモートホストのポート2345への接続を開いていると見なされます。 Netstatはpsを介してそれを実行し、プロセス名はncatであると教えてくれます。

うまくいけば、それはいくつかの役に立ちます。

23
MadHatter

私はまったく同じ問題を抱えていましたが、残念ながらauditdはあまり役に立ちませんでした。

一部のサーバーからGoogle DNSアドレス8.8.8.8および8.8.4.4に向かうトラフィックがありました。現在、私のネットワーク管理者は穏やかなOCDを持っており、インターンDNSキャッシュがあるので、彼はすべての不要なトラフィックをクリーンアップしたいと考えていました。彼は、これらのキャッシュサーバー以外のすべてのユーザーに対して、発信ポート53を無効にしたいと考えていました。

したがって、auditctlで失敗した後、私は systemtap を調べます。次のスクリプトを思いつきました。

# cat >> udp_detect_domain.stp <<EOF
probe udp.sendmsg {
  if ( dport == 53 && daddr == "8.8.8.8" ) {
    printf ("PID %5d (%s) sent UDP to %15s 53\n", pid(), execname(), daddr)
  }
}
EOF

次に、単に実行します:

stap -v udp_detect_domain.stp

これは私が得た出力です:

PID  3501 (python) sent UDP to  8.8.8.8 53
PID  3501 (python) sent UDP to  8.8.8.8 53
PID  3506 (python) sent UDP to  8.8.8.8 53

それでおしまい! resolv.confを変更した後、それらのPIDは変更を反映しませんでした。


お役に立てれば :)

19
Jakov Sosic

Stap verson 1.8以降で使用可能なnetfilterプローブを使用したsystemtapオプションを次に示します。 man probe::netfilter.ip.local_outもご覧ください。

# stap -e 'probe netfilter.ip.local_out {
  if (dport == 53) # or parametrize
      printf("%s[%d] %s:%d\n", execname(), pid(), daddr, dport)
}'
ping[24738] 192.168.1.10:53
ping[24738] 192.168.1.10:53
^C
5
fche

DNS要求を表示するには、tcpdumpやWiresharkなどのネットスニファーを使用します。クエリの内容により、どのプログラムがそれらを発行しているかがわかります。

4
RedGrittyBrick

たとえば、autitctlを使用する場合、DNSクエリを実行するとき、nscdはソケットシステムコールでわずかに異なるパラメーターを使用することに注意してください。

socket(AF_INET, SOCK_DGRAM|SOCK_NONBLOCK, IPPROTO_IP)

したがって、上記のクエリに加えてこれらのクエリを確実にキャッチするために、必要に応じて同じ名前のフィルタを追加できます。

auditctl -a exit,always -F Arch=b64 -F a0=2  -F a1=2050 -S socket -k SOCKET

ここで2050はビット単位ですOR ofSOCK_DGRAM(2)andSOCK_NONBLOCK(2048)。

次に、検索によって、同じキーSOCKETを持つ両方のフィルターが見つかります。

ausearch -i -ts today -k SOCKET

私がここで見つけたソケット定数の16進値: https://golang.org/pkg/syscall/#pkg-constants

私はコメントする評判ポイントがないので、これを追加しました。

3
Silverfibre