contrack TCP协议状态转换

索引和TCP状态值

三维数组tcp_conntracks定义了TCP连接的状态转换表,

第一维表示方向,0和1分别表示原和反方向;

第二维表示6个报文标志,如下tcp_bit_set所示;

第三位表示当前的状态,最终索引对应的值为新状态。

 

static unsigned int get_conntrack_index(const struct tcphdr *tcph)
{
    if (tcph->rst) return TCP_RST_SET;
    else if (tcph->syn) return (tcph->ack ? TCP_SYNACK_SET : TCP_SYN_SET);
    else if (tcph->fin) return TCP_FIN_SET;
    else if (tcph->ack) return TCP_ACK_SET;
    else return TCP_NONE_SET;
}

 

/* What TCP flags are set from RST/SYN/FIN/ACK. */
enum tcp_bit_set {
    TCP_SYN_SET,
    TCP_SYNACK_SET,
    TCP_FIN_SET,
    TCP_ACK_SET,
    TCP_RST_SET,
    TCP_NONE_SET,
};

最新状态:

new_state = tcp_conntracks[0][get_conntrack_index(th)][TCP_CONNTRACK_NONE];
/* Invalid: delete conntrack */

具体逻辑为:org方向初始状态为TCP_CONNTRACK_NONE收到get_conntrack_index(th) 报文后状态为new_stat。

 

 

#define sNO TCP_CONNTRACK_NONE         //初始状态
#define sSS TCP_CONNTRACK_SYN_SENT     //SYN报文
#define sSR TCP_CONNTRACK_SYN_RECV     //SYN-ACK报文
#define sES TCP_CONNTRACK_ESTABLISHED  //ACK报文。三次握手的第三个ACK报文。
#define sFW TCP_CONNTRACK_FIN_WAIT     //FIN报文
#define sCW TCP_CONNTRACK_CLOSE_WAIT   //FIN报文之后,又观察到ACK报文
#define sLA TCP_CONNTRACK_LAST_ACK     //FIN报文之后,又观察到另一个方向的FIN报文
#define sTW TCP_CONNTRACK_TIME_WAIT    //最后的ACK报文
#define sCL TCP_CONNTRACK_CLOSE        //RST报文
#define sS2 TCP_CONNTRACK_SYN_SENT2    //回复方向SYN报文。TCP两端同时发起握手(simultaneous open)
#define sIV TCP_CONNTRACK_MAX          //真正的无效报文
#define sIG TCP_CONNTRACK_IGNORE       //可能无效的报文,接收端可能回复RST或SYN/ACK.


/* What TCP flags are set from RST/SYN/FIN/ACK. */
enum tcp_bit_set {
    TCP_SYN_SET,
    TCP_SYNACK_SET,
    TCP_FIN_SET,
    TCP_ACK_SET,
    TCP_RST_SET,
    TCP_NONE_SET,
};

/*
 * The TCP state transition table needs a few words...
 *
 * We are the man in the middle. All the packets go through us
 * but might get lost in transit to the destination.
 * It is assumed that the destinations can't receive segments
 * we haven't seen.
 *
 * The checked segment is in window, but our windows are *not*
 * equivalent with the ones of the sender/receiver. We always
 * try to guess the state of the current sender.
 *
 * The meaning of the states are:
 *
 * NONE:    initial state
 * SYN_SENT:    SYN-only packet seen
 * SYN_SENT2:    SYN-only packet seen from reply dir, simultaneous open
 * SYN_RECV:    SYN-ACK packet seen
 * ESTABLISHED:    ACK packet seen
 * FIN_WAIT:    FIN packet seen
 * CLOSE_WAIT:    ACK seen (after FIN)
 * LAST_ACK:    FIN seen (after FIN)
 * TIME_WAIT:    last ACK seen
 * CLOSE:    closed connection (RST)
 *
 * Packets marked as IGNORED (sIG):
 *    if they may be either invalid or valid
 *    and the receiver may send back a connection
 *    closing RST or a SYN/ACK.
 *
 * Packets marked as INVALID (sIV):
 *    if we regard them as truly invalid packets
 */
