简体   繁体   English

使用 tun/tap 接口的错误序列号

[英]wrong sequence number using tun/tap interface

I'm trying to read TCP packets into a struct using tun/tap, So IFF_TUN flag is set to use tun device (no ethernet headers).我正在尝试使用 tun/tap 将 TCP 数据包读取到结构中,因此将 IFF_TUN 标志设置为使用 tun 设备(无以太网标头)。

I have structs like these (I don't care about endian issues):我有这样的结构(我不关心字节序问题):

Tcp Header: Tcp Header:

struct tcphdr {
  uint16_t sport;
  uint16_t dport;
  uint32_t seq;
  uint32_t ack_seq;
  uint8_t rsvd : 4;
  uint8_t dataoff : 4;
  uint8_t fin : 1,
          syn : 1,
          rst : 1,
          psh : 1,
          ack : 1,
          urg : 1,
          ece : 1,
          cwr : 1;
  uint16_t win;
  uint16_t csum;
  uint16_t urp;
} __attribute__((packed));

Ipv4 Header: ipv4 Header:

struct ipv4hdr {
  uint8_t ihl : 4;
  uint8_t version : 4;
  uint8_t tos;
  uint16_t len;
  uint16_t id;
  uint16_t frag_offset;
  uint8_t ttl;
  uint8_t proto;
  uint16_t csum;
  uint32_t saddr;
  uint32_t daddr;
} __attribute__((packed));

and read packets like this:并像这样读取数据包:

size_t nbytes = read(fd, bytes, 1504); // fd is eg. fd = open("/dev/net/tun", O_RDWR)

uint16_t eth_flags = bytes[0] << 8 | bytes[1]; // big-endian
uint16_t eth_proto = bytes[2] << 8 | bytes[3]; // big-endian

if (eth_proto != 0x800)
  // ignore no ipv4 packets
  // https://en.wikipedia.org/wiki/EtherType
  continue;

if (ip_hdr->proto != 0x06)
  // ignore non-TCP packets
  // https://en.wikipedia.org/wiki/List_of_IP_protocol_numbers
  continue;

and so far, so good.到目前为止,一切都很好。 but when i try to read the TCP sequece number i get wrong number:但是当我尝试读取 TCP 序列号时,我得到了错误的数字:

ipv4hdr *ip_hdr = (ipv4hdr *)(bytes + 4); // 4 first bytes are packet information provided by kernel
tcphdr *tcp_hdr = (tcphdr *)(bytes + 4 + ip_hdr->ihl * 4); // reading TCP at the end of the IP header
std::cout << std::hex << ntohl(tcp_hdr->seq) << std::endl; // the output number is wrong!

tshark output shows seq=0 (like below): tshark output 显示 seq=0 (如下所示):

Capturing on 'tun0'
    1 0.000000000  192.168.0.1 → 192.168.0.2  TCP 60 44248 → 8000 [SYN] Seq=0 Win=29200 Len=0 MSS=1460 SACK_PERM=1 TSval=1233752815 TSecr=0 WS=128

but my code output is 7be53b39但我的代码 output 是7be53b39

After some search i found the solution.经过一番搜索,我找到了解决方案。

refer to wireshark wiki :参考wireshark wiki

By default Wireshark and TShark will keep track of all TCP sessions and convert all Sequence Numbers (SEQ numbers) and Acknowledge Numbers (ACK Numbers) into relative numbers.默认情况下,Wireshark 和 TShark 将跟踪所有 TCP 会话并将所有序列号(SEQ 编号)和确认编号(ACK 编号)转换为相对编号。 This means that instead of displaying the real/absolute SEQ and ACK numbers in the display, Wireshark will display a SEQ and ACK number relative to the first seen segment for that conversation.这意味着,Wireshark 不会在显示中显示真实/绝对的 SEQ 和 ACK 编号,而是显示与该对话的第一个看到的片段相关的 SEQ 和 ACK 编号。

all sequence numbers always start at 0 for the first packet seen in each conversation, so my output wasn't wrong:)对于每个对话中看到的第一个数据包,所有序列号始终从 0 开始,所以我的 output 没有错:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM