Chinaunix

标题: [讨论] 清除本地服务器已建立TCP连接的方法[有了一个实现方法] [打印本页]

作者: Godbach    时间: 2010-08-09 10:35
标题: [讨论] 清除本地服务器已建立TCP连接的方法[有了一个实现方法]
本帖最后由 Godbach 于 2010-08-10 19:23 编辑

应用场景:
本地服务器有大量已建连接,现在需要根据指定的源IP,清除这些源IP建立的所有TCP连接。

大家有什么好的方法?

--------------------
测试了一下使用hping发送RST包 断开连接的方式是可行的,但是需要指定序列号,也就是seq。
举例如下:
#hping2 192.168.1.50 -R -s 55692 -p 22 -a 192.168.1.176 -M 1876579253 -L 0 -k -c 1

解释一下:
目的IP: 192.168.1.50
-s 55692 : 源端口
-p 22: 目的端口
-a 192.168.1.176: 伪造的源IP。也就是已建立链接的源IP地址
-M 1876579253 :指定序列号,源IP方向上的序列号
-L 0 : RST包,ack_seq置为0
-k :  使用固定源端口
-c 1 : 发送1个数据包


执行的结果是netstat -an和ip_conntrack中这个链接都没有了。如果不指定序列号-M 的话,则发出的RST包没法断开连接。

不知道大家是否有测试过不指定序列号能够断开当前连接的实现?
作者: Godbach    时间: 2010-08-09 12:41
大家集思广益啊。。:wink:
作者: vermouth    时间: 2010-08-09 13:41
kill ?
作者: platinum    时间: 2010-08-09 13:53
记得 hping 好像可以解决类似的问题,但忘记是解决 TCP socket 问题还是 conntrack 问题了,反正是可以断掉连接的
作者: Godbach    时间: 2010-08-09 14:14
kill ?
vermouth 发表于 2010-08-09 13:41


多谢,怎么个kill法?
作者: Godbach    时间: 2010-08-09 14:14
记得 hping 好像可以解决类似的问题,但忘记是解决 TCP socket 问题还是 conntrack 问题了,反正是可以断掉 ...
platinum 发表于 2010-08-09 13:53

多谢白金兄。

我查一下,我这里是不开启conntrack的。
作者: Godbach    时间: 2010-08-09 14:23
看来之前也有网友问过这个问题
http://linux.chinaunix.net/bbs/thread-591634-1-1.html


kill的方法就把listen的进程给kill掉了。
作者: vermouth    时间: 2010-08-09 15:30
可以只杀线程么?
作者: Godbach    时间: 2010-08-09 15:31
我这里用的是squid,所有tcp已建连接都是squid进程的ID
作者: Godbach    时间: 2010-08-09 15:32
白金兄上面说的hping网上说是可以的,我测试之后发现没有效果
作者: Godbach    时间: 2010-08-09 15:56
记得 hping 好像可以解决类似的问题,但忘记是解决 TCP socket 问题还是 conntrack 问题了,反正是可以断掉 ...
platinum 发表于 2010-08-09 13:53


另外一个帖子看到白金兄的回复:
#!/bin/bash

echo
echo "############################"
echo "# Edit by Youngh 2003.06.24 v1.1 "
echo "# Usage : clr_conns IpAddress"
echo "# This will clear all connections from this IP_Address"
echo "# Example:/root/clr_conns 10.0.3.3 "
echo "############################"
echo

if [ -z $1 ] ; then
exit
fi

grep -E "^tcp .{10,25}ESTABLISHED src=$1 " /proc/net/ip_conntrack | while read line ; do
S_IP=`echo $line | awk '{print substr($5,5)}'`
S_SOCK=`echo $line | awk '{print substr($7,7)}'`
D_IP=`echo $line | awk '{print substr($6,5)}'`
D_SOCK=`echo $line | awk '{print substr($8,7)}'`
echo "$S_IP:$S_SOCK $D_IP:$D_SOCK"

hping2 $D_IP -R -s $S_SOCK -p $D_SOCK -a $S_IP -k -c 1 >/dev/null 2> /dev/null &

