iptables的基础知识-iptables中TCP三次握手:
一个TCP连接是通过三次握手的方式完成的。首先,客户程序发出一个同步请求(发出一个SYN分组);接着,服务器端回应一个SYN|ACK分组;最后返回一个ACK分组,连接完成,一共需要三个步骤,整个iptables过程如下所示:
- Client Server
- 1 SYN --->
- 2 <--- SYN+ACK
- 3 ACK --->
- <--- ACK
- ACK --->
接下来我们看具体iptables的过程,假设client(192.168.10.7)要访问server(192.168.10.100,同时启用iptables)的WEB主页。
1 client首先发出一个SYN的连线请求(注意ack,rst等的值),源端口是1286,目的端口是80。
2 Server收到着请求后应答一个SYN+ACK,因为是SERVER应答client,所以源端口是80,目的端口是1286。
3 client再答复一个ACK,至此三步握手的过程结束,一个正常的连接建立。
从以上的三步中可以看到,一个正常的tcp连接建立的过程。值得注意的是一个正常的tcp发起的请求,tcp中包头中SYN位是1,这就意味着如果一个新的包但是SYN却不置位,这个包肯定有问题。
为了跟踪一个TCP连接的状态,我们在SERVER使用了如下命令:
- iptables -A INPUT -p tcp -m state --state NEW,ESTABLISHED -j ACCEPT
- iptables -A OUTPUT -p tcp -m state --state ESTABLISHED -j ACCEPT
接着看在连接建立过程中iptables状态表的变化:
1> 由于CLIENT和SERVER之前没有任何连接,CLIENT发送的SYN(此时的TCP状态是SYN_SENT)请求进入iptables 的INPUT链,发现是一个新包,那么此时iptables将此状态定义为NEW,因为我们的规则允许,这个请求包被接受。
2> server返回一个SYN+ACK的包(此时的TCP状态是SYN_RECIV),这个包要经过OUTPUT链(因为这个包是从本机发出的,目的地址是client),由于之前曾经收到一个包,此时个状态,已经变成了ESTABLISHED,按照规则,这个包成功发送出去。
3> 接下来client发送一个ACK,同样由于INPUT中允许,server接受这个包,至此连接完成,在整个过程中状态从NEW变为ESTABLISHED(此时的TCP也是established)
注意:在第二步的时候,server上TCP的状态是SYN_RECVD,对于iptables来讲,状态已经是established,但此时的三次握手并没有完成,实际是半连接(对与TCP来讲,必须是三次握手完成以后,状态才是established)。所以iptables面对SYNFLOOD攻击,可以通过控制SYN流量结合tc等实现。但是对于SYN攻击,即便能保护服务器,对于带宽的消耗也是没有办法的,因为攻击者消耗了你大部分带宽。具体连接过程中TCP状态是如何变化可参考看TCP/IP V1等著作(douglas E.comer或者Steven Richard等的经典之作)。
注意iptables状态机制在用户空间里的部分不会查看TCP包的标志位(也就是说TCP标志对它而言是透明的)。如果我们想让NEW状态的包通过防火墙,就要指定NEW状态,我们理解的NEW状态的意思就是指SYN包,可是iptables又不查看这些标志位。这就是问题所在。有些没有设置SYN或ACK的包,也会被看作NEW状态的。这样的包可能会被冗余防火墙用到,但对只有一个防火墙的网络是很不利的(可能会被攻击哦)。那我们怎样才能不受这样的包的影响呢?可以使用tcp-flags进行检查。
上一节:iptables中的状态检测 下一节:iptables中的ICMP。
【编辑推荐】