Chinaunix

标题: [欢迎进入讨论] 关于syn-proxy的一些问题 [打印本页]

作者: Godbach    时间: 2009-03-12 17:53
标题: [欢迎进入讨论] 关于syn-proxy的一些问题
Linux内核中提供了SYN Cookie的检验机制,用来防御SYN Flood攻击。因此,延伸出来的在SYN Cookie Firewall,用来验证SYN连接,并对通过验证报文进行转发。
具体的内容可以参考《SYN Cookie原理及其在Linux内核中的实现
http://www.ibm.com/developerworks/cn/linux/l-syncookie/index.html

使用syn cookie检验机制的Firewall,实际上相当于一个syn proxy。它会代替server对client三次握手,对syn报文进行cookie验证,然后再将client初始的syn报文发给server,并做三次握手。这个过程中,很明显client记录的server的seq实际上firewal初始的seq。
如下图所示:


因此,Firewall就要负责这个序列号在client和server交互的报文之间进行转换(维护一个差值),直到这个连接结束。

这里的问题如下:

通常情况下,Firewall对于多个syn连接处理的时候,FW是不是就得维护多个差值。 这样的话是不是需要记录连接的五元组,并且维护一个hash表。这个hash表应该包含那些内容呢?
作者: dreamice    时间: 2009-03-12 21:31
标题: 回复 #1 Godbach 的帖子
如果是完全的拦截,其实对序列号不需要多做考虑
作者: Godbach    时间: 2009-03-12 22:12
原帖由 dreamice 于 2009-3-12 21:31 发表
如果是完全的拦截,其实对序列号不需要多做考虑


关键是防火墙做一下验证,正常的访问还得继续。不考虑序列号不行吧?
作者: dreamice    时间: 2009-03-12 22:23
原帖由 Godbach 于 2009-3-12 22:12 发表


关键是防火墙做一下验证,正常的访问还得继续。不考虑序列号不行吧?


关键是你拦截在什么地方,包能否走到tcp层?
一个syn包,是不会走到应用层的,只是在内核检查到有应用程序在监听这个端口,那么在tcp层就直接回ack+syn包了,
所以,这个就看你在哪里拦截了,你若在ip层阻挡了,不让他上去,那考虑序列号也没什么意义,除非你在这个ip层模拟发ack。
作者: Godbach    时间: 2009-03-12 22:30
原帖由 dreamice 于 2009-3-12 22:23 发表


关键是你拦截在什么地方,包能否走到tcp层?
一个syn包,是不会走到应用层的,只是在内核检查到有应用程序在监听这个端口,那么在tcp层就直接回ack+syn包了,
所以,这个就看你在哪里拦截了,你若在ip层 ...


dreamice兄可能没有理解那个附图的意思吧。你首先代替服务器发送了SYNcookie ,但是真正再把这个SYN发送到服务器,建立连接之后,从server发向client的报文的seq和client预期的是不一样的。
作者: dreamice    时间: 2009-03-12 22:47
标题: 回复 #5 Godbach 的帖子
看昏了,我以为是透明代理
作者: Godbach    时间: 2009-03-12 22:59
原帖由 dreamice 于 2009-3-12 22:47 发表
看昏了,我以为是透明代理


呵呵,有时间讨论一下这个转换以及实现啊。
作者: dreamice    时间: 2009-03-12 23:11
原帖由 Godbach 于 2009-3-12 22:59 发表


呵呵,有时间讨论一下这个转换以及实现啊。


现在内核支持透明代理,就不用考虑这些东东了
作者: dreamice    时间: 2009-03-12 23:12
标题: 回复 #7 Godbach 的帖子
不过我不太清楚这个应用,可能和我想的不一样
作者: qtdszws    时间: 2009-03-13 09:02
我想可以参考ftp的conntrack和nat实现
作者: Godbach    时间: 2009-03-13 09:30
原帖由 dreamice 于 2009-3-12 23:11 发表


现在内核支持透明代理,就不用考虑这些东东了


dreamice兄给推荐几篇透明代理的文章啊。
作者: Godbach    时间: 2009-03-13 09:37
原帖由 dreamice 于 2009-3-12 23:12 发表
不过我不太清楚这个应用,可能和我想的不一样


呵呵,其实我这里并不是讨论什么应用。主要就是了解一下这个proxy的实现。

因为在这个代理中,很明显Firewall要负责转换的是client到server的ack号,和server到client的seq号。

如果是这样的话,Firewall如何判断server发过来的包就是对上一次client报文的响应呢,是不是需要借助链接跟踪?
作者: richardhesidu    时间: 2009-03-13 09:46
需要跟踪连接吧,每个连接对应一个差值。
作者: dreamice    时间: 2009-03-13 09:55
原帖由 Godbach 于 2009-3-13 09:37 发表


呵呵,其实我这里并不是讨论什么应用。主要就是了解一下这个proxy的实现。

因为在这个代理中,很明显Firewall要负责转换的是client到server的ack号,和server到client的seq号。

如果是这样的话,Fire ...


如果是纯代理,一切都由代理服务器搞定了;也就是client直接和代理服务器通信,代理服务器单独和server通信,对client端透明。

如果是透明代理,tcp握手阶段,client和proxy之间进行,而真正的通信,proxy只是个中转。

所以,我说应用和我想的不一样
作者: dreamice    时间: 2009-03-13 09:55
原帖由 richardhesidu 于 2009-3-13 09:46 发表
需要跟踪连接吧,每个连接对应一个差值。


