0226-UDP 请求报文

环境

  • Time 2022-11-20
  • 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 792

目标

了解 UDP 协议的的字段。
从这里开始,将进入第四层,传输层协议。UDP 协议基于 IP 协议。

配置 TUN

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

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

main.rs

use pnet::packet::{ip::IpNextHeaderProtocols, ipv4::Ipv4Packet};
use pnet::packet::{udp::UdpPacket, Packet};
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::Udp {
            println!("not udp packet, continue");
            continue;
        }

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

        // 源端口
        println!("source {:?}", packet.get_source());
        // 目的端口
        println!("get_destination {:?}", packet.get_destination());
        // 长度,包含 UDP 头和数据
        println!("length {:?}", packet.get_length());
        // 校验和
        println!("checksum {:?}", packet.get_checksum());
        // 数据
        let payload = String::from_utf8_lossy(packet.payload());
        print!("udp say: {}", payload);

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

发送 UDP 请求

root@jiangbo12490:~# nc 192.168.144.2 4444 -u
jiangbo

程序输出

source 33092
get_destination 4444
length 16
checksum 10644
udp say: jiangbo
length: 36, [69, 0, 0, 36, 164, 101, 64, 0, 64, 17, 245, 14, 192, 168, 144, 1, 192, 168, 144, 2, 129, 68, 17, 92, 0, 16, 41, 148, 106, 105, 97, 110, 103, 98, 111, 10]

源端口是 33092,目的端口 4444,长度 8 字节的 UDP 头加上 8 字节的数据(含换行),共 16 个字节。

查看源端口

root@jiangbo12490:~# ss -un
Recv-Q    Send-Q    Local Address:Port    Peer Address:Port     Process
0         0         192.168.144.1:33092   192.168.144.2:4444

tcpdump 抓包

root@jiangbo12490:~# tcpdump -An -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

23:42:22.881236 IP 192.168.144.1.33092 > 192.168.144.2.4444: UDP, length 8
E..$.f@.@............D.\..).jiangbo

Wireshark

UDP协议

总结

了解了 UDP 协议的字段,该协议基于 IP 协议,是一个比较简单的协议。

附录

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