#!/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
此外,一般来说,正如 Jacek Lakomiec 所建议的那样,您不能可靠地通过轮询来进行计数,因为某些连接的开始和结束速度会比轮询周期快。在某些情况下,这种方法可能是可以接受的,因为您确定建立连接的时间足够长,但我想不出更好的理由来选择它。
正如 Jenny D 和 Daniel Alder 所建议的,您在连接发生时对连接进行计数的选项基本上是基于防火墙的计数器和基于数据包捕获的计数器。两者通常都能很好地工作,但如果您的系统受 CPU 限制,如果您使用基于数据包的方法,您可能无法计算某些连接,并且可能会消耗更多的系统资源来进行计数。另一方面,基于数据包捕获的方法可以更简单、更安全地设置用于临时调查。
打开 iptables 并将其设置为
LOG
用于传入连接。示例规则:(其中 4711 是您要跟踪的端口)。
然后通过您喜欢的任何脚本运行生成的日志,以便为您做摘要。
您可以使用 tcpdump 记录所有 SYN(无 ACK)数据包:
或记录所有 SYN+ACK 数据包(已建立的连接):
然后将它与 a 结合起来
wc -l
计算所有行您还需要一种测量固定时间段的方法(您可以让 cron 定期向其发送 SIGINT,tcpdump 将计算字节和数据包,但只记录时间)
更新:没必要说,看看 tcpdump 的手册页并考虑使用一些选项,如:(
-i
只听一个接口)、-p
(禁用混杂模式;侵入性较小)或一些输出选项。Tcpdump 需要 root 权限,你的老板可能不喜欢它,因为它是一种黑客工具。另一方面,您不需要触摸系统上的任何东西来运行它(与iptables LOG
解决方案相反)还请注意过滤器中的小 src/dsk 差异。如果您捕获 SYN+ACK 数据包并想计算到端口 4711 的服务器连接数,则需要 src.src。如果您要捕获 SYN+!ACK 数据包以获得相同的结果,则需要 dst。如果您计算服务器本身的连接数,则始终必须使用相反的方法。
SystemTap 解决方案
受tcp_connections.stp示例启发的脚本:
输出:
strace 解决方案
在 strace 下启动程序:
或跟踪已经运行的程序:
-r
在进入每个系统调用时打印一个相对时间戳,以防以后需要进行额外的性能分析。-f
跟踪子进程,可能不需要它。输出看起来像这样:
并且可以通过以下方式过滤:
AKW one-liner的简短解释:
m[1]
是PID,m[2]
是时间戳,m[3]
是远程端口,m[4]
是远程地址。此解决方案的优点是,如果服务器在同一用户下运行,则不需要 root。缺点是所有连接都被计算在内,没有过滤,所以如果应用程序监听多个端口,它就不起作用。
除非您告诉系统,否则您的系统不会记住过去连接的计数,因此不要期望找到像您一样通过接口的总流量的计数器,除非您设置了一些东西来进行计数。
此外,一般来说,正如 Jacek Lakomiec 所建议的那样,您不能可靠地通过轮询来进行计数,因为某些连接的开始和结束速度会比轮询周期快。在某些情况下,这种方法可能是可以接受的,因为您确定建立连接的时间足够长,但我想不出更好的理由来选择它。
正如 Jenny D 和 Daniel Alder 所建议的,您在连接发生时对连接进行计数的选项基本上是基于防火墙的计数器和基于数据包捕获的计数器。两者通常都能很好地工作,但如果您的系统受 CPU 限制,如果您使用基于数据包的方法,您可能无法计算某些连接,并且可能会消耗更多的系统资源来进行计数。另一方面,基于数据包捕获的方法可以更简单、更安全地设置用于临时调查。
还有另一类通用的解决方案,即 netflow。设置起来更复杂,但如果做得好,它会特别有效,如果你正在进行大规模或持续监控,我会朝这个方向看。捕获原始数据可以在您的防火墙中完成(例如 fprobe-ulo)或使用速度较慢的 libpcap(例如 fprobeg)。捕获系统通过网络将流数据发送到收集器(例如 nfdump),然后您可以使用各种工具来分析该数据(例如 nfsen)。
一些路由器(尤其是cisco gear)自带netflow capture,也可以通过第三方固件配置到其他路由器中,当然你也可以在你的linux系统上运行它。如果您愿意,许多收集点可以将其流量数据转发到单个收集器。您可以在例如http://www.networkuptime.com/tools/netflow/找到免费软件选项,并且还有许多商业产品。
Netflow 专为工业规模使用而设计,但我发现它非常适用于收集有关在共享房屋中使用家庭网络的数据,这样当流量使用率高于预期时,我就可以确定谁或什么负责。
任何时候你在远程服务器上弄乱防火墙规则时都要小心,一般来说,我建议你找一个好的前端来配置你的防火墙,而不是直接发出 iptables 命令。(我喜欢ferm,但有很多好的)。
要考虑的另一件事-有时您根本不想在网络层执行此操作。有时使用 strace 或类似的方法监视守护进程的系统调用是合适的。它是 CPU 密集型的,并且要小心减慢守护进程的速度,但在某些情况下,它可能是合适的,主要取决于您需要同时收集哪些其他信息,或者您是否需要隔离单个分叉子进程的守护进程。
到目前为止,最适合我的解决方案是每 20 秒抓取一次 /proc/net/ip_conntrack 的内容,将其记录到文件名包含适当时间戳的文件中,并将其用作任何过滤脚本的输入,或者必要时甚至使用单线器。为了节省您的时间,您可以使用我的脚本。我使用 crontab 条目来确保脚本每分钟运行一次(在当前配置中持续 60 秒,请随意修改它:-)
您可以通过相应地更改 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
.自己写日志:
nohub将把这个进程移到后台,这样它就可以在你的注销后继续存在
netstat -c将导致 netstat 每秒、连续、永远打印所选信息
grep -E "xxx|xxxx"将获取您想要的内容,例如端口和
>> netstat_log ... 将其写入“./netstat_log”(在此处使用所需的日志文件)
将输出管道连接到
| wc -l
它的行数(wc)。看一下
黑暗状态,
iplog ,
iptraf ,
宝马
顶部
vnstat
. 它们都有点陈旧,但编写脚本来完成其他人做得更好的工作很无聊。有些给你漂亮的图片,有些更专注于取证分析和搞砸坏人,有些(iplog)只是记录到数据库的非常简单的计数器,有些有闪亮的前端,你可以向你的老板展示。
还有一大堆工具可以在 linux 上实现免费的 netflow 兼容堆栈。还有一大群人试图围绕这个兜售支持。(我不会推荐商业产品......)您所要求的远比其中一些产品的功能要简单得多。
恕我直言(免费|网络|开放)BSD多年来一直领先于分析。pFsense 防火墙将为您提供至少 7 个开箱即用的选项。