老大很少发言啊
作者: Godbach    时间: 2009-03-13 09:57
原帖由 richardhesidu 于 2009-3-13 09:46 发表
需要跟踪连接吧,每个连接对应一个差值。


恩,应该是的。改天找对应的代码研究一下。
作者: Godbach    时间: 2009-03-13 09:58
如果是透明代理,tcp握手阶段,client和proxy之间进行,而真正的通信,proxy只是个中转。

所以,我说应用和我想的不一样


透明代理的话,能保证第一次syn包还正确到达server吗?
作者: Godbach    时间: 2009-03-13 09:59
原帖由 dreamice 于 2009-3-13 09:55 发表


老大很少发言啊


是啊。richardhesidu 兄最近在忙什么呢?
作者: dreamice    时间: 2009-03-13 10:01
原帖由 Godbach 于 2009-3-13 09:58 发表


透明代理的话,能保证第一次syn包还正确到达server吗?


透明代理的话,tcp握手直接和proxy完成了,不用关心这个问题。
但后续通信的包,需要proxy和server再建立一次连接。
作者: richardhesidu    时间: 2009-03-13 10:04
哎,水平太烂。不敢多发言啊。
作者: Godbach    时间: 2009-03-13 10:09
原帖由 dreamice 于 2009-3-13 10:01 发表


透明代理的话,tcp握手直接和proxy完成了,不用关心这个问题。
但后续通信的包,需要proxy和server再建立一次连接。


tcp握手时,client知道他是直接和proxy握手的呢,还是client一直是以为和server在握手?
作者: dreamice    时间: 2009-03-13 10:14
原帖由 Godbach 于 2009-3-13 10:09 发表


tcp握手时,client知道他是直接和proxy握手的呢,还是client一直是以为和server在握手?


如果是透明代理的话,client当然是不知道的是在和proxy握手的。
如果是反向代理,那就知道了
作者: richardhesidu    时间: 2009-03-13 10:32
这样行不行
自己定一个my_sock结构,里面存储源地址,源端口,目标地址,目标端口,差值,skb_buff链表(存储SYN包),连接状态。再创建一个my_sock的hash表。client和firewall第一次握手的时候,创建一个my_sock。firewall和server完成第二次握手的时候给my_sock的差值赋值。完成所有六次握手以后,把my_sock.state设为TCP_ESTABLISHED。对以后所有收到的包,匹配其地址和端口。并判断state是否established。如果是,就根据情况修改ack或是syn。
作者: dreamice    时间: 2009-03-13 12:12
原帖由 richardhesidu 于 2009-3-13 10:32 发表
这样行不行
自己定一个my_sock结构,里面存储源地址,源端口,目标地址,目标端口,差值,skb_buff链表(存储SYN包),连接状态。再创建一个my_sock的hash表。client和firewall第一次握手的时候,创建一个my_s ...


老大,你这个实现太复杂了。
现在新版内核也支持透明代理,实现非常简单:client发起和server的连接,被proxy拦截(注意这里是拦截),然后伪装成server和client建立起连接,
连接建立成功以后,proxy在伪装成client向server请求数据(当然这里也要和server建立tcp连接),server返回数据后,再次被proxy拦截,proxy此时伪装成server
向client返回数据。

这个过程就是完全的透明代理。

反向代理则不同:
client不知道server的存在,把proxy当成server,而proxy有自己的IP,client请求proxy的时候,proxy再以自己的身份向真正的server发起请求,并获取返回包,最后proxy再以自己的身份向client返回包。这个过程,可以说对server来说,他的client只是proxy,对client来说,server就是proxy。
作者: richardhesidu    时间: 2009-03-13 12:59
原帖由 dreamice 于 2009-3-13 12:12 发表


老大,你这个实现太复杂了。
现在新版内核也支持透明代理,实现非常简单:client发起和server的连接,被proxy拦截(注意这里是拦截),然后伪装成server和client建立起连接,
连接建立成功以后,proxy在伪 ...

透明代理的确是一个不错的解决方法。
楼主说的syn proxy跟透明代理还是不同。syn proxy只是对Client和Server之间的三次握手做一个类似的透明代理。建立连接后,数据的传输只是转发而已。
如果纯粹是防SYN Flood攻击,可能syn proxy效率会高一些吧。
作者: dreamice    时间: 2009-03-13 13:07
原帖由 richardhesidu 于 2009-3-13 12:59 发表

透明代理的确是一个不错的解决方法。
楼主说的syn proxy跟透明代理还是不同。syn proxy只是对Client和Server之间的三次握手做一个类似的透明代理。建立连接后,数据的传输只是转发而已。
如果纯粹是防SYN F ...


嗯,这个应用倒是。
作者: Godbach    时间: 2009-03-13 13:07
syn proxy只是对Client和Server之间的三次握手做一个类似的透明代理。建立连接后,数据的传输只是转发而已。


我觉得这里在建立连接后,数据的传输报文还是需要被修改的啊。怎么会是透明的呢?
作者: richardhesidu    时间: 2009-03-13 13:17
原帖由 Godbach 于 2009-3-13 13:07 发表


我觉得这里在建立连接后,数据的传输报文还是需要被修改的啊。怎么会是透明的呢?

透明的意思就是看不到或者不用关心啊。syn proxy中,client和server都不知道firewall的存在。
透不透明,跟firewall是否修改报文没有关系。
作者: Godbach    时间: 2009-03-13 13:34
标题: 回复 #28 richardhesidu 的帖子
明白:wink:
那这样来说syn-proxy应该就是透明代理啊。用户一直是不知道Firewall的。