static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = {
    {
/* ORIGINAL *///第二行表示接收到相应标志的报文(如SYN)之后,新的状态
/*          sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2    */
/*syn*/       { sSS, sSS, sIG, sIG, sIG, sIG, sIG, sSS, sSS, sS2 },
/*
 *    sNO -> sSS    Initialize a new connection客户端发起一个新连接;
 *    sSS -> sSS    Retransmitted SYN客户端重传SYN报文;
 *    sS2 -> sS2    Late retransmitted SYN
 *    sSR -> sIG  客户端正常应回复ACK,但是其又发送了SYN报文,服务端接收到此SYN报文之后,可能RST此连接,也可能回复SYN-ACK;
 *    sES -> sIG    Error: SYNs in window outside the SYN_SENT state
 *            are errors. Receiver will reply with RST
 *            and close the connection.
 *            Or we are not in sync and hold a dead connection.
 *    sFW -> sIG在FIN_WAIT状态接收到客户端SYN报文;
 *    sCW -> sIG
 *    sLA -> sIG
 *    sTW -> sSS    Reopened connection (RFC 1122).对于TIME_WAIT状态的连接,客户端又发送SYN报文,快速重开连接
 *    sCL -> sSS
 */
/*          sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2    */
/*synack*/ { sIV, sIV, sSR, sIV, sIV, sIV, sIV, sIV, sIV, sSR },
/*
 *    sNO -> sIV    Too late and no reason to do anything
 *    sSS -> sIV    Client can't send SYN and then SYN/ACK 客户端发送完SYN报文,又发送SYN-ACK报文
 *    sS2 -> sSR    SYN/ACK sent to SYN2 in simultaneous open
 *    sSR -> sSR    Late retransmitted SYN/ACK in simultaneous open客户端重传SYN-ACK报文,发生在两端同时发起连接的情况下
 *    sES -> sIV    Invalid SYN/ACK packets sent by the client  在连接建立状态下,接收到客户端的SYN-ACK报文
 *    sFW -> sIV
 *    sCW -> sIV
 *    sLA -> sIV
 *    sTW -> sIV
 *    sCL -> sIV
 */
/*          sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2    */
/*fin*/    { sIV, sIV, sFW, sFW, sLA, sLA, sLA, sTW, sCL, sIV },
/*
 *    sNO -> sIV    Too late and no reason to do anything...
 *    sSS -> sIV    Client migth not send FIN in this state:
 *            we enforce waiting for a SYN/ACK reply first.
 *    sS2 -> sIV
 *    sSR -> sFW    Close started.
 *    sES -> sFW
 *    sFW -> sLA    FIN seen in both directions, waiting for
 *            the last ACK.
 *            Migth be a retransmitted FIN as well...
 *    sCW -> sLA
 *    sLA -> sLA    Retransmitted FIN. Remain in the same state.
 *    sTW -> sTW
 *    sCL -> sCL
 */
/*          sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2    */
/*ack*/       { sES, sIV, sES, sES, sCW, sCW, sTW, sTW, sCL, sIV },
/*
 *    sNO -> sES    Assumed.
 *    sSS -> sIV    ACK is invalid: we haven't seen a SYN/ACK yet.
 *    sS2 -> sIV
 *    sSR -> sES    Established state is reached.
 *    sES -> sES    :-)
 *    sFW -> sCW    Normal close request answered by ACK.
 *    sCW -> sCW
 *    sLA -> sTW    Last ACK detected (RFC5961 challenged)
 *    sTW -> sTW    Retransmitted last ACK. Remain in the same state.
 *    sCL -> sCL
 */
/*          sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2    */
/*rst*/    { sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL },
/*none*/   { sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV }
    },
    {
/* REPLY 回复方向状态变换*/
/*          sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2    */
/*syn*/       { sIV, sS2, sIV, sIV, sIV, sIV, sIV, sSS, sIV, sS2 },
/*
 *    sNO -> sIV    Never reached.
 *    sSS -> sS2    Simultaneous open客户端发送了SYN报文,又接收到服务端的SYN报文,表明两端在同时开启连接
 *    sS2 -> sS2    Retransmitted simultaneous SYN 服务端重传SYN报文
 *    sSR -> sIV    Invalid SYN packets sent by the server 服务端发送的无效SYN报文
 *    sES -> sIV
 *    sFW -> sIV
 *    sCW -> sIV
 *    sLA -> sIV
 *    sTW -> sSS    Reopened connection, but server may have switched role 服务端重新开启连接
 *    sCL -> sIV
 */
/*          sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2    */
/*synack*/ { sIV, sSR, sIG, sIG, sIG, sIG, sIG, sIG, sIG, sSR },
/*
 *    sSS -> sSR    Standard open.
 *    sS2 -> sSR    Simultaneous open
 *    sSR -> sIG    Retransmitted SYN/ACK, ignore it.
 *    sES -> sIG    Late retransmitted SYN/ACK?
 *    sFW -> sIG    Might be SYN/ACK answering ignored SYN
 *    sCW -> sIG
 *    sLA -> sIG
 *    sTW -> sIG
 *    sCL -> sIG
 */
/*          sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2    */
/*fin*/    { sIV, sIV, sFW, sFW, sLA, sLA, sLA, sTW, sCL, sIV },
/*
 *    sSS -> sIV    Server might not send FIN in this state.
 *    sS2 -> sIV
 *    sSR -> sFW    Close started.
 *    sES -> sFW
 *    sFW -> sLA    FIN seen in both directions.
 *    sCW -> sLA
 *    sLA -> sLA    Retransmitted FIN.
 *    sTW -> sTW
 *    sCL -> sCL
 */
/*          sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2    */
/*ack*/       { sIV, sIG, sSR, sES, sCW, sCW, sTW, sTW, sCL, sIG },
/*
 *    sSS -> sIG    Might be a half-open connection.
 *    sS2 -> sIG
 *    sSR -> sSR    Might answer late resent SYN.
 *    sES -> sES    :-)
 *    sFW -> sCW    Normal close request answered by ACK.
 *    sCW -> sCW
 *    sLA -> sTW    Last ACK detected (RFC5961 challenged)
 *    sTW -> sTW    Retransmitted last ACK.
 *    sCL -> sCL
 */
/*          sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2    */
/*rst*/    { sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL },
/*none*/   { sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV }
    }
};

 

posted @ 2023-03-15 13:40  codestacklinuxer  阅读(136)  评论(0编辑  收藏  举报