0219-使用 TAP 来进行通信
环境
- 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_packet/latest/pnet_packet/index.html
参考:https://www.kernel.org/doc/html/latest/networking/tuntap.html
目标
通过 TAP 来模拟二层设备,接收之前发送的 ARP 请求。
新增设备
root@jiangbo12490:~# ip tuntap add tap0 mode tap
root@jiangbo12490:~# ip addr add 172.24.51.244/24 dev tap0
root@jiangbo12490:~# ip link set up dev tap0
root@jiangbo12490:~# ip addr show tap0
20: tap0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc fq_codel state DOWN group default qlen 1000
link/ether ea:f3:f5:24:7a:dd brd ff:ff:ff:ff:ff:ff
inet 172.24.51.244/24 scope global tap0
valid_lft forever preferred_lft forever
inet6 fe80::e8f3:f5ff:fe24:7add/64 scope link
valid_lft forever preferred_lft forever
可以通过 ip tuntap add
命令新增 TUN/TAP 设备。
main
use std::net::IpAddr;
use pnet_datalink::{channel, Channel, MacAddr, NetworkInterface};
use pnet_packet::arp::{ArpHardwareTypes, ArpOperations, ArpPacket, MutableArpPacket};
use pnet_packet::ethernet::{EtherTypes, MutableEthernetPacket};
use pnet_packet::{MutablePacket, Packet};
fn main() {
let interface = pnet_datalink::interfaces()
.into_iter()
.find(|iface| iface.name == "tap0")
.unwrap();
let channel = channel(&interface, Default::default());
let (mut sender, mut reader) = match channel {
Ok(Channel::Ethernet(tx, rx)) => (tx, rx),
_ => panic!("Not a valid channel returned"),
};
let mut ethernet = init_ethernet(&interface);
let mut arp = init_arp(interface);
let mut ethernet = MutableEthernetPacket::new(&mut ethernet).unwrap();
let mut arp = MutableArpPacket::new(&mut arp).unwrap();
ethernet.set_payload(arp.packet_mut());
sender.send_to(ethernet.packet(), None).unwrap().unwrap();
println!("Sent ARP request");
let buf = reader.next().unwrap();
let arp = ArpPacket::new(&buf[MutableEthernetPacket::minimum_packet_size()..]).unwrap();
println!("Target MAC address: {}", arp.get_sender_hw_addr());
}
地址解析协议还是使用之前的一篇的 ARP 请求。
Cargo.toml
[package]
edition = "2021"
name = "network"
version = "1.0.0"
[dependencies]
pnet_datalink = "0.31.0"
pnet_packet = "0.31.0"
tun-tap = "0.1.3"
控制 TAP
use tun_tap::{Iface, Mode};
fn main() -> std::io::Result<()> {
let iface = Iface::without_packet_info("tap0", Mode::Tap)?;
let mut buffer = vec![0; 1500];
loop {
let size = iface.recv(&mut buffer)?;
println!("{:?}", &buffer[..size]);
}
}
抓包结果
19:38:40.700686 ea:f3:f5:24:7a:dd > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 42: Request who-has 172.24.51.244 tell 172.24.51.244, length 28
程序输出
[255, 255, 255, 255, 255, 255, 234, 243, 245, 36, 122, 221, 8, 6, 0, 1, 8, 0, 6, 4, 0, 1, 234, 243, 245, 36, 122, 221, 172, 24, 51, 244, 0, 0, 0, 0, 0, 0, 172, 24, 51, 244]
程序收到发来的 ARP 请求,并且发送端阻塞了,因为并没有回消息。
总结
新增了 TAP 设备,可以接收链路层的网络包,并且接收到了发送的 ARP 请求。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
2020-08-12 【JavaScript】Object 构造函数和属性