Running XNS Resolver

XNS Resolver makes .xns names available to ordinary Linux applications. In I2P mode it asks an indeXer for the owner key, derives the extended address, and opens application TCP streams through the router's SOCKS5 listener.

The route is:

.xns hostname -> rightmost XNS name -> owner key -> extended I2P address -> I2P SOCKS

Requirements

The current implementation requires:

  • Linux
  • systemd-resolved
  • an I2P router with a SOCKS5 listener
  • root privileges for TUN and route setup
  • an XNS indeXer URL chosen by the user

Clone and build it:

git clone https://github.com/exilens/xns-resolver
cd xns-resolver
go build -o xns-resolver ./cmd/xns-resolver

Run it in I2P mode:

sudo ./xns-resolver \
  --network i2p \
  --indexer <xns-indexer-url> \
  --i2p-socks <i2p-socks-url>

The network, indeXer and I2P SOCKS URL are all required. XNS Resolver does not silently choose any of them.

Port 4447 is the conventional I2P SOCKS port. Use it if that is where your router exposes SOCKS, otherwise pass the listener you actually configured.

Check the listener:

ss -ltn | grep ':4447'

What it changes

XNS Resolver creates a TUN interface and assigns a private virtual IPv4 range to it. It starts a DNS listener on the virtual gateway and asks systemd-resolved to send only .xns queries there.

For an active name, the resolver:

  1. requests /lookup?name= from the configured indeXer
  2. validates the returned name, owner key and source transactions
  3. derives the extended Ed25519 I2P address
  4. returns a synthetic IPv4 address to the application
  5. maps TCP connections through the configured I2P SOCKS5 listener

Other DNS names remain on the system's normal resolver path.

Stop the process with Ctrl+C or SIGTERM. It reverts the systemd-resolved route, removes the virtual interface and discards all cached mappings.

Local network options

The implementation defaults are:

--tun xns0
--cidr 10.204.0.0/16
--gateway 10.204.0.1
--dns 10.204.0.1:53
--mtu 1500

They are not XNS protocol constants. Change them when they conflict with an existing route, interface or listener.

Cache and confirmations

The cache exists only in memory. Finalized records are cached until their estimated expiration based on remaining_blocks and Monero's two-minute target. A record whose latest claim or renewal has fewer than ten confirmations is checked again after at most one minute.

Restarting the resolver clears the cache and obtains current registry state again.

Subdomains

The rightmost label before .xns is looked up:

example.xns           -> example
indexer.example.xns   -> example
api.v2.example.xns    -> example

The complete hostname remains visible to the application. XNS Resolver carries TCP streams; the service reached by a destination is determined by its I2P tunnel configuration.

Continue with using XNS names and testing every layer of the route.