{"record":{"id":"1535e0d601c75eb5","repo":"XX-net/XX-Net","slug":"dnsovertlsquery-connect-s-s-d-fail-r","errorCode":null,"errorMessage":"DnsOverTlsQuery connect %s %s:%d fail:%r","messagePattern":"DnsOverTlsQuery connect (.+?) (.+?):(.+?) fail:%r","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"code/default/smart_router/local/dns_query.py","lineNumber":491,"sourceCode":"                    \"ipv4s\": [b\"9.9.9.9\", b\"149.112.112.112\"],\n                }\n            ]\n\n        DnsOverTcpQuery.__init__(self, server_list=server_list, port=853)\n        self.protocol = \"DoT\"\n        self.ssl_context = ssl.create_default_context()\n        self.ssl_context.check_hostname = False\n        self.ssl_context.verify_mode = ssl.CERT_REQUIRED\n\n    def connect(self, host, port):\n        domain = host[\"domain\"]\n        ipv4 =  random.choice(host[\"ipv4s\"])\n        try:\n            s = super(DnsOverTlsQuery, self).connect(ipv4, port)\n            sock = self.ssl_context.wrap_socket(s, server_hostname=domain)\n            return sock\n        except Exception as e:\n            xlog.warn(\"DnsOverTlsQuery connect %s %s:%d fail:%r\", ipv4, domain, port, e)\n            return None\n\n\nclass DnsOverHttpsQuery(object):\n    def __init__(self, timeout=6):\n        self.protocol = \"DoH\"\n        self.timeout = timeout\n        self.cn_servers = [\"https://1.12.12.12/dns-query\", \"https://223.5.5.5/dns-query\"]\n        self.other_servers = [\n            \"https://1.1.1.1/dns-query\",\n            \"https://dns10.quad9.net/dns-query\",\n            \"https://dns.aa.net.uk/dns-query\",\n        ]\n        self.connection_timeout = 60\n        self.connections = []\n\n    def get_connection(self):\n        while len(self.connections):","sourceCodeStart":473,"sourceCodeEnd":509,"githubUrl":"https://github.com/XX-net/XX-Net/blob/cfa5bc17b67676e467f37ec50766127e0ab5f0aa/code/default/smart_router/local/dns_query.py#L473-L509","documentation":"DnsOverTlsQuery.connect() failed to establish a DNS-over-TLS session: it picked a random IPv4 from the server's bootstrap IPs, connected via the parent connect(), then wrapped the socket in TLS with wrap_socket(server_hostname=domain). Any failure in either step logs this warning and returns None.","triggerScenarios":"Randomly selecting a dead/unreachable IPv4 from host['ipv4s']; TCP 853 blocked by the firewall; TLS handshake failure — certificate mismatch/expire, unsupported TLS version, SNI-based blocking, or protocol corruption by a middlebox.","commonSituations":"DoT on port 853 blocked by ISPs/corporate firewalls (very common), stale bootstrap IPs for the resolver, TLS-intercepting proxies rejecting the DoT certificate, outdated CA bundle for the ssl_context.","solutions":["Test DoT reachability: 'openssl s_client -connect 1.1.1.1:853 -servername cloudflare-dns.com'","If 853 is blocked, switch to DnsOverHttpsQuery (DoH over 443)","Refresh the bootstrap ipv4s list for the resolver host","Ensure the ssl_context CA bundle is current so certificate validation succeeds"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"import socket\ndef dot_reachable(ip, port=853, timeout=3):\n    try:\n        s = socket.create_connection((ip, port), timeout)\n        s.close()\n        return True\n    except OSError:\n        return False\nservers = [ip for ip in host['ipv4s'] if dot_reachable(ip)]","typeGuard":null,"tryCatchPattern":"sock = dot_client.connect(host, port)\nif sock is None:\n    sock = doh_client.connect(host, 443)  # DoH fallback","preventionTips":["Always null-check connect() results","Probe 853 reachability at startup and prune dead bootstrap IPs","Deploy DoH as the automatic fallback when DoT fails"],"tags":["dns","dot","tls-handshake","ssl","port-853"],"backgroundTag":"tls-handshake-failed","analyzedSha":"cfa5bc17b67676e467f37ec50766127e0ab5f0aa","analyzedAt":"2026-08-27T19:28:28.225Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}