发布于 4年前

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

用户态的连接跟踪中的几种状态

连接跟踪系统中定义了一个连接可能处于以下几种状态:

  • 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,并且其状态不为IP_CT_UNTRACKED时,即认为其状态为XT_STATE_INVALID。

配置样例

配置设备只接受ssh流量(INPOUT节点默认策略配置成DROP)

-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p tcp --dport 22 -m state --state NEW -j ACCEPT 

如果配置成:

-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT   
-A INPUT -p tcp --dport 22 -j ACCEPT 

这种配置不仅会接收正常的ssh请求报文,也会接收INVALID状态的报文。

©2020 edoou.com   京ICP备16001874号-3