使用 iptables 调试 netstat 中的“连接尝试失败”

使用 iptables 调试 netstat 中的“连接尝试失败”

http://farm4.static.flickr.com/3305/4588110530_a60c934289_o.png

该图表是 munin 收集netstat -s输出的。

我想确定连接来自哪里。wireshark 转储中没有明显的信息。

我已经很久没有用 iptables 做过什么了。我该如何记录这些内容?

谢谢

-s

答案1

要确定连接来自哪里....以下是记录 SSH 流量的示例。格式在内核日志中如下所示

MONTH DAY TIME SERVERNAME kernel: [IPTABLES] : IN=eth0 OUT= MAC=00:00:00:00:00:00:00:00:00:00:00:00:00:00 SRC=REMOTEIP DST=SERVERIP LEN=00 TOS=0x00 PREC=0x00 TTL=# ID=# DF PROTO=TCP SPT=# DPT=22 WINDOW=# RES=0x00 SYN URGP=0 OPT (#)

这里我们创建一个名为MyLOG的新链

# iptables -N MyLOG

冲洗新链条以防万一

# iptables -F MyLOG

在 tcp 端口 22 上创建日志功能,将日志设置为警报,并将易于查看的“[IPTABLES]”字符串设置为日志行的开头。

# iptables -A MyLOG -i eth0 -p tcp --dport 22 -j LOG --log-level alert --log-tcp-options --log-ip-options --log-prefix '[IPTABLES] : '

将 MyLOG 链附加到输入链

# iptables -A INPUT -i eth0 -j MyLOG

这应该会将日志发送到您的内核日志(尽管某些版本的 Linux 可能会改变结果)。您可以通过跟踪内核日志来测试日志记录。

# tail -f /var/log/kern.log

如果你在控制台上,注意到屏幕上有大量数据,你可以尝试使用以下命令设置控制台日志输出

dmesg -n 1

如果你想获得“统计数据”,你可以运行

# iptables -nvxL

输出将显示从链创建时发送的数据包和字节的数量。

Chain MyLOG (1 references)
    pkts      bytes target     prot opt in     out     source               destination
      61     4416 LOG        tcp  --  eth0   *       0.0.0.0/0            0.0.0.0/0

我这里有一个脚本http://www.hilands.com/code-shell-fw.html我用它来记录某些端口活动,并收集 serverstats serverstats 的数据(可从 berlios 下载),设置 NAT,端口转发,尝试中断端口扫描,并使用 tcp-rejects 而不是 drop。

Serverstats 可能很难理解。它是一组使用 RRDTool 的 PHP 脚本。它使用 shell 脚本来触发 iptables 输出。我的乱码笔记告诉我,您需要使用类似这样的内容修改配置数组才能使其运行

'ssh-traffic' => array(
        'used' => true,
        'chains' => array('MyLOG'),
        'graphs' => array(
            'combined_bps' => array('used' => true, 'title' => 'Combined (bps)'),
            'single_bps' => array('used' => true, 'title' => '%s (bps)'),
            'combined_count' => array('used' => true, 'title' => 'Combined (count)'),
            'single_count' => array('used' => true, 'title' => '%s (count)')
        )
    ),

答案2

谢谢大家的回复。

我的目标是了解图表中的峰值为何有规律且周期性,然后让它们停止。这些峰值以缓慢的涓流(每次 5 个左右)涌入。我知道 TCP 连接会因某种原因而失败,但显然由于它们的规律性而发生了一些事情。我怀疑某个地方的 cron 作业、负载平衡器配置错误或监控设备是罪魁祸首。

我决定采用 UTSL 方法,目前情况如下:

netstat -s 从 /proc/net/snmp 获取其统计数据。

太好了。因此,每次连接尝试失败时,内核都会更新 SNMP 计数器。

我想要实现的是,每次连接失败时,不仅更新此计数器,还记录“在 $timestamp 时来自 IP $foo 的连接尝试失败”

那么...什么样的情况才算是连接尝试失败?

下载内核源代码 查找周围 得出的结论是,我正在寻找的计数器是 TCP_MIB_ATTEMPTFAILS

通过 2.6.18 源代码树,我发现了两个引用此内容的地方:

./net/ipv4/tcp_minisocks.c:

453 struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb,
454                            struct request_sock *req,
455                            struct request_sock **prev)
456 {

592                 if (flg & (TCP_FLAG_RST|TCP_FLAG_SYN)) {
593                         TCP_INC_STATS_BH(TCP_MIB_ATTEMPTFAILS);
594                         goto embryonic_reset;
595                 }

640 }

...并且,include/net/tcp.h

915 static inline void tcp_done(struct sock *sk)
916 {
917         if(sk->sk_state == TCP_SYN_SENT || sk->sk_state == TCP_SYN_RECV)
918                 TCP_INC_STATS_BH(TCP_MIB_ATTEMPTFAILS);
919 
920         tcp_set_state(sk, TCP_CLOSE);
921         tcp_clear_xmit_timers(sk);
922 
923         sk->sk_shutdown = SHUTDOWN_MASK;
924 
925         if (!sock_flag(sk, SOCK_DEAD))
926                 sk->sk_state_change(sk);
927         else
928                 inet_csk_destroy_sock(sk);
929 } 

我有点惊讶,这只是两个产生计数器更新的条件,但无论如何。

第一个块看起来很明显。“如果您看到 TCP 数据包同时设置了 RST 和 SYN 标志,请更新 TCP_MIB_ATTEMPTFAILS 计数器并重置连接”。

为了捕获这些,我添加了以下 iptables 规则

iptables -A INPUT -p tcp -m tcp --tcp-flags SYN,RST SYN,RST -j LOG
iptables -A OUTPUT -p tcp -m tcp --tcp-flags SYN,RST SYN,RST -j LOG

等待…..没什么。=(

第二个块有点神秘,但我猜测并假设这意味着“如果套接字在拆除时处于某种状态,则更新 TCP_MIB_ATTEMPTFAILS 计数器”

这个,我不知道如何测试这个。

我现在的问题是:1) 我是否误解了这张图?2) 我走在正确的轨道上吗?3) 除了编写内核模块(我远没有足够的技能来做这件事)之外,我怎样才能实现我的日志记录目标?

谢谢

-s

答案3

我不确定 iptables 是否是您想要的,可能有一个保持活动状态并轮询 netstat 使用的相同系统调用的工具,或者您可以编写一个。

iptables 对数据包做出反应并处理它们。您所看到的基本上是所有活动套接字的分配表。

现在,根据这些实际情况,您可能能够在这些连接上捕获数据包。

如果有很多套接字处于不太明显的状态,并且持续很长时间,数字不断增长,我会更关注 netstat -anp 的输出,如果我没记错的话,它会告诉您程序。也许有人在泄漏套接字。

我对此抱有很大的怀疑。请详细说明一下您希望在该图表中看到哪些变化。

我自己评论了,但没有显示出来,所以我就编辑一下——另一篇文章绝对清楚地说明了如何使用 iptables 记录您应该能够使用 wireshark 看到的流量。在我看来,你问的是套接字,而不是数据包。难以追踪的套接字通常不会获取/发送数据包,有时这表明资源浪费。

相关内容