[ 本帖最后由 Godbach 于 2009-3-13 13:35 编辑 ]
作者: dreamice    时间: 2009-03-13 13:43
原帖由 Godbach 于 2009-3-13 13:34 发表
明白:wink:
那这样来说syn-proxy应该就是透明代理啊。用户一直是不知道Firewall的。


那不就跟我说的那个差不多了
如果除了syn包都不走proxy的话,那只能说是syn cookie的transparent proxy吧
作者: Godbach    时间: 2009-03-13 13:49
标题: 回复 #30 dreamice 的帖子
而且防火墙是要负责这个SYN连接的数据传输中所有来往报文的转换吧
作者: dreamice    时间: 2009-03-13 13:56
原帖由 Godbach 于 2009-3-13 13:49 发表
而且防火墙是要负责这个SYN连接的数据传输中所有来往报文的转换吧


透明代理就是这么个意思。具体实现还是蛮复杂的。
作者: Godbach    时间: 2009-03-13 13:58
原帖由 dreamice 于 2009-3-13 13:56 发表


透明代理就是这么个意思。具体实现还是蛮复杂的。


恩。dreamice觉得这个实现中难点在于什么啊?
作者: dreamice    时间: 2009-03-13 14:57
原帖由 Godbach 于 2009-3-13 13:58 发表


恩。dreamice觉得这个实现中难点在于什么啊?


tcp握手,源IP为非本地IP的路由,目的IP为非本地IP的拦截
作者: Godbach    时间: 2009-03-13 15:17
原帖由 dreamice 于 2009-3-13 14:57 发表


tcp握手,源IP为非本地IP的路由,目的IP为非本地IP的拦截

说的通俗点哈。

我觉得透明代理在数据传输的过程中:
(1)要记录一个五元组,包含client和server之间通信的五元组,这样才能保证对双方数据传输的(client)ACK和SYN(server)的正确转换。
(2)如果有多个SYN连接的话,是不是还要为每个SYN链接做(1)中的设计?
作者: dreamice    时间: 2009-03-13 15:23
标题: 回复 #35 Godbach 的帖子
你所谓的这个记录,实际上内核tcp本身就有实现了,两台机子机的通信。

这里只是要考虑的是非本地IP地址的问题。
作者: Godbach    时间: 2009-03-13 15:27
原帖由 dreamice 于 2009-3-13 15:23 发表
你所谓的这个记录,实际上内核tcp本身就有实现了,两台机子机的通信。

这里只是要考虑的是非本地IP地址的问题。


我说的记录是有如下情况啊:
双方数据传输的(client)ACK和SYN(server)的正确转换


这个转换是应该防火墙来实现的。所以你必须记录那些链接需要转换啊。因为Firewall对传输的报文做了手脚,所以在以后的数据传输中它都要做这个工作。
这个应该是syn-proxy的内部实现了吧。
作者: richardhesidu    时间: 2009-03-13 15:29
原帖由 dreamice 于 2009-3-13 12:12 发表


老大,你这个实现太复杂了。
现在新版内核也支持透明代理,实现非常简单:client发起和server的连接,被proxy拦截(注意这里是拦截),然后伪装成server和client建立起连接,
连接建立成功以后,proxy在伪 ...

好像内核对透明代理的支持,只是内核把数据包forward到一个本地的proxy服务器吧。比如squid。还是内核有了新的功能,可以完全实现代理服务?
作者: Godbach    时间: 2009-03-13 15:50
原帖由 richardhesidu 于 2009-3-13 15:29 发表

好像内核对透明代理的支持,只是内核把数据包forward到一个本地的proxy服务器吧。比如squid。还是内核有了新的功能,可以完全实现代理服务?


对,正想了解这个地方哈
作者: dreamice    时间: 2009-03-13 16:11
原帖由 richardhesidu 于 2009-3-13 15:29 发表

好像内核对透明代理的支持,只是内核把数据包forward到一个本地的proxy服务器吧。比如squid。还是内核有了新的功能,可以完全实现代理服务?


是的,2.6.28版内核支持这个东东,我做国squid的完全透明代理。
其实内核实现了握手这一系列机制,无非就是我上面说的增加了对非本地IP的目的和源包的处理,以及握手机制。

God兄考虑得太复杂了,你首先要明白什么是真正含义的透明代理。
作者: dreamice    时间: 2009-03-13 16:14
双方数据传输的(client)ACK和SYN(server)的正确转换

==》你这个误解了透明代理的意思。tcp连接的过程中,完全是proxy来处理的,不涉及到server;只有真正的数据包,才会转过去;同理,proxy和server要通信,那就是他们而这的tcp连接过程,不涉及到client。
如果握手都要转那么遥远的话,就太复杂了,实际上也没有必要。
作者: Godbach    时间: 2009-03-13 16:23
标题: 回复 #41 dreamice 的帖子
你的意思数据部分的传输时,proxy截获server发过来的数据,然后组装自己的报文,再发给client?
作者: dreamice    时间: 2009-03-13 16:29
原帖由 Godbach 于 2009-3-13 16:23 发表
你的意思数据部分的传输时,proxy截获server发过来的数据,然后组装自己的报文,再发给client?


是的,server过来的数据,也会被截获,然后发给client。

