web-dev-qa-db-ja.com

IPで特定のポートと期間のTCP接続の総数を確認するにはどうすればよいですか?

Linuxシステムでは、currentTCP接続をIPに接続することで一覧表示する方法がたくさんありますが、 :一定期間のソースIPごとのポートへの接続の総数をどのようにカウントできますか?

6
Dave Forgac

Iptablesをオンにして、着信接続に対してLOGに設定します。ルールの例:

 -A INPUT --state NEW -p tcp --dport 4711 -j LOG

(4711は追跡するポートです)。

次に、結果のログを実行して、要約を実行できる任意のスクリプトを実行します。

14
Jenny D

Tcpdumpを使用して、すべてのSYN(ACKなし)パケットをログに記録できます。

_tcpdump "dst port 4711 and tcp[tcpflags] & (tcp-syn|tcp-ack) == tcp-syn"
_

または、すべてのSYN + ACKパケット(確立された接続)をログに記録します。

_tcpdump "src port 4711 and tcp[tcpflags] & (tcp-syn|tcp-ack) == (tcp-syn|tcp-ack)"
_

そして、それを_wc -l_と組み合わせて、すべての行をカウントします

一定の期間を測定する方法も必要です(cronに一定の間隔でSIGINTを送信させることができます。tcpdumpはバイトとパケットをカウントしますが、時間のみをログに記録します)

更新:言うまでもありませんが、tcpdumpのマニュアルページを見て、次のようなオプションの使用を検討してください:_-i_(1つのインターフェイスのみをリッスンする)、_-p_(プロミスキャスモードを無効にする、侵襲性が低い)、またはいくつかの出力オプション。 Tcpdumpにはroot権限が必要ですが、ハッカーツールの一種であるため、上司はそれを気に入らない可能性があります。一方、システムを実行するためにシステム上の何にも触れる必要はありません(_iptables LOG_ソリューションとは対照的)

フィルタのsrc/dskのわずかな違いにも注意してください。 SYN + ACKパケットをキャッチし、接続をカウントしたい場合toポート4711のサーバーにはsrcが必要です。同じ結果でSYN +!ACKパケットをキャッチしている場合は、dstが必要です。サーバー自体の接続をカウントする場合は、常にその逆を使用する必要があります。

7
Daniel Alder

SystemTapソリューション

tcp_connections.stp の例に触発されたスクリプト:

#!/usr/bin/env stap
# To monitor another TCP port run:
#     stap -G port=80 tcp_connections.stp
# or
#     ./tcp_connections.stp -G port=80
global port = 22
global connections

function report() {
  foreach (addr in connections) {
    printf("%s: %d\n", addr, @count(connections[addr]))
  }
}

probe end {
  printf("\n=== Summary ===\n")
  report()
}

probe kernel.function("tcp_accept").return?,
      kernel.function("inet_csk_accept").return? {
  sock = $return
  if (sock != 0) {
    local_port = inet_get_local_port(sock)
    if (local_port == port) {
      remote_addr = inet_get_ip_source(sock)
      connections[remote_addr] <<< 1
      printf("%s New connection from %s\n", ctime(gettimeofday_s()), remote_addr)
    }
  }
}

出力:

[root@bubu ~]# ./tcp_connections.stp -G port=80
Mon Mar 17 04:13:03 2014 New connection from 192.168.122.1
Mon Mar 17 04:13:04 2014 New connection from 192.168.122.1
Mon Mar 17 04:13:08 2014 New connection from 192.168.122.4
^C
=== Summary ===
192.168.122.1: 2
192.168.122.4: 1

straceソリューション

Straceでプログラムを起動します。

strace -r -f -e trace=accept -o /tmp/strace ${PROGRAM} ${ARGS}

または、すでに実行中のプログラムをトレースします。

strace -r -f -e trace=accept -o /tmp/strace -p ${PID_OF_PROGRAM}

-r後で追加のパフォーマンス分析が必要になった場合に備えて、各システムコールへの入力時に相対タイムスタンプを出力します。 -fは子プロセスをトレースしますが、必要ない場合があります。

出力は次のようになります。

999        0.000000 accept(3, {sa_family=AF_INET, sin_port=htons(34702), sin_addr=inet_addr("192.168.122.4")}, [16]) = 5
999        0.008079 --- SIGCHLD (Child exited) @ 0 (0) ---
999        1.029846 accept(3, {sa_family=AF_INET, sin_port=htons(34703), sin_addr=inet_addr("192.168.122.4")}, [16]) = 5
999        0.008276 --- SIGCHLD (Child exited) @ 0 (0) ---
999        3.580122 accept(3, {sa_family=AF_INET, sin_port=htons(50114), sin_addr=inet_addr("192.168.122.1")}, [16]) = 5

次の方法でフィルタリングできます。

# gawk 'match($0, /^([0-9]+)[[:space:]]+([0-9.]+)[[:space:]]+accept\(.*htons\(([^)]+)\),.*inet_addr\("([^"]+)"\).*[[:space:]]+=[[:space:]]+([1-9][0-9]*)/, m) {connections[m[4]]++} END {for (addr in connections) printf("%s: %d\n", addr, connections[addr]); }' /tmp/strace
192.168.122.4: 3
192.168.122.1: 2

AKWワンライナーの簡単な説明:m[1]はPID、m[2]はタイムスタンプ、m[3]はリモートポートであり、m[4]はリモートアドレスです。

このソリューションの利点は、サーバーが同じユーザーで実行されている場合、rootが不要なことです。 欠点は、すべての接続がカウントされ、フィルタリングが行われないため、アプリケーションが複数のポートでリッスンしている場合は機能しないことです。

3

