分类: LINUX
2017-08-15 15:15:38
我们先来看一下iptables定义的连接状态:
INVALID :无效连接,防火墙一般会丢弃该连接
NEW:新建立的,既只是通信双方中只一方发送了报文,还没有得到回应的
ESTABLISHED:已经得到回应的连接。既通信双方都发送过报文的连接
RELATED:关联的连接,既有期望连接关联的连接
UNTRACKED:不进行连接跟踪的连接
SNAT:配置了SNAT的连接
DNAT:配置了DNAT的连接
这里我们拿一个udp通信的例子来走一遍连接建立的过程。先不具体到代码的实现。
1、首先,PC和SERVER使用udp报文进行通信。
PC--------->SERVER
报文的元组信息如下:
Sip:1.1.1.6
Sport:1116
Dip:1.1.1.5
Dport:1115
l4protonum:udp
L3num:INET
报文到达防火墙,防火墙的处理如下:
防火墙入口处
conntrack模块截获报文。
根据报文的元组信息在防火墙内的连接表中查找是否已经存在建立的连接,因为第一次通信,没有已建立的连接。
建立一个新的连接,连接的正反向元组信息如下图,并把该连接的正向连接A挂到unconfirmed链表上
如上,新建连接后,把该连接和报文进行关联,连接状态是NEW。
防火墙出口处:
拦截报文后,根据报文携带的连接信息,找到连接,把该连接的正向连接A从unconfirmed链表上摘下来,把该连接的正反向连接A和B加入到连接hash表中。并把该连接确认状态置为confirmed状态,即置位status的IPS_CONFIRMED_BIT位。
SERVER----->PC
SERVER回应PC的报文元组信息如下:
Sip:1.1.1.5
Sport:1115
Dip:1.1.1.6
Dport:1116
l4protonum:udp
L3num:INET
报文到达防火墙,防火墙的处理如下:
防火墙入口处
conntrack模块截获报文。
根据报文的元组信息在防火墙内的连接表中查找是否已经存在建立的连接,可以找到已建立的连接B。
发现连接B里的dir是reply,表明该连接已经有回应报文了,给连接中的status置位IPS_SEEN_REPLY_BIT,表明该连接已经收到了回应报文。这时把报文的连接状态变为ESTABLISHED
防火墙出口处:
拦截报文后,根据报文携带的连接信息,找到连接,发现该连接确认状态是confirmed的,直接不进行连接处理。
至此,连接建立完成。
后续该连接的正反方向的报文都可以在连接表中查到相应的连接,就可以根据连接进行相应的处理了。
这里我们先大致了解一下期望连接的建立关联过程。偷个懒,以比较简单的tftp协议来举例。
我们先来简要的说明一下tftp协议。tftp报文格式如下(图片摘自TCP/IP详解)。
当client主动和server发起通信时,使用熟知的端口号69。Server要和client进行数据传输时,会申请一个没有使用的端口来进行通信,留着69号端口来接收其他client的连接请求。
这样client主动和server发起通信的第一个报文就算是控制报文,该报文的操作码是0或1。其后的报文就是数据报文。
如下图,假设tftp server使用端口1115来和client进行数据通信。
1、在Netfilter中,tftp需要提供根据熟知端口69来建立期望连接的处理函数helper()。
tftp 提供的helper函数及查找该helper的元组信息如下:
(helper使用的tuple信息时源端口号,L3协议类型,L4协议类型)
2、PC--->SERVER
Client主动发起连接。报文元组信息如下
Dip 1.1.1.5
Sip.1.1.1.6
Dport:69
Sport:1116
Protonum:udp
L3num:Inet
(1)、Netfilter入口,conntrackl连接报文
建立正反向连接,和一般连接处理一样。
新建连接的过程中,会根据连接的反向连接B中的sport,protonum,L3num来在Netfilter中查找已注册的helper函数。找到已注册的tftp的helper函数,并把该函数指针赋给连接。
连接状态设置为NEW
防火墙出口处:
拦截报文后,根据报文携带的连接信息,找到连接。并执行连接带的helper函数。
Tftp的helper函数做如下处理
<1>创建一个期望连接。初始化如下
*(期望连接使用的tuple信息是源IP,目的IP,目的端口号,L3协议类型,L4协议类型)
把该期望连接插入到全局的期望连接表中。
把该连接的正向连接A从unconfirmed链表上摘下来,把该连接的正反向连接A和B加入到连接hash表中。并把该连接确认状态置为confirmed状态。
SERVER--->PC
SERVER回应Client的请求,报文元组信息如下
Dip 1.1.1.6
Sip.1.1.1.5
Dport:1116
Sport:1115
Protonum:udp
L3num:Inet
防火墙入口处
conntrack模块截获报文。
在连接表中查找已建立的连接,没有找到,新建一个连接。现在整个Netfiler中建立的连接如下:
总共有A,B,C,D,E五个方向上的连接。
在新建连接的过程中,会根据连接的正方向连接D的dport,dip,protonum,L3num为hash key来在expect_hash表中查找,找到对应的期望连接C。置连接status的IPS_EXPECTED_BIT位。
设置连接的状态为RELATED。
防火墙出口处
确认连接,至此,期望连接的建立和关联完毕。
以后SERVER来的每个报文在连接表中查找到已建立的连接,发现该连接的status中置了IPS_EXPECTED_BIT位,就指定该连接是期望连接,设置报文的连接状态为RELATED。
(未完待续)