由拦截的含义可知,至于tcp建立,那完全不涉及到server与client的直接进行。
作者: Godbach    时间: 2009-03-13 16:31
标题: 回复 #43 dreamice 的帖子
看来是我想的复杂了。
我以为Firewall只是把client的报文做一下ACK的修改,然后转发这个报文就可以了。
相反,对于server过来的报文,也做一下SEQ的修改,接着转发就OK了。
作者: dreamice    时间: 2009-03-13 16:36
原帖由 Godbach 于 2009-3-13 16:31 发表
看来是我想的复杂了。
我以为Firewall只是把client的报文做一下ACK的修改,然后转发这个报文就可以了。
相反,对于server过来的报文,也做一下SEQ的修改,接着转发就OK了。


你这样做的话,如果client太多,没办法控制的,会造成proxy维护一个庞大的表,性能一下就拖下来了。。。
作者: Godbach    时间: 2009-03-13 16:39
原帖由 dreamice 于 2009-3-13 16:36 发表


你这样做的话,如果client太多,没办法控制的,会造成proxy维护一个庞大的表,性能一下就拖下来了。。。


呵呵,是啊。我就觉得按照我的想法,内核是需要维护一个比较大的表的。

那你现在说的这种透明方式在那个版本的内核支持啊。

它对SYN包也是要进行Cookie验证的吧。
作者: richardhesidu    时间: 2009-03-13 16:40
原帖由 dreamice 于 2009-3-13 16:11 发表


是的,2.6.28版内核支持这个东东,我做国squid的完全透明代理。
其实内核实现了握手这一系列机制,无非就是我上面说的增加了对非本地IP的目的和源包的处理,以及握手机制。

God兄考虑得太复杂了,你首先 ...

dreamice 兄说一下具体实现的代码内核那一部分吧。
作者: Godbach    时间: 2009-03-13 16:42
原帖由 richardhesidu 于 2009-3-13 16:40 发表

dreamice 兄说一下具体实现的代码内核那一部分吧。


恩。看来对syn-proxy的理解已经远远落后了啊。
作者: dreamice    时间: 2009-03-13 16:46
原帖由 richardhesidu 于 2009-3-13 16:40 发表

dreamice 兄说一下具体实现的代码内核那一部分吧。


2.6.28版本的代码里面已经实现了,具体部分主要涉及到tcp握手机制的部分、还有一个setsockopt的选项以及路由部分。
其实这种机制在2.2版本的内核已经实现了,只是当时可能考虑到安全的问题,在2.4版内核又去掉了。
常规的路由策略,对与源IP不是本地的包,是没办法路由出去的,包在协议栈会被drop掉,所以内核修改了这一部分的源码实现;
另外setsockopt部分的设定,可以允许一个socket监听目的地址不是本地的包。
大致就是这样一些支持,当然了,要让一个包被拦截到本地,还需要策略路由的支持。

说起来还是蛮复杂的,涉及到的知识点也就是上面这些,具体就参考代码吧。
作者: Godbach    时间: 2009-03-13 16:50
标题: 回复 #49 dreamice 的帖子
看来dreamice兄已经研究的比较熟了啊
作者: Godbach    时间: 2009-03-13 16:52
应该是最近发布的内核版本中正式支持透明代理的吧。

像偶这样不怎么跟踪内核发展的人,是难以知道这些情况的。向dreamice兄学习啊
作者: dreamice    时间: 2009-03-13 16:53
原帖由 Godbach 于 2009-3-13 16:52 发表
应该是最近发布的内核版本中正式支持透明代理的吧。

像偶这样不怎么跟踪内核发展的人,是难以知道这些情况的。向dreamice兄学习啊

我干无聊的事情
作者: Godbach    时间: 2009-03-13 16:55
标题: 回复 #52 dreamice 的帖子
不啊。这样在设计某些东西的时候,可以利用当前最新的成果。不然自己吭哧吭哧在那里编呢,结果人家已经有开源的了。多影响效率啊。
作者: Godbach    时间: 2009-03-13 16:57
那在内核2。6.28版本之前,是不是需要实现syn-proxy的,就类似于我说的那种方式啊
作者: dreamice    时间: 2009-03-13 16:58
原帖由 Godbach 于 2009-3-13 16:57 发表
那在内核2。6.28版本之前,是不是需要实现syn-proxy的,就类似于我说的那种方式啊


不太清楚,应该有补丁支持的
作者: Godbach    时间: 2009-03-13 17:01
原帖由 dreamice 于 2009-3-13 16:58 发表


不太清楚,应该有补丁支持的



恩,就是想看看这个是如何实现的
作者: richardhesidu    时间: 2009-03-13 17:01
原帖由 dreamice 于 2009-3-13 16:11 发表


是的,2.6.28版内核支持这个东东,我做国squid的完全透明代理。
其实内核实现了握手这一系列机制,无非就是我上面说的增加了对非本地IP的目的和源包的处理,以及握手机制。

God兄考虑得太复杂了,你首先 ...

内核可以完全实现透明代理,不需要象squid这样的程序协助吗?
前面你说的听起来像是nat,又感觉不是。还请教。

[ 本帖最后由 richardhesidu 于 2009-3-13 17:05 编辑 ]
作者: Godbach    时间: 2009-03-13 17:03
原帖由 richardhesidu 于 2009-3-13 17:01 发表

内核可以完全实现透明代理,不需要象squid这样的程序协助吗?


估计直接放到内核中做这个工作了。看来需要看一下代码了。
作者: dreamice    时间: 2009-03-13 17:08
原帖由 richardhesidu 于 2009-3-13 17:01 发表

内核可以完全实现透明代理,不需要象squid这样的程序协助吗?
前面你说的听起来像是nat,又感觉不是。还请教。



