0227-TCP 请求报文

环境

  • Time 2022-11-24
  • WSL-Ubuntu 22.04
  • Rust 1.65.0
  • pnet 0.31.0
  • tun-tap 0.1.3

前言

说明

参考:https://docs.rs/pnet/latest/pnet/index.html
RFC 793

目标

了解 TCP 协议头中的字段,其也是基于 IP 协议的。

配置 TUN

IP 地址不要和主机的网卡地址在一个段,以便选择这个网卡进行路由。

root@jiangbo12490:~# ip tuntap add tun0 mode tun
root@jiangbo12490:~# ip addr add 192.168.44.144/24 dev tun0
root@jiangbo12490:~# ip link set up dev tun0
root@jiangbo12490:~# ip add show dev tun0
7: tun0: <NO-CARRIER,POINTOPOINT,MULTICAST,NOARP,UP> mtu 1500 qdisc fq_codel state DOWN group default qlen 500
    link/none
    inet 192.168.44.144/24 scope global tun0
       valid_lft forever preferred_lft forever

main.rs

use pnet::packet::ip::IpNextHeaderProtocols;
use pnet::packet::{ipv4::Ipv4Packet, tcp::TcpPacket};
use tun_tap::{Iface, Mode};

fn main() -> std::io::Result<()> {
    let iface = Iface::without_packet_info("tun0", Mode::Tun)?;

    let mut buffer = vec![0; 1500];

    loop {
        let size = iface.recv(&mut buffer)?;
        let packet = Ipv4Packet::new(&buffer).unwrap();

        if packet.get_version() == 6 {
            println!("IPv6 packet, continue");
            continue;
        }

        if packet.get_next_level_protocol() != IpNextHeaderProtocols::Tcp {
            println!("not tcp packet, continue");
            continue;
        }

        // 因为头部长度的单位是 4 字节
        let length = packet.get_header_length() as usize * 4;
        let packet = TcpPacket::new(&buffer[length..]).unwrap();

        // 2 字节的源端口
        println!("source {}", packet.get_source());
        // 2 字节的目的端口
        println!("destination {}", packet.get_destination());
        // 4 字节的序列号号
        println!("sequence {}", packet.get_sequence());
        // 4 字节的确认号
        println!("acknowledgement {}", packet.get_acknowledgement());
        // 4 位 TCP 首部长度,单位是 4 字节,最长 60 字节
        println!("data_offset {}", packet.get_data_offset());
        // 3 位的保留位
        println!("reserved {}", packet.get_reserved());
        // 9 位的控制位,标志位
        println!("flags {}", packet.get_flags());
        // 2 字节的窗口大小
        println!("window {}", packet.get_window());
        // 2 字节的校验和
        println!("checksum {}", packet.get_checksum());
        // 2 字节的紧急指针
        println!("urgent_ptr {}", packet.get_urgent_ptr());
        // TCP 20 字节的首部,可以加上最长 40 个字节的选项
        println!("options {:?}", packet.get_options());

        println!("length: {}, {:?}", size, &buffer[..size]);
    }
}

发送 TCP 请求

当想建立连接时,会发起握手请求,发送第一个 TCP 数据包。

root@jiangbo12490:~# nc 192.168.44.244 4444

程序输出

source 35788
destination 4444
sequence 3640119208
acknowledgement 0
data_offset 10
reserved 0
flags 2
window 64240
checksum 41834
urgent_ptr 0
options [TcpOption { number: TcpOptionNumber(2), length: [4], data: [5, 180] }, TcpOption { number: TcpOptionNumber(4), length: [2], data: [] }, TcpOption { number: TcpOptionNumber(8), length: [10], data: [188, 204, 204, 53, 0, 0, 0, 0] }, TcpOption { number: TcpOptionNumber(1), length: [], data: [] }, TcpOption { number: TcpOptionNumber(3), length: [3], data: [7] }]
length: 60, [69, 0, 0, 60, 99, 220, 64, 0, 64, 6, 252, 10, 192, 168, 44, 144, 192, 168, 44, 244, 139, 208, 17, 92, 216, 247, 207, 168, 0, 0, 0, 0, 160, 2, 250, 240, 163, 106, 0, 0, 2, 4, 5, 180, 4, 2, 8, 10, 188, 204, 204, 53, 0, 0, 0, 0, 1, 3, 3, 7]

tcpdump 抓包

root@jiangbo12490:~# tcpdump -A -n -i tun0
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on tun0, link-type RAW (Raw IP), snapshot length 262144 bytes

20:22:54.371126 IP 192.168.44.144.35788 > 192.168.44.244.4444: Flags [S], seq 3383309069, win 64240, options [mss 1460,sackOK,TS val 3167330987 ecr 0,nop,wscale 7], length 0
E..<q.@.@..B..,...,....\..3.........x..........
............

其中的 flags 和 options 字段,之后再看。

Wireshark

TCP协议

总结

了解了 TCP 协议的字段,该协议基于 IP 协议。

附录

posted @   jiangbo4444  阅读(12)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
历史上的今天:
2020-08-14 【JavaScript】Object 实例方法
点击右上角即可分享
微信分享提示