How to Configure Bitcoin Core for Tor and I2P Privacy Networks
Bitcoin Core routes peer-to-peer traffic through Tor and I2P using SOCKS5 proxies and SAM bridges, while optionally exposing ephemeral hidden services via the -listenonion and -i2pacceptincoming options.
The bitcoin/bitcoin repository implements privacy network support in its networking layer (src/net.cpp), Tor controller (src/torcontrol.cpp), and address management (src/netaddress.cpp). This allows nodes to operate without revealing public IP addresses, preventing traffic correlation attacks while maintaining full participation in the Bitcoin network.
Tor Configuration Basics
Bitcoin Core connects to the Tor anonymity network through a local SOCKS5 proxy and optionally creates a Version 3 onion service (hidden service) for inbound connections.
Outbound Connections via SOCKS5
Configure your node to route all traffic through Tor’s SOCKS port by setting the proxy address in bitcoin.conf:
proxy=127.0.0.1:9050
The InitProxy() function in src/net.cpp parses this setting and establishes the SOCKS5 connection. When IsolateSOCKSAuth is enabled (default), Bitcoin Core forces a new Tor circuit for each outbound connection, preventing peers from correlating your traffic streams.
Creating an Ephemeral Onion Service
To make your node reachable as a hidden service, enable the Tor control port and activate onion listening:
onion=127.0.0.1:9051
listenonion=1
The TorController class in src/torcontrol.cpp opens a non-blocking socket to the control port, authenticates using the Tor cookie file, and issues the ADD_ONION command. This creates an ephemeral v3 service without manual configuration files. The private key is automatically persisted to onion_v3_private_key in your data directory, allowing the service identity to survive restarts.
I2P Configuration Setup
I2P support utilizes the SAM (Simple Anonymous Messaging) bridge to create encrypted tunnels through the I2P overlay network.
Connecting to the SAM Bridge
Enable I2P by pointing Bitcoin Core to your local SAM service:
i2psam=127.0.0.1:7656
i2pacceptincoming=1
When CreateI2PSession() in src/net.cpp executes, it establishes a TCP connection to the SAM bridge, creates a stream session, and obtains your node’s base-32 .b32.i2p address. The I2P address is treated as a distinct network type (NET_I2P) throughout the codebase, separate from IPv4, IPv6, or Tor.
Address Advertisement
Both Tor and I2P addresses propagate via the addrv2 protocol (BIP 155). When you enable listening, your node advertises its .onion or .b32.i2p address to peers using 33-byte serialized public keys for Tor v3 or the corresponding I2P destination format, ensuring discoverability without IP exposure.
Network Isolation and Security
Restrict your node to privacy-only connections to prevent accidental clearnet leaks:
onlynet=onion
# OR
onlynet=i2p
# OR both
onlynet=onion,i2p
The CNetPermissions system in src/net_processing.cpp validates each peer’s network type against your -onlynet list. Peers matching excluded network types are discarded before connection establishment, ensuring no IPv4/IPv6 traffic occurs.
For authenticated SOCKS proxies (useful when running multiple services through Tor), add credentials:
proxyuser=your_username
proxypassword=your_password
Internal Implementation Details
The privacy networking stack operates through several key components:
Proxy Management – The CConnman class manages proxy configurations separately for generic SOCKS (-proxy), Tor-specific (-onion), and I2P SAM (-i2psam). Each proxy type is stored as a CService object used during outbound connection attempts.
Tor Control Protocol – When -listenonion is active, src/torcontrol.cpp handles the full lifecycle:
- Authenticates via
CookieAuthFile - Issues
ADD_ONIONwith flagsFlags=Detach,DiscardPK,BasicAuth - Parses the
ServiceIDresponse to extract the onion address - Writes the private key to disk using
WriteFile()in the data directory
I2P Session Handling – The SAM protocol implementation sends SESSION CREATE commands with STYLE=STREAM, then parses the DESTINATION field to extract the public key used for your .b32.i2p address.
Debugging and Verification
Enable verbose logging to audit privacy network activity:
debug=tor
debug=i2p
These flags activate the BCLog::TOR and BCLog::I2P categories, emitting detailed logs about circuit creation, proxy handshakes, SAM session establishment, and connection failures. Check your debug log for entries like Created Tor hidden service or I2P SAM session established to confirm proper initialization.
Verify your configuration using the getnetworkinfo RPC command, which displays separate sections for tor and i2p networks, showing whether they are reachable and whether the service is private (inbound capable).
Summary
- Tor integration requires a SOCKS5 proxy (
proxy=) for outbound traffic and the control port (onion=) withlistenonion=1to create ephemeral hidden services. - I2P integration uses the SAM bridge (
i2psam=) withi2pacceptincoming=1to establish anonymous inbound and outbound streams. - Network isolation via
onlynet=onion,i2pprevents clearnet connections, enforced byCNetPermissionsin the networking stack. - Key files involved include
src/torcontrol.cpp(hidden service management),src/net.cpp(proxy and I2P sessions), andsrc/netaddress.cpp(address serialization for BIP 155). - Persistent identity for Tor onion services is stored in
onion_v3_private_keyin your Bitcoin data directory.
Frequently Asked Questions
How do I verify that Bitcoin Core is actually using Tor for all connections?
Run the getnetworkinfo RPC command and check the networks array. The tor entry should show "reachable": true, and if you have listenonion=1 enabled, you should see a localaddresses section containing your .onion address. Additionally, enable debug=tor and look for SOCKS5 connecting messages in the debug log, which confirm traffic is routing through the proxy.
What is the difference between -proxy and -onion configuration options?
The -proxy setting applies to all outbound connections across all network types, while -onion specifically targets Tor hidden service connections and control port communication. If you specify only -proxy, Bitcoin Core will route onion connections through that generic proxy but cannot create inbound hidden services. Use -onion when you need to authenticate with the Tor ControlPort to create ephemeral onion services via the ADD_ONION command.
Can I run Bitcoin Core as both a Tor hidden service and an I2P eepsite simultaneously?
Yes, configure both networks in your bitcoin.conf by setting listenonion=1 with a Tor control port and i2pacceptincoming=1 with a SAM bridge address. Your node will advertise both addresses via the addrv2 protocol, allowing peers to connect through either network. Use onlynet=onion,i2p to restrict all traffic to these privacy networks exclusively.
Where does Bitcoin Core store the private key for my Tor onion service?
The private key for ephemeral v3 onion services is persisted in a file named onion_v3_private_key located in your Bitcoin data directory. This file is created by the TorController::add_onion_cb function in src/torcontrol.cpp when the hidden service is first established, ensuring your onion address remains consistent across restarts without requiring manual Tor configuration files.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →