summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.rs8
-rw-r--r--src/pkt.rs51
-rw-r--r--src/platform/windows.rs6
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)?;
diff --git a/src/pkt.rs b/src/pkt.rs
index 1a329cd..69450dc 100644
--- a/src/pkt.rs
+++ b/src/pkt.rs
@@ -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)?;