hypertor 0.2.2

Tor HTTP client and onion service library with Python bindings
Documentation
---
title: "SOCKS5 Proxy"
permalink: /docs/proxy/
excerpt: "Run a local SOCKS5 proxy to route any application through Tor"
---

Run a local SOCKS5 proxy server that routes any SOCKS5-compatible application through the Tor network.

## Overview

The `Socks5Proxy` component provides a standard SOCKS5 proxy interface, allowing you to:

- **Universal Tor Access** — Route any SOCKS5-compatible application through Tor
- **Zero Configuration** — Default binds to `127.0.0.1:9050` (Tor standard)
- **Circuit Isolation** — Separate Tor circuits per connection or user
- **Multi-Identity** — Run multiple proxies with different isolation tokens

## Basic Usage

### Rust

```rust
use hypertor::{Socks5Proxy, Result};

#[tokio::main]
async fn main() -> Result<()> {
    // Start SOCKS5 proxy on default address (127.0.0.1:9050)
    let proxy = Socks5Proxy::with_defaults();
    
    println!("SOCKS5 proxy running on 127.0.0.1:9050");
    println!("Press Ctrl+C to stop");
    
    proxy.run().await?;
    Ok(())
}
```

### Custom Configuration

```rust
use hypertor::{Socks5Proxy, ProxyConfig};
use std::net::{IpAddr, Ipv4Addr, SocketAddr};

let config = ProxyConfig {
    bind_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 1080),
    isolation_by_auth: true,  // Different Tor identity per SOCKS auth
    timeout_secs: 120,
};

let proxy = Socks5Proxy::with_config(config);
proxy.run().await?;
```

## Using the Proxy

Once the SOCKS5 proxy is running, you can route any SOCKS5-compatible application through Tor:

### curl

```bash
curl --socks5-hostname 127.0.0.1:9050 https://check.torproject.org/api/ip
```

> **Note**: Use `--socks5-hostname` (not `--socks5`) to resolve DNS through Tor. This prevents DNS leaks.

### wget

```bash
wget -e use_proxy=yes -e http_proxy=socks5://127.0.0.1:9050 https://example.com
```

### Python (requests)

```python
import requests

proxies = {
    'http': 'socks5h://127.0.0.1:9050',
    'https': 'socks5h://127.0.0.1:9050'
}

resp = requests.get('https://check.torproject.org/api/ip', proxies=proxies)
print(f"Tor IP: {resp.json()['IP']}")
```

> **Note**: Use `socks5h://` (with 'h') to resolve DNS through the proxy (Tor). Plain `socks5://` leaks DNS.

### Python (aiohttp)

```python
import aiohttp
import aiohttp_socks

async def fetch_via_tor():
    connector = aiohttp_socks.ProxyConnector.from_url('socks5://127.0.0.1:9050')
    async with aiohttp.ClientSession(connector=connector) as session:
        async with session.get('https://check.torproject.org/api/ip') as resp:
            data = await resp.json()
            print(f"Tor IP: {data['IP']}")
```

### Git

```bash
git config --global http.proxy socks5h://127.0.0.1:9050
git clone https://github.com/example/repo.git
```

### SSH

```bash
ssh -o ProxyCommand='nc -x 127.0.0.1:9050 %h %p' user@host
```

### Firefox/Browsers

1. Settings → Network Settings
2. Manual proxy configuration
3. SOCKS Host: `127.0.0.1`, Port: `9050`
4. SOCKS v5
5. ✅ "Proxy DNS when using SOCKS v5"

## Circuit Isolation

Control how Tor circuits are assigned to connections:

### Per-Connection Isolation

```rust
use hypertor::{Socks5Proxy, ProxyConfig};

// Each connection gets its own Tor circuit (different exit IP)
let proxy = Socks5Proxy::builder()
    .isolation_per_connection(true)
    .build();
```

### Authentication-Based Isolation

```rust
// Different SOCKS auth credentials = different Tor identity
let proxy = Socks5Proxy::builder()
    .isolation_by_auth(true)
    .build();

// Client A: socks5://user1:pass1@127.0.0.1:9050 → Circuit A
// Client B: socks5://user2:pass2@127.0.0.1:9050 → Circuit B
```

### Custom Isolation Tokens

```rust
use hypertor::{Socks5Proxy, IsolationToken};

// Create proxy with custom isolation token
let token = IsolationToken::new();
let proxy = Socks5Proxy::builder()
    .isolation_token(token.clone())
    .build();

// All connections through this proxy share the same Tor circuit
```

## Multi-Identity Proxies

Run multiple SOCKS5 proxies with different identities:

```rust
use hypertor::{Socks5Proxy, IsolationToken};
use std::net::{IpAddr, Ipv4Addr, SocketAddr};

// Proxy 1: Identity for browsing
let proxy1 = Socks5Proxy::builder()
    .bind(SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 9051))
    .isolation_token(IsolationToken::new())
    .build();

// Proxy 2: Identity for API access  
let proxy2 = Socks5Proxy::builder()
    .bind(SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 9052))
    .isolation_token(IsolationToken::new())
    .build();

// Run both
tokio::join!(proxy1.run(), proxy2.run());
```

## Security Considerations

### DNS Leaks

Always use `socks5h://` (with 'h') in clients that support it, or `--socks5-hostname` for curl. This ensures DNS resolution happens through Tor, not locally.

### Local Binding

By default, the proxy binds to `127.0.0.1` (localhost only). If you need to expose it on a network:

```rust
// ⚠️ Exposes Tor proxy to network - use with caution!
let proxy = Socks5Proxy::builder()
    .bind("0.0.0.0:9050".parse()?)
    .build();
```

### Authentication

For network-exposed proxies, enable authentication:

```rust
let proxy = Socks5Proxy::builder()
    .auth("username", "password")
    .build();
```

## Example: Full Application

```rust
use hypertor::{Socks5Proxy, ProxyConfig, Result};
use std::net::{IpAddr, Ipv4Addr, SocketAddr};

#[tokio::main]
async fn main() -> Result<()> {
    // Configure proxy
    let proxy = Socks5Proxy::builder()
        .bind(SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 9050))
        .isolation_by_auth(true)
        .build();
    
    println!("╔════════════════════════════════════════╗");
    println!("║  hypertor SOCKS5 Proxy                ║");
    println!("╠════════════════════════════════════════╣");
    println!("║  Address: 127.0.0.1:9050              ║");
    println!("║  Isolation: Per-authentication        ║");
    println!("╚════════════════════════════════════════╝");
    println!();
    println!("Test with:");
    println!("  curl --socks5-hostname 127.0.0.1:9050 https://check.torproject.org/api/ip");
    
    proxy.run().await?;
    Ok(())
}
```

## Next Steps

- [TorClient Documentation]/docs/client/ — Direct HTTP client API
- [OnionApp Documentation]/docs/server/ — Host your own .onion service
- [Security Features]/docs/security/ — PoW, Vanguards, Leak Detection