SYN包TCP选项的设置

本文深入探讨了TCP连接初始阶段的SYN包及其包含的选项设置,包括MSS、WS、TS等,解释了它们在确保高效、可靠通信中的作用。通过理解这些选项,读者将能更好地掌握TCP连接的建立过程。
摘要由CSDN通过智能技术生成

一个SYN可能包括这些内容:初始系列号、初始窗口大小、MSS、窗口扩大因子、时间戳。
那么是怎么决定是否设置某个选项,怎样设置的呢?例如窗口扩大因子有关传输的性能,我可以怎么样改动这个值呢?
下面来看看内核是怎么做的?
设置SYN包的TCP选项的函数(tcp_output.c中):
/* Compute TCP options for SYN packets. This is not the final
 * network wire format yet.
 */
static unsigned int tcp_syn_options( struct sock *sk, struct sk_buff *skb,
                         struct tcp_out_options *opts,
                         struct tcp_md5sig_key **md5)
{
       struct tcp_sock *tp = tcp_sk(sk);
       //TCP选项的最大长度
       unsigned int remaining = MAX_TCP_OPTION_SPACE;
       struct tcp_fastopen_request *fastopen = tp->fastopen_req;

#ifdef CONFIG_TCP_MD5SIG
      *md5 = tp->af_specific->md5_lookup(sk, sk);
       if (*md5) {
            opts->options |= OPTION_MD5;
            remaining -= TCPOLEN_MD5SIG_ALIGNED;
      }
#else
      *md5 = NULL;
#endif

       /* We always get an MSS option.  The option bytes which will be seen in
       * normal data packets should timestamps be used, must be in the MSS
       * advertised.  But we subtract them from tp->mss_cache so that
       * calculations in tcp_sendmsg are simpler etc.  So account for this
       * fact here if necessary.  If we don't do this correctly, as a
       * receiver we won't recognize data packets as being full sized when we
       * should, and thus we won't abide by the delayed ACK rules correctly.
       * SACKs don't matter, we never delay an ACK when we have any of those
       * going out.  */
      opts->mss = tcp_advertise_mss(sk);
      remaining -= TCPOLEN_MSS_ALIGNED;

       if (likely(sysctl_tcp_timestamps && *md5 == NULL)) {
            opts->options |= OPTION_TS;
            opts->tsval = TCP_SKB_CB(skb)->when + tp->tsoffset;
            opts->tsecr = tp->rx_opt.ts_recent;
            remaining -= TCPOLEN_TSTAMP_ALIGNED;
      }
       if (likely(sysctl_tcp_window_scaling)) {
            opts->ws = tp->rx_opt.rcv_wscale;
            opts->options |= OPTION_WSCALE;
            remaining -= TCPOLEN_WSCALE_ALIGNED;
      }
       if (likely(sysctl_tcp_sack)) {
            opts->options |= OPTION_SACK_ADVERTISE;
             if (unlikely(!(OPTION_TS &
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用golang中的net库和raw socket来构造一个TCP SYN并添加TCP选项字段。以下是一个示例代码: ```go package main import ( "net" "syscall" ) func main() { // 构造TCP SYN srcIP := net.ParseIP("192.168.1.100") dstIP := net.ParseIP("192.168.1.1") srcPort := 12345 dstPort := 80 seqNum := uint32(123456789) tcpHeaderLen := 20 tcpFlags := syscall.TCP_SYN // 构造TCP选项字段 tcpOptions := []byte{0x02, 0x04, 0x05, 0xb4, 0x04, 0x02, 0x08, 0x0a, 0x00, 0x0f, 0x48, 0x61, 0x63, 0x6b, 0x65, 0x72, 0x20, 0x57, 0x65, 0x62, 0x21} // 构造TCP头部 tcpHeader := make([]byte, tcpHeaderLen) tcpHeader[0] = byte(srcPort >> 8) tcpHeader[1] = byte(srcPort) tcpHeader[2] = byte(dstPort >> 8) tcpHeader[3] = byte(dstPort) tcpHeader[4] = byte(seqNum >> 24) tcpHeader[5] = byte(seqNum >> 16) tcpHeader[6] = byte(seqNum >> 8) tcpHeader[7] = byte(seqNum) tcpHeader[8] = byte(0) tcpHeader[9] = byte(0) tcpHeader[10] = byte(tcpHeaderLen >> 8) tcpHeader[11] = byte(tcpHeaderLen) tcpHeader[13] = byte(tcpFlags) tcpHeader[14] = byte(0x10) tcpHeader[15] = byte(0xff) // 添加TCP选项字段 copy(tcpHeader[tcpHeaderLen:], tcpOptions) // 构造IP头部 ipHeaderLen := 20 ipVersion := 4 ipHeader := make([]byte, ipHeaderLen) ipHeader[0] = byte(ipVersion<<4 | ipHeaderLen>>2) ipHeader[1] = byte(0) ipHeader[2] = byte(0) ipHeader[3] = byte(0) ipHeader[4] = byte(0) ipHeader[5] = byte(0) ipHeader[6] = byte(0) ipHeader[7] = byte(0) ipHeader[8] = byte(0) ipHeader[9] = byte(0) ipHeader[10] = byte(0xff) ipHeader[11] = byte(0xff) copy(ipHeader[12:16], srcIP.To4()) copy(ipHeader[16:20], dstIP.To4()) // 计算IP头部校验和 checksum := checksum(ipHeader) // 添加IP头部校验和 ipHeader[10] = byte(checksum >> 8) ipHeader[11] = byte(checksum) // 合并IP和TCP头部 packet := make([]byte, len(ipHeader)+len(tcpHeader)) copy(packet, ipHeader) copy(packet[len(ipHeader):], tcpHeader) // 发送TCP SYN conn, err := net.Dial("ip4:tcp", dstIP.String()) if err != nil { panic(err) } defer conn.Close() _, err = conn.Write(packet) if err != nil { panic(err) } } // 计算校验和 func checksum(data []byte) uint16 { var sum uint32 for i := 0; i < len(data)-1; i += 2 { sum += uint32(data[i])<<8 | uint32(data[i+1]) } if len(data)%2 != 0 { sum += uint32(data[len(data)-1]) << 8 } for (sum >> 16) > 0 { sum = (sum & 0xffff) + (sum >> 16) } return ^uint16(sum) } ``` 这段代码构造了一个源IP为192.168.1.100,目标IP为192.168.1.1,源端口为12345,目标端口为80的TCP SYN,并添加了TCP选项字段。在发送之前,需要使用`net.Dial("ip4:tcp", dstIP.String())`连接到目标IP地址,然后将构造好的TCP SYN写入连接中即可。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值