done


这个脚本执行完毕之后,感觉连接并没清除。 单独执行hping也是一样的问题。

大家谁用过么?
作者: platinum    时间: 2010-08-09 15:58
终结的可能是 conntrack 里面的信息,而不是 TCP 栈的 socket 占用
作者: Godbach    时间: 2010-08-09 16:05
他这个方面其实是通过hping来构造了RST包,如果发送成功的话,应该是结束TCP连接了,对conntrack和tcp socket应该都会生效啊。

我当前测试之后,对conntrack也没有什么影响。
作者: Godbach    时间: 2010-08-09 16:10
我把测试的情况也贴一下:
[root@Godbach hping2-rc2]# cat /proc/net/ip_conntrack | grep 192.168.6.49
tcp      6 431699 ESTABLISHED src=192.168.6.49 dst=192.168.6.50 sport=3232 dport=22 packets=65 bytes=5695 src=192.168.6.50 dst=192.168.6.49 sport=22 dport=3232 packets=66 bytes=9752 [ASSURED] mark=0 secmark=0 use=1
tcp      6 428378 ESTABLISHED src=192.168.6.49 dst=192.168.6.50 sport=3228 dport=22 packets=26 bytes=2783 src=192.168.6.50 dst=192.168.6.49 sport=22 dport=3228 packets=32 bytes=4284 [ASSURED] mark=0 secmark=0 use=1
[root@Godbach hping2-rc2]#  ./hping2 192.168.6.50 -R -s 3228 -p 22 -a 192.168.6.49 -k -c 1
HPING 192.168.6.50 (eth0 192.168.6.50): R set, 40 headers + 0 data bytes

--- 192.168.6.50 hping statistic ---
1 packets tramitted, 0 packets received, 100% packet loss
round-trip min/avg/max = 0.0/0.0/0.0 ms
[root@Godbach hping2-rc2]# cat /proc/net/ip_conntrack | grep 192.168.6.49
tcp      6 431668 ESTABLISHED src=192.168.6.49 dst=192.168.6.50 sport=3232 dport=22 packets=65 bytes=5695 src=192.168.6.50 dst=192.168.6.49 sport=22 dport=3232 packets=66 bytes=9752 [ASSURED] mark=0 secmark=0 use=1
tcp      6 428347 ESTABLISHED src=192.168.6.49 dst=192.168.6.50 sport=3228 dport=22 packets=26 bytes=2783 src=192.168.6.50 dst=192.168.6.49 sport=22 dport=3228 packets=32 bytes=4284 [ASSURED] mark=0 secmark=0 use=1
[root@Godbach hping2-rc2]#

执行完毕之后,状态依然是ESTABLISHED
hping2显示发出一个包,应该是RST包吧。 这里虽然用的是netstat,但是conntrack也是一样的
作者: platinum    时间: 2010-08-09 16:51
是不是序号问题?
作者: Godbach    时间: 2010-08-09 17:10
白金兄指的是TCP的序号吗。
作者: platinum    时间: 2010-08-09 17:18
恩是的,会不会是序号不对导致 TCP 栈将其视为无效,且 conntrack 自身也有维护序号的功能,也认为其无效了

如果利用 RST 注入技术,应该是可以满足需求的
作者: Godbach    时间: 2010-08-09 17:23
我在网上查的,这个工具应该会先探测一下,获取到序列号吧。
不然的话,就只能相当于发送RST包,没办法断开连接了
作者: Godbach    时间: 2010-08-09 17:26
hping有两个参数
  -M  --setseq     set TCP sequence number
  -L  --setack     set TCP ack

是设置seq和ack_seq的吧,但是如果这两个序号我能获取到,那我自己都可以写程序发送RST了
作者: platinum    时间: 2010-08-09 17:27

作者: Godbach    时间: 2010-08-09 17:31
呵呵,网上很多结果都是说用hping来发送RST包,指定srcip, sport, dip,dport。

唉,要么只能看他的源码了。

