linux内核tcp syn seq读取

一 书上讲tcp 连接初始seq是随机取的,这里分析一下流程。

二 代码流程梳理

want_cookie 不在本文讨论范围,洪泛攻击的情况这里就不做分析了。

linux内核通过tcp_conn_request 完成握手动作。

初始syn的seq分为两种情况。

2.1 复用之前的timewait端口连接的最后一次的序列号。

__u32 isn = TCP_SKB_CB(skb)->tcp_tw_isn;

这样在接受连接一端,就会判断seq是符合递增的逻辑的,不会拒绝这次syn请求。

2.2 之前没有过连接的端口

isn = af_ops->init_seq(skb);

.init_seq  =   tcp_v4_init_seq,

分析一下tcp_v4_init_seq 函数。

static u32 tcp_v4_init_seq(const struct sk_buff *skb)

{

    return secure_tcp_seq(ip_hdr(skb)->daddr,

                  ip_hdr(skb)->saddr,

                  tcp_hdr(skb)->dest,

                  tcp_hdr(skb)->source);

}

tcp_v4_init_seq 参数是链接四元组

u32 secure_tcp_seq(__be32 saddr, __be32 daddr,

           __be16 sport, __be16 dport)

{

    u32 hash;

    net_secret_init(); // 获取随机数,用随机数生成密钥,存入net_secret

    hash = siphash_3u32((__force u32)saddr, (__force u32)daddr,

                (__force u32)sport << 16 | (__force u32)dport,

                &net_secret);//全局变量 net_secret 

//通过net_secret 得到一个hash值

    return seq_scale(hash); 

}

static u32 seq_scale(u32 seq)

{

    /*

     *  As close as possible to RFC 793, which

     *  suggests using a 250 kHz clock.

     *  Further reading shows this assumes 2 Mb/s networks.

     *  For 10 Mb/s Ethernet, a 1 MHz clock is appropriate.

     *  For 10 Gb/s Ethernet, a 1 GHz clock should be ok, but

     *  we also need to limit the resolution so that the u32 seq

     *  overlaps less than one time per MSL (2 minutes).

     *  Choosing a clock of 64 ns period is OK. (period of 274 s)

     */

    return seq + (ktime_get_real_ns() >> 6);

}

尽可能接近RFC 793

*建议使用250 kHz时钟。

*进一步的阅读表明,这是假设2 Mb/s的网络。

*对于10 Mb/s以太网,1 MHz时钟是合适的。

*对于10 Gb/s以太网,1 GHz时钟应该可以,但是

*我们还需要限制分辨率,以便u32-seq

*每个MSL重叠少于一次(2分钟)。

*选择64 ns周期的时钟是可以的。(274 s周期)

通过上面的seq_scale 生成最终的随机数seq

你可能感兴趣的:(tcp/ip,linux,网络)