Deep Understanding of the INVALID State of Connection Tracking

Keywords: C firewall iptables ftp

Several states in user-mode connection tracking

A connection tracking system defines several states in which a connection may be in:

  • NEW: The initial state of a connection (e.g. the arrival of a SYN packet in a TCP connection), or the firewall receives only traffic in one direction (e.g. before the firewall receives a reply packet).
  • ESTABLISHED: The connection has been established. In other words, the firewall has seen the two-way communication of the connection.
  • RELATED: This is an associated connection, a sub-connection of a main link, such as a connection to the data channel of ftp.
  • INVALID: This is a special state for recording connections that do not behave as expected (e.g. DR of LVS, INVALID is the first syn message in TUNNEL mode, INVALID does not necessarily lose a message without setting rules). System administrators can define an iptables rule to record and discard such data packets. As mentioned earlier, connection tracking does not filter packets, but it provides a way to filter them.

How do you correspond to these states in the kernel?

Several states in the kernel

/* 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,//Request direction of ESTABLISHED corresponding to user state

    /* Like NEW, but related to an existing connection, or ICMP error
       (in either direction). */
    IP_CT_RELATED,//Request direction of REATED corresponding to user state

    /* Started a new connection to track (only
           IP_CT_DIR_ORIGINAL); may be a retransmission. */
    IP_CT_NEW,//NEW corresponding to user state

    /* >= this indicates reply direction */
    IP_CT_IS_REPLY,//Equivalent to IP_CT_ESTABLISHED_REPLY, which is why IP_CT_ESTABLISHED is set to 0

    IP_CT_ESTABLISHED_REPLY = IP_CT_ESTABLISHED + IP_CT_IS_REPLY,//Response Direction of ESTABLISHED Corresponding to User State
    IP_CT_RELATED_REPLY = IP_CT_RELATED + IP_CT_IS_REPLY,//Response Direction of RELATED Corresponding to User State
    /* 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,//Without connection tracking, user mode can set rules to keep messages from connection tracking.
#endif
};

From the above comparison, we can see that the INVALID state of user state has no corresponding description in the kernel, so that state represents the INVALID state, we can see the execution function of "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 is defined as unsigned long_nfct;
//There are two functions in connection tracking. LSB three bits are used to represent the status of connection tracking, i.e. enumerating the values in ip_conntrack_info, and the remaining bits are used to represent the status of connection tracking.
//Represents the address of its corresponding ct, which is obtained by forced type conversion. This is because the address of CT is aligned by 8 bytes when memory is allocated (this is through the slab allocator)
//The SLB_HWCACHE_ALIGN flag is implemented, so the three bit s of lsb are always 0, and the kernel just uses this feature to represent the state.

It can be seen from this function that when a message does not have ct and its state is not XT_STATE_UNTRACKED, it is considered as XT_STATE_INVALID.

Posted by Jeremiah on Fri, 27 Sep 2019 06:01:27 -0700