неверный порядковый номер при использовании интерфейса tun/tap

Я пытаюсь прочитать TCP-пакеты в структуру с помощью tun/tap, поэтому установлен флаг IFF_TUN для использования tun-устройства (без заголовков Ethernet).

У меня есть такие структуры (меня не волнуют проблемы с порядком байтов):

TCP-заголовок:

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:

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));

и читать пакеты следующим образом:

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;

и пока так хорошо. но когда я пытаюсь прочитать номер последовательности 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 показывает 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

но мой вывод кода 7be53b39


person AMIR    schedule 08.04.2020    source источник


Ответы (1)


После некоторого поиска я нашел решение.

обратитесь к вики Wireshark:

По умолчанию Wireshark и TShark будут отслеживать все сеансы TCP и преобразовывать все порядковые номера (номера SEQ) и номера подтверждений (номера ACK) в относительные числа. Это означает, что вместо отображения реальных/абсолютных номеров SEQ и ACK на дисплее Wireshark будет отображать номер SEQ и ACK относительно первого увиденного сегмента для этого диалога.

все порядковые номера всегда начинаются с 0 для первого пакета, увиденного в каждом разговоре, поэтому мой вывод не был неправильным :)

person AMIR    schedule 08.04.2020