环境
- Time 2022-11-20
- VirtualBox 7.0.2
- Rust 1.65.0
- pnet 0.31.0
- CentOS 7
前言
说明
参考:https://docs.rs/pnet_packet/latest/pnet_packet/index.html
目标
使用两台虚拟机,启动 CentOS 系统,然后进行跨主机的通信。
主机1网卡
[root@centos7 ~]# hostname
centos7
[root@centos7 ~]# ip link list
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
link/ether 08:00:27:93:92:f2 brd ff:ff:ff:ff:ff:ff
3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
link/ether 08:00:27:16:d2:3f brd ff:ff:ff:ff:ff:ff
4: enp0s9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
link/ether 08:00:27:de:8a:c8 brd ff:ff:ff:ff:ff:ff
主机2网卡
[root@centos7-1 ~]# ip link list
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
link/ether 08:00:27:68:ff:42 brd ff:ff:ff:ff:ff:ff
3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
link/ether 08:00:27:36:b1:35 brd ff:ff:ff:ff:ff:ff
4: enp0s9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
link/ether 08:00:27:92:6f:8a brd ff:ff:ff:ff:ff:ff
[root@centos7-1 ~]# hostname
centos7-1
后面将从主机1的 enp0s8 发送到主机2的 enp0s9 网卡。
reader.rs
use pnet_datalink::{channel, Channel};
fn main() {
let interface = pnet_datalink::interfaces()
.into_iter()
.find(|iface| iface.name == "enp0s9")
.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"),
};
loop {
let buf = reader.next().unwrap();
println!("{:?}", buf);
}
}
sender.rs
use pnet_datalink::{channel, Channel};
use pnet_packet::ethernet::{EtherTypes, MutableEthernetPacket};
fn main() {
let interface = pnet_datalink::interfaces()
.into_iter()
.find(|iface| iface.name == "enp0s8")
.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 buffer = [0; 14];
let mut packet = MutableEthernetPacket::new(&mut buffer).unwrap();
// 这个是 enp0s9 的 MAC 地址
let dest = "08:00:27:de:8a:c8".parse().unwrap();
packet.set_destination(dest);
packet.set_source(interface.mac.unwrap());
packet.set_ethertype(EtherTypes::Ipv4);
sender.send_to(&buffer, None).unwrap().unwrap();
}
enp0s8 的抓包
20:02:53.244715 08:00:27:16:d2:3f > 08:00:27:92:6f:8a, ethertype IPv4 (0x0800), length 14: [|ip]
enp0s9 的抓包
20:02:52.545920 08:00:27:16:d2:3f > 08:00:27:92:6f:8a, ethertype IPv4 (0x0800), length 60: IP0
总结
在数据链路层上,通过 MAC 地址,实现了两台主机之间的通信。