如何通过IP查找给定端口和时间段的TCP连接总数?

在Linux系统中,有很多方法可以通过连接IP列出给定端口的当前 TCP连接,但是: 如何计算每个源IP在一段时间内连接到端口的总数?

打开iptables并将其设置为LOG以传入连接。 示例规则:

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

(其中4711是你想跟踪的港口)。

然后通过你喜欢的任何脚本运行生成的日志,可以为你做总结。

您可以使用tcpdumplogging所有SYN(无ACK)数据包:

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

或logging所有SYN + ACK数据包(build立的连接):

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

然后将它与一个wc -l结合来统计所有行

您还需要一种方法来测量固定的时间段(您可以让cron定期发送一个SIGINT,tcpdump会计算字节和数据包,但只logging时间)

更新:不必说,看看tcpdump的手册页,并考虑使用一些选项,如: -i (只听一个接口),- -p (禁用混杂模式;较less入侵),或一些输出选项。 Tcpdump需要root权限,你的老板可能不喜欢它,因为它是一种黑客工具。 另一方面,您不需要触摸系统上的任何东西来运行它(与iptables LOG解决scheme相反)

还请注意filter中的小src / dsk差异。 如果您捕获SYN + ACK数据包并且想要在端口4711处统计服务器的连接,则需要src。 如果捕获SYN +!ACK数据包的结果相同,则需要dst。 如果您计算服务器本身的连接数,则必须始终使用相反的值。

SystemTap解决scheme

脚本受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解决scheme

在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跟踪subprocess,可能不需要。

输出看起来像这样:

 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]是远程地址。

此解决scheme的优点是,如果服务器在同一用户下运行,则不需要root。 缺点是所有连接都被计数,没有过滤,所以如果应用程序在多个端口上侦听,它将不起作用。

除非你告诉它,否则你的系统将不会记得过去连接的计数,所以不要指望find类似于通过接口的总stream量的计数器,除非你设置了一些计数。

另外,一般来说,你不能可靠地通过投票来进行计数,正如Jacek Lakomiec所build议的那样,因为有些连接将比你的投票时间开始和结束得更快。 这种方法在某些情况下可能是可以接受的,在这种情况下,你确定时间连接的时间足够长,但是我不能想到有更好的理由去select它。

正如Jenny D和Daniel Alder所build议的那样,在发生连接时对连接进行计数的选项基本上是基于防火墙的计数器和基于数据包捕获的计数器。 两者通常都能正常工作,但是如果你的系统受到CPU的限制,如果你使用基于数据包的方法,那么你可能无法计算一些连接,并且可能会消耗更多的系统资源来进行计数。 另一方面,基于数据包捕获的方法可以更简单,更安全地进行临时调查。

还有另外一个通用的解决scheme,就是netflow。 它的build立更为重要,但是如果做得对,这样做效率特别高,如果你正在进行大规模的或持续的监测,我会朝这个方向看。 捕获原始数据可以在防火墙(例如fprobe-ulo)中使用,也可以使用较慢的libpcap(例如fprobeg)。 捕获系统通过networking将stream量数据发送到收集器(例如nfdump),然后您可以使用各种工具分析数据(例如nfsen)。

一些路由器(尤其是思科设备)带有netflow捕获function,也可以通过第三方固件将其configuration到其他路由器上,当然也可以在Linux系统上运行。 如果您愿意,许多收集点可以将其stream量数据转发给单个收集器。 您可以在http://www.networkuptime.com/tools/netflow/find免费的软件选项,也有很多商业产品&#x3002;

Netflow是为工业规模使用而devise的,但是我发现它非常有用,可以在共享networking中收集有关使用家庭networking的数据,以便在stream量使用率高于预期时确定究竟由谁来负责。

任何时候你在远程服务器上搞乱防火墙规则时都要小心,总的来说,我build议找一个好的前端来configuration你的防火墙,而不是直接发出iptables命令。 (我喜欢ferm,但是有很多好的)。

还有一件事要考虑 – 有时候你根本不想在networking层做这个事情。 有时用strace或类似的方式来监视守护进程的系统调用是合适的。 这是CPU密集型的,要小心放慢守护进程,但在某些情况下,它可能是适当的,主要取决于你需要同时收集什么其他信息,或者如果你需要孤立一个分叉的孩子的守护进程。

到目前为止,最适合我的解决scheme是每隔20秒捕获一次/ proc / net / ip_conntrack的内容,将其logging到文件名中包含适当的时间戳的文件中,并将其用作任何过滤脚本的input,或甚至在必要的时候也可以打线。 为了节省您的时间,您可以使用我的脚本。 我使用crontab条目来确保脚本每分钟运行一次(它在当前configuration中持续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来扫描您感兴趣的文件,并使用grep来过滤您感兴趣的源IP /端口(或者使用zgrep)。 grep -c会计算你以后的任何东西。 你也可以使用grep src=1.2.3.4 | grep dport=63793 | sort | uniq | wc -l grep src=1.2.3.4 | grep dport=63793 | sort | uniq | wc -l grep src=1.2.3.4 | grep dport=63793 | sort | uniq | wc -l

看一下

  • darkstat ,

  • iplog ,

  • iptraf ,

  • BWM-NG

  • 的NTOP

  • vnstat

。 他们都有点陈旧,但写脚本去做其他人做得更好的工作是无聊的。 一些给你漂亮的图片,一些更专注于法医分析和拧坏坏人,一些(iplog)只是真正简单的计数器login到数据库,一些shiny的前端,你可以告诉你的老板。

还有一大堆工具可以在Linux上实现一个免费的netflow兼容堆栈。 还有一大群人试图在这方面出售支持。 (我不打算推​​荐一个商业产品…)你所要求的比其中一些能够做到的要简单得多。

恕我直言(免费|networking|开放)BSD已经遥遥领先于多年的分析。 一个pFsense防火墙会给你至less7个选项。