这里要澄清一下,内核只是支持透明代理。
这种代理,肯定是应用层做的事情了,所以,必须要有应用层的软件实现代理才行。
我不知道是不是可以在内核来实现这个代理,理论上是可以的吧。
作者: Godbach    时间: 2009-03-13 17:16
原帖由 dreamice 于 2009-3-13 17:08 发表



这里要澄清一下,内核只是支持透明代理。
这种代理,肯定是应用层做的事情了,所以,必须要有应用层的软件实现代理才行。
我不知道是不是可以在内核来实现这个代理,理论上是可以的吧。


想安全的处理SYN包,要考虑的方面确实比较多啊
作者: richardhesidu    时间: 2009-03-13 17:27
原帖由 Godbach 于 2009-3-13 16:39 发表


呵呵,是啊。我就觉得按照我的想法,内核是需要维护一个比较大的表的。

那你现在说的这种透明方式在那个版本的内核支持啊。

它对SYN包也是要进行Cookie验证的吧。

如果纯粹为了解决syn flood的话,用linux+squid的效率还是没有syn-proxy高。
这里要维护的表,远没有维护一个socket的消耗高。
作者: Godbach    时间: 2009-03-13 17:42
原帖由 richardhesidu 于 2009-3-13 17:27 发表

如果纯粹为了解决syn flood的话,用linux+squid的效率还是没有syn-proxy高。
这里要维护的表,远没有维护一个socket的消耗高。


恩。这样都可以在内核态完成,不过可能需要hash表吧。
作者: Godbach    时间: 2009-03-15 15:44
原帖由 richardhesidu 于 2009-3-13 17:27 发表

如果纯粹为了解决syn flood的话,用linux+squid的效率还是没有syn-proxy高。
这里要维护的表,远没有维护一个socket的消耗高。



richardhesidu兄觉得如果实现这样一个syn-proxy,关键的步骤有哪些?
作者: 独孤九贱    时间: 2009-03-16 10:30
原帖由 Godbach 于 2009-3-12 17:53 发表
Linux内核中提供了SYN Cookie的检验机制,用来防御SYN Flood攻击。因此,延伸出来的在SYN Cookie Firewall,用来验证SYN连接,并对通过验证报文进行转发。
具体的内容可以参考《SYN Cookie原理及其在Linux内核 ...


是的,这个差值必须要维护。如果你的状态跟踪就是借助于Linux的Netfiter的话,这个跟踪结构就变得很简单,直接在ip_conntrack中增加相应的成员字段值就可以了。

  1. struct syn_cookie{
  2.         __u32 cookie;
  3.         __u32 seq;
  4. };
复制代码


  1. struct ip_conntrack
  2. {
  3.         ……
  4.   
  5.         /* tcp syn cookie */
  6.         struct syn_cookie syncookie;
  7. }
复制代码

[ 本帖最后由 独孤九贱 于 2009-3-16 10:34 编辑 ]
作者: Godbach    时间: 2009-03-16 10:37
标题: 回复 #64 独孤九贱 的帖子
多谢九贱兄的指导啊。确实可以在链接跟踪结构体中增加一些字段
如果利用的链接跟踪,是不是就不需要判断报文的一些特征了,比如s->c的报文是不是对上一次c->s的回复呢?
作者: 独孤九贱    时间: 2009-03-16 11:02
是的,借助于conntrack,可以省很多很多的代码和时间,自己的要实现的话,其实就是实现它其中的一部份功能,核心部件是TCP的状态机的维护(偶承认,偶水平有限,当时看Netfilter的TCP状态机的实现都看了好几天,如果自己写的话——所以说“省很多的时间”)。
但是,问题在于:大家都知道conntrack的性能受到广泛批评,所以,要高性能的话,就自己搞吧,而且借助于Netfilter,涉及到跟Netfilter的各个子模块的交互,这需要对Netfilter的整个工作流程了然于胸,比如,欺骗Netfilter的状态检测等等。
另一个技术问题在于cookie的处理,这个内核有现成的了,调用API即可。
还有一个问题是自己截包、发包,这需要了解内核态网络层组包发送的API。
还有就是性能问题,因为如果真的发生syn flooding,pps是非常多的。
还有就是ack flooding问题。例如100Mb的syn流量,要构造cookie ack,又是100Mb的回应包,但是众所周知,其中有99%都是不用回应的——这个问题很头痛,可能需要一个数学统计学的模型,My god,以前跟我们上统计学的老师是一个双博士学位的老处女,我对她没有兴趣,所以没有认真听讲,后悔呀!如果你有好的解决方案,一起讨论一下。
还有其它一些技术问题,记不得了。

————
PS:我认为,我不让攻击包进入conntrack,在pre_routing之前全处理了,保证进入conntrack的,都是正常的包,就不存在性能方面的问题了吧?哈哈,主要是我比较懒,有现成的不用,我太对不起自己了。
作者: Godbach    时间: 2009-03-16 11:08
PS:我认为,我不让攻击包进入conntrack,在pre_routing之前全处理了,保证进入conntrack的,都是正常的包,就不存在性能方面的问题了吧?哈哈,主要是我比较懒,有现成的不用,我太对不起自己了。


这样的话,进入系统的都是正常的包,也就没有必要在做syn-proxy了吧
作者: 独孤九贱    时间: 2009-03-16 11:12
顶楼上,我的意思是说,“在连接跟踪之外做syn cookie,这样,连接跟踪中保存的都是正常数据包的会话,因为数量相对少几个数量级(比起所有包都进来的话),性能问题相对而言,就不那么敏感了!”
作者: Godbach    时间: 2009-03-16 11:13
是的,借助于conntrack,可以省很多很多的代码和时间,自己的要实现的话,其实就是实现它其中的一部份功能,核心部件是TCP的状态机的维护(偶承认,偶水平有限,当时看Netfilter的TCP状态机的实现都看了好几天,如果自己写的话——所以说“省很多的时间”)。

