summaryrefslogtreecommitdiffhomepage
path: root/src/platform
diff options
context:
space:
mode:
Diffstat (limited to 'src/platform')
-rw-r--r--src/platform/linux/iptables.rs19
-rw-r--r--src/platform/linux/nftables.rs59
-rw-r--r--src/platform/windows.rs24
3 files changed, 96 insertions, 6 deletions
diff --git a/src/platform/linux/iptables.rs b/src/platform/linux/iptables.rs
index 91fa1da..4264967 100644
--- a/src/platform/linux/iptables.rs
+++ b/src/platform/linux/iptables.rs
@@ -138,6 +138,21 @@ pub fn install_iptables_rules(ipt: &IPTables) -> Result<()> {
1
).map_err(iptables_err)?;
+ if opt::fake_autottl() {
+ let synack_rule = vec![
+ "-p", "tcp",
+ "--sport", "443",
+ "-m", "tcp", "--tcp-flags", "SYN,ACK", "SYN,ACK",
+ "-j", "NFQUEUE", "--queue-num", &q_num, "--queue-bypass",
+ ];
+
+ ipt.append("mangle", DPIBREAK_CHAIN, &synack_rule).map_err(iptables_err)?;
+ log_println!(LogLevel::Info, "{}: add SYN/ACK learning rule on mangle/{}", ipt.cmd, DPIBREAK_CHAIN);
+
+ ipt.insert("mangle", "INPUT", &["-j", DPIBREAK_CHAIN], 1).map_err(iptables_err)?;
+ log_println!(LogLevel::Info, "{}: add jump to {} chain on INPUT", ipt.cmd, DPIBREAK_CHAIN);
+ }
+
ipt.append("mangle", DPIBREAK_CHAIN, &rule).map_err(iptables_err)?;
log_println!(LogLevel::Info, "{}: new chain {} on table mangle", ipt.cmd, DPIBREAK_CHAIN);
@@ -152,6 +167,10 @@ pub fn cleanup_iptables_rules(ipt: &IPTables) -> Result<()> {
log_println!(LogLevel::Info, "{}: delete jump to {} from mangle/POSTROUTING", ipt.cmd, DPIBREAK_CHAIN);
}
+ if opt::fake_autottl() && ipt.delete("mangle", "INPUT", &["-j", DPIBREAK_CHAIN]).is_ok() {
+ log_println!(LogLevel::Info, "{}: delete jump to {} from mangle/INPUT", ipt.cmd, DPIBREAK_CHAIN);
+ }
+
if ipt.flush_chain("mangle", DPIBREAK_CHAIN).is_ok() {
log_println!(LogLevel::Info, "{}: flush chain {}", ipt.cmd, DPIBREAK_CHAIN);
}
diff --git a/src/platform/linux/nftables.rs b/src/platform/linux/nftables.rs
index ccb918e..27e1830 100644
--- a/src/platform/linux/nftables.rs
+++ b/src/platform/linux/nftables.rs
@@ -103,6 +103,65 @@ pub fn install_nft_rules() -> Result<()> {
opt::queue_num());
log_println!(LogLevel::Debug, "nftables: rule json={}", rule);
+ if opt::fake_autottl() {
+ let synack_rule = serde_json::json!(
+ {
+ "nftables": [
+ // SYN,ACK (for --fake-autottl)
+ {
+ "add": {
+ "chain": {
+ "family": "inet",
+ "table": DPIBREAK_TABLE,
+ "name": "INPUT",
+ "type": "filter",
+ "hook": "input",
+ "prio": 0,
+ "policy": "accept",
+ }
+ }
+ },
+ {
+ "add" : {
+ "rule": {
+ "family": "inet",
+ "table": DPIBREAK_TABLE,
+ "chain": "INPUT",
+ "expr": [
+ {
+ "match": {
+ "left": { "payload": { "protocol": "tcp", "field": "sport" }},
+ "op": "==", "right": 443
+ }
+ },
+ {
+ "match": {
+ "left": { "payload": { "protocol": "tcp", "field": "flags" }},
+ "op": "==", "right": 18 // 18 = SYN(2) | ACK(16)
+ }
+ },
+ {
+ "queue": {
+ "num": crate::opt::queue_num(),
+ "flags": [ "bypass" ]
+ }
+ }
+ ]
+ },
+ }
+ }
+ ]
+ }
+ );
+
+ apply_nft_rules(&serde_json::to_string(&synack_rule)?)?;
+
+ log_println!(LogLevel::Info,
+ "nftables: add chain INPUT, match tcp sport 443 & SYN|ACK -> queue {})",
+ opt::queue_num());
+ log_println!(LogLevel::Debug, "nftables: synack rule json={}", synack_rule);
+ }
+
// clienthello filtered by nft
IS_U32_SUPPORTED.store(true, Ordering::Relaxed);
log_println!(LogLevel::Info, "nftables: create table inet {DPIBREAK_TABLE}");
diff --git a/src/platform/windows.rs b/src/platform/windows.rs
index 4303a65..37a6654 100644
--- a/src/platform/windows.rs
+++ b/src/platform/windows.rs
@@ -23,17 +23,29 @@ use windivert::{
use std::sync::{atomic::Ordering, LazyLock, Mutex, MutexGuard};
use crate::{log::LogLevel, log_println, splash};
+fn windivert_filter() -> String {
+ let base = "(outbound and tcp and tcp.DstPort == 443 \
+ and tcp.Payload[0] == 22 \
+ and tcp.Payload[5] == 1)";
+
+ if crate::opt::fake_autottl() {
+ let synack = "(!outbound and tcp and tcp.SrcPort == 443 \
+ and tcp.Syn and tcp.Ack)";
+ format!("({base} or {synack}) and !impostor")
+ } else {
+ format!("{base} and !impostor")
+ }
+}
+
+
pub static WINDIVERT_HANDLE: LazyLock<Mutex<WinDivert<NetworkLayer>>> = LazyLock::new(|| {
use windivert::*;
- const FILTER: &str = "outbound and tcp and tcp.DstPort == 443 \
- and tcp.Payload[0] == 22 \
- and tcp.Payload[5] == 1 \
- and !impostor"; // to prevent inf loop
+ let filter = windivert_filter();
- let h = match WinDivert::network(FILTER, 0, prelude::WinDivertFlags::new()) {
+ let h = match WinDivert::network(&filter, 0, prelude::WinDivertFlags::new()) {
Ok(h) => {
- log_println!(LogLevel::Info, "windivert: HANDLE constructed for {}", FILTER);
+ log_println!(LogLevel::Info, "windivert: HANDLE constructed for {}", filter);
h
},
Err(e) => {