Developed by: Aryan
A production-grade Tor-like onion routing implementation in Go, providing multi-layer encryption and anonymous internet access through globally distributed nodes.
- Overview
- Architecture
- System Flow
- Prerequisites
- Quick Start
- Azure Deployment
- Testing
- Security
- Troubleshooting
- References
This onion network provides true internet anonymity by routing traffic through multiple encrypted hops across different geographical locations. Unlike VPNs that only provide single-hop encryption, this system implements Tor-like onion routing with multiple layers of RSA + AES encryption.
- Multi-layer Encryption: RSA-2048 + AES-256-GCM hybrid encryption
- Global Distribution: Nodes deployed across Europe, Australia, and USA
- Real-time Circuit Creation: Dynamic path selection through available nodes
- Directory Service: Centralized node discovery and registration
- Production Ready: Deployed on Microsoft Azure with real IP transparency
You β πͺπΊ Guard (Europe) β π¦πΊ Relay (Australia) β πΊπΈ Exit (USA) β Internet
graph TB
Client[π€ Client<br/>Local Machine]
Directory[π Directory Server<br/>172.191.95.78:9000<br/>πΊπΈ East US]
Guard[π‘οΈ Guard Node<br/>172.201.12.43:8080<br/>πͺπΊ West Europe]
Relay[π Relay Node<br/>68.218.3.154:8081<br/>π¦πΊ Australia East]
Exit[πͺ Exit Node<br/>172.191.84.146:8082<br/>πΊπΈ East US]
Internet[π Internet<br/>Target Website]
Client -->|1. Register & Discover| Directory
Directory -->|Node List| Client
Client -->|2. Create Circuit| Guard
Guard -->|Forward| Relay
Relay -->|Forward| Exit
Exit -->|3. HTTP Request| Internet
Internet -->|Response| Exit
Exit -->|Response| Relay
Relay -->|Response| Guard
Guard -->|Response| Client
style Client fill:#e1f5fe
style Directory fill:#fff3e0
style Guard fill:#e8f5e8
style Relay fill:#fff9c4
style Exit fill:#fce4ec
style Internet fill:#f3e5f5
graph LR
subgraph "ποΈ Core Components"
Main[main.go<br/>Entry Point]
Node[pkg/node/<br/>Node Logic]
Client[pkg/client/<br/>Client Logic]
Directory[pkg/directory/<br/>Directory Service]
Circuit[pkg/circuit/<br/>Circuit Management]
Crypto[pkg/crypto/<br/>Encryption Engine]
Message[pkg/message/<br/>Message Types]
end
Main --> Node
Main --> Client
Main --> Directory
Client --> Circuit
Client --> Crypto
Node --> Crypto
Circuit --> Message
Node --> Message
style Main fill:#ffeb3b
style Node fill:#4caf50
style Client fill:#2196f3
style Directory fill:#ff9800
style Circuit fill:#9c27b0
style Crypto fill:#f44336
style Message fill:#607d8b
sequenceDiagram
participant C as Client
participant G as Guard Node
participant R as Relay Node
participant E as Exit Node
participant W as Website
Note over C: Create 3-layer onion
C->>C: Data β AES(Exit) β AES(Relay) β AES(Guard)
C->>C: RSA encrypt each AES key
Note over C,E: Forward Direction
C->>G: Encrypted Packet (910 bytes)
G->>G: RSA decrypt β AES decrypt
G->>R: Layer 2 (626 bytes)
R->>R: RSA decrypt β AES decrypt
R->>E: Layer 1 (342 bytes)
E->>E: RSA decrypt β AES decrypt
E->>W: Plain HTTP Request
Note over E,C: Response Direction
W->>E: HTTP Response
E->>R: Encrypted Response
R->>G: Re-encrypted Response
G->>C: Final Response
sequenceDiagram
participant N as Node
participant D as Directory Server
N->>N: Generate RSA-2048 keypair
N->>D: POST /register {id, type, address, port, public_key}
D->>D: Store node info with timestamp
D->>N: 200 OK - Registration confirmed
sequenceDiagram
participant C as Client
participant D as Directory Server
C->>D: GET /nodes/guard
D->>C: Guard node list
C->>D: GET /nodes/relay
D->>C: Relay node list
C->>D: GET /nodes/exit
D->>C: Exit node list
C->>C: Select path: Guard β Relay β Exit
C->>C: Create circuit ID
sequenceDiagram
participant C as Client
participant G as Guard (EU)
participant R as Relay (AU)
participant E as Exit (US)
participant W as httpbin.org
C->>C: Create HTTP request
C->>C: Apply 3-layer onion encryption
C->>G: Send encrypted packet
G->>G: Decrypt guard layer
G->>R: Forward to relay
R->>R: Decrypt relay layer
R->>E: Forward to exit
E->>E: Decrypt final layer
E->>W: Make actual HTTP request
W->>E: HTTP response
E->>R: Encrypted response
R->>G: Forward response
G->>C: Final response
- Go 1.21 or higher
- Git
- Terminal/Command Line access
- Microsoft Azure account ($100 student credit recommended)
- Azure CLI installed and configured
- SSH key pair generated
| Component | VM Size | vCPU | RAM | Monthly Cost |
|---|---|---|---|---|
| Directory Server | Standard_B1s | 1 | 1GB | $7.30 |
| Guard Node | Standard_B1s | 1 | 1GB | $7.30 |
| Relay Node | Standard_B1s | 1 | 1GB | $7.30 |
| Exit Node | Standard_B1s | 1 | 1GB | $7.30 |
| Total | 4 | 4GB | $29.20 |
-
Clone and Build
git clone <repository> cd onion-network go build -o onion-network
-
Start Directory Server
./onion-network -mode=directory -port=9000
-
Start Nodes (separate terminals)
# Guard Node ./onion-network -mode=node -type=guard -port=8080 # Relay Node ./onion-network -mode=node -type=relay -port=8081 # Exit Node ./onion-network -mode=node -type=exit -port=8082
-
Test Client
./onion-network -mode=client create request https://httpbin.org/ip quit
-
Install Azure CLI
brew install azure-cli # macOS # or visit: https://docs.microsoft.com/en-us/cli/azure/install-azure-cli
-
Login and Create Resource Group
az login az group create --name onion-network-rg --location eastus
-
Create VMs
# Directory Server (East US) az vm create \ --resource-group onion-network-rg \ --name directory-server \ --location eastus \ --image Ubuntu2204 \ --size Standard_B1s \ --admin-username onion \ --generate-ssh-keys \ --public-ip-sku Standard # Guard Node (West Europe) az vm create \ --resource-group onion-network-rg \ --name guard-node-eu \ --location westeurope \ --image Ubuntu2204 \ --size Standard_B1s \ --admin-username onion \ --generate-ssh-keys \ --public-ip-sku Standard # Relay Node (Australia East) az vm create \ --resource-group onion-network-rg \ --name relay-node-au \ --location australiaeast \ --image Ubuntu2204 \ --size Standard_B1s \ --admin-username onion \ --generate-ssh-keys \ --public-ip-sku Standard # Exit Node (East US) az vm create \ --resource-group onion-network-rg \ --name exit-node-us \ --location eastus \ --image Ubuntu2204 \ --size Standard_B1s \ --admin-username onion \ --generate-ssh-keys \ --public-ip-sku Standard
-
Open Network Ports
az vm open-port --resource-group onion-network-rg --name directory-server --port 9000 --priority 1100 az vm open-port --resource-group onion-network-rg --name guard-node-eu --port 8080 --priority 1100 az vm open-port --resource-group onion-network-rg --name relay-node-au --port 8081 --priority 1100 az vm open-port --resource-group onion-network-rg --name exit-node-us --port 8082 --priority 1100
-
Build for Linux
GOOS=linux GOARCH=amd64 go build -o onion-network-linux
-
Deploy to Servers
# Get VM IP addresses az vm list-ip-addresses --resource-group onion-network-rg --output table # Deploy binary (replace with actual IPs) scp onion-network-linux onion@DIRECTORY_IP:~/ scp onion-network-linux onion@GUARD_IP:~/ scp onion-network-linux onion@RELAY_IP:~/ scp onion-network-linux onion@EXIT_IP:~/
Start services in this exact order:
-
Directory Server
ssh onion@DIRECTORY_IP chmod +x onion-network-linux ./onion-network-linux -mode=directory -port=9000
-
Guard Node (wait 30 seconds)
ssh onion@GUARD_IP chmod +x onion-network-linux ./onion-network-linux -mode=node -type=guard -port=8080
-
Relay Node
ssh onion@RELAY_IP chmod +x onion-network-linux ./onion-network-linux -mode=node -type=relay -port=8081
-
Exit Node
ssh onion@EXIT_IP chmod +x onion-network-linux ./onion-network-linux -mode=node -type=exit -port=8082
-
Start Client
./onion-network -mode=client
-
Create Circuit
onion> create Created circuit circuit_abc123: node_guard -> node_relay -> node_exit -
Make Anonymous Request
onion> request https://httpbin.org/ip Making request to https://httpbin.org/ip via circuit circuit_abc123 π§ Creating onion encryption layers... π Encrypting request with 3 layers... π¦ Encrypted packet size: 910 bytes β Encrypted request sent successfully!
Guard Node Log:
[GUARD] Received 910 bytes of data
[GUARD] π Successfully decrypted layer, forwarding to relay
[GUARD] β
Successfully forwarded to RELAY
Relay Node Log:
[RELAY] Received 626 bytes of data
[RELAY] π Successfully decrypted layer, forwarding to exit
[RELAY] β
Successfully forwarded to EXIT
Exit Node Log:
[EXIT] Received 342 bytes of data
[EXIT] π Successfully decrypted final layer
[EXIT] π Making REAL request to: https://httpbin.org/ip
[EXIT] β
SUCCESS! Got 30 bytes from https://httpbin.org/ip
[EXIT] π Response Status: 200 OK
[EXIT] π Response Preview: {"origin": "172.191.84.146"}
The response shows the exit node's IP (172.191.84.146), not your real IP.
Test with multiple services:
request https://httpbin.org/ip
request https://api.ipify.org?format=json
request https://ifconfig.me/ip
β
IP Address Anonymity: Websites see exit node IP, not yours
β
Traffic Encryption: Multi-layer RSA + AES encryption
β
Geographic Distribution: Traffic routes through multiple countries
β
No Single Point of Failure: Distributed architecture
graph TB
subgraph "π Encryption Layers"
L1[Layer 1: AES-256-GCM<br/>Exit Node Key]
L2[Layer 2: AES-256-GCM<br/>Relay Node Key]
L3[Layer 3: AES-256-GCM<br/>Guard Node Key]
end
subgraph "π Key Management"
K1[RSA-2048 Keys<br/>Generated per node]
K2[AES Keys<br/>Generated per session]
K3[Perfect Forward Secrecy<br/>Keys rotated on restart]
end
Data[π Original Data] --> L1
L1 --> L2
L2 --> L3
L3 --> Encrypted[π 3-Layer Encrypted Onion]
K1 --> K2
K2 --> K3
- Monitor Logs: Watch for unusual activity
- Regular Updates: Keep Azure VMs updated
- Cost Monitoring: Track Azure spending
- Key Rotation: Restart nodes periodically
β Failed to send request: dial tcp: connect: connection refused
Solutions:
- Verify all nodes are running
- Check firewall ports (9000, 8080, 8081, 8082)
- Ensure nodes listen on
0.0.0.0, not127.0.0.1 - Start services in correct order
β Failed to decrypt layer: crypto/rsa: decryption error
Solutions:
- Create fresh circuit after restarting nodes
- Ensure all nodes running latest binary
- Check node registration with directory
Warning: Failed to register with directory: connection refused
Solutions:
- Start directory server first
- Wait 30 seconds before starting nodes
- Verify directory server port 9000 is accessible
# Check process status
ssh onion@SERVER_IP "ps aux | grep onion"
# Check port listening
ssh onion@SERVER_IP "ss -tlnp | grep PORT"
# Monitor network traffic
ssh onion@SERVER_IP "iftop"
# Monitor resources
ssh onion@SERVER_IP "htop"-
Dingledine, R., Mathewson, N., & Syverson, P. (2004)
Tor: The Second-Generation Onion Router
USENIX Security Symposium
Paper Link -
Goldschlag, D., Reed, M., & Syverson, P. (1999)
Onion Routing for Anonymous and Private Internet Connections
Communications of the ACM, 42(2), 39-41
Paper Link -
Syverson, P., Tsudik, G., Reed, M., & Landwehr, C. (2000)
Towards an Analysis of Onion Routing Security
Workshop on Design Issues in Anonymity and Unobservability
Paper Link
onion-network/
βββ main.go # Entry point and CLI
βββ go.mod # Go module definition
βββ pkg/
β βββ node/ # Node implementation
β β βββ node.go # Guard/Relay/Exit logic
β βββ client/ # Client implementation
β β βββ client.go # Circuit creation & requests
β βββ directory/ # Directory service
β β βββ directory.go # Node registration & discovery
β βββ circuit/ # Circuit management
β β βββ circuit.go # Circuit creation & selection
β βββ crypto/ # Encryption engine
β β βββ onion.go # Multi-layer encryption
β βββ message/ # Message types
β βββ message.go # Protocol definitions
βββ README.md # This file
βββ DEMO-GUIDE.md # Step-by-step demo guide
Start Production Network:
# 1. Directory (first)
ssh [email protected] "./onion-network-linux -mode=directory -port=9000"
# 2. Guard (wait 30s)
ssh [email protected] "./onion-network-linux -mode=node -type=guard -port=8080"
# 3. Relay
ssh [email protected] "./onion-network-linux -mode=node -type=relay -port=8081"
# 4. Exit
ssh [email protected] "./onion-network-linux -mode=node -type=exit -port=8082"Test Client:
./onion-network -mode=client
create
request https://httpbin.org/ip
quitEmergency Shutdown:
az vm deallocate --resource-group onion-network-rg --name directory-server
az vm deallocate --resource-group onion-network-rg --name guard-node-eu
az vm deallocate --resource-group onion-network-rg --name relay-node-au
az vm deallocate --resource-group onion-network-rg --name exit-node-us