c++ - 使用 tun/tap 接口的错误序列号
问题描述
我正在尝试使用 tun/tap 将 TCP 数据包读入结构,因此将 IFF_TUN 标志设置为使用 tun 设备(无以太网标头)。
我有这样的结构(我不关心字节序问题):
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
解决方案
经过一番搜索,我找到了解决方案。
默认情况下,Wireshark 和 TShark 将跟踪所有 TCP 会话并将所有序列号(SEQ 编号)和确认编号(ACK 编号)转换为相对编号。这意味着,Wireshark 不会在显示屏中显示真实/绝对的 SEQ 和 ACK 编号,而是显示相对于该对话的第一个看到的片段的 SEQ 和 ACK 编号。
对于每个对话中看到的第一个数据包,所有序列号始终从 0 开始,所以我的输出没有错 :)
推荐阅读
- elasticsearch - 如何允许在 Kibana 内/从 Kibana 进行编辑
- docker - 为什么有些 docker 文件是复制文件而不是作为卷挂载
- sql - 跟随开始和结束日期列
- python - 如何使用带有省略号的下一个按钮使用 Scrapy 抓取数据
- vue.js - 如何在 Vuetify 中将 v-flex 元素彼此移开?
- ios - 通知画外音用户他们已突出显示容器中的元素
- python-3.x - 想要获取列表中目录中的子目录
- python - 比较两个无序列表中单个元素的差异
- cakephp - 如何在 CakePHP 3.x 中基于单个值查询 HasMany 关联
- deep-learning - 在 pytorch 的 GPU 上计算损失需要很长时间