FortiGate 防火墙 TCP 会话状态详解 版本 1.0 时间支持的版本作者状态反馈 2015 年 10 月 5.x,4.x 宋占军已审核 support_cn@fortinet.com 文档说明 : 文档主要描述了当数据流穿过防火墙时, 相关的 TCP 会话状态的变化过程及其原理, 以及如何修改会话相关地计时器 目录 1. TCP 状态类型... 2 2. TCP 状态跟踪... 3 3. TCP 状态描述... 5 3.1. 阶段 1: 会话协商... 5 3.2. 阶段 2: 会话建立... 5 3.3. 阶段 3: 会话拆除... 5 4. TCP 状态分析... 6 4.1. 防火墙如何标记会话状态... 7 4.2. 为何没有 TCP_S_FIN_WAIT 状态... 7 4.3. TCP_S_CLOSE 状态说明... 8 4.4. 特殊的 TCP_S_LAST_ACK 状态... 8 4.5. TIME_WAIT 状态... 8 1 / 9 support.fortinet.com.cn
1. TCP 状态类型 TCP 会话状态变迁图如下 : 有关 TCP 状态的描述是基于 client 和 server 的, 防火墙位于 client 与 server 端之间, 需 要根据 TCP 数据包的传送, 对防火墙状态进行跟踪并更新 在 FortiGate 中,TCP 会话状态定义如下 : FGT60D4614023369 # diagnose sys session filter proto-state <x> <0-9> (from). //tcp 状态 0: ANY 1: TCP_S_ESTABLISHED, SCTP_S_ESTABLISHED 2: TCP_S_SYN_SENT, SCTP_S_CLOSED 3: TCP_S_SYN_RECV, SCTP_S_COOKIE_WAIT 4: TCP_S_FIN_WAIT, SCTP_S_COOKIE_ECHOED 5: TCP_S_TIME_WAIT, SCTP_S_SHUTDOWN_SENT 6: TCP_S_CLOSE, SCTP_S_SHUTDOWN_RECD 7: TCP_S_CLOSE_WAIT, SCTP_S_SHUTDOWN_ACK_SENT 8: TCP_S_LAST_ACK 9: TCP_S_LISTEN 2 / 9 support.fortinet.com.cn
2. TCP 状态跟踪 通过对数据包进行回放, 来对防火墙 TCP 会话状态进行跟踪 本例中共 10 个数据包,1-3 建立会话,4-6 传输数据,7-10 关闭会话 数据包经过 防火墙后防火墙的会话信息如下所示 : 1.pcapng 1. FGT60D4614023369 # diagnose sys session list session info: proto=6 proto_state=02 duration=2 expire=7 timeout=3600 flags=00000000 sockflag=00000000 sockport=0 av_idx=0 use=3 origin-shaper= reply-shaper= per_ip_shaper= ha_id=0 policy_dir=0 tunnel=/ state=may_dirty statistic(bytes/packets/allow_err): org=52/1/1 reply=0/0/0 tuples=2 orgin->sink: org pre->post, reply pre->post dev=3->4/4->3 gwy=1.1.1.2/0.0.0.0 hook=pre dir=org act=noop 192.168.1.168:58176->1.1.1.2:80(0.0.0.0:0) hook=post dir=reply act=noop 1.1.1.2:80->192.168.1.168:58176(0.0.0.0:0) pos/(before,after) 0/(0,0), 0/(0,0) misc=0 policy_id=2 id_policy_id=0 auth_info=0 chk_client_info=0 vd=0 serial=0005d657 tos=ff/ff ips_view=0 app_list=0 app=0 dd_type=0 dd_mode=0 npu_state=0x000001 no_offload total session 1 2. FGT60D4614023369 # diagnose sys session list 3 / 9 support.fortinet.com.cn
session info: proto=6 proto_state=03 duration=8 expire=7 timeout=3600 flags=00000000 3. FGT60D4614023369 # diagnose sys session list session info: proto=6 proto_state=01 duration=14 expire=3597 timeout=3600 flags=00000000 4. FGT60D4614023369 # diagnose sys session list session info: proto=6 proto_state=01 duration=21 expire=3597 timeout=3600 flags=00000000 5. FGT60D4614023369 # diagnose sys session list session info: proto=6 proto_state=01 duration=26 expire=3598 timeout=3600 flags=00000000 6. FGT60D4614023369 # diagnose sys session list session info: proto=6 proto_state=01 duration=31 expire=3598 timeout=3600 flags=00000000 7. FGT60D4614023369 # diagnose sys session list session info: proto=6 proto_state=07 duration=38 expire=117 timeout=3600 flags=00000000 8. FGT60D4614023369 # diagnose sys session list session info: proto=6 proto_state=07 duration=45 expire=116 timeout=3600 flags=00000000 9. FGT60D4614023369 # diagnose sys session list session info: proto=6 proto_state=05 duration=53 expire=58 timeout=3600 flags=00000000 4 / 9 support.fortinet.com.cn
10. FGT60D4614023369 # diagnose sys session list session info: proto=6 proto_state=05 duration=61 expire=56 timeout=3600 flags=00000000 3. TCP 状态描述 3.1. 阶段 1: 会话协商 防火墙接收到 1 SYN 包, 会话状态 proto_state=02 TCP_S_SYN_SENT, expire=7: 防火墙接收到 2 SYN-ACK 包, 会话状态 proto_state=03 TCP_S_SYN_RECV, expire=7: 这 2 个状态的超时时间由 halfopen 计时器控制, 配置参数如下 : Config sys global set tcp-halfopen-timer 10 // 默认 10 秒 3.2. 阶段 2: 会话建立 防火墙接收到 3 ACK 包之后, 会话建立成功,proto_state=01,TCP_S_ESTABLISHED, expire=3597 ( 默认 3600) 会话建立之后, 超时时间受 session ttl 控制, 通过 Config system session-ttl 来配置 任何匹配该会话的数据包都会重置该计时器 如防火墙接收到 4,5,6 包之后, 都会刷新该计时器 3.3. 阶段 3: 会话拆除 防火墙接收到 7 FIN 包, 会话进入 proto_state=07,tcp_s_close_wait 状态,expire=117 防火墙接收到 8 ACK 包, 会话依然为 proto_state=07 状态,expire=116, 该包会重置 计时器为 120 秒 5 / 9 support.fortinet.com.cn
这个状态的超时时间由 tcp-halfclose-timer 控制, 配置命令 : Config sys global set tcp-halfclose-timer 120 // 默认 120 秒 防火墙接收到另一端的 9 FIN 包, 会话进入 proto_state=05 TCP_S_TIME_WAIT 状态, expire=58.( 为了便于说明, 上例中将 TIME_WAIT 配置为 60 秒, 在 5.0.12 版本中默认为 1 秒 ) Config sys global Set tcp-timewait-timer 10 // 默认 1 秒, 建议改为 5-10 秒 防火墙接收到另一端的 10 ACK 包, 会话状态为 proto_state=05,expire=56, 该包会刷新 tcp-timewait-timer 计时器 4. TCP 状态分析 由于 TCP 状态机制是基于 TCP 的服务器和客户端进行定义, 上述 TCP 会示例中, 并未在防火墙的会话表中看到所有的 TCP 状态, 只涉及到 2,3,1,7,5 这几个状态 更多 TCP 状态可以参考如下图 : 6 / 9 support.fortinet.com.cn
4.1. 防火墙如何标记会话状态 防火墙根据发送数据包的源地址 ( 服务器或者客户端 ) 的 TCP 状态来标识防火墙的会话状态 如当防火防火墙接收到客户端的 SYN 包时,TCP 的客户端属于 SYN-sent 状态 会话状态为 SYN-sent 状态 收到服务器的 (SYN,ACK) 包时, 服务器处于 SYN-received 状态, 防火墙接收到第三个 ACK 包, 客户端进入 ESTABLISHED 状态, 而无需关心服务器端是否接收到了该 ACK 包 4.2. 为何没有 TCP_S_FIN_WAIT 状态 本例是由服务器端 1.1.1.2 来首先发起结束会话, 根据上图所示, 服务器端发送 FIN, 和接收到相应的 ACK 之后, 处于 7: TCP_S_CLOSE_WAIT 状态 如果上例中第 7 个包是由客户端 192.168.1.168 发出 FIN 来结束会话, 那么防火墙会话的状态会为 4: TCP_S_FIN_WAIT 超时时间也是受 half-close 的 timer 控制,120 秒 7 / 9 support.fortinet.com.cn
FG#diagnose sys session list session info: proto=6 proto_state=04 duration=46 expire=115 timeout=3600 flags=00000000 sockflag=00000000 sockport=0 av_idx=0 use=3 如果上例中第 8 个包是由服务器 1.1.1.2 发出 ACK 包来对 FIN 进行取认, 会话状态为 4: TCP_S_FIN_WAIT 防火墙没有对 FIN_WAIT1 和 FIN_WAIT 2 做更细致的区分 4.3. TCP_S_CLOSE 状态说明 当防火墙收到任何一方发送的 RST 报文后, 防火墙会话进入 06:TCP_S_CLOSE 状态 默认为 10 秒 FG # diagnose sys session list session info: proto=6 proto_state=06 duration=27 expire=8 timeout=3600 flags=00000000 sockflag=00000000 sockport=0 av_idx=0 use=3 4.4. 特殊的 TCP_S_LAST_ACK 状态 该状态描述为当客户端 FIN--- 服务器 ACK---- 服务器 FIN 三个包发送后, 服务器端等待最有一个客户端发出的 ACK 包时的状态 由于最后一个包是由客户端发出, 防火墙接收到最有一个 ACK 包后, 会话状态会标识为客户端的状态, 也就是完成整个会话后的 TIME_WAIT 状态 所以通过 dia sys session full 查不到处于 LAST_ACK 状态的会话 4.5. TIME_WAIT 状态 当 T C P 执行一个主动关闭, 并发回最后一个 A C K, 该连接必须在 T I M E WA I T 状态停留一段时间, 这样可让 T C P 再次发送最后的 A C K 以防这个 A C K 丢失 ( 另一端超时并重发最后的 F I N) 等待期间, 定义这个连接的插口 ( 客户的 I P 地址和端口号, 服务器的 I P 地址和端口号 ) 不能再被使用 由于最后一个 FIN 和 ACK 都可能被重传, 所以在收到最后一个 FIN 之后, 防火墙会话进入 T I M E WA I T 状态 在 5.0 版本中, 默认为 1 秒, 由于涉及到 2 个数据包的传送, 所 8 / 9 support.fortinet.com.cn
以建议适当增加 ( 范围 0-300 秒 ) 参考文献 : http://kb.fortinet.com/kb/microsites/search.do?cmd=displaykc&doctype=kc&externalid=f D30042&sliceId=1&docTypeID=DT_KCARTICLE_1_1&dialogID=8444147&stateId=0%200%207311 4513 9 / 9 support.fortinet.com.cn