私のマシンは継続的に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
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
_
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
であると教えてくれます。
うまくいけば、それはいくつかの役に立ちます。
私はまったく同じ問題を抱えていましたが、残念ながら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は変更を反映しませんでした。
お役に立てれば :)
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
DNS要求を表示するには、tcpdumpやWiresharkなどのネットスニファーを使用します。クエリの内容により、どのプログラムがそれらを発行しているかがわかります。
たとえば、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
私はコメントする評判ポイントがないので、これを追加しました。