diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/main.rs | 8 | ||||
| -rw-r--r-- | src/pkt.rs | 51 | ||||
| -rw-r--r-- | src/platform/windows.rs | 6 |
3 files changed, 50 insertions, 15 deletions
diff --git a/src/main.rs b/src/main.rs index 498fed2..ab7becc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -// Copyright 2025 Dillution <[email protected]>. +// Copyright 2025-2026 Dillution <[email protected]>. // // This file is part of DPIBreak. // @@ -54,7 +54,7 @@ fn split_packet( end: Option<u32>, out_buf: &mut Vec<u8> ) -> Result<()> { - pkt::split_packet_0(view, start, end, out_buf, None, None) + pkt::split_packet_0(view, start, end, out_buf, None, None, None) } fn send_segment( @@ -158,6 +158,7 @@ Options: --fake Enable fake clienthello injection --fake-ttl <u8> Override ttl of fake clienthello (default: 8) + --fake-badsum Modifies the TCP checksum of the fake packet to an invalid value. -h, --help Show this help"# ); @@ -183,6 +184,7 @@ fn parse_args_1() -> Result<()> { let mut no_splash: bool = false; let mut fake: bool = false; let mut fake_ttl: u8 = 8; + let mut fake_badsum: bool = false; #[cfg(debug_assertions)] let mut log_level: log::LogLevel = LogLevel::Debug; @@ -206,6 +208,7 @@ fn parse_args_1() -> Result<()> { "--fake" => { fake = true; } "--fake-ttl" => { fake_ttl = take_value(&mut args, argv)?; } + "--fake-badsum" => { fake_badsum = true } #[cfg(target_os = "linux")] "--queue-num" => { queue_num = take_value(&mut args, argv)?; } @@ -223,6 +226,7 @@ fn parse_args_1() -> Result<()> { set_opt("OPT_DELAY_MS", &OPT_DELAY_MS, delay_ms)?; set_opt("OPT_FAKE", &OPT_FAKE, fake)?; set_opt("OPT_FAKE_TTL", &pkt::OPT_FAKE_TTL, fake_ttl)?; + set_opt("OPT_FAKE_BADSUM", &pkt::OPT_FAKE_BADSUM, fake_badsum)?; #[cfg(target_os = "linux")] set_opt("OPT_QUEUE_NUM", &platform::OPT_QUEUE_NUM, queue_num)?; #[cfg(target_os = "linux")] set_opt("OPT_NFT_COMMAND", &platform::OPT_NFT_COMMAND, nft_command)?; @@ -1,4 +1,4 @@ -// Copyright 2025 Dillution <[email protected]>. +// Copyright 2025-2026 Dillution <[email protected]>. // // This file is part of DPIBreak. // @@ -83,11 +83,16 @@ const DEFAULT_FAKE_TLS_CLIENTHELLO: &'static [u8] = &[ ]; pub static OPT_FAKE_TTL: OnceLock<u8> = OnceLock::new(); +pub static OPT_FAKE_BADSUM: OnceLock<bool> = OnceLock::new(); fn fake_ttl() -> u8 { *OPT_FAKE_TTL.get().expect("OPT_FAKE_TTL not initialized") } +fn fake_badsum() -> bool { + *OPT_FAKE_BADSUM.get().expect("OPT_FAKE_BADSUM not initialized") +} + pub struct PktView<'a> { pub ip: IpSlice<'a>, pub tcp: TcpSlice<'a> @@ -106,14 +111,15 @@ impl<'a> PktView<'a> { /// Write TCP/IP packet (payload = view.tcp.payload[start..Some(end)]) /// to out_buf, explicitly clearing before. /// -/// If payload or ttl is given, override view's one. +/// If payload, ttl or tcp_checksum is given, override view's one. pub fn split_packet_0( view: &PktView, start: u32, end: Option<u32>, out_buf: &mut Vec<u8>, payload: Option<&[u8]>, - ttl: Option<u8> + ttl: Option<u8>, + tcp_checksum: Option<u16> ) -> Result<()> { use etherparse::*; @@ -131,33 +137,49 @@ pub fn split_packet_0( let mut tcp_hdr = tcp.to_header(); tcp_hdr.sequence_number += start; - let builder = match ip { + let (builder, l3_len) = match ip { IpSlice::Ipv4(hdr) => { let mut ip_hdr = hdr.header().to_header(); if let Some(t) = ttl { ip_hdr.time_to_live = t; }; - PacketBuilder::ip(IpHeaders::Ipv4( + let exts = hdr.extensions().to_header(); + let l3_len = ip_hdr.header_len() + exts.header_len(); + + (PacketBuilder::ip(IpHeaders::Ipv4( ip_hdr, hdr.extensions().to_header() - )) + )), l3_len) }, IpSlice::Ipv6(hdr) => { let mut ip6_hdr = hdr.header().to_header(); if let Some(t) = ttl { ip6_hdr.hop_limit = t; }; - PacketBuilder::ip(IpHeaders::Ipv6( + let l3_len = Ipv6Header::LEN; + + (PacketBuilder::ip(IpHeaders::Ipv6( ip6_hdr, Default::default() - )) + )), l3_len) } - }.tcp_header(tcp_hdr).options_raw(opts)?; + }; + + let builder = builder.tcp_header(tcp_hdr).options_raw(opts)?; let payload = &payload[start as usize..end as usize]; out_buf.clear(); builder.write(out_buf, payload)?; + if let Some(cs) = tcp_checksum { + let tcp_csum_off = l3_len + 16; + + if out_buf.len() < tcp_csum_off + 2 { + return Err(anyhow!("packet too short for tcp checksum patch")); + } + out_buf[tcp_csum_off..tcp_csum_off + 2].copy_from_slice(&cs.to_be_bytes()); + } + Ok(()) } @@ -167,6 +189,15 @@ pub fn fake_clienthello( end: Option<u32>, out_buf: &mut Vec<u8> ) -> Result<()> { + + let tcp_checksum = if fake_badsum() { + Some(0) + } else { + None + }; + split_packet_0(view, start, end, out_buf, - Some(DEFAULT_FAKE_TLS_CLIENTHELLO), Some(fake_ttl())) + Some(DEFAULT_FAKE_TLS_CLIENTHELLO), + Some(fake_ttl()), + tcp_checksum) } diff --git a/src/platform/windows.rs b/src/platform/windows.rs index 4d75e0e..4303a65 100644 --- a/src/platform/windows.rs +++ b/src/platform/windows.rs @@ -1,4 +1,4 @@ -// Copyright 2025 Dillution <[email protected]>. +// Copyright 2025-2026 Dillution <[email protected]>. // // This file is part of DPIBreak. // @@ -72,8 +72,8 @@ pub fn send_to_raw(pkt: &[u8]) -> Result<()> { let mut p = unsafe { packet::WinDivertPacket::<NetworkLayer>::new(pkt.to_vec()) }; p.address.set_outbound(true); - p.address.set_ip_checksum(true); - p.address.set_tcp_checksum(true); + p.address.set_ip_checksum(true); // TODO: test if this is needed + p.address.set_tcp_checksum(false); // For badsum; anyway it is already calculated p.address.set_impostor(true); // to prevent inf loop lock_handle().send(&p)?; |
