summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--build.rs7
-rw-r--r--dpibreak.131
-rw-r--r--dpibreak.1.md20
-rw-r--r--src/main.rs8
-rw-r--r--src/pkt.rs51
-rw-r--r--src/platform/windows.rs6
6 files changed, 91 insertions, 32 deletions
diff --git a/build.rs b/build.rs
index e4f4286..e39c48c 100644
--- a/build.rs
+++ b/build.rs
@@ -1,4 +1,4 @@
-// Copyright 2025 Dillution <[email protected]>.
+// Copyright 2025-2026 Dillution <[email protected]>.
//
// This file is part of DPIBreak.
//
@@ -16,6 +16,11 @@
// along with DPIBreak. If not, see <https://www.gnu.org/licenses/>.
fn main() {
+ if std::env::var_os("DPIBREAK_SKIP_BUILD_RS").is_some() {
+ println!("cargo:warning=build.rs skipped (DPIBREAK_SKIP_BUILD_RS is set)");
+ return;
+ }
+
let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap_or_default();
if target_os != "windows" {
eprintln!("target_os is not windows");
diff --git a/dpibreak.1 b/dpibreak.1
index 09096ac..56cb116 100644
--- a/dpibreak.1
+++ b/dpibreak.1
@@ -64,20 +64,33 @@ ClientHello. Typical values are 0–1000; larger values may increase
handshake latency. (default: 0)
.TP
.B \-\-fake
-Enable fake ClientHello packet injection before sending each
-packet fragmented. The injected fake packet’s TTL / Hop Limit is
-overridden with
-.B \-\-fake\-ttl.
-All other TCP/IP header fields follow the original packet.
-Packets are transmitted in an interleaved order:
-(fake 1), (orig 1), (fake 2), (orig 2), ...
+Enable
+.B fake
+ClientHello packet injection before sending each packet
+fragmented. TCP/IP header fields follow the original packet unless you
+override it using the
+.B \-\-fake\-*
+options described below. Packets are transmitted in an interleaved
+order: (fake 1), (orig 1), (fake 2), (orig 2), ...
.TP
.B \-\-fake\-ttl \fIu8\fR
-Override ttl (IPv4) / hop_limit (IPv6) of fake ClientHello packet.
-Ignored unless
+Override ttl (IPv4) / hop_limit (IPv6) of
+.B fake
+packet. Ignored unless
.B \-\-fake
is enabled. (default: 8)
.TP
+.B \-\-fake\-badsum
+Corrupts the TCP checksum of
+.B fake
+packets. When enabled,
+.B fake
+packets cannot pass through most routers and will not behave as
+expected. It can be useful if your router/firewall provides an option
+to disable TCP checksum verification. Ignored unless
+.B \-\-fake
+is enabled.
+.TP
.B \-\-queue\-num \fIu16\fR
.Linux only.
NFQUEUE number to attach to. The same queue number is
diff --git a/dpibreak.1.md b/dpibreak.1.md
index f303b04..a11475b 100644
--- a/dpibreak.1.md
+++ b/dpibreak.1.md
@@ -46,15 +46,21 @@ ClientHello. Typical values are 0–1000; larger values may increase
handshake latency. (default: 0)
**--fake**
-Enable fake ClientHello packet injection before sending each packet
-fragmented. The injected fake packet’s TTL / Hop Limit is overridden
-with **--fake-ttl.** All other TCP/IP header fields follow the original
-packet. Packets are transmitted in an interleaved order: (fake 1), (orig
-1), (fake 2), (orig 2), ...
+Enable **fake** ClientHello packet injection before sending each packet
+fragmented. TCP/IP header fields follow the original packet unless you
+override it using the **--fake-\*** options described below. Packets are
+transmitted in an interleaved order: (fake 1), (orig 1), (fake 2), (orig
+2), ...
**--fake-ttl *u8***
-Override ttl (IPv4) / hop_limit (IPv6) of fake ClientHello packet.
-Ignored unless **--fake** is enabled. (default: 8)
+Override ttl (IPv4) / hop_limit (IPv6) of **fake** packet. Ignored
+unless **--fake** is enabled. (default: 8)
+
+**--fake-badsum**
+Corrupts the TCP checksum of **fake** packets. When enabled, **fake**
+packets cannot pass through most routers and will not behave as
+expected. It can be useful if your router/firewall provides an option to
+disable TCP checksum verification. Ignored unless **--fake** is enabled.
**--queue-num *u16***
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)?;