九贱兄的意思是借助于conntrack,已经不用考虑报文发送方和接收方的状态验证了,已经在conntrack中tcp部分做了对应的验证?

比如,欺骗Netfilter的状态检测等等。

这个欺骗之前没听说过啊,九贱兄可否介绍一下。

还有就是性能问题,因为如果真的发生syn flooding,pps是非常多的。
还有就是ack flooding问题。例如100Mb的syn流量,要构造cookie ack,又是100Mb的回应包,但是众所周知,其中有99%都是不用回应的——这个问题很头痛,可能需要一个数学统计学的模型,My god,以前跟我们上统计学的老师是一个双博士学位的老处女,我对她没有兴趣,所以没有认真听讲,后悔呀!如果你有好的解决方案,一起讨论一下。


是啊,大量的ACK包,也是个问题。
作者: Godbach    时间: 2009-03-16 11:15
原帖由 独孤九贱 于 2009-3-16 11:12 发表
顶楼上,我的意思是说,“在连接跟踪之外做syn cookie,这样,连接跟踪中保存的都是正常数据包的会话,因为数量相对少几个数量级(比起所有包都进来的话),性能问题相对而言,就不那么敏感了!”


看来抗synflood和conntrack他俩之间的关系很紧密啊。要是想减轻conntrack的负载,就要在它之前做synflood的防御。如果向方便快捷的实现防御synflood,最好利用conntrack。 唉,矛盾啊
作者: dreamice    时间: 2009-03-16 11:19
原帖由 Godbach 于 2009-3-16 11:15 发表


看来抗synflood和conntrack他俩之间的关系很紧密啊。要是想减轻conntrack的负载,就要在它之前做synflood的防御。如果向方便快捷的实现防御synflood,最好利用conntrack。 唉,矛盾啊


synflood和syncookie机制是不是差不太多?
作者: Godbach    时间: 2009-03-16 11:22
原帖由 dreamice 于 2009-3-16 11:19 发表


synflood和syncookie机制是不是差不太多?


可以利用SYNcookie机制应对synflood攻击
作者: 独孤九贱    时间: 2009-03-16 11:28
不矛盾的,在实现中,很容易解决这个问题,或者说,事实上,它根本不存在。

1、首先,在pre_routing挂一个Hook,它监听所有的tcp syn包(这里也可以做一些过滤,比如,只保护指定的目的地址等等,或者是做一个缓存,存下已验证正确的主机等等)。
2、伪造syn+ack,当然,是包含cookie的,因为这个回应的数量级非常之大,所以,效率很重要。
3、凡是收到ack,验证cookie,这里并不需要状态机。只要验证cookie就可以了,这是跟syn proxy最核心的区别了。
4、如果cookie验证不过,就不用多说了。如果过了,就要接下来伪装跟服务器端的三次握手了。这样的包才会被放进conntrack表,最多是需要做点小小的欺骗。
5、两端三次握手OK后,后续数据包都要更改序列号,就是你一开始提的问题,因为序列号保存在ip_conntrack,自己也不用维护状态机,很简单,直接更改,重新计算校验和就行了。
作者: Godbach    时间: 2009-03-16 11:33
1、首先,在pre_routing挂一个Hook,它监听所有的tcp syn包(这里也可以做一些过滤,比如,只保护指定的目的地址等等,或者是做一个缓存,存下已验证正确的主机等等)。
2、伪造syn+ack,当然,是包含cookie的,因为这个回应的数量级非常之大,所以,效率很重要。
3、凡是收到ack,验证cookie,这里并不需要状态机。只要验证cookie就可以了,这是跟syn proxy最核心的区别了。
4、如果cookie验证不过,就不用多说了。如果过了,就要接下来伪装跟服务器端的三次握手了。这样的包才会被放进conntrack表,最多是需要做点小小的欺骗。
5、两端三次握手OK后,后续数据包都要更改序列号,就是你一开始提的问题,因为序列号保存在ip_conntrack,自己也不用维护状态机,很简单,直接更改,重新计算校验和就行了。


多谢啊。九贱兄的这个方法确实很不错。

只是这里你在conntrack之前做了cookie验证,那么你通过什么方式把这个差值告诉conntrrack呢?
作者: 独孤九贱    时间: 2009-03-16 11:40
你看我给你的数据结构应知道了。
通过了cookie验证,则ip_conntrack中的相应自定义字段记录cookie。而通过cookie处理的话,cookie一定是一个定值,否则为0。所以,如果cookie > 0,则应该处理seq,就这样简单噻。
实现这个框架其实不难,主要是cookie 的实现是现成的API,Netfilter的状态机也是现成的,内核截包、组包的API还是现成的。自己动手多试几回就整搞出来了,从Netfilter挂个Hook,自己动手截包伪装三次握手开始。我觉得关键还是要完善它比较困难一些,就是让它更快,更快……

[ 本帖最后由 独孤九贱 于 2009-3-16 11:41 编辑 ]
作者: Godbach    时间: 2009-03-16 12:44
原帖由 独孤九贱 于 2009-3-16 11:40 发表
你看我给你的数据结构应知道了。
通过了cookie验证,则ip_conntrack中的相应自定义字段记录cookie。而通过cookie处理的话,cookie一定是一个定值,否则为0。所以,如果cookie > 0,则应该处理seq,就这样简单噻 ...


