DNS Nameserver Types in Xray-core: DoH, DoT, QUIC, TCP, and UDP Explained

Xray-core supports eight DNS nameserver types—UDP, TCP, DoH, DoT, QUIC, Local, and FakeDNS—each implemented as a dedicated client in app/dns/ to handle different privacy, performance, and network compatibility requirements.

The DNS subsystem in Xray-core is designed for flexibility. Whether you need unencrypted speed for trusted networks, TLS encryption for privacy, or QUIC for low-latency encrypted queries, Xray-core implements each transport as a discrete nameserver type. These implementations live in app/dns/nameserver_*.go files and share a common interface defined in app/dns/nameserver.go.

This guide examines each DNS nameserver type in Xray-core, their implementation details, and when to use each one.


UDP Nameserver: Default Fast Resolution

Implementation and Behavior

The UDP nameserver is Xray-core's default DNS transport. Implemented in app/dns/nameserver_udp.go, it sends standard DNS queries over UDP port 53.

UDP DNS offers the lowest latency for small queries. The implementation handles UDP's stateless nature with proper timeout and retry logic. When you specify a bare IP like 8.8.8.8 in your configuration, Xray-core automatically selects the UDP nameserver.

Configuration Example

{
  "dns": {
    "servers": [
      "8.8.8.8",
      "1.1.1.1"
    ]
  }
}

When to Use UDP

  • Trusted networks where query privacy isn't a concern
  • Low latency requirements and small DNS responses
  • Compatibility with any standard DNS resolver
  • Default fallback when encrypted transports fail

TCP Nameserver: Reliable Large Responses

Implementation and Behavior

The TCP nameserver in app/dns/nameserver_tcp.go handles DNS over TCP port 53. Unlike UDP, TCP provides guaranteed delivery and supports responses larger than 512 bytes without truncation.

The TCP implementation in Xray-core manages connection reuse where possible and handles TCP's higher overhead through efficient connection pooling. Large DNSSEC-signed responses often require TCP transport.

Configuration Example

{
  "dns": {
    "servers": [
      "tcp://1.1.1.1:53",
      "tcp://8.8.8.8:53"
    ]
  }
}

When to Use TCP

  • Large DNS responses exceeding UDP size limits
  • DNSSEC validation requiring full signature records
  • UDP-blocked networks where only TCP egress is allowed
  • Reliability over raw speed

DoH (DNS-over-HTTPS): Privacy Through Web Infrastructure

Implementation and Behavior

DNS-over-HTTPS is implemented in app/dns/nameserver_doh.go. DoH encapsulates DNS queries within HTTPS requests, providing encryption and leveraging existing web infrastructure.

The DoH implementation in Xray-core uses the project's generic HTTP client, supporting features like proxy chaining and connection pooling. DoH queries appear as standard HTTPS traffic to network observers, making them difficult to block without blocking all HTTPS.

Configuration Example

{
  "dns": {
    "servers": [
      "https://dns.google/dns-query",
      "https://cloudflare-dns.com/dns-query",
      "https://1.1.1.1/dns-query"
    ]
  }
}

When to Use DoH

  • Maximum privacy against network-level DNS surveillance
  • Bypassing DNS blocking when raw DNS ports are restricted
  • Corporate networks allowing HTTPS but not custom protocols
  • CDN benefits from major DoH providers

DoT (DNS-over-TLS): Dedicated TLS Encryption

Implementation and Behavior

DNS-over-TLS shares the same app/dns/nameserver_tcp.go implementation as plain TCP, with TLS enabled via configuration flag. DoT uses a dedicated TLS connection on port 853 without HTTP encapsulation.

The implementation negotiates TLS 1.3 where supported, falling back to TLS 1.2. DoT provides encryption equivalent to DoH with lower protocol overhead—no HTTP headers or request/response framing.

Configuration Example

{
  "dns": {
    "servers": [
      "tls://1.1.1.1:853",
      "tls://8.8.8.8:853",
      "tls://dns.google:853"
    ]
  }
}

When to Use DoT

  • TLS encryption with minimal protocol overhead
  • Simpler stack without HTTP dependencies
  • Network environments where port 853 is open but 443 is monitored
  • Performance-critical encrypted DNS scenarios

QUIC Nameserver: Modern Encrypted UDP

Implementation and Behavior

The QUIC nameserver in app/dns/nameserver_quic.go implements DNS over QUIC (DoQ) per RFC 9250. QUIC combines UDP's speed with TLS 1.3 encryption in a single handshake.

Xray-core's QUIC implementation uses the project's QUIC transport layer, providing 0-RTT connection resumption where supported. The protocol multiplexes queries on a single connection without head-of-line blocking.

Configuration Example

{
  "dns": {
    "servers": [
      "quic://dns.quad9.net:784",
      "quic://dns.google:443"
    ]
  }
}

When to Use QUIC

  • Lowest latency encrypted DNS with 0-RTT support
  • Modern networks with QUIC-friendly infrastructure
  • Avoiding TCP connection overhead while maintaining encryption
  • Resilient to packet loss better than TCP-based TLS

