VeilSwap
← All posts
Privacy2026-11-068 min read

Does Your Wallet Really Use Tor? A SOCKS5 Audit

Four wallets, one SOCKS5 handshake: where Electrum, Sparrow, Feather and Monero GUI send the hostname, where DNS leaks, and five checks you can run.

A wallet's Tor switch is a promise about every packet it sends, and the promise is easiest to check at the one place it is actually made: the SOCKS5 request. This audit reads that request in four wallets - Electrum, Sparrow, Feather and Monero GUI - and measures the difference on a SOCKS5 proxy that logs what it is asked to connect to. The result is not "Tor works" or "Tor is broken". It is a map: three of the four hand the server name to the proxy on their default path, and each one has a specific place where traffic goes around. None of that is visible in the interface, which is why the checks at the end matter more than the toggle. (Is Tor safe for swaps?)

One byte decides who resolves. SOCKS5 names a destination in the request's ATYP field: 0x01 for an IPv4 literal, 0x03 for a domain name. Send 0x03 and the proxy - Tor - resolves. Send 0x01 and your machine already resolved, so that query went out before the tunnel existed. I ran a logging SOCKS5 listener on 127.0.0.1:1081 and pointed curl at the same host twice. `curl --socks5` logged `ATYP=1 HOST=172.66.147.243:80`. `curl --socks5-hostname` logged `ATYP=3 HOST=example.com:80`. Same proxy, same destination, one difference: in the first case the DNS answer existed before Tor was involved. Every wallet below makes exactly this choice, in code, and never mentions it. (Is Tor safe for swaps?)

Electrum: it probes, and the probe is strict. With no proxy configured - the shipped default - Electrum can auto-detect a local Tor by probing 127.0.0.1 on ports 9050, 9051 and 9150 in parallel. The probe is not a TCP connect. It sends an 18-byte SOCKS5 handshake ending in command 0xF0, Tor's RESOLVE extension, for 0.0.0.0, and accepts only the exact 12-byte reply `05 00 05 00 00 01 00 00 00 00 00 00`. Against my emulator the source's own bytes logged `CMD=0xf0 ATYP=3 HOST=0.0.0.0:0`, which is the shape Tor answers. Two practical consequences: a generic SOCKS5 server that does not implement RESOLVE (ssh -D, dante) fails detection, and Electrum then simply stays direct - no error, no warning; and port 9051 is Tor's control port, so one of the three probes is normally dead by design. (Is Tor safe for swaps?)

Where Electrum does go through a proxy, the main path is clean: its SOCKS layer encodes a hostname as ATYP 0x03, so the server name reaches the proxy unresolved. The exception sits in the same repository. `dnssec.py` resolves against a hard-coded 8.8.8.8, with a source comment that reads "FIXME this method is not using the network proxy", and `contacts.py` calls it to look up payment identifiers. Use a name@domain identifier and that DNS query is made by your machine, in the clear, with Tor running and the proxy enabled. It is a narrow path - not the blockchain connection - but narrow paths are exactly what identifies a wallet session. (Is Tor safe for swaps?)

Sparrow: two transports, opposite answers. The same application behaves differently depending on the server protocol you pick. With SSL (port 50002) and a proxy set, Sparrow builds `ProxyTcpOverTlsTransport`, whose socket call is `InetSocketAddress.createUnresolved(server.getHost(), port)`: the hostname goes to the SOCKS proxy and the local resolver is never asked. With plain TCP (port 50001) and a proxy set, it falls back to `TcpTransport` plus `ProxySocketFactory`, and there `createAddress` keeps only .onion hosts unresolved; a clearnet host goes through `new InetSocketAddress(address, port)`, which resolves during construction. The IP, not the name, is then sent to Tor. Sparrow's default public server uses SSL, so the common configuration is the safe one - the exception is one click away in the server list. (Is Tor safe for swaps?)

Feather: the default is Tor, minus the first sync. Feather ships with proxy = Tor and starts its own tor binary with `--SocksPort 127.0.0.1:19450`. The gap is in the privacy level: the default is all-except-initial-sync, and the function that decides whether to attach a proxy returns "onion nodes only" whenever the mode is Tor - a condition that stays false until the wallet has refreshed once, or until the chain is within the init-sync threshold of the network height. Translated: the initial sync, the largest and most distinctive burst of traffic a wallet ever produces, goes directly to a clearnet node. After sync the proxy applies, and with onion-only enabled it applies to .onion nodes with TLS deliberately off, because Tor already encrypts that hop. (Is Tor safe for swaps?)

