共计 2265 个字符,预计需要花费 6 分钟才能阅读完成。
用户态的连接跟踪中的几种状态
连接跟踪系统中定义了一个连接可能处于以下几种状态:
- NEW:一个连接的初始状态(例如:TCP 连接中,一个 SYN 包的到来),或者防火墙只收到一个方向的流量(例如:防火墙在没有收到回复包之前)。
- ESTABLISHED:连接已经建立完成,换句话说防火墙已经看到了这条连接的双向通信。
- RELATED:这是一个关联连接,是一个主链接的子连接,例如 ftp 的数据通道的连接。
- INVALID:这是一个特殊的状态,用于记录那些没有按照预期行为进行的连接 (比如 LVS 的 DR,TUNNEL 模式的非第一个 syn 报文就是 INVALID 的,INVALID 并不一定会丢报文,不设定规则是不会丢弃这种报文的)。系统管理员可以定义一个 iptables 规则来记录和丢弃这种数据包。就像前面说的连接跟踪不会过滤数据包,但是他提供了一种方法来过滤。
在内核中如何对应这些状态呢?
内核中的几种状态
/* Connection state tracking for netfilter. This is separated from,
but required by, the NAT layer; it can also be used by an iptables
extension. */
enum ip_conntrack_info {/* Part of an established connection (either direction). */
IP_CT_ESTABLISHED,// 对应用户态的 ESTABLISHED 的请求方向
/* Like NEW, but related to an existing connection, or ICMP error
(in either direction). */
IP_CT_RELATED,// 对应用户态的 RELATED 的请求方向
/* Started a new connection to track (only
IP_CT_DIR_ORIGINAL); may be a retransmission. */
IP_CT_NEW,// 对应用户态的 NEW
/* >= this indicates reply direction */
IP_CT_IS_REPLY,// 等价于 IP_CT_ESTABLISHED_REPLY,这就是为什么将 IP_CT_ESTABLISHED 设置为 0 的原因了
IP_CT_ESTABLISHED_REPLY = IP_CT_ESTABLISHED + IP_CT_IS_REPLY,// 对应用户态的 ESTABLISHED 的应答方向
IP_CT_RELATED_REPLY = IP_CT_RELATED + IP_CT_IS_REPLY,// 对应于用户态的 RELATED 的应答方向
/* No NEW in reply direction. */
/* Number of distinct IP_CT types. */
IP_CT_NUMBER,
/* only for userspace compatibility */
#ifndef __KERNEL__
IP_CT_NEW_REPLY = IP_CT_NUMBER,
#else
IP_CT_UNTRACKED = 7,// 没有进行连接跟踪,用户态可以通过设置规则让报文不进行连接跟踪
#endif
};
从上面的对比可以看出,用户态的 INVALID 状态在内核中没有对应的描述,那么那个状态表示 INVALID 状态了,我们可以看一下”state“match 的执行函数
static bool
state_mt(const struct sk_buff *skb, struct xt_action_param *par)
{
const struct xt_state_info *sinfo = par->matchinfo;
enum ip_conntrack_info ctinfo;
unsigned int statebit;
struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
if (ct)
statebit = XT_STATE_BIT(ctinfo);
else if (ctinfo == IP_CT_UNTRACKED)
statebit = XT_STATE_UNTRACKED;
else
statebit = XT_STATE_INVALID;
return (sinfo->statemask & statebit);
}
/* Return conntrack_info and tuple hash for given skb. */
static inline struct nf_conn *
nf_ct_get(const struct sk_buff *skb, enum ip_conntrack_info *ctinfo)
{
*ctinfo = skb->_nfct & NFCT_INFOMASK;
return (struct nf_conn *)(skb->_nfct & NFCT_PTRMASK);
}
//skb->_nfct 的定义为:unsigned long _nfct;
// 在连接跟踪中的作用有两个,LSB 三个 bit 用来表示连接跟踪的状态,即枚举 ip_conntrack_info 中的值,剩下的 bit 用来
// 表示其对应的 ct 的地址,通过强制类型转换得到。这是因为在分配内存时 ct 的地址是按照 8 字节对齐的 ( 这是通过 slab 分配器中
// 的 SLAB_HWCACHE_ALIGN 标志实现的 ),所以 lsb 三个 bit 永远为 0,kernel 刚好使用该特性来表示状态。
从这个函数可以看出,当报文不存在 ct,并且其状态不为 XT_STATE_UNTRACKED 时,即认为其状态为 XT_STATE_INVALID。
正文完