feat: added the ability to respond to ARP requests
This commit is contained in:
@@ -10,8 +10,8 @@ use log::{debug, error, info, trace};
|
||||
use nl_sys::{netlink, route};
|
||||
|
||||
use packets::{
|
||||
self, EthernetPacket, IPv4Packet, IPv4Pkt, Layer3Packet, Layer3Pkt, Layer4Packet, Layer4Pkt,
|
||||
TCPPacket, TCPPacketBuilder, TCPPkt,
|
||||
self, ARPMode, ARPPacket, ARPProto, EthernetPacket, IPv4Packet, IPv4Pkt, Layer3Packet,
|
||||
Layer3Pkt, Layer4Packet, Layer4Pkt, TCPPacket, TCPPacketBuilder, TCPPkt,
|
||||
};
|
||||
use pcap_sys;
|
||||
use tokio::{sync::mpsc, task};
|
||||
@@ -71,7 +71,7 @@ impl TcpOptions {
|
||||
}
|
||||
}
|
||||
|
||||
fn socket_accepts_packet(socket: &TcpSocket, ip: IPv4Pkt<'_>, tcp: TCPPkt<'_>) -> bool {
|
||||
fn socket_accepts_packet(socket: &TcpSocket, ip: &IPv4Pkt<'_>, tcp: &TCPPkt<'_>) -> bool {
|
||||
if let Some(peer) = &socket.peer_info {
|
||||
peer.local_addr == ip.dest_ip()
|
||||
&& peer.remote_addr == ip.source_ip()
|
||||
@@ -110,7 +110,7 @@ fn connect(
|
||||
.syn(true)
|
||||
.window(64240)
|
||||
.seqnumber(socket.local_seq_no)
|
||||
.options([TcpOptions::MaxSegmentSize(64240).get_bytes()].concat())
|
||||
//.options([TcpOptions::MaxSegmentSize(64240).get_bytes()].concat())
|
||||
.build(local_addr, remote_addr, vec![], None);
|
||||
|
||||
(local_port, packet)
|
||||
@@ -127,8 +127,11 @@ fn process_packet(
|
||||
Ok((None, None))
|
||||
}
|
||||
|
||||
fn send_data(socket: &mut TcpSocket, data: Vec<u8>) -> anyhow::Result<(TCPPacketBuilder, Vec<u8>)> {
|
||||
Ok(todo!())
|
||||
fn send_data(
|
||||
socket: &mut TcpSocket,
|
||||
data: Vec<u8>,
|
||||
) -> anyhow::Result<Option<(TCPPacketBuilder, Vec<u8>)>> {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
struct TcpSocketHandle {
|
||||
@@ -167,7 +170,7 @@ async fn main() -> anyhow::Result<()> {
|
||||
.ok_or(anyhow!("could not get target IP"))?
|
||||
.parse::<Ipv4Addr>()?;
|
||||
|
||||
let (routes, (ifname, ifindex, srcip, src_mac, dst_mac, src_snmask)) = {
|
||||
let (ifname, _, srcip, src_mac, dst_mac, _) = {
|
||||
let socket = netlink::Socket::new()?;
|
||||
|
||||
let routes = socket.get_routes()?;
|
||||
@@ -175,16 +178,21 @@ async fn main() -> anyhow::Result<()> {
|
||||
let links = socket.get_links()?;
|
||||
let addrs = socket.get_addrs()?;
|
||||
|
||||
let res = route::get_macs_and_src_for_ip(&addrs, &routes, &neighs, &links, ip)
|
||||
.ok_or(anyhow!("unable to find a route to the IP"))?;
|
||||
|
||||
(routes, res)
|
||||
route::get_macs_and_src_for_ip(&addrs, &routes, &neighs, &links, ip)
|
||||
.ok_or(anyhow!("unable to find a route to the IP"))?
|
||||
};
|
||||
|
||||
let mut socket = TcpSocket::default();
|
||||
|
||||
let mut interface = pcap_sys::Interface::<pcap_sys::DevDisabled>::new(&ifname)?;
|
||||
|
||||
let srcip: u32 = srcip.into();
|
||||
let srcip = srcip + 10;
|
||||
let srcip: Ipv4Addr = srcip.into();
|
||||
dbg!(srcip, src_mac, dst_mac);
|
||||
|
||||
let dst_mac = [0x00, 0x16, 0x3e, 0xde, 0xa9, 0x93];
|
||||
|
||||
interface.set_buffer_size(8192)?;
|
||||
interface.set_non_blocking(true)?;
|
||||
interface.set_promisc(false)?;
|
||||
@@ -194,18 +202,14 @@ async fn main() -> anyhow::Result<()> {
|
||||
|
||||
macro_rules! format_packet {
|
||||
($tcp_packet:expr) => {{
|
||||
let layer3pkt = Layer3Packet::IPv4(IPv4Packet::construct(
|
||||
srcip,
|
||||
ip,
|
||||
&Layer4Packet::TCP($tcp_packet),
|
||||
));
|
||||
EthernetPacket::construct(src_mac, dst_mac, &layer3pkt)
|
||||
let ippkt = IPv4Packet::construct(srcip, ip, &Layer4Packet::TCP($tcp_packet));
|
||||
EthernetPacket::construct(src_mac, dst_mac, &Layer3Packet::IPv4(ippkt))
|
||||
}};
|
||||
}
|
||||
|
||||
let (port, packet) = connect(&mut socket, ip, 54248, srcip);
|
||||
|
||||
interface.set_filter(&format!("inbound and tcp port {port}"), true, None)?;
|
||||
interface.set_filter(&format!("arp or (inbound and tcp port {port})"), true, None)?;
|
||||
|
||||
if interface.datalink() != pcap_sys::consts::DLT_EN10MB {
|
||||
bail!("interface does not support ethernet");
|
||||
@@ -226,23 +230,50 @@ async fn main() -> anyhow::Result<()> {
|
||||
task::spawn(async move { use_socket(socket_handle) });
|
||||
|
||||
loop {
|
||||
let Some((builder, data)) = tokio::select! {
|
||||
let Some(packet) = tokio::select! {
|
||||
Some(Ok(bytes)) = packets.next() => {
|
||||
let pkt = bytes.pkt();
|
||||
let Ok(Layer3Pkt::IPv4Pkt(ip_pkt)) = pkt.get_layer3_pkt() else { continue; };
|
||||
let Ok(Layer4Pkt::TCP(tcp_pkt)) = ip_pkt.get_layer4_packet() else { continue; };
|
||||
|
||||
let Ok((to_send, received)) = process_packet(&mut socket, tcp_pkt) else { continue; };
|
||||
match pkt.get_layer3_pkt() {
|
||||
Ok(Layer3Pkt::IPv4Pkt(ip_pkt)) => {
|
||||
let Ok(Layer4Pkt::TCP(tcp_pkt)) = ip_pkt.get_layer4_packet() else { continue; };
|
||||
|
||||
if let Some(received) = received {
|
||||
_ = receive_packet.send(received).await;
|
||||
if !socket_accepts_packet(&socket, &ip_pkt, &tcp_pkt) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let Ok((to_send, received)) = process_packet(&mut socket, tcp_pkt) else { continue; };
|
||||
|
||||
if let Some(received) = received {
|
||||
_ = receive_packet.send(received).await;
|
||||
}
|
||||
|
||||
to_send.map(|(b, d)| format_packet!(b.build(srcip, ip, d, None)))
|
||||
},
|
||||
Ok(Layer3Pkt::ARP(arp)) => {
|
||||
if arp.opcode() != 1 || arp.plen() != 4 || arp.hwlen() != 6 {
|
||||
continue;
|
||||
}
|
||||
|
||||
let senderip: [u8; 4] = arp.srcprotoaddr().try_into().unwrap();
|
||||
let sendermac: &[u8] = arp.srchwaddr();
|
||||
let queryip: [u8; 4] = arp.targetprotoaddr().try_into().unwrap();
|
||||
let queryip: Ipv4Addr = queryip.into();
|
||||
|
||||
if queryip != srcip {
|
||||
continue;
|
||||
}
|
||||
|
||||
let response = ARPPacket::construct(ARPMode::Reply, ARPProto::IPv4, &src_mac, &sendermac, &queryip.octets(), &senderip);
|
||||
|
||||
Some(EthernetPacket::construct(src_mac, sendermac.try_into().unwrap(), &Layer3Packet::ARP(response)))
|
||||
},
|
||||
_ => continue
|
||||
}
|
||||
|
||||
to_send
|
||||
},
|
||||
Some(to_send) = send_packet.recv() => {
|
||||
match send_data(&mut socket, to_send) {
|
||||
Ok(v) => Some(v),
|
||||
Ok(v) => v.map(|(b, d)| format_packet!(b.build(srcip, ip, d, None))),
|
||||
Err(_) => continue
|
||||
}
|
||||
},
|
||||
@@ -251,7 +282,6 @@ async fn main() -> anyhow::Result<()> {
|
||||
continue;
|
||||
};
|
||||
|
||||
let packet = builder.build(srcip, ip, data, None);
|
||||
_ = packets.sendpacket(format_packet!(packet).pkt());
|
||||
_ = packets.sendpacket(packet.pkt());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user