那在syn cookie验证的过程中好像还得存储一下报文的相关信息吧。
作者: richardhesidu    时间: 2009-03-16 13:33
原帖由 Godbach 于 2009-3-16 12:44 发表


那在syn cookie验证的过程中好像还得存储一下报文的相关信息吧。

主要是在防火墙向server发送syn包以后,它需要知道去截获从server响应的怎么样的syn+ack包吧。
所以我觉得总得有个地方存储连接信息。
作者: 独孤九贱    时间: 2009-03-16 13:38
楼上的,你让给服务器的syn请求穿过netfilter连接跟踪表(事实上,如何是使用netfilter的状态跟踪,而不是自己来实现,也应该这样做),这个信息不就有地方存储了吗?
作者: dreamice    时间: 2009-03-16 13:40
原帖由 独孤九贱 于 2009-3-16 13:38 发表
楼上的,你让给服务器的syn请求穿过netfilter连接跟踪表(事实上,如何是使用netfilter的状态跟踪,而不是自己来实现,也应该这样做),这个信息不就有地方存储了吗?


我比较赞同这种利用已有机制的实现方式,风险小,而且可行性要好一些。
本身netfilter的contrack机制就是比较好的。
作者: richardhesidu    时间: 2009-03-16 13:43
原帖由 独孤九贱 于 2009-3-16 13:38 发表
楼上的,你让给服务器的syn请求穿过netfilter连接跟踪表(事实上,如何是使用netfilter的状态跟踪,而不是自己来实现,也应该这样做),这个信息不就有地方存储了吗?

对哦。我对这个conntrack不熟悉。
多谢!
作者: platinum    时间: 2009-03-16 14:13
记得当初九贱兄也是自己一点一点慢慢摸索出来的,大概有一年了吧?
不知道效率如何?有没有新的改动呢?
作者: Godbach    时间: 2009-03-16 14:24
原帖由 独孤九贱 于 2009-3-16 13:38 发表
楼上的,你让给服务器的syn请求穿过netfilter连接跟踪表(事实上,如何是使用netfilter的状态跟踪,而不是自己来实现,也应该这样做),这个信息不就有地方存储了吗?


采用syncookie + conntrack机制的话,个人觉得流程如下可以:
(1)在PREROUTING处conntrack前注册syncookie的hook函数。fw完成处理和client端SYN三次握手,同时保存初始的SYN包,并记录cookie值。经过验证之后,将保存的SYN包发给server。
(2)fw发给server的syn包经过conntrack,新建一个conntrack表项,并在报文离开fw时加入连接跟踪表。
这里如何获取cookie的值,让(1)模块中提供函数吗?
(3)server回复的SYN+ACK报文,
fw应该在哪里拦截,应该是在conntrack之后吧。这样可以保证conntrak得到更新。这里可以记录server发过来的SEQ。
(4)fw拦截到SYN+ACK,构造ACK报文,
这次还能再更新conntrack吗?ACK报文应该是经过FORWARD点从POSTROUTING出去了吧。如果可以更新,则conntrack表有了这一项。
(5)以后属于这个链接的报文,就直接查链接跟踪。并根据报文的方向和差值对ACK(client)号就行修改还是对SEQ号进行修改。
而这个差值应该就是fw构造的cookie值和server回复SYN+ACK的SEQ的差值。

以上是个人觉得实现的流程,还有一些疑问。大家分析一下可行性啊.

作者: Godbach    时间: 2009-03-16 14:57
继续讨论这个:wink:
作者: richardhesidu    时间: 2009-03-16 15:06
原帖由 Godbach 于 2009-3-16 14:24 发表


采用syncookie + conntrack机制的话,个人觉得流程如下可以:
采用syncookie + conntrack机制的话,个人觉得流程如下可以:
(1)在PREROUTING处conntrack前注册syncookie的hook函数。fw完成处理和client端SYN三次握手,同时保存初始的SYN包,并记录cookie值。经过验证之后,将保存的SYN包发给server。
(2)fw发给server的syn包经过conntrack,新建一个conntrack表项,并在报文离开fw时加入连接跟踪表。这里如何获取cookie的值,让(1)模块中提供函数吗?

我觉得(2)可以在(1)中完成。在拦截到client发来的ack包的时候。
作者: Godbach    时间: 2009-03-16 15:11
原帖由 richardhesidu 于 2009-3-16 15:06 发表

我觉得(2)可以在(1)中完成。在拦截到client发来的ack包的时候。


拦截到ACK的时候,fw应该是将原先保留的SYN包发出去,然后这个SYN包就会进入conntrack进行处理了。按理说这个时候新建了conntrack,应该让conntrack记录下之前的cookie值了。
作者: Godbach    时间: 2009-03-16 15:12
标题: 回复 #84 richardhesidu 的帖子
这个应该没有太大关系。关键是后面的(3)、(4)、(5)。具体的处理方式是否正确呢
作者: richardhesidu    时间: 2009-03-16 15:15
原帖由 Godbach 于 2009-3-16 15:11 发表


拦截到ACK的时候,fw应该是将原先保留的SYN包发出去,然后这个SYN包就会进入conntrack进行处理了。按理说这个时候新建了conntrack,应该让conntrack记录下之前的cookie值了。

cookie值在client的ack包里有啊。
作者: Godbach    时间: 2009-03-16 15:18
原帖由 richardhesidu 于 2009-3-16 15:15 发表

cookie值在client的ack包里有啊。


