refactor: update configuration keys and improve documentation for HTTP proxy settings

This commit is contained in:
Abolfazl
2026-05-05 06:47:51 +03:30
parent 603e96b631
commit e9fda55adf
9 changed files with 140 additions and 130 deletions
+11
View File
@@ -107,6 +107,17 @@ FRONT_SNI_POOL_GOOGLE: tuple[str, ...] = (
)
# ── Bypass hosts (direct, no MITM/relay) ────────────────────────────────
# Applied when bypass_hosts is omitted from config.json.
# Advanced users can override this list in config.json under "bypass_hosts".
DEFAULT_BYPASS_HOSTS: tuple[str, ...] = (
"localhost",
".local",
".lan",
".home.arpa",
)
# ── Per-host stats ────────────────────────────────────────────────────────
STATS_LOG_INTERVAL = 300.0 # seconds — how often to log per-host totals
STATS_LOG_TOP_N = 10 # how many hosts to include in the log
+16 -7
View File
@@ -22,6 +22,7 @@ except Exception: # optional dependency fallback
from core.constants import (
CACHE_MAX_MB,
CLIENT_IDLE_TIMEOUT,
DEFAULT_BYPASS_HOSTS,
GOOGLE_DIRECT_ALLOW_EXACT,
GOOGLE_DIRECT_ALLOW_SUFFIXES,
GOOGLE_DIRECT_EXACT_EXCLUDE,
@@ -73,14 +74,15 @@ class ProxyServer:
def __init__(self, config: dict):
self.host = config.get("listen_host", "127.0.0.1")
self.port = config.get("listen_port", 8080)
self.socks_enabled = config.get("socks5_enabled", True)
# Prefer the new key (http_port) but keep listen_port for old configs.
self.port = config.get("http_port", config.get("listen_port", 8080))
self.socks_enabled = True
self.socks_host = config.get("socks5_host", self.host)
self.socks_port = config.get("socks5_port", 1080)
if self.socks_enabled and self.socks_host == self.host \
and int(self.socks_port) == int(self.port):
raise ValueError(
f"listen_port and socks5_port must differ on the same host "
f"http_port and socks5_port must differ on the same host "
f"(both set to {self.port} on {self.host}). "
f"Change one of them in config.json."
)
@@ -137,12 +139,19 @@ class ProxyServer:
}
# ── Per-host policy ────────────────────────────────────────
# block_hosts — refuse traffic entirely (close or 403)
# bypass_hosts — route directly (no MITM, no relay)
# block_hosts — refuse traffic entirely (close or 403)
# direct_hosts — route directly (no MITM, no relay)
# bypass_hosts — legacy alias kept for backward compatibility
# Both accept exact hostnames and leading-dot suffix patterns,
# e.g. ".local" matches any *.local domain.
self._block_hosts = load_host_rules(config.get("block_hosts", []))
self._bypass_hosts = load_host_rules(config.get("bypass_hosts", []))
direct_hosts = config.get("direct_hosts", [])
bypass_hosts = config.get("bypass_hosts")
if bypass_hosts is None:
bypass_hosts = list(DEFAULT_BYPASS_HOSTS)
self._bypass_hosts = load_host_rules(
list(bypass_hosts) + list(direct_hosts)
)
# Route YouTube through the relay when requested; the Google frontend
# IP can enforce SafeSearch on the SNI-rewrite path.
@@ -428,7 +437,7 @@ class ProxyServer:
return
if self._is_bypassed(host):
log.info("Bypass tunnel → %s:%d (matches bypass_hosts)", host, port)
log.info("Direct tunnel → %s:%d (matches direct_hosts/bypass_hosts)", host, port)
await self._do_direct_tunnel(host, port, reader, writer)
return
+4 -5
View File
@@ -137,10 +137,9 @@ class DomainFronter:
config, "tls_connect_timeout", TLS_CONNECT_TIMEOUT, minimum=1.0,
)
self._sni_probe_timeout = min(self._tls_connect_timeout, 4.0)
self._max_response_body_bytes = self._cfg_int(
config, "max_response_body_bytes", MAX_RESPONSE_BODY_BYTES,
minimum=1024,
)
# Keep response cap as a code-level constant to avoid exposing an
# advanced memory-safety knob in end-user config.
self._max_response_body_bytes = MAX_RESPONSE_BODY_BYTES
# Connection pool — TTL-based, pre-warmed, with concurrency control
self._pool: list[tuple[asyncio.StreamReader, asyncio.StreamWriter, float]] = []
@@ -1418,7 +1417,7 @@ class DomainFronter:
502,
"Relay response exceeds cap "
f"({self._max_response_body_bytes} bytes). "
"Increase max_response_body_bytes if your system has enough RAM.",
"Increase MAX_RESPONSE_BODY_BYTES in src/core/constants.py if your system has enough RAM.",
)
if min_size > 0 and total_size < min_size:
return self._rewrite_206_to_200(first_resp)
+1 -1
View File
@@ -224,7 +224,7 @@ def parse_relay_json(data: dict, max_body_bytes: int) -> bytes:
return error_response(
502,
f"Relay response exceeds cap ({max_body_bytes} bytes). "
"Increase max_response_body_bytes if your system has enough RAM.",
"Increase MAX_RESPONSE_BODY_BYTES in src/core/constants.py if your system has enough RAM.",
)
status_text = {