summaryrefslogtreecommitdiffhomepage
path: root/src/platform/linux
diff options
context:
space:
mode:
Diffstat (limited to 'src/platform/linux')
-rw-r--r--src/platform/linux/iptables.rs19
-rw-r--r--src/platform/linux/nftables.rs59
2 files changed, 78 insertions, 0 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}");