Local Nameserver: System Resolver Delegation

Implementation and Behavior

The Local nameserver in app/dns/nameserver_local.go delegates queries to the operating system's native DNS resolver. It reads system configuration from /etc/resolv.conf on Unix systems or uses Windows DNS APIs.

This implementation is a thin wrapper that doesn't implement DNS protocol logic itself. Instead, it relies on the OS's resolver, including any caching, search domains, or split-horizon configuration the system maintains.

Configuration Example

{
  "dns": {
    "servers": [
      "local"
    ]
  }
}

When to Use Local

  • OS-level DNS caching and configuration inheritance
  • Corporate environments with complex internal DNS resolution
  • Split-horizon scenarios where internal vs. external resolution differs
  • Minimal configuration using existing system setup

FakeDNS Nameserver: Synthetic Resolution for Routing

Implementation and Behavior

The FakeDNS nameserver in app/dns/nameserver_fakedns.go generates synthetic A and AAAA records for domain names without performing real DNS resolution. It maps domains to configurable fake IP ranges.

This implementation enables domain-based routing without external DNS queries. When a client requests a domain, FakeDNS returns a synthetic IP from a configured pool. Xray-core's routing layer then uses the original domain for rule matching, while the transport layer uses the fake IP for connection establishment.

Configuration Example

{
  "dns": {
    "servers": [
      "fakedns"
    ],
    "final": "8.8.8.8"
  },
  "fakedns": {
    "ipPool": "198.18.0.0/15",
    "poolSize": 65535
  }
}

When to Use FakeDNS

  • Domain-based routing rules without DNS leakage
  • Split-tunneling scenarios where only specific domains use proxy
  • Reduced DNS latency by avoiding external queries for routed domains
  • Preventing DNS pollution in restrictive network environments

Comparing DNS Nameserver Types in Xray-core

Protocol Encryption Transport Latency Best For
UDP None UDP Lowest Speed, trusted networks
TCP None TCP Medium Large responses, UDP blocked
DoH TLS 1.2/1.3 HTTPS Medium-High Privacy, proxy compatibility
DoT TLS 1.2/1.3 TCP Medium Encrypted, low overhead
QUIC TLS 1.3 UDP Low Fast encrypted, modern networks
Local OS-dependent Varies Varies System integration
FakeDNS N/A Internal None Routing optimization

Configuration Parsing and Server Selection

The app/dns/config.go file handles parsing of DNS server URIs and determines which nameserver implementation to instantiate. The URI scheme prefixes (https://, tls://, quic://, tcp://) trigger the corresponding constructor.

When no scheme is specified, Xray-core defaults to UDP. The features/dns/client.go file coordinates the high-level DNS client logic, managing query distribution across configured nameservers and handling fallback behavior.


Summary

  • UDP nameserver (nameserver_udp.go) provides fastest resolution for trusted networks, defaulting to port 53.

  • TCP nameserver (nameserver_tcp.go) handles large DNS responses and UDP-restricted environments, with TLS mode for DoT.

  • DoH nameserver (nameserver_doh.go) encrypts DNS within HTTPS traffic, ideal for privacy and proxy compatibility.

  • DoT nameserver (nameserver_tcp.go with TLS) offers dedicated TLS encryption without HTTP overhead.

  • QUIC nameserver (nameserver_quic.go) delivers encrypted UDP performance with TLS 1.3 and 0-RTT.

  • Local nameserver (nameserver_local.go) delegates to OS resolver for system integration.

  • FakeDNS nameserver (nameserver_fakedns.go) enables domain-based routing without external DNS queries.


Frequently Asked Questions

What is the default DNS nameserver type in Xray-core?

The default is UDP. When you specify a bare IP address like 8.8.8.8 without any URI scheme, Xray-core instantiates the UDP nameserver from app/dns/nameserver_udp.go and queries port 53.

Can I use multiple DNS nameserver types simultaneously?

Yes. Xray-core's dns.servers array accepts mixed types. You can configure ["https://dns.google/dns-query", "8.8.8.8", "local"] to try DoH first, fall back to UDP, then use the system resolver. The resolver in features/dns/client.go manages this priority order.

When should I choose DoH over DoT in Xray-core?

Choose DoH (nameserver_doh.go) when you need DNS traffic to blend with regular HTTPS traffic, traverse HTTP proxies, or benefit from CDN caching. Choose DoT (nameserver_tcp.go with TLS) when you want lower protocol overhead, direct TLS encryption, or operation on port 853 where HTTP-based traffic is monitored or restricted.

Does Xray-core support DNS-over-HTTP/3?

DNS-over-QUIC (nameserver_quic.go) provides equivalent functionality. QUIC uses TLS 1.3 and offers similar performance characteristics to HTTP/3. Configure quic://dns.google:443 or quic://dns.quad9.net:784 to use this modern encrypted transport.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →