diff --git a/tests/config/test_tor_script_rules.py b/tests/config/test_tor_script_rules.py new file mode 100644 index 0000000..437a2d8 --- /dev/null +++ b/tests/config/test_tor_script_rules.py @@ -0,0 +1,48 @@ +from __future__ import annotations + +from pathlib import Path + +TOR_SCRIPT_PATH = Path(__file__).resolve().parents[2] / "tor.sh" + + +def _tor_script_rule_lines() -> list[str]: + return [ + line.strip() + for line in TOR_SCRIPT_PATH.read_text().splitlines() + if line.strip().startswith("iptables ") + ] + + +def _line_index(lines: list[str], needle: str) -> int: + return next(index for index, line in enumerate(lines) if needle in line) + + +def test_tor_nat_rules_bypass_private_networks_before_tcp_redirect(): + lines = _tor_script_rule_lines() + tcp_redirect_index = _line_index(lines, "--syn -j REDIRECT --to-ports 9040") + + for cidr in ("127.0.0.0/8", "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"): + rule_index = _line_index(lines, f"-d {cidr} -j RETURN") + assert rule_index < tcp_redirect_index + + +def test_tor_nat_rules_exempt_tor_process_before_dns_and_tcp_redirects(): + lines = _tor_script_rule_lines() + + owner_index = _line_index(lines, "-m owner --uid-owner") + udp_dns_index = _line_index(lines, "-p udp --dport 53") + tcp_dns_index = _line_index(lines, "-p tcp --dport 53") + tcp_redirect_index = _line_index(lines, "--syn -j REDIRECT --to-ports 9040") + + assert owner_index < udp_dns_index + assert owner_index < tcp_dns_index + assert owner_index < tcp_redirect_index + + +def test_tor_nat_rules_handle_dns_before_tcp_redirect(): + lines = _tor_script_rule_lines() + + tcp_redirect_index = _line_index(lines, "--syn -j REDIRECT --to-ports 9040") + + assert _line_index(lines, "-p udp --dport 53") < tcp_redirect_index + assert _line_index(lines, "-p tcp --dport 53") < tcp_redirect_index diff --git a/tor.sh b/tor.sh index a097318..345758b 100644 --- a/tor.sh +++ b/tor.sh @@ -213,20 +213,29 @@ echo "[*] Setting up iptables rules..." iptables -F iptables -t nat -F +TOR_UID=$(id -u debian-tor) # Allow loopback iptables -t nat -A OUTPUT -o lo -j RETURN -# Redirect all TCP to Tor's TransPort -iptables -t nat -A OUTPUT -p tcp --syn -j REDIRECT --to-ports 9040 +# Allow Tor itself to reach the network +iptables -t nat -A OUTPUT -m owner --uid-owner "$TOR_UID" -j RETURN # For UDP DNS queries iptables -t nat -A OUTPUT -p udp --dport 53 ! -d 127.0.0.1 -j DNAT --to-destination 127.0.0.1:53 - # For TCP DNS queries (some DNS queries may use TCP) iptables -t nat -A OUTPUT -p tcp --dport 53 ! -d 127.0.0.1 -j DNAT --to-destination 127.0.0.1:53 +# Bypass Tor for local/private networks +iptables -t nat -A OUTPUT -d 127.0.0.0/8 -j RETURN +iptables -t nat -A OUTPUT -d 10.0.0.0/8 -j RETURN +iptables -t nat -A OUTPUT -d 172.16.0.0/12 -j RETURN +iptables -t nat -A OUTPUT -d 192.168.0.0/16 -j RETURN + +# Redirect all TCP to Tor's TransPort +iptables -t nat -A OUTPUT -p tcp --syn -j REDIRECT --to-ports 9040 + echo "[✓] Transparent Tor routing enabled." sleep 5