XX-net/XX-Net · info
remove local DNS server %s from upstream
Error message
remove local DNS server %s from upstream
What it means
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.
Source
Thrown at code/default/smart_router/local/dns_query.py:176
ctypes.byref(ctypes.wintypes.DWORD(len(buf))))
ipcount = struct.unpack('I', buf[0:4])[0]
iplist = []
for i in range(4, ipcount * 4 + 4, 4):
ip = socket.inet_ntoa(buf[i:i + 4])
iplist.append(ip)
elif os.path.isfile('/etc/resolv.conf'):
try:
with open('/etc/resolv.conf', 'rb') as fp:
iplist = re.findall(br'(?m)^nameserver\s+(\S+)', fp.read())
xlog.debug("DNS resolve servers:%s", iplist)
local_ips = g.local_ips
for ip in local_ips:
if ip in iplist:
xlog.warn("remove local DNS server %s from upstream", ip)
iplist.remove(ip)
except Exception as e:
xlog.warn("load /etc/resolv.conf fail:%r", e)
if not iplist:
if g.config.country_code == "CN":
iplist = [
b"114.114.114.114",
b"114.114.115.115",
b"119.29.29.29",
b"182.254.118.118",
b"223.5.5.5",
b"223.6.6.6",
b"180.76.76.76"
]
else:
iplist = [
b"1.1.1.1",View on GitHub (pinned to cfa5bc17b6)
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.
Example fix
// before
for ip in local_ips:
if ip in iplist:
xlog.warn("remove local DNS server %s from upstream", ip)
iplist.remove(ip)
// after
for ip in local_ips:
if ip in iplist:
xlog.info("skip local DNS server %s to avoid resolver loop", ip)
iplist = [x for x in iplist if x != ip] Defensive patterns
Strategy: validation
Validate before calling
with open('/etc/resolv.conf') as f:
nameservers = [l.split()[1] for l in f if l.startswith('nameserver')]
local = set(g.local_ips)
if set(nameservers) <= local:
print('warning: only local resolvers configured; will fall back to public DNS') Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- get ip address e:%r
- query_dns_from_xxnet fail status:%d, cost=%f
- query_dns_from_xxnet %s json:%s parse fail:%s
- load /etc/resolv.conf fail:%r
- Servers could not be resolved, %r.
AI-assisted analysis of XX-net/XX-Net@cfa5bc17b6 (2026-08-27).
Data as JSON: /api/errors/9ab7eead929aacc7.
Report an issue: GitHub.