0220-发送 ARP 回应

环境

  • 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 操作系统不再自动回应,编写一个自己的回应消息。
发送 ARP 请求还是使用之前编写好的,同时 TAP 也是使用之前建好的。

判断 ARP 协议

use pnet_packet::arp::{ArpHardwareTypes, ArpOperations};
use pnet_packet::arp::{ArpPacket, MutableArpPacket};
use pnet_packet::ethernet::MutableEthernetPacket;
use pnet_packet::ethernet::{EtherTypes, EthernetPacket};
use pnet_packet::MutablePacket;
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)?;

        let ethernet = EthernetPacket::new(&buffer).unwrap();
        if EtherTypes::Arp == ethernet.get_ethertype() {
            println!("{:?}", &buffer[..size]);
        }
    }
}

构造以太网协议

let packet = ArpPacket::new(&buffer[EthernetPacket::minimum_packet_size()..]).unwrap();

let mut content = [0; 42];
let mut eth = MutableEthernetPacket::new(&mut content).unwrap();

eth.set_destination(ethernet.get_source());
eth.set_source("44:44:44:44:44:44".parse().unwrap());
eth.set_ethertype(EtherTypes::Arp);

地址解析协议还是使用之前的一篇的 ARP 请求。

构造 ARP 回应

let mut buf = [0; 28];
let mut arp = MutableArpPacket::new(&mut buf).unwrap();

arp.set_hardware_type(ArpHardwareTypes::Ethernet);
arp.set_protocol_type(EtherTypes::Ipv4);
arp.set_hw_addr_len(6);
arp.set_proto_addr_len(4);
arp.set_operation(ArpOperations::Reply);
arp.set_sender_hw_addr("44:44:44:44:44:44".parse().unwrap());
arp.set_sender_proto_addr(packet.get_target_proto_addr());
arp.set_target_hw_addr(packet.get_sender_hw_addr());
arp.set_target_proto_addr(packet.get_sender_proto_addr());

eth.set_payload(arp.packet_mut());

发送回应

iface.send(eth.packet_mut()).unwrap();

抓包结果

20:20:05.230635 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
        0x0000:  0001 0800 0604 0001 eaf3 f524 7add ac18  ...........$z...
        0x0010:  33f4 0000 0000 0000 ac18 33f4            3.........3.
20:20:05.230718 44:44:44:44:44:44 > ea:f3:f5:24:7a:dd, ethertype ARP (0x0806), length 42: Reply 172.24.51.244 is-at 44:44:44:44:44:44, length 28
        0x0000:  0001 0800 0604 0002 4444 4444 4444 ac18  ........DDDDDD..
        0x0010:  33f4 eaf3 f524 7add ac18 33f4            3....$z...3.

程序输出

Sent ARP request
Received reply: 44:44:44:44:44:44

总结

使用 TAP 设备,模拟了 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"

main.rs

use pnet_packet::arp::{ArpHardwareTypes, ArpOperations};
use pnet_packet::arp::{ArpPacket, MutableArpPacket};
use pnet_packet::ethernet::MutableEthernetPacket;
use pnet_packet::ethernet::{EtherTypes, EthernetPacket};
use pnet_packet::MutablePacket;
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)?;

        let ethernet = EthernetPacket::new(&buffer).unwrap();
        if EtherTypes::Arp == ethernet.get_ethertype() {
            println!("{:?}", &buffer[..size]);

            let packet = ArpPacket::new(&buffer[EthernetPacket::minimum_packet_size()..]).unwrap();

            let mut content = [0; 42];
            let mut eth = MutableEthernetPacket::new(&mut content).unwrap();

            eth.set_destination(ethernet.get_source());
            eth.set_source("44:44:44:44:44:44".parse().unwrap());
            eth.set_ethertype(EtherTypes::Arp);

            let mut buf = [0; 28];
            let mut arp = MutableArpPacket::new(&mut buf).unwrap();

            arp.set_hardware_type(ArpHardwareTypes::Ethernet);
            arp.set_protocol_type(EtherTypes::Ipv4);
            arp.set_hw_addr_len(6);
            arp.set_proto_addr_len(4);
            arp.set_operation(ArpOperations::Reply);
            arp.set_sender_hw_addr("44:44:44:44:44:44".parse().unwrap());
            arp.set_sender_proto_addr(packet.get_target_proto_addr());
            arp.set_target_hw_addr(packet.get_sender_hw_addr());
            arp.set_target_proto_addr(packet.get_sender_proto_addr());

            eth.set_payload(arp.packet_mut());

            println!("s: {:?}", eth.packet_mut());
            iface.send(eth.packet_mut()).unwrap();
        }
    }
}

sender.rs

use std::net::IpAddr;

use pnet_datalink::{channel, Channel, MacAddr};
use pnet_packet::arp::{ArpHardwareTypes, ArpOperations, ArpPacket, MutableArpPacket};
use pnet_packet::ethernet::EtherTypes;
use pnet_packet::{ethernet::MutableEthernetPacket, 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 buffer = [0; 42];
    let mut ethernet = MutableEthernetPacket::new(&mut buffer).unwrap();

    ethernet.set_destination(MacAddr::broadcast());
    ethernet.set_source(interface.mac.unwrap());
    ethernet.set_ethertype(EtherTypes::Arp);

    let mut buffer = [0; 28];
    let mut arp = MutableArpPacket::new(&mut buffer).unwrap();

    let ip = interface.ips.get(0).unwrap();

    let source_ip = match ip.ip() {
        IpAddr::V4(ip) => ip,
        _ => unreachable!(),
    };

    arp.set_hardware_type(ArpHardwareTypes::Ethernet);
    arp.set_protocol_type(EtherTypes::Ipv4);
    arp.set_hw_addr_len(6);
    arp.set_proto_addr_len(4);
    arp.set_operation(ArpOperations::Request);
    arp.set_sender_hw_addr(interface.mac.unwrap());
    arp.set_sender_proto_addr(source_ip);
    arp.set_target_hw_addr(MacAddr::zero());
    arp.set_target_proto_addr("172.24.51.244".parse().unwrap());

    ethernet.set_payload(arp.packet_mut());

    sender.send_to(ethernet.packet(), None).unwrap().unwrap();

    println!("Sent ARP request");

    loop {
        let buf = reader.next().unwrap();
        let arp = ArpPacket::new(&buf[MutableEthernetPacket::minimum_packet_size()..]).unwrap();
        println!("Received reply: {:?}", arp.get_sender_hw_addr());
    }
}
posted @   jiangbo4444  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
历史上的今天:
2020-08-12 【JavaScript】Object 构造函数和属性
点击右上角即可分享
微信分享提示