白金兄使用以前测试过吗?
作者: Godbach    时间: 2010-08-09 18:48
转过来一个mailist上的解决方法,同样是用hping。作者自己测试结果说works well.
杨华  youngh0702@21cn.com
Wed, 25 Jun 2003 11:06:53 +0800

    * Previous message: clear the ip_conntrack entry
    * Next message: clear the ip_conntrack entry
    * Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]

Hi everyone :
        I have notice that many request about how to clear the
/proc/net/ip_conntrack entry , and someone suggest that it have no
resolution except restart the interface .
        I think the answer : send a fake ip packet (with RST set) to
firewall , to let it think the connection terminate .
        By this methode , I have the following script written , it work
well for me.
        To use this script , you must have hping2 installed , it can be
download from http://www.hping.org
--------- clr_conns start  ------------------
echo
echo "############################"
echo "# Edit by Youngh 2003.06.24 v1.1 "
echo "# Usage : clr_conns IpAddress"
echo "#            This will clear all connections from this IP_Address"
echo "# Example:/root/clr_conns  10.0.3.3 "
echo "############################"
echo



if [ -z $1 ] ; then
        exit
fi


grep -E "^tcp .{10,25}ESTABLISHED src=$1 " /proc/net/ip_conntrack | while read line ; do
        S_IP=`echo $line | awk '{print substr($5,5)}'`
        S_SOCK=`echo $line | awk '{print substr($7,7)}'`
        D_IP=`echo $line | awk '{print substr($6,5)}'`
        D_SOCK=`echo $line | awk '{print substr($8,7)}'`       
        echo "$S_IP:$S_SOCK $D_IP:$D_SOCK"

        hping2 $D_IP -R -s $S_SOCK -p $D_SOCK -a $S_IP -k -c 1 >/dev/null 2>/dev/null &

done       

----------------clr_conns end --------------------------------

作者: platinum    时间: 2010-08-09 21:17
很遗憾,我没有测试过……
作者: Godbach    时间: 2010-08-10 10:25
是否可以考虑内核态做一些工作呢:
记下内核中所有新建连接对应的sock,然后需要删除的时候,对相应的sock调用tcp_close函数。
作者: Godbach    时间: 2010-08-10 19:23
初步验证了hping的实现,可参考1楼的实现方法。
作者: 急不通    时间: 2010-08-12 11:56
回复 13# Godbach


    conntrack是做连接跟踪,如果连接很规范的断开,conntrack表项当然就会被清除掉,否则就要等到表项timeout,各种连接状态下,timeout值是不同的,tcp established状态默认要5天才timeout。
作者: Godbach    时间: 2010-08-12 12:55
,tcp established状态默认要5天才timeout。

这个值好像也是和conntrack关联的,我测试了,将其修改的时间短一些,conntrack的记录是没有了,但是netstat的结果还有的
作者: heidern    时间: 2010-08-13 09:54
回复 1# Godbach


    怎么获得连接的序列号?
作者: Godbach    时间: 2010-08-13 10:02
回复  Godbach


    怎么获得连接的序列号?
heidern 发表于 2010-08-13 09:54


你问的就是关键问题。
如果获取某个已经建立连接的序列号,准确点说,就是客户端下次发包应该使用的序列号。

大家可以讨论一下,有哪些好的方法?
作者: heidern    时间: 2010-08-13 15:27
....一天了没人回复{:3_180:}
作者: Godbach    时间: 2010-08-13 19:36
连接中好像是可以记录tcp连接的序列号的:
struct nf_conn
{
       ......

        /* Storage reserved for other modules: */
        union nf_conntrack_proto proto;

        /* Extensions */
        struct nf_ct_ext *ext;
};

以上粗体标出的union是记录ip协议之上的若干协议的传输数据及状态:
/* per conntrack: protocol private data */
union nf_conntrack_proto {
        /* insert conntrack proto private data here */
        struct ip_ct_sctp sctp;
        struct ip_ct_tcp tcp;
        struct ip_ct_icmp icmp;
        struct nf_ct_icmpv6 icmpv6;
        struct nf_ct_gre gre;
};

