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

  1. 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).
  2. 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.
  3. 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.
  4. 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

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


AI-assisted analysis of XX-net/XX-Net@cfa5bc17b6 (2026-08-27). Data as JSON: /api/errors/9ab7eead929aacc7. Report an issue: GitHub.