【问题标题】:setting the maximum segment size in the tcp header在 tcp 标头中设置最大段大小
【发布时间】:2009-08-18 19:20:38
【问题描述】:

我正在组装一个端口扫描仪作为学习练习。我的问题是我试图在 TCP 标头中设置最大段大小选项(MSS)。我查看了 tcp.h,但我无法弄清楚如何设置它。我希望会有这样的选择:

tcp_header->mss(32000);

与上面类似的东西在 tcp.h 中,但不在正确的结构中。诚然,我对阅读结构定义还很陌生,而且我对 tcp.h 没有太多意义,所以最后我尝试将必要的字节添加到 TCP 标头的末尾:

struct tcphdr *CreateTcpHeader()
{
    struct tcphdr *tcp_header;

    tcp_header = (struct tcphdr *)malloc(sizeof(struct tcphdr)+4*sizeof(int));


    tcp_header->source = htons(SRC_PORT);
    tcp_header->dest = htons(DST_PORT);
    tcp_header->seq = htonl(0);             
    tcp_header->ack_seq = htonl(0);         
    tcp_header->res1 = 0;
    tcp_header->doff = (sizeof(struct tcphdr))/4;
    tcp_header->syn = 1;
    tcp_header->window = htons(4096);
    tcp_header->check = 0; /* Will calculate the checksum with pseudo-header later */
    tcp_header->urg_ptr = 0;


    /*memcpy the mss data onto the end of the tcp header. */
    int mssCode = 2;
    int mssLength = 4;
    uint16_t mss = htonl(32000);
    int offset = sizeof(struct tcphdr);
    memcpy( (tcp_header+offset), &mssCode, 1 );
    memcpy( (tcp_header+offset+1), &mssLength, 1 );
    memcpy( (tcp_header+offset+2), &mss, 2);

    return (tcp_header);
}

但是在我写完之后很明显这不是一个真正的解决方案,而且它仍然不起作用:P 那么有没有更好的方法?

【问题讨论】:

  • 你是如何使用这个标题的?你是用 libnet 发送的吗?
  • 我只是在使用原始套接字。尽管即使使用了新的 mss 选项,我的数据包仍然被忽略,尽管它实际上与 nmap 相同。有什么想法吗?
  • 根据您正在学习的内容 - C 或网络,您可能需要查看 secdev.org/projects/scapy
  • 哇,谢谢,我去看看它看起来棒极了。此外,我的数据包仅在环回适配器上被忽略,我猜一定是内核。
  • 在 C 中,将值添加到指针实际上会进一步提供指向 n 个元素的指针,而不是进一步的 n 个字节。所以你的 memcpy 将数据复制到地址 tcp_header + (offset * sizeof(*tcp_header)),可能会在其他地方造成损坏。

标签: c linux sockets tcp struct


【解决方案1】:

tcp.h 中的struct tcphdr 定义了 TCP 标头的强制部分。 (查看TCP header,您可以将struct tcphdr 中的定义与标题中出现的实际位相匹配。)C 中的结构具有恒定大小,但TCP 允许可选数据。标头长度字段(结构中的doff)是标头的总长度,包括选项,因此您需要添加一个单词来说明 MSS 选项:

tcp_header->doff = (sizeof(struct tcphdr))/4 + 1;

让我们为 MSS 选项定义一个结构:

struct tcp_option_mss {
    uint8_t kind; /* 2 */
    uint8_t len; /* 4 */
    uint16_t mss;
} __attribute__((packed));

现在您可以按正确的顺序填充结构:

/*memcpy the mss data onto the end of the tcp header. */
struct tcp_option_mss mss;
mss.kind = 2;
mss.len = 4;
mss.mss = htons(32000);

让我们更进一步,为你的数据包定义一个单一的结构,让编译器 帮助我们:

struct tcphdr_mss {
    struct tcphdr tcp_header;
    struct tcp_option_mss mss;
};

(您可能需要在末尾添加一个 end-of-option-list 选项,并使用 nop 选项将选项列表填充到 8 个字节。)

现在我们可以将所有部分放在一起:

struct tcphdr *CreateTcpHeader()
{
    struct tcphdr_mss *tcp_header;

    tcp_header = malloc(sizeof(struct tcphdr_mss));

    tcp_header->tcp_header.source = htons(SRC_PORT);
    tcp_header->tcp_header.dest = htons(DST_PORT);
    tcp_header->tcp_header.seq = htonl(0);             
    tcp_header->tcp_header.ack_seq = htonl(0);         
    tcp_header->tcp_header.res1 = 0;
    tcp_header->tcp_header.doff = (sizeof(struct tcphdr_mss))/4;
    tcp_header->tcp_header.syn = 1;
    tcp_header->tcp_header.window = htons(4096);
    tcp_header->tcp_header.check = 0; /* Will calculate the checksum with pseudo-header later */
    tcp_header->tcp_header.urg_ptr = 0;

    tcp_header->mss.kind = 2;
    tcp_header->mss.len = 2;
    tcp_header->mss.mss = htons(32000);

    return (tcp_header);
}

【讨论】:

  • 啊,现在一切都说得通了。非常感谢。
猜你喜欢
  • 2011-04-20
  • 1970-01-01
  • 2011-10-13
  • 1970-01-01
  • 1970-01-01
  • 2016-09-05
  • 2021-01-13
  • 1970-01-01
  • 2023-04-03
相关资源
最近更新 更多