{"record":{"id":"9ab7eead929aacc7","repo":"XX-net/XX-Net","slug":"remove-local-dns-server-s-from-upstream","errorCode":null,"errorMessage":"remove local DNS server %s from upstream","messagePattern":"remove local DNS server (.+?) from upstream","errorType":"console","errorClass":null,"httpStatus":null,"severity":"info","filePath":"code/default/smart_router/local/dns_query.py","lineNumber":176,"sourceCode":"                                                ctypes.byref(ctypes.wintypes.DWORD(len(buf))))\n            ipcount = struct.unpack('I', buf[0:4])[0]\n\n            iplist = []\n            for i in range(4, ipcount * 4 + 4, 4):\n                ip = socket.inet_ntoa(buf[i:i + 4])\n                iplist.append(ip)\n\n        elif os.path.isfile('/etc/resolv.conf'):\n            try:\n                with open('/etc/resolv.conf', 'rb') as fp:\n                    iplist = re.findall(br'(?m)^nameserver\\s+(\\S+)', fp.read())\n\n                xlog.debug(\"DNS resolve servers:%s\", iplist)\n\n                local_ips = g.local_ips\n                for ip in local_ips:\n                    if ip in iplist:\n                        xlog.warn(\"remove local DNS server %s from upstream\", ip)\n                        iplist.remove(ip)\n            except Exception as e:\n                xlog.warn(\"load /etc/resolv.conf fail:%r\", e)\n\n        if not iplist:\n            if g.config.country_code == \"CN\":\n                iplist = [\n                    b\"114.114.114.114\",\n                    b\"114.114.115.115\",\n                    b\"119.29.29.29\",\n                    b\"182.254.118.118\",\n                    b\"223.5.5.5\",\n                    b\"223.6.6.6\",\n                    b\"180.76.76.76\"\n                ]\n            else:\n                iplist = [\n                    b\"1.1.1.1\",","sourceCodeStart":158,"sourceCodeEnd":194,"githubUrl":"https://github.com/XX-net/XX-Net/blob/cfa5bc17b67676e467f37ec50766127e0ab5f0aa/code/default/smart_router/local/dns_query.py#L158-L194","documentation":"While reading /etc/resolv.conf to find upstream DNS servers, the code detected that one of the machine's own local IPs (from g.local_ips) appears in the resolver list. Because the smart router itself runs a local DNS server, using it as an upstream would create a loop, so that IP is removed and this warning is logged.","triggerScenarios":"Instantiating LocalDnsQuery (via get_local_dns_server during __init__) on Linux/macOS where /etc/resolv.conf points to 127.0.0.1 or another local interface IP — typical when dnsmasq/NetworkManager/systemd-resolved or a previous smart-router instance set the system resolver to loopback.","commonSituations":"systemd-resolved (127.0.0.53) or dnsmasq managing DNS; a prior XX-Net run left the system pointing at its own DNS server; VPN clients setting local resolvers; the smart router started twice so the second instance sees the first's listener IP.","solutions":["Benign in most setups — the code correctly strips the looped resolver and proceeds; verify real upstreams remain (check the fallback to public DNS when iplist is empty).","If iplist becomes empty after removal, configure a real fallback (the code already falls back to public DNS in CN/non-CN branches); optionally hardcode trusted upstreams.","Restore a genuine upstream in /etc/resolv.conf (e.g. 8.8.8.8, 1.1.1.1) if a stale local entry is all that exists.","Avoid running the smart router's local DNS server on the same port a system resolver already uses."],"exampleFix":"// before\nfor ip in local_ips:\n    if ip in iplist:\n        xlog.warn(\"remove local DNS server %s from upstream\", ip)\n        iplist.remove(ip)\n\n// after\nfor ip in local_ips:\n    if ip in iplist:\n        xlog.info(\"skip local DNS server %s to avoid resolver loop\", ip)\n        iplist = [x for x in iplist if x != ip]","handlingStrategy":"validation","validationCode":"with open('/etc/resolv.conf') as f:\n    nameservers = [l.split()[1] for l in f if l.startswith('nameserver')]\nlocal = set(g.local_ips)\nif set(nameservers) <= local:\n    print('warning: only local resolvers configured; will fall back to public DNS')","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep at least one non-local nameserver in /etc/resolv.conf so upstream resolution survives the de-loop filter.","Don't run multiple smart-router DNS instances bound to the resolver IP.","Recognize this warning as informational: the loop is correctly prevented by design."],"tags":["dns","resolv-conf","loopback","smart-router","linux"],"backgroundTag":"dns-resolver-loop","analyzedSha":"cfa5bc17b67676e467f37ec50766127e0ab5f0aa","analyzedAt":"2026-08-27T19:28:28.225Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}