对。但是client的ACK到fw的syncookie就被处理了,不会交给conntrack处理了。fw再次发送的SYN到server才经过了conntrack的。前面的cookie值应该通过一定的方式给conntrack。
作者: richardhesidu    时间: 2009-03-16 15:31
可能我有什么没考虑到。
不能在接收到client的ack包的地方建立conntrack表项吗?
作者: Godbach    时间: 2009-03-16 15:49
原帖由 richardhesidu 于 2009-3-16 15:31 发表
可能我有什么没考虑到。
不能在接收到client的ack包的地方建立conntrack表项吗?


cookie的验证过程是在conntrack之前的。需要建conntrack表的时候是从fw发送SYN包到server的过程,这个过程会建conntrack表。这个表的源IP和目的IP就是client和server的。
作者: ShadowStar    时间: 2009-03-16 22:05
其实,我这边也要作这个东西。目前有2个方法。

我觉得SYN-FLOOD这个问题需要考虑如下几个关键点。
1. 效率,处理的速度(时间)。
2. 资源,防火墙的资源占用和被保护服务器的资源占用。

相比之下,代理握手的方式是效率相对较低、防火墙资源占用较大,服务器资源占用较小的。
尤其是保存syn包的方式,我觉得比较不可取。
我担心在大流量SYN-FLOOD时,防火墙被打死。

而另一种正好相对。

so, I'm in thinking.
作者: Godbach    时间: 2009-03-16 22:29
标题: 回复 #91 ShadowStar 的帖子
有效的抵御SYN flood,也许得多种方法结合着使用。
ShadowStar兄可否介绍一下另一种方法。。
作者: ShadowStar    时间: 2009-03-17 09:42
所谓的另一种方法,是针对于SYN-FLOOD的危害的采取的。

SYN-FLOOD主要危害是由于服务器的半开连接消耗较大资源导致的。

所以,我们可以把半开连接处理为完成连接。
也就是,放过SYN和SYN-ACK。伪造一个发送给服务器的ACK,并丢弃原始client的ACK。

这种方法会造成受到SYN-FLOOD攻击的服务器建立大量的连接。
但是防火墙本身的负担小了很多。
作者: Godbach    时间: 2009-03-17 09:48
所谓的另一种方法,是针对于SYN-FLOOD的危害的采取的。

SYN-FLOOD主要危害是由于服务器的半开连接消耗较大资源导致的。

所以,我们可以把半开连接处理为完成连接。
也就是,放过SYN和SYN-ACK。伪造一个发送给服务器的ACK,并丢弃原始client的ACK。

这种方法会造成受到SYN-FLOOD攻击的服务器建立大量的连接。
但是防火墙本身的负担小了很多。


ShadowStar兄的意思是让在server端建立起来连接。已建立的连接要比半连接节省资源。

但是本身使用fw保护server的,现在反而成了牺牲server保护fw,这样合适吗?
作者: ShadowStar    时间: 2009-03-17 10:07
原帖由 Godbach 于 2009-3-17 09:48 发表


ShadowStar兄的意思是让在server端建立起来连接。已建立的连接要比半连接节省资源。

但是本身使用fw保护server的,现在反而成了牺牲server保护fw,这样合适吗?


其实这个问题看怎么考虑了,因为这种处理方式已经处理了“SYN-FLOOD”攻击的主要危害。
而且,从防火墙和服务器整体考虑的话,这种方式的整体效率要好于代理方式,资源占用也不大。

并且可以通过对超时的syn连接(防火墙伪装完的)发送RST包,来降低服务器的连接数量。

可以保证正常的连接不受影响。

代理的方式在负载较大时,防火墙很容易成为网络的瓶颈,进而崩溃,影响的就不是一台服务器了。
作者: Godbach    时间: 2009-03-17 10:09
代理的方式在负载较大时,防火墙很容易成为网络的瓶颈,进而崩溃,影响的就不是一台服务器了。


恩,反正两个是串在一个绳子上的。
作者: ShadowStar    时间: 2009-03-17 10:13
原帖由 Godbach 于 2009-3-17 10:09 发表


恩,反正两个是串在一个绳子上的。


当然,这第二种方法与一般的用户理解还是有冲突的。
作者: Godbach    时间: 2009-03-17 10:16
不知ShadowStar兄是否已经采用了这种方式,效果怎么样啊?

另外,怎么确定这个SYN连接是攻击报文,而不是正常的请求呢? 因为你是拦截了server的SYN+ACK, 直接构造了ACK报文
作者: Godbach    时间: 2009-03-17 10:17
原帖由 ShadowStar 于 2009-3-17 10:13 发表


当然,这第二种方法与一般的用户理解还是有冲突的。


恩,我也觉得现在一般的用户可能还不容易接受这个方式。
作者: ShadowStar    时间: 2009-03-17 10:23
原帖由 Godbach 于 2009-3-17 10:16 发表
不知ShadowStar兄是否已经采用了这种方式,效果怎么样啊?

另外,怎么确定这个SYN连接是攻击报文,而不是正常的请求呢? 因为你是拦截了server的SYN+ACK, 直接构造了ACK报文


并不拦截SYN-ACK,而是在收到SYN-ACK时,直接伪造一个ACK发给服务器。
这样处理的成本小的多。

也不需要判断是否是攻击报文,只要在正常的SYN-RECV超时后发送RST就OK了;如果不超时,定时器刷新的话,自然也不会发送RST。

我还没有作,因为我手里还有别的在忙。另外,还没考虑好这样是否是最优的。




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