From b0af17bcb4f3ca7a41ccf53a63c3d4c99e38e106 Mon Sep 17 00:00:00 2001 From: chuan Date: Thu, 28 May 2026 00:34:54 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=9E=E7=8E=B0=20fake=20dns?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyproject.toml | 2 +- pyxray/libs/xray_config/generator.py | 20 +++++++++++++++++++- pyxray/libs/xray_config/settings.py | 1 + pyxray/web/templates/configs/dns.html | 4 ++++ pyxray/web/xray_config.py | 1 + tests/libs/test_xray_config.py | 26 ++++++++++++++++++++++++++ tests/web/test_xray_assets_web.py | 7 ++++++- 7 files changed, 58 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 78d143d..6112a27 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "pyxray" -version = "1.0.4" +version = "1.0.5" description = "A lightweight Linux xray control plane." readme = "README.md" requires-python = ">=3.14" diff --git a/pyxray/libs/xray_config/generator.py b/pyxray/libs/xray_config/generator.py index fa89994..a9cefef 100644 --- a/pyxray/libs/xray_config/generator.py +++ b/pyxray/libs/xray_config/generator.py @@ -31,6 +31,8 @@ def generate_xray_config(node: Node, settings: XrayConfigSettings | None = None) log = _build_log(settings) if log: config["log"] = log + if _fakedns_enabled(settings): + config["fakedns"] = [{"ipPool": "198.18.0.0/15", "poolSize": 65535}] config["routing"]["rules"].extend(_build_dns_routing(settings)) config["routing"]["rules"].append({"type": "field", "inboundTag": _dns_inbound_tags(settings), "outboundTag": "dns-out"}) config["routing"]["rules"].extend(_build_rule_port_routing(settings)) @@ -157,9 +159,12 @@ def _transparent_inbounds(settings: XrayConfigSettings) -> list[dict[str, Any]]: def _with_sniffing(inbound: dict[str, Any], settings: XrayConfigSettings) -> dict[str, Any]: if settings.inbounds.inbound_sniffing == "disable": return inbound + dest_override = settings.inbounds.inbound_sniffing.split(",") + if _fakedns_enabled(settings) and "fakedns" not in dest_override: + dest_override.append("fakedns") inbound["sniffing"] = { "enabled": True, - "destOverride": settings.inbounds.inbound_sniffing.split(","), + "destOverride": dest_override, "domainsExcluded": _split_lines(settings.inbounds.domains_excluded), "routeOnly": settings.inbounds.route_only, } @@ -207,6 +212,9 @@ def _dns_inbound_tags(settings: XrayConfigSettings) -> list[str]: def _build_dns(settings: XrayConfigSettings, node: Node) -> dict[str, Any]: servers: list[Any] = [] + fakedns_domains = _fakedns_domains(settings) + if fakedns_domains: + servers.append({"address": "fakedns", "domains": fakedns_domains}) routing_domains = _domains_to_lookup(settings, node) for rule in settings.dns.rules: domains = _split_lines(rule.domains) @@ -230,6 +238,16 @@ def _build_dns(settings: XrayConfigSettings, node: Node) -> dict[str, Any]: return dns +def _fakedns_enabled(settings: XrayConfigSettings) -> bool: + return settings.dns.special_mode == "fakedns" + + +def _fakedns_domains(settings: XrayConfigSettings) -> list[str]: + if not _fakedns_enabled(settings): + return [] + return _split_lines(settings.dns.fakedns_domains) or ["geosite:geolocation-!cn"] + + def _dns_server(rule: DnsRuleSettings, domains: list[str]) -> Any: address, port = _parse_dns_addr(rule.server) server_address = rule.server if "://" in rule.server else address diff --git a/pyxray/libs/xray_config/settings.py b/pyxray/libs/xray_config/settings.py index 5c8e5c1..1363771 100644 --- a/pyxray/libs/xray_config/settings.py +++ b/pyxray/libs/xray_config/settings.py @@ -126,6 +126,7 @@ class DnsSettings: ) antipollution: str = "closed" special_mode: str = "none" + fakedns_domains: str = "geosite:geolocation-!cn" @dataclass(slots=True) diff --git a/pyxray/web/templates/configs/dns.html b/pyxray/web/templates/configs/dns.html index 94d1058..cf7576e 100644 --- a/pyxray/web/templates/configs/dns.html +++ b/pyxray/web/templates/configs/dns.html @@ -43,6 +43,10 @@ +