システムは、指示がない限り過去の接続のカウントを記憶しません。そのため、カウントを行うように設定しない限り、インターフェイスを介した合計トラフィックのカウンターを見つけることを期待しないでください。

また、Jacek Lakomiecが示唆しているように、一般に、ポーリングによってこのカウントを確実に行うことはできません。一部の接続は、ポーリング期間よりも速く開始および終了するためです。このようなアプローチは、接続が確立されるまでの時間が十分に長いことが確実であるいくつかの状況では受け入れられるかもしれませんが、私はそれを好む十分な理由を考えることができません。

JennyDとDanielAlderが提案しているように、接続が発生したときにカウントするためのオプションは、基本的にファイアウォールベースのカウンターとパケットキャプチャベースのカウンターです。システムにCPUの制約がある場合、パケットベースのアプローチを使用すると一部の接続のカウントに失敗する可能性があります。また、カウントを行うためにより多くのシステムリソースを消費する可能性があります。一方、パケットキャプチャベースのアプローチは、アドホック調査用に設定する方が簡単で安全です。

別の一般的なクラスのソリューションがあります。それはnetflowです。セットアップはより複雑ですが、正しく行われている場合は特に効率的です。大規模なモニタリングや継続的なモニタリングを行っている場合は、この方向を検討します。生データのキャプチャは、ファイアウォール(fprobe-uloなど)で行うか、低速のlibpcap(fprobegなど)を使用して行うことができます。キャプチャシステムは、ネットワークを介してフローデータをコレクター(nfdumpなど)に送信し、そのデータを分析するためのさまざまなツール(nfsenなど)を使用できます。

一部のルーター(特にCiscoギア)にはnetflowキャプチャが付属しており、サードパーティのファームウェアを介して他のルーターに構成することもできます。もちろん、Linuxシステムで実行することもできます。必要に応じて、多くの収集ポイントがフローデータを単一のコレクターに転送できます。フリーソフトウェアのオプションは、たとえば http://www.networkuptime.com/tools/netflow/ で見つけることができます。また、多くの商用製品もあります。

Netflowは産業規模での使用向けに設計されていますが、シェアハウスでのホームネットワークの使用に関するデータを収集するのに非常に有用であることがわかりました。

リモートサーバーのファイアウォールルールをいじるときは常に注意してください。一般に、iptablesコマンドを直接発行するのではなく、ファイアウォールを構成するための適切なフロントエンドを見つけることをお勧めします。 (私はシダが好きですが、良いものはたくさんあります)。

もう1つ検討する必要があります-場合によっては、ネットワーク層でこれを実行したくない場合があります。デーモンプロセスのシステムコールをstraceなどで監視することが適切な場合があります。 CPUを集中的に使用し、デーモンプロセスの速度を落とさないように注意してください。ただし、状況によっては、同時に収集する必要のある他の情報に応じて、または1つのフォークされた子を分離する必要がある場合に適切な場合があります。デーモンの。

2
mc0e

これまでのところ、私にとって最も効果的な解決策は、20秒ごとに/ proc/net/ip_conntrackのコンテンツを取得し、適切なタイムスタンプを含むファイル名でファイルにログインし、フィルタリングスクリプトの入力として使用することでした。必要に応じてonelinersでさえ。時間を節約するために、私のスクリプトを使用できます。私はcrontabエントリを使用して、スクリプトが毎分実行されることを確認しています(現在の構成では60秒間持続します。自由に変更してください:-)

 cat conn_minute.sh
#!/bin/bash

function save_log {
LOG_DIR=/mnt/logs/ip_conntrack/`date +%Y%m%d`
TEMP_FILE=$LOG_DIR/`date +%Y%m%d_%H%M%S`.gz
LOG_FILE=$LOG_DIR/`date +%Y%m%d_%H`.tar
if [ ! -d $LOG_DIR ]
then
    mkdir $LOG_DIR
fi
gzip -c /proc/net/ip_conntrack > $TEMP_FILE
if [ -f $LOG_FILE ]; then
    tar -rf $LOG_FILE $TEMP_FILE 2> /dev/null
else
    tar -cf $LOG_FILE $TEMP_FILE 2> /dev/null
fi
rm $TEMP_FILE
}
function log_minute {
i=1;
LOOP_COUNTER=3
LOOP_TIME=20
while [ $i -le $LOOP_COUNTER ]; do
    save_log
    i=$[i+1]
    sleep $LOOP_TIME
done
}

log_minute

LOOP_COUNTERとLOOP_TIMEを適宜変更することで、ip_conntrackのコンテンツをダンプする頻度を調整できます。したがって、5秒ごとに取得するには、LOOP_COUNTER = 12、LOOP_TIME = 5となります。 LOG_DIRは、ログが保存される場所を意味します。

その後、zcatを使用して関心のあるファイルをcatし、grepを使用して関心のあるソースIP /ポートをフィルタリングできます(または単にzgrepを使用します)。 grep -cは、あなたが求めているものをすべてカウントします。 grep src=1.2.3.4 | grep dport=63793 | sort | uniq | wc -lも使用できます。

1
Jacek Lakomiec

自分でログを書きます:

$> Nohup netstat -c | grep -E "xxx|xxxx" >> netstat_log 2>&1 &

nohubこのプロセスをバックグラウンドに移動し、ログオフ後も存続するようにします

netstat -cは、netstatが選択した情報を毎秒、継続的に、永久に出力します。

grep -E "xxx | xxxx"ポートやポートなどの目的のコンテンツを取得します

>> netstat_log ...それを "./netstat_log"に書き込みます(ここで目的のログファイルを使用します)

出力を| wc -l woud count(wc)にパイプします。その行(-l)。

0
Dai Kaixian