Monero GUI: one flag, wider scope than expected. The GUI accepts `--socks5-proxy address:port`, described in its own source as covering remote node connections, update downloads and price-source fetches. The wallet's own `--proxy` argument is narrower - a socks proxy for daemon connections - and the SOCKS client underneath builds a `v5_domain_connect` request, ATYP 0x03, so the daemon hostname goes to the proxy instead of your resolver. Two things follow. The setting is a generic SOCKS5, not a Tor switch: pointing it at a non-Tor proxy adds a hop and zero anonymity. And the scope includes update checks and price lookups, which means a third-party price API gets a request at the same moment you broadcast, through the same circuit. (Is Tor safe for swaps?)

Even a correct ATYP is not invisibility. With 0x03 everywhere the local resolver is out of the picture, but the exit node still sees the destination hostname and, on clearnet TLS, the SNI. A .onion node is the only configuration that removes both: no DNS lookup, and no hostname for an exit to read. What remains either way is timing - a wallet connecting to a node moments before a transaction appears is a correlation an observer with both views can attempt. Tor moves the observation point; it does not delete it. Anyone who says a Tor toggle makes an on-chain transfer private is selling something that does not exist. (Is Tor safe for swaps?)

Five checks you can run in ten minutes. (1) With the wallet idle, `ss -tnp` should show no outbound 50001, 50002, 18081 or 18089 connection that is not owned by tor. (2) Run `sudo tcpdump -ni any udp port 53` and restart the wallet; every query printed is a lookup that never reached the tunnel. (3) Point the system resolver at a sinkhole such as 127.0.0.1 and restart: if the wallet still connects, it was not resolving locally; if it fails, it was. (4) In Electrum, compare `--proxy socks5:127.0.0.1:9050` against a non-Tor SOCKS server and watch auto-detect refuse the latter. (5) In Sparrow, switch one server between 50001 and 50002 with the proxy on, and watch which one triggers a DNS query. (Is Tor safe for swaps?)

Why this matters for a swap, and what it does not fix. Sending to a deposit address involves no DNS lookup at all: you paste a string and sign. The leak, when there is one, is the wallet's link to its node, and that link exists before and after the order. Treat the two as separate problems. The order page's job is to not log you - this site runs a Tor mirror at 4jyoxqdyx7dh3xfjctihpld7fgliowhimajfszcgypxash5rjqhas3yd.onion and asks for no account. The wallet's job is to not announce you. As a live check at 10:05 UTC on 6 November 2026: 100 USDT-TRON quoted 0.1420618 XMR, an implied 703.9 dollars per XMR against a spot of 617.43, while 1 XMR quoted 612.157 USDT across 2 routes. The small-ticket gap is the locked-rate route, not a privacy surcharge, and the live quote governs. What the SOCKS5 audit buys you is smaller and more useful: the knowledge that "Tor" in a wallet's settings describes one byte in one request - and that you can go and look at it. (Is Tor safe for swaps?)

Frequently asked questions

Does setting a SOCKS5 proxy guarantee no DNS leak?

No. It depends on the ATYP byte in the request. With 0x03 the proxy resolves; with 0x01 your machine resolved first and the query already left. In my test on 6 November 2026, curl sent ATYP=1 with 172.66.147.243 under --socks5 and ATYP=3 with example.com under --socks5-hostname, through the same proxy. The setting proves intent, not behaviour - check with tcpdump on udp/53.

Does Tor Browser protect my wallet's traffic?

No. Tor Browser proxies its own process only; a wallet is a separate application with its own sockets and no proxy inheritance. Electrum, Sparrow, Feather and Monero GUI each need their proxy configured (or their own Tor running), and each has the exceptions described above. A wallet talking to a node over clearnet reveals your IP to that node operator regardless of what browser you have open.

Which of these wallets actually send the hostname to Tor?

Electrum's node connections (aiorpcx encodes the name as ATYP 0x03), Sparrow over SSL port 50002 (createUnresolved), and Monero's SOCKS client (v5_domain_connect). Exceptions: Sparrow's plain-TCP 50001 path resolves the host first and sends an IP; Electrum's payment-identifier DNS goes to 8.8.8.8 outside the proxy; Feather's default privacy level skips the initial sync.

Keep reading

All articles →

Ready to swap?

No account · No KYC · No email

Exchange now
Does Your Wallet Really Use Tor? A SOCKS5 Audit — VeilSwap