再展开struct ip_ct_tcp tcp这个结构体
struct ip_ct_tcp
{
        struct ip_ct_tcp_state seen[2];        /* connection parameters per direction */
        u_int8_t        state;                /* state of the connection (enum tcp_conntrack) */
        /* For detecting stale connections */
        u_int8_t        last_dir;        /* Direction of the last packet (enum ip_conntrack_dir) */
        u_int8_t        retrans;        /* Number of retransmitted packets */
        u_int8_t        last_index;        /* Index of the last packet */
        u_int32_t        last_seq;        /* Last sequence number seen in dir */
        u_int32_t        last_ack;        /* Last sequence number seen in opposite dir */
        u_int32_t        last_end;        /* Last seq + len */

        u_int16_t        last_win;        /* Last window advertisement seen in dir */
};

这里面记录了最后传输的seq,ack等等有关的数据。
作者: Godbach    时间: 2010-08-13 19:42
可以考虑写个代码测试一下
作者: Godbach    时间: 2010-08-13 19:47
如果是tcp协议,给定sip,sport,dip和dport,应该可以快速查找到这个链接,进而取出对应的序列号等相关信息。
作者: salmon5    时间: 2010-08-14 11:24
hping2有一个替代工具http://nmap.org/nping/
作者: Godbach    时间: 2010-08-14 11:29
多谢LS的,看了一下这个工具的TCP方面的选项:
TCP PROBE MODE:
   -g, --source-port <portnumber>  : Set source port.
   -p, --dest-port <port spec>     : Set destination port(s).
   --seq <seqnumber>               : Set sequence number.
   --flags <flag list>             : Set TCP flags (ACK,PSH,RST,SYN,FIN...)
   --ack <acknumber>               : Set ACK number.
   --win <size>                    : Set window size.
   --badsum                        : Use a random invalid checksum.

这个和hping2差不多,可以指定seq和ack。
我想断开一个连接,还是需要自己先获取到seq
作者: heidern    时间: 2010-08-16 11:13
没有简单的方法得到seq吗?
作者: platinum    时间: 2010-08-16 11:22
通过 conn 里面的 tcp 状态来找到 seq,需要启用 conn 才可以
但有些环境是不能启用 conntrack 的,否则会有更大问题
作者: Godbach    时间: 2010-08-16 11:37
通过 conn 里面的 tcp 状态来找到 seq,需要启用 conn 才可以
但有些环境是不能启用 conntrack 的,否则会 ...
platinum 发表于 2010-08-16 11:22

嗯,白金兄说的这个问题是需要注意。
如果不利用conn的话,则需要考虑直接从tcp的那个全局sock变量中获取了。
作者: platinum    时间: 2010-08-16 13:08
嗯,白金兄说的这个问题是需要注意。
如果不利用conn的话,则需要考虑直接从tcp的那个全局sock变量中获取 ...
Godbach 发表于 2010-08-16 11:37


是,但这种数据可能没有 EXPORT 出来,自己要修改代码
作者: Godbach    时间: 2010-08-16 13:23
嗯。不考虑其他因素的话,还是连接跟踪上方便一些。
另外,如果是一个服务器的话,它的连接数应该不像网络安全设备那样不会特别多
作者: ccjsj1    时间: 2011-04-13 13:42
楼上说通过conn找seq,是通过/proc/net/ip_conntrack文件吗?

里面没有seq的的内容,怎样找seq呢?

ip_conntrack部分内容:
tcp      6 431803 ESTABLISHED src=10.199.75.169 dst=10.199.75.203 sport=47229 dport=1689 packets=17 bytes=2636 src=10.199.75.203 dst=10.199.75.169 sport=1689 dport=47229 packets=15 bytes=3316 [ASSURED] mark=0 secmark=0 use=1

tcp      6 431868 ESTABLISHED src=10.199.75.169 dst=10.199.75.203 sport=58254 dport=1689 packets=14 bytes=2516 src=10.199.75.203 dst=10.199.75.169 sport=1689 dport=58254 packets=11 bytes=3126 [ASSURED] mark=0 secmark=0 use=1




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2