对连接跟踪的INVALID状态的深入理解

22次阅读

共计 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。

正文完
 0