Documentation
¶
Overview ¶
Package tornago provides a Tor client/server helper library that can launch tor for development and connect to existing Tor instances in production.
What is Tor? ¶
Tor (The Onion Router) is a network of relays that anonymizes internet traffic by routing connections through multiple encrypted hops. Key concepts:
SocksPort: The SOCKS5 proxy port that applications use to route traffic through Tor. Think of it as the "entrance" to the Tor network for your application's outbound connections.
ControlPort: A text-based management interface for controlling a running Tor instance. Used for operations like rotating circuits (NewIdentity), creating hidden services, and querying Tor's internal state.
Hidden Service (Onion Service): A service accessible only through the Tor network, identified by a .onion address. This allows you to host servers that are both anonymous and accessible without requiring a public IP address or DNS registration.
Circuit: The path your traffic takes through multiple Tor relays. Each circuit typically consists of 3 relays (guard, middle, exit) for outbound connections.
Quick Start ¶
For the simplest use case (making HTTP requests through Tor), you need:
- A running Tor instance (installed via package manager or launched by tornago)
- A Client configured with the Tor SocksPort address
- Use the Client's HTTP() method to get an *http.Client that routes through Tor
See Example_quickStart for a complete minimal example.
Main Use Cases ¶
**Making HTTP requests through Tor** (most common):
- Create a Client pointing to a Tor SocksPort
- Use client.HTTP() to get an *http.Client that routes through Tor
- All HTTP requests automatically go through Tor's anonymizing network
**Launching Tor programmatically** (development/testing):
- Use StartTorDaemon() to launch a tor process managed by your application
- tornago handles port allocation, startup synchronization, and cleanup
- Useful when you don't want to require users to install/configure Tor separately
**Creating Hidden Services** (hosting anonymous servers):
- Use ControlClient.CreateHiddenService() to create a .onion address
- Map your local server port to a virtual onion port
- Your service becomes accessible via Tor without exposing your IP address
**Rotating Tor circuits** (getting a new IP address):
- Use ControlClient.NewIdentity() to signal Tor to build new circuits
- Subsequent requests will use different exit nodes (different public IPs)
- Useful for rate-limiting evasion or additional anonymity
Architecture Overview ¶
tornago provides several components that work together:
- Client: High-level HTTP/TCP client with automatic Tor routing and retry logic
- ControlClient: Low-level interface to Tor's ControlPort for management commands
- TorProcess: Represents a tor daemon launched by StartTorDaemon()
- Server: Simple wrapper for existing Tor instance addresses
- HiddenService: Represents a created .onion service
All configurations use functional options pattern for flexibility and immutability.
API Design Principles ¶
**Method Naming Conventions**
tornago follows a consistent naming convention to distinguish between different types of verification operations:
Check*() methods perform internal health checks and status verification
Check() - Verifies SOCKS and ControlPort connectivity
CheckDNSLeak() - Detects if DNS queries are leaking outside Tor
CheckTorDaemon() - Checks if the Tor process is running properly
These methods are faster but rely on internal heuristics
Verify*() methods use external validation via third-party services
VerifyTorConnection() - Confirms Tor usage via check.torproject.org
These methods are more authoritative but depend on external services
This distinction helps you choose the appropriate method:
- Use Check*() for quick health monitoring and internal validation
- Use Verify*() when you need authoritative external confirmation
Authentication ¶
Tor's ControlPort requires authentication. tornago supports:
- Cookie authentication (default): Tor writes a random cookie file, tornago reads it
- Password authentication: You configure a hashed password in Tor and provide it to tornago
When using StartTorDaemon(), cookie authentication is configured automatically. When connecting to an existing Tor instance, you must provide appropriate credentials.
Error Handling ¶
All tornago errors are wrapped in TornagoError with a Kind field for programmatic handling. Use errors.Is() to check error kinds:
if errors.Is(err, &tornago.TornagoError{Kind: tornago.ErrSocksDialFailed}) {
// Handle connection failure
}
Common error kinds:
- ErrTorBinaryNotFound: tor executable not in PATH (install via package manager)
- ErrSocksDialFailed: Cannot connect to Tor SocksPort (is Tor running?)
- ErrControlRequestFail: ControlPort command failed (check authentication)
- ErrTimeout: Operation exceeded deadline (increase timeout or check network)
Configuration ¶
**Timeout Recommendations**
Tor adds significant latency due to multi-hop routing:
- Dial timeout: 20-30 seconds for production, 30-60 seconds for .onion sites
- Request timeout: 60-120 seconds for typical requests, 120-300 seconds for large downloads
- Startup timeout: 60-120 seconds for first launch, 30-60 seconds with cached state
**Development Environment**
Launch ephemeral Tor daemon for testing:
launchCfg, _ := tornago.NewTorLaunchConfig(
tornago.WithTorSocksAddr(":0"), // Random port
tornago.WithTorControlAddr(":0"),
tornago.WithTorStartupTimeout(60*time.Second),
)
torProcess, _ := tornago.StartTorDaemon(launchCfg)
defer torProcess.Stop()
clientCfg, _ := tornago.NewClientConfig(
tornago.WithClientSocksAddr(torProcess.SocksAddr()),
tornago.WithClientRequestTimeout(30*time.Second),
)
**Production Environment**
Connect to system Tor daemon:
clientCfg, _ := tornago.NewClientConfig(
tornago.WithClientSocksAddr("127.0.0.1:9050"),
tornago.WithClientDialTimeout(30*time.Second),
tornago.WithClientRequestTimeout(120*time.Second),
)
System Tor configuration (/etc/tor/torrc):
SocksPort 127.0.0.1:9050 ControlPort 127.0.0.1:9051 CookieAuthentication 1
**With Metrics and Rate Limiting**
metrics := tornago.NewMetricsCollector()
rateLimiter := tornago.NewRateLimiter(5.0, 10) // 5 req/s, burst 10
clientCfg, _ := tornago.NewClientConfig(
tornago.WithClientSocksAddr("127.0.0.1:9050"),
tornago.WithClientMetrics(metrics),
tornago.WithClientRateLimiter(rateLimiter),
)
// Check metrics
fmt.Printf("Requests: %d, Success: %d, Avg latency: %v\n",
metrics.RequestCount(), metrics.SuccessCount(), metrics.AverageLatency())
**With Observability (Logging and Health Checks)**
// Structured logging
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
slogAdapter := tornago.NewSlogAdapter(logger)
clientCfg, _ := tornago.NewClientConfig(
tornago.WithClientSocksAddr("127.0.0.1:9050"),
tornago.WithClientLogger(slogAdapter),
)
client, _ := tornago.NewClient(clientCfg)
// Health check
health := client.Check(context.Background())
if !health.IsHealthy() {
log.Printf("Client unhealthy: %s", health.Message())
}
**Hidden Service with Persistent Key**
const keyPath = "/var/lib/myapp/onion.pem"
// Try to load existing key
privateKey, err := tornago.LoadPrivateKey(keyPath)
if err != nil {
// First run: create new service
hsCfg, _ := tornago.NewHiddenServiceConfig(
tornago.WithHiddenServicePort(80, 8080),
)
hs, _ := controlClient.CreateHiddenService(ctx, hsCfg)
// Save key for next time
tornago.SavePrivateKey(keyPath, hs.PrivateKey())
os.Chmod(keyPath, 0600)
} else {
// Reuse existing key - same .onion address
hsCfg, _ := tornago.NewHiddenServiceConfig(
tornago.WithHiddenServicePrivateKey(privateKey),
tornago.WithHiddenServicePort(80, 8080),
)
hs, _ := controlClient.CreateHiddenService(ctx, hsCfg)
}
Security Best Practices ¶
**Connection Verification**
Always verify that your application is routing traffic through Tor:
status, err := client.VerifyTorConnection(ctx)
if err != nil {
log.Fatalf("Verification failed: %v", err)
}
if !status.IsUsingTor() {
log.Fatalf("CRITICAL: Traffic is NOT going through Tor!")
}
When to verify:
- On application startup
- After configuration changes
- Periodically in long-running services
- Before handling sensitive operations
**DNS Leak Prevention**
Check if DNS queries are leaking outside Tor:
leakCheck, err := client.CheckDNSLeak(ctx)
if err != nil {
log.Fatalf("DNS leak check failed: %v", err)
}
if leakCheck.HasLeak() {
log.Fatalf("WARNING: DNS leak detected! IPs: %v", leakCheck.ResolvedIPs())
}
DNS leaks reveal which domains you're accessing to your ISP or DNS provider.
**Hidden Service Private Key Management**
Private keys determine your .onion address. Keep them secure:
// File permissions
sudo chmod 600 /var/lib/myapp/onion.pem
sudo chown myapp:myapp /var/lib/myapp/onion.pem
// Encrypted backups
openssl enc -aes-256-cbc -salt \
-in /var/lib/myapp/onion.pem \
-out onion.pem.enc
Best practices:
- Store keys in secure directory with restricted permissions (chmod 600)
- Keep encrypted backups in separate physical location
- Test restoration regularly
- Use SELinux/AppArmor for additional protection
- Monitor key file access with audit logs
**Common Security Pitfalls**
1. Using HTTP instead of HTTPS:
- Exit nodes can see unencrypted HTTP traffic
- Always use HTTPS for end-to-end encryption
2. Leaking metadata:
- Remove identifying headers (User-Agent, X-Forwarded-For)
- Minimize timestamps and other identifying information
3. Circuit reuse correlation:
- Rotate circuits for sensitive operations using NewIdentity()
- Wait 5-10 seconds after rotation for new circuit to build
4. Insufficient timeouts:
- Use minimum 30s dial timeout, 60-120s request timeout
- .onion sites require even longer timeouts (60s+ dial, 120s+ request)
5. Not verifying .onion addresses:
- Hardcode trusted .onion addresses
- Verify addresses through trusted channels to avoid phishing
**Client Authentication for Hidden Services**
Restrict hidden service access to authorized clients:
// Server side
auth := tornago.HiddenServiceAuth{
ClientName: "authorized-client-1",
PublicKey: "descriptor:x25519:AAAA...base64-public-key",
}
hsCfg, _ := tornago.NewHiddenServiceConfig(
tornago.WithHiddenServiceClientAuth(auth),
)
Generate x25519 key pairs:
openssl genpkey -algorithm x25519 -out private.pem openssl pkey -in private.pem -pubout -out public.pem openssl pkey -in public.pem -pubin -outform DER | tail -c 32 | base64
Security benefits:
- Only authorized clients can discover the service
- Protects against descriptor enumeration attacks
- Provides end-to-end authentication
Troubleshooting ¶
**Tor binary not found**
Error: tor_binary_not_found: tor executable not found in PATH Solution: Install Tor via package manager Ubuntu/Debian: sudo apt install tor macOS: brew install tor Verify: tor --version
**Cannot connect to Tor daemon**
Error: control_request_failed: failed to dial ControlPort Solution: Verify Tor is running ps aux | grep tor sudo netstat -tlnp | grep tor Check /etc/tor/torrc for correct SocksPort/ControlPort
**ControlPort authentication failed**
Error: control_auth_failed: AUTHENTICATE failed
Solution: Check authentication method and credentials
For system Tor with cookie auth:
auth, _, _ := tornago.ControlAuthFromTor("127.0.0.1:9051", 30*time.Second)
Verify cookie file permissions:
ls -l /run/tor/control.authcookie
Add user to tor group if needed:
sudo usermod -a -G debian-tor $USER
**Requests timeout**
Error: timeout: context deadline exceeded
Solution: Increase timeouts for slow Tor connections
.onion sites take 5-30 seconds to connect typically
Use longer timeouts:
tornago.WithClientDialTimeout(60*time.Second)
tornago.WithClientRequestTimeout(120*time.Second)
**Hidden Service not accessible**
Symptoms: .onion address times out, local server works Solution: Wait for service to establish (30-60 seconds after creation) Access through Tor Browser or tornago client Verify local service is listening before creating hidden service
**Checking error types**
resp, err := client.Do(req)
if err != nil {
var torErr *tornago.TornagoError
if errors.As(err, &torErr) {
switch torErr.Kind {
case tornago.ErrTimeout:
// Increase timeout
case tornago.ErrSocksDialFailed:
// Check Tor connection
case tornago.ErrHTTPFailed:
// Handle HTTP error
}
}
}
**Testing Tor connection manually**
# Test SOCKS proxy curl --socks5 127.0.0.1:9050 https://check.torproject.org/api/ip # Test .onion access curl --socks5 127.0.0.1:9050 http://your-address.onion
Rate Limiting Recommendations ¶
Tor network capacity is limited. Use appropriate rate limits:
// Conservative (respectful scraping) rateLimiter := tornago.NewRateLimiter(1.0, 3) // 1 req/s, burst 3 // Moderate (general use) rateLimiter := tornago.NewRateLimiter(5.0, 10) // 5 req/s, burst 10 // Aggressive (high volume) rateLimiter := tornago.NewRateLimiter(10.0, 20) // 10 req/s, burst 20
Excessive requests may degrade Tor network performance for everyone.
Environment-Specific Configurations ¶
**CI/CD Testing**
Use fast timeouts and ephemeral instances:
launchCfg, _ := tornago.NewTorLaunchConfig(
tornago.WithTorSocksAddr(":0"),
tornago.WithTorControlAddr(":0"),
tornago.WithTorStartupTimeout(120*time.Second), // CI may be slow
)
**Docker Container**
Mount persistent DataDirectory:
launchCfg, _ := tornago.NewTorLaunchConfig(
tornago.WithTorSocksAddr("127.0.0.1:9050"),
tornago.WithTorControlAddr("127.0.0.1:9051"),
tornago.WithTorDataDirectory("/var/lib/tor"),
)
**High-Availability Service**
Use system Tor with health monitoring:
// Verify Tor availability
auth, _, err := tornago.ControlAuthFromTor("127.0.0.1:9051", 5*time.Second)
if err != nil {
log.Fatal("Tor not available")
}
client, _ := tornago.NewClient(clientCfg)
health := client.Check(ctx)
if !health.IsHealthy() {
log.Fatalf("Tor unhealthy: %s", health.Message())
}
Additional Resources ¶
For working code examples, see the examples/ directory:
- examples/simple_client - Basic HTTP requests through Tor
- examples/onion_client - Accessing .onion sites
- examples/onion_server - Creating Hidden Services
- examples/existing_tor - Connecting to system Tor daemon
- examples/circuit_rotation - Rotating circuits to change exit IP
- examples/error_handling - Proper error handling patterns
- examples/metrics_ratelimit - Metrics collection and rate limiting
- examples/persistent_onion - Hidden Service with persistent key
- examples/observability - Structured logging, metrics, and health checks
- examples/security - Tor connection verification and DNS leak detection
Complete API documentation: https://pkg.go.dev/github.com/nao1215/tornago
Example (Client) ¶
Example_client demonstrates how to create a Tor client configuration for making HTTP requests through the Tor network.
package main
import (
"fmt"
"log"
"github.com/nao1215/tornago"
)
func main() {
// Create a client configuration with default settings
clientCfg, err := tornago.NewClientConfig(
tornago.WithClientSocksAddr("127.0.0.1:9050"), // Use local Tor SOCKS proxy
)
if err != nil {
log.Fatalf("failed to create client config: %v", err)
}
// Create a new Tor client
client, err := tornago.NewClient(clientCfg)
if err != nil {
log.Fatalf("failed to create client: %v", err)
}
defer client.Close()
fmt.Printf("Client configured with SOCKS: %s\n", clientCfg.SocksAddr())
}
Output: Client configured with SOCKS: 127.0.0.1:9050
Example (ClientWithRetry) ¶
Example_clientWithRetry demonstrates how to configure retry behavior for HTTP requests through Tor.
package main
import (
"fmt"
"log"
"time"
"github.com/nao1215/tornago"
)
func main() {
clientCfg, err := tornago.NewClientConfig(
tornago.WithClientSocksAddr("127.0.0.1:9050"),
tornago.WithRetryAttempts(3),
tornago.WithRetryDelay(2*time.Second),
)
if err != nil {
log.Fatalf("failed to create client config: %v", err)
}
client, err := tornago.NewClient(clientCfg)
if err != nil {
log.Fatalf("failed to create client: %v", err)
}
defer client.Close()
fmt.Printf("Client configured with 3 retry attempts and 2s delay\n")
}
Output: Client configured with 3 retry attempts and 2s delay
Example (ConnectToExistingTor) ¶
Example_connectToExistingTor demonstrates connecting to an already-running Tor instance. This is the recommended approach for production environments.
package main
import (
"fmt"
"log"
"github.com/nao1215/tornago"
)
func main() {
// Configure client to connect to a running Tor instance
// (Note: This example shows configuration only; actual connection requires Tor to be running)
clientCfg, err := tornago.NewClientConfig(
tornago.WithClientSocksAddr("127.0.0.1:9050"),
// Optionally configure ControlPort for circuit rotation and hidden services
// tornago.WithClientControlAddr("127.0.0.1:9051"),
// tornago.WithClientControlCookie("/var/lib/tor/control_auth_cookie"),
)
if err != nil {
log.Fatalf("failed to create config: %v", err)
}
// In production, you would create and use the client like this:
// client, err := tornago.NewClient(clientCfg)
// if err != nil {
// log.Fatalf("failed to create client: %v", err)
// }
// defer client.Close()
fmt.Printf("Configured to connect to Tor at %s\n", clientCfg.SocksAddr())
}
Output: Configured to connect to Tor at 127.0.0.1:9050
Example (ControlClient) ¶
Example_controlClient demonstrates how to configure a control client for interacting with a running Tor instance.
package main
import (
"fmt"
"github.com/nao1215/tornago"
)
func main() {
// Create a control client configuration with password authentication
auth := tornago.ControlAuthFromPassword("my-password")
fmt.Printf("Control auth configured with password\n")
_ = auth // Use auth variable
}
Output: Control auth configured with password
Example (ErrorHandling) ¶
Example_errorHandling demonstrates how to handle tornago-specific errors.
package main
import (
"fmt"
)
func main() {
fmt.Println("tornago uses TornagoError with Kind field for error classification")
fmt.Println("Use errors.Is() to check specific error kinds")
fmt.Println("Common kinds: ErrTorBinaryNotFound, ErrSocksDialFailed, ErrTimeout")
}
Output: tornago uses TornagoError with Kind field for error classification Use errors.Is() to check specific error kinds Common kinds: ErrTorBinaryNotFound, ErrSocksDialFailed, ErrTimeout
Example (HiddenService) ¶
Example_hiddenService demonstrates how to configure a Tor hidden service (onion service) that can be accessed via the Tor network.
package main
import (
"fmt"
"log"
"github.com/nao1215/tornago"
)
func main() {
// Configure a hidden service that maps port 80 to local port 8080
hsCfg, err := tornago.NewHiddenServiceConfig(
tornago.WithHiddenServicePort(80, 8080),
)
if err != nil {
log.Fatalf("failed to create hidden service config: %v", err)
}
fmt.Printf("Hidden service configured: virtual port %d -> local port %d\n", 80, 8080)
fmt.Printf("Key type: %s\n", hsCfg.KeyType())
}
Output: Hidden service configured: virtual port 80 -> local port 8080 Key type: ED25519-V3
Example (HiddenServiceWithAuth) ¶
Example_hiddenServiceWithAuth demonstrates how to create a hidden service with client authorization for restricted access.
package main
import (
"fmt"
"log"
"github.com/nao1215/tornago"
)
func main() {
// Configure hidden service with client authorization
auth := tornago.NewHiddenServiceAuth("alice", "descriptor:x25519:ABCDEF1234567890")
_, err := tornago.NewHiddenServiceConfig(
tornago.WithHiddenServicePort(80, 8080),
tornago.WithHiddenServiceClientAuth(auth),
)
if err != nil {
log.Fatalf("failed to create config: %v", err)
}
fmt.Printf("Configured hidden service with auth for: %s\n", auth.ClientName())
}
Output: Configured hidden service with auth for: alice
Example (LaunchAndUse) ¶
Example_launchAndUse demonstrates launching a Tor daemon and using it for HTTP requests. This is useful when you want your application to manage its own Tor instance.
package main
import (
"fmt"
"log"
"time"
"github.com/nao1215/tornago"
)
func main() {
// Launch a Tor daemon with automatic port selection
launchCfg, err := tornago.NewTorLaunchConfig(
tornago.WithTorSocksAddr(":0"), // Let Tor pick a free port
tornago.WithTorControlAddr(":0"), // Let Tor pick a free port
tornago.WithTorStartupTimeout(time.Minute),
)
if err != nil {
log.Fatalf("failed to create launch config: %v", err)
}
// StartTorDaemon blocks until Tor is ready to accept connections
// (Note: This example doesn't actually start Tor to keep tests fast)
// torProc, err := tornago.StartTorDaemon(launchCfg)
// if err != nil {
// log.Fatalf("failed to start tor: %v", err)
// }
// defer torProc.Stop()
// Create a client using the launched Tor instance
// clientCfg, err := tornago.NewClientConfig(
// tornago.WithClientSocksAddr(torProc.SocksAddr()),
// )
// client, err := tornago.NewClient(clientCfg)
fmt.Printf("Configured to launch Tor with timeout: %v\n", launchCfg.StartupTimeout())
}
Output: Configured to launch Tor with timeout: 1m0s
Example (NewIdentity) ¶
Example_newIdentity demonstrates the concept of requesting a new Tor identity. In practice, you would call client.NewIdentity(ctx) on an authenticated control client to rotate circuits and get a new IP address.
package main
import (
"fmt"
)
func main() {
fmt.Println("To request a new identity, use client.NewIdentity(ctx)")
}
Output: To request a new identity, use client.NewIdentity(ctx)
Example (QuickStart) ¶
Example_quickStart demonstrates the simplest way to make HTTP requests through Tor. This example assumes you have Tor running locally on the default port (9050). To install Tor: apt-get install tor (Ubuntu), brew install tor (macOS), or choco install tor (Windows).
package main
import (
"fmt"
"log"
"github.com/nao1215/tornago"
)
func main() {
// Create a client that uses your local Tor instance
clientCfg, err := tornago.NewClientConfig(
tornago.WithClientSocksAddr("127.0.0.1:9050"),
)
if err != nil {
log.Fatalf("failed to create config: %v", err)
}
client, err := tornago.NewClient(clientCfg)
if err != nil {
log.Fatalf("failed to create client: %v", err)
}
defer client.Close()
// Get the HTTP client and use it like any http.Client
// All requests automatically go through Tor
httpClient := client.HTTP()
_ = httpClient // Use for http.Get, http.Post, etc.
fmt.Println("HTTP client ready to make requests through Tor")
}
Output: HTTP client ready to make requests through Tor
Example (RotateCircuit) ¶
Example_rotateCircuit demonstrates how to request a new Tor identity (new exit node/IP).
package main
import (
"fmt"
)
func main() {
// This example shows the concept; actual execution requires a running Tor instance
fmt.Println("To rotate circuits:")
fmt.Println("1. Create a Client with ControlAddr configured")
fmt.Println("2. Call client.Control().NewIdentity(ctx)")
fmt.Println("3. Subsequent requests use new circuits with different exit IPs")
}
Output: To rotate circuits: 1. Create a Client with ControlAddr configured 2. Call client.Control().NewIdentity(ctx) 3. Subsequent requests use new circuits with different exit IPs
Example (Server) ¶
Example_server demonstrates how to start a Tor server that can host hidden services and handle incoming connections.
package main
import (
"fmt"
"log"
"github.com/nao1215/tornago"
)
func main() {
// Create server configuration
serverCfg, err := tornago.NewServerConfig(
tornago.WithServerSocksAddr("127.0.0.1:9050"),
tornago.WithServerControlAddr("127.0.0.1:9051"),
)
if err != nil {
log.Fatalf("failed to create server config: %v", err)
}
// Create a server instance
server, err := tornago.NewServer(serverCfg)
if err != nil {
log.Fatalf("failed to create server: %v", err)
}
fmt.Printf("Tor server configured with SOCKS: %s, Control: %s\n",
server.SocksAddr(), server.ControlAddr())
}
Output: Tor server configured with SOCKS: 127.0.0.1:9050, Control: 127.0.0.1:9051
Example (StartTorDaemon) ¶
Example_startTorDaemon demonstrates how to configure a Tor daemon launch configuration with custom settings.
package main
import (
"fmt"
"log"
"time"
"github.com/nao1215/tornago"
)
func main() {
// Create launch configuration with custom settings
launchCfg, err := tornago.NewTorLaunchConfig(
tornago.WithTorSocksAddr("127.0.0.1:9050"),
tornago.WithTorControlAddr("127.0.0.1:9051"),
tornago.WithTorStartupTimeout(2*time.Minute),
)
if err != nil {
log.Fatalf("failed to create launch config: %v", err)
}
fmt.Printf("Tor daemon configured with SOCKS: %s, Control: %s\n",
launchCfg.SocksAddr(), launchCfg.ControlAddr())
}
Output: Tor daemon configured with SOCKS: 127.0.0.1:9050, Control: 127.0.0.1:9051
Index ¶
- Constants
- func As(err error, target any) bool
- func LoadPrivateKey(path string) (string, error)
- func WaitForControlPort(controlAddr string, timeout time.Duration) error
- type CircuitInfo
- type CircuitManager
- func (m *CircuitManager) IsRunning() bool
- func (m *CircuitManager) PerformanceTracker() *RelayPerformanceTracker
- func (m *CircuitManager) PrewarmCircuits(ctx context.Context) error
- func (m *CircuitManager) RotateNow(ctx context.Context) error
- func (m *CircuitManager) StartAutoRotation(ctx context.Context, interval time.Duration) error
- func (m *CircuitManager) StartPerformanceMonitor(ctx context.Context, interval time.Duration) error
- func (m *CircuitManager) Stats() CircuitStats
- func (m *CircuitManager) Stop()
- func (m *CircuitManager) StopPerformanceMonitor()
- func (m *CircuitManager) WithLogger(logger Logger) *CircuitManager
- func (m *CircuitManager) WithPerformanceTracker(tracker *RelayPerformanceTracker) *CircuitManager
- type CircuitStats
- type Client
- func (c *Client) Check(ctx context.Context) HealthCheck
- func (c *Client) CheckDNSLeak(ctx context.Context) (DNSLeakCheck, error)
- func (c *Client) Close() error
- func (c *Client) Control() *ControlClient
- func (c *Client) Dial(network, addr string) (net.Conn, error)
- func (c *Client) DialContext(ctx context.Context, network, addr string) (net.Conn, error)
- func (c *Client) Dialer() func(ctx context.Context, network, addr string) (net.Conn, error)
- func (c *Client) Do(req *http.Request) (*http.Response, error)
- func (c *Client) HTTP() *http.Client
- func (c *Client) Listen(ctx context.Context, virtualPort, localPort int) (*TorListener, error)
- func (c *Client) ListenWithConfig(ctx context.Context, hsCfg HiddenServiceConfig, localPort int) (*TorListener, error)
- func (c *Client) Metrics() *MetricsCollector
- func (c *Client) RelayPerformanceStats() (RelayPerformanceStats, bool)
- func (c *Client) VerifyTorConnection(ctx context.Context) (TorConnectionStatus, error)
- type ClientConfig
- func (c ClientConfig) ControlAddr() string
- func (c ClientConfig) ControlAuth() ControlAuth
- func (c ClientConfig) DialTimeout() time.Duration
- func (c ClientConfig) Logger() Logger
- func (c ClientConfig) Metrics() *MetricsCollector
- func (c ClientConfig) PerformanceTracker() *RelayPerformanceTracker
- func (c ClientConfig) RateLimiter() *RateLimiter
- func (c ClientConfig) RequestTimeout() time.Duration
- func (c ClientConfig) RetryAttempts() uint
- func (c ClientConfig) RetryDelay() time.Duration
- func (c ClientConfig) RetryMaxDelay() time.Duration
- func (c ClientConfig) RetryOnError() func(error) bool
- func (c ClientConfig) SlowRelayAvoidanceEnabled() bool
- func (c ClientConfig) SlowRelayOptions() []SlowRelayOption
- func (c ClientConfig) SocksAddr() string
- type ClientOption
- func WithClientControlAddr(addr string) ClientOption
- func WithClientControlCookie(path string) ClientOption
- func WithClientControlCookieBytes(data []byte) ClientOption
- func WithClientControlPassword(password string) ClientOption
- func WithClientDialTimeout(timeout time.Duration) ClientOption
- func WithClientLogger(logger Logger) ClientOption
- func WithClientMetrics(m *MetricsCollector) ClientOption
- func WithClientPerformanceTracker(tracker *RelayPerformanceTracker) ClientOption
- func WithClientRateLimiter(r *RateLimiter) ClientOption
- func WithClientRequestTimeout(timeout time.Duration) ClientOption
- func WithClientSocksAddr(addr string) ClientOption
- func WithRetryAttempts(attempts uint) ClientOption
- func WithRetryDelay(delay time.Duration) ClientOption
- func WithRetryMaxDelay(delay time.Duration) ClientOption
- func WithRetryOnError(fn func(error) bool) ClientOption
- func WithSlowRelayAvoidance(opts ...SlowRelayOption) ClientOption
- type ControlAuth
- type ControlClient
- func (c *ControlClient) Authenticate() error
- func (c *ControlClient) ClearExcludeNodes(ctx context.Context) error
- func (c *ControlClient) Close() error
- func (c *ControlClient) CreateHiddenService(ctx context.Context, cfg HiddenServiceConfig) (HiddenService, error)
- func (c *ControlClient) ExcludeNodes(ctx context.Context, fingerprints []string) error
- func (c *ControlClient) GetCircuitStatus(ctx context.Context) ([]CircuitInfo, error)
- func (c *ControlClient) GetConf(ctx context.Context, key string) (string, error)
- func (c *ControlClient) GetHiddenServiceStatus(ctx context.Context) ([]HiddenServiceStatus, error)
- func (c *ControlClient) GetInfo(ctx context.Context, key string) (string, error)
- func (c *ControlClient) GetInfoNoAuth(ctx context.Context, key string) (string, error)
- func (c *ControlClient) GetStreamStatus(ctx context.Context) ([]StreamInfo, error)
- func (c *ControlClient) MapAddress(ctx context.Context, fromAddr, toAddr string) (string, error)
- func (c *ControlClient) NewIdentity(ctx context.Context) error
- func (c *ControlClient) ResetConf(ctx context.Context, key string) error
- func (c *ControlClient) SaveConf(ctx context.Context) error
- func (c *ControlClient) SetConf(ctx context.Context, key, value string) error
- type DNSLeakCheck
- type ErrorKind
- type HealthCheck
- func (h HealthCheck) IsDegraded() bool
- func (h HealthCheck) IsHealthy() bool
- func (h HealthCheck) IsUnhealthy() bool
- func (h HealthCheck) Latency() time.Duration
- func (h HealthCheck) Message() string
- func (h HealthCheck) Status() HealthStatus
- func (h HealthCheck) String() string
- func (h HealthCheck) Timestamp() time.Time
- type HealthStatus
- type HiddenService
- type HiddenServiceAuth
- type HiddenServiceConfig
- type HiddenServiceOption
- func WithHiddenServiceClientAuth(auth ...HiddenServiceAuth) HiddenServiceOption
- func WithHiddenServiceHTTP(localPort int) HiddenServiceOption
- func WithHiddenServiceHTTPS(localPort int) HiddenServiceOption
- func WithHiddenServiceKeyType(keyType string) HiddenServiceOption
- func WithHiddenServicePort(virtualPort, targetPort int) HiddenServiceOption
- func WithHiddenServicePorts(ports map[int]int) HiddenServiceOption
- func WithHiddenServicePrivateKey(privateKey string) HiddenServiceOption
- func WithHiddenServicePrivateKeyFile(path string) HiddenServiceOption
- func WithHiddenServiceSamePort(port int) HiddenServiceOption
- type HiddenServiceStatus
- type Latency
- type Logger
- type Metrics
- type MetricsCollector
- func (m *MetricsCollector) AverageLatency() time.Duration
- func (m *MetricsCollector) ConnectionReuseCount() uint64
- func (m *MetricsCollector) ConnectionReuseRate() float64
- func (m *MetricsCollector) DialCount() uint64
- func (m *MetricsCollector) ErrorCount() uint64
- func (m *MetricsCollector) ErrorsByKind() map[ErrorKind]uint64
- func (m *MetricsCollector) MaxLatency() time.Duration
- func (m *MetricsCollector) MinLatency() time.Duration
- func (m *MetricsCollector) RequestCount() uint64
- func (m *MetricsCollector) Reset()
- func (m *MetricsCollector) SuccessCount() uint64
- func (m *MetricsCollector) TotalLatency() time.Duration
- type OnionAddr
- type RateLimiter
- type RelayFingerprint
- type RelayMeasurement
- type RelayPerformanceStats
- type RelayPerformanceTracker
- func (t *RelayPerformanceTracker) BlockedRelays() []RelayFingerprint
- func (t *RelayPerformanceTracker) Clear()
- func (t *RelayPerformanceTracker) ClearExcludeNodes(ctx context.Context) error
- func (t *RelayPerformanceTracker) GetStats(fingerprint RelayFingerprint) *RelayStats
- func (t *RelayPerformanceTracker) IsBlocked(fingerprint RelayFingerprint) bool
- func (t *RelayPerformanceTracker) RecordCircuitMeasurement(path []string, latency time.Duration, success bool)
- func (t *RelayPerformanceTracker) RecordMeasurement(fingerprint RelayFingerprint, latency time.Duration, success bool)
- func (t *RelayPerformanceTracker) Stats() TrackerStats
- type RelayStats
- type RelayThreshold
- func (t RelayThreshold) BlockDuration() time.Duration
- func (t RelayThreshold) MaxLatency() Latency
- func (t RelayThreshold) MinSamples() int
- func (t RelayThreshold) MinSuccessRate() SuccessRate
- func (t RelayThreshold) WithBlockDuration(d time.Duration) RelayThreshold
- func (t RelayThreshold) WithMaxLatency(d time.Duration) RelayThreshold
- func (t RelayThreshold) WithMinSamples(n int) RelayThreshold
- func (t RelayThreshold) WithMinSuccessRate(rate float64) RelayThreshold
- type RelayThresholdStats
- type RelayTrackerOption
- func WithTrackerAutoExclude(enabled bool) RelayTrackerOption
- func WithTrackerControl(control *ControlClient) RelayTrackerOption
- func WithTrackerLogger(logger Logger) RelayTrackerOption
- func WithTrackerMeasureWindow(d time.Duration) RelayTrackerOption
- func WithTrackerThreshold(threshold RelayThreshold) RelayTrackerOption
- type Server
- type ServerConfig
- type ServerOption
- type SlowRelayOption
- func SlowRelayAutoExclude(enabled bool) SlowRelayOption
- func SlowRelayBlockDuration(d time.Duration) SlowRelayOption
- func SlowRelayMaxLatency(d time.Duration) SlowRelayOption
- func SlowRelayMinSamples(n int) SlowRelayOption
- func SlowRelayMinSuccessRate(rate float64) SlowRelayOption
- func SlowRelayMonitorInterval(d time.Duration) SlowRelayOption
- type StreamInfo
- type SuccessRate
- type TestServer
- type TorConnectionStatus
- type TorLaunchConfig
- func (c TorLaunchConfig) ControlAddr() string
- func (c TorLaunchConfig) DataDir() string
- func (c TorLaunchConfig) ExtraArgs() []string
- func (c TorLaunchConfig) LogReporter() func(string)
- func (c TorLaunchConfig) Logger() Logger
- func (c TorLaunchConfig) SocksAddr() string
- func (c TorLaunchConfig) StartupTimeout() time.Duration
- func (c TorLaunchConfig) TorBinary() string
- func (c TorLaunchConfig) TorConfigFile() string
- type TorLaunchOption
- func WithTorBinary(path string) TorLaunchOption
- func WithTorConfigFile(path string) TorLaunchOption
- func WithTorControlAddr(addr string) TorLaunchOption
- func WithTorDataDir(path string) TorLaunchOption
- func WithTorExtraArgs(args ...string) TorLaunchOption
- func WithTorLogReporter(fn func(string)) TorLaunchOption
- func WithTorLogger(logger Logger) TorLaunchOption
- func WithTorSocksAddr(addr string) TorLaunchOption
- func WithTorStartupTimeout(timeout time.Duration) TorLaunchOption
- type TorListener
- type TorProcess
- type TornagoError
- type TrackerStats
Examples ¶
- Package (Client)
- Package (ClientWithRetry)
- Package (ConnectToExistingTor)
- Package (ControlClient)
- Package (ErrorHandling)
- Package (HiddenService)
- Package (HiddenServiceWithAuth)
- Package (LaunchAndUse)
- Package (NewIdentity)
- Package (QuickStart)
- Package (RotateCircuit)
- Package (Server)
- Package (StartTorDaemon)
Constants ¶
const (
// CircuitStatusBuilt indicates a circuit has been fully established.
CircuitStatusBuilt = "BUILT"
)
Variables ¶
This section is empty.
Functions ¶
func LoadPrivateKey ¶ added in v0.2.0
LoadPrivateKey reads a private key from a file and returns it as a string suitable for use with WithHiddenServicePrivateKey.
Example:
key, _ := tornago.LoadPrivateKey("/path/to/key")
cfg, _ := tornago.NewHiddenServiceConfig(
tornago.WithHiddenServicePrivateKey(key),
tornago.WithHiddenServicePort(80, 8080),
)
func WaitForControlPort ¶
WaitForControlPort waits until Tor's control port is usable. Tor may accept TCP connections before it can respond to PROTOCOLINFO, because the cookie might not be created yet. This function verifies that PROTOCOLINFO succeeds AND the cookie file exists before returning.
Types ¶
type CircuitInfo ¶ added in v0.2.0
type CircuitInfo struct {
// ID is the circuit identifier.
ID string
// Status is the circuit status (e.g., "BUILT", "EXTENDED", "LAUNCHED").
Status string
// Path is the list of relay fingerprints in the circuit.
Path []string
// BuildFlags contains circuit build flags.
BuildFlags []string
// Purpose is the circuit purpose (e.g., "GENERAL", "HS_CLIENT_INTRO").
Purpose string
// TimeCreated is when the circuit was created.
TimeCreated string
}
CircuitInfo represents information about a Tor circuit.
type CircuitManager ¶ added in v0.3.0
type CircuitManager struct {
// contains filtered or unexported fields
}
CircuitManager manages Tor circuits with advanced features like automatic rotation, circuit prewarming, and per-site circuit isolation.
Circuit management is useful for:
- Automatic IP rotation on a schedule
- Pre-building circuits before they're needed (prewarming)
- Isolating circuits for specific destinations (privacy)
- Recovering from circuit failures
Example usage:
manager := tornago.NewCircuitManager(controlClient) manager.StartAutoRotation(ctx, 10*time.Minute) // Rotate every 10 minutes defer manager.Stop()
func NewCircuitManager ¶ added in v0.3.0
func NewCircuitManager(control *ControlClient) *CircuitManager
NewCircuitManager creates a new CircuitManager with the given ControlClient.
func (*CircuitManager) IsRunning ¶ added in v0.3.0
func (m *CircuitManager) IsRunning() bool
IsRunning returns true if automatic rotation is currently active.
func (*CircuitManager) PerformanceTracker ¶ added in v0.4.0
func (m *CircuitManager) PerformanceTracker() *RelayPerformanceTracker
PerformanceTracker returns the configured RelayPerformanceTracker, or nil if not set.
func (*CircuitManager) PrewarmCircuits ¶ added in v0.3.0
func (m *CircuitManager) PrewarmCircuits(ctx context.Context) error
PrewarmCircuits builds new circuits in advance to reduce latency for future requests. This calls NewIdentity() to signal Tor to build fresh circuits.
Prewarming is useful before:
- Starting a batch of requests
- After a long idle period
- When you know you'll need fresh circuits soon
After calling this, wait a few seconds (5-10s) for Tor to build new circuits before making requests.
func (*CircuitManager) RotateNow ¶ added in v0.3.0
func (m *CircuitManager) RotateNow(ctx context.Context) error
RotateNow immediately rotates circuits by calling NewIdentity(). This is useful for manual circuit rotation outside of the automatic schedule.
func (*CircuitManager) StartAutoRotation ¶ added in v0.3.0
StartAutoRotation begins automatic circuit rotation at the specified interval. Circuits will be rotated by calling NewIdentity() at regular intervals.
This is useful for:
- Changing exit IPs periodically for privacy
- Avoiding rate limiting by rotating IPs
- Refreshing circuits that may have become slow
The rotation continues until Stop() is called or the context is canceled.
Example:
manager.StartAutoRotation(ctx, 10*time.Minute) // Circuits rotate every 10 minutes
func (*CircuitManager) StartPerformanceMonitor ¶ added in v0.4.0
StartPerformanceMonitor begins monitoring circuit performance and rotating slow circuits. This requires a RelayPerformanceTracker to be set via WithPerformanceTracker.
The monitor periodically checks circuit latency and rotates circuits that use slow relays. This is useful for:
- Automatically avoiding slow Tor relays
- Maintaining consistent performance
- Adapting to network conditions
Example:
tracker := tornago.NewRelayPerformanceTracker() manager.WithPerformanceTracker(tracker) manager.StartPerformanceMonitor(ctx, 30*time.Second)
func (*CircuitManager) Stats ¶ added in v0.3.0
func (m *CircuitManager) Stats() CircuitStats
Stats returns current statistics about circuit management.
func (*CircuitManager) Stop ¶ added in v0.3.0
func (m *CircuitManager) Stop()
Stop stops automatic circuit rotation if it's running.
func (*CircuitManager) StopPerformanceMonitor ¶ added in v0.4.0
func (m *CircuitManager) StopPerformanceMonitor()
StopPerformanceMonitor stops the performance monitor if running.
func (*CircuitManager) WithLogger ¶ added in v0.3.0
func (m *CircuitManager) WithLogger(logger Logger) *CircuitManager
WithLogger sets a logger for circuit management operations.
func (*CircuitManager) WithPerformanceTracker ¶ added in v0.4.0
func (m *CircuitManager) WithPerformanceTracker(tracker *RelayPerformanceTracker) *CircuitManager
WithPerformanceTracker sets a RelayPerformanceTracker for slow relay avoidance. When set, the CircuitManager will monitor circuit performance and automatically rotate circuits that use slow relays.
type CircuitStats ¶ added in v0.3.0
type CircuitStats struct {
// AutoRotationEnabled indicates if automatic rotation is running.
AutoRotationEnabled bool
// RotationInterval is the configured rotation interval (0 if not running).
RotationInterval time.Duration
// PerformanceMonitorEnabled indicates if performance monitoring is running.
PerformanceMonitorEnabled bool
// PerformanceMonitorInterval is the configured performance monitor interval.
PerformanceMonitorInterval time.Duration
}
CircuitStats provides statistics about circuit management operations.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client bundles HTTP/TCP over Tor along with optional ControlPort access. It rewrites Dial/HTTP operations to go through Tor's SOCKS5 proxy and automatically retries failures based on ClientConfig.
Client is the main entry point for making HTTP requests or TCP connections through Tor. It handles:
- Automatic SOCKS5 proxying through Tor's SocksPort
- Exponential backoff retry logic for failed requests
- Optional ControlPort access for circuit rotation and hidden services
- Thread-safe operation for concurrent requests
Example usage:
cfg, _ := tornago.NewClientConfig(
tornago.WithClientSocksAddr("127.0.0.1:9050"),
)
client, _ := tornago.NewClient(cfg)
defer client.Close()
// Make HTTP requests through Tor
resp, err := client.HTTP().Get("https://check.torproject.org")
// Make raw TCP connections through Tor
conn, err := client.Dial("tcp", "example.onion:80")
func NewClient ¶
func NewClient(cfg ClientConfig) (*Client, error)
NewClient builds a Client that routes traffic through the configured Tor server. The client is ready to use immediately after creation - all connections will automatically be routed through Tor's SOCKS5 proxy.
If cfg includes a ControlAddr, the client will also connect to Tor's ControlPort for management operations (e.g., circuit rotation, hidden service creation).
Always call Close() when done to clean up resources.
func NewDefaultClient ¶ added in v0.3.0
NewDefaultClient creates a Client with default settings for connecting to a local Tor daemon running on localhost:9050 (the default Tor SOCKS port).
This is a convenience function equivalent to:
cfg, _ := tornago.NewClientConfig() client, _ := tornago.NewClient(cfg)
For custom configuration (timeouts, control port, metrics, etc.), use NewClient with a custom ClientConfig instead.
Example:
client, err := tornago.NewDefaultClient()
if err != nil {
log.Fatal(err)
}
defer client.Close()
resp, err := client.HTTP().Get("https://check.torproject.org")
func (*Client) Check ¶ added in v0.3.0
func (c *Client) Check(ctx context.Context) HealthCheck
Check performs a health check on the Tor connection. It verifies that:
- SOCKS proxy is reachable
- ControlPort is accessible (if configured)
- Authentication is valid (if configured)
The check includes a timeout to prevent hanging on unresponsive services.
Example:
client, _ := tornago.NewClient(cfg)
health := client.Check(context.Background())
if !health.IsHealthy() {
log.Printf("Tor unhealthy: %s", health.Message())
}
func (*Client) CheckDNSLeak ¶ added in v0.3.0
func (c *Client) CheckDNSLeak(ctx context.Context) (DNSLeakCheck, error)
CheckDNSLeak verifies that DNS queries are going through Tor and not leaking to your local DNS resolver. It does this by resolving a hostname through the Tor SOCKS proxy and comparing it with what Tor's DNS resolution returns.
DNS leaks occur when your system's DNS resolver is used instead of Tor's, potentially revealing which domains you're accessing to your ISP or DNS provider.
This check resolves "check.torproject.org" through Tor and verifies the result.
Example:
client, _ := tornago.NewClient(cfg)
leakCheck, err := client.CheckDNSLeak(context.Background())
if err != nil {
log.Fatalf("DNS leak check failed: %v", err)
}
if leakCheck.HasLeak {
log.Printf("WARNING: DNS leak detected! IPs: %v", leakCheck.ResolvedIPs)
}
func (*Client) Close ¶
Close closes the ControlClient and underlying HTTP transport resources. If slow relay avoidance is enabled, the background monitor is also stopped.
func (*Client) Control ¶
func (c *Client) Control() *ControlClient
Control returns the ControlClient, which may be nil if ControlAddr was empty.
func (*Client) Dial ¶
Dial establishes a TCP connection via Tor's SOCKS5 proxy. This is equivalent to DialContext with context.Background().
func (*Client) DialContext ¶ added in v0.2.0
DialContext establishes a TCP connection via Tor's SOCKS5 proxy with context support. The context can be used for cancellation and deadlines.
func (*Client) Dialer ¶ added in v0.2.0
Dialer returns a net.Dialer-compatible function that routes connections through Tor. This can be used with libraries that accept a custom dial function.
Example:
dialer := client.Dialer() conn, err := dialer(ctx, "tcp", "example.onion:80")
func (*Client) Listen ¶ added in v0.2.0
Listen creates a TorListener that exposes a local TCP listener as a Tor Hidden Service. The virtualPort is the port exposed on the .onion address, and localPort is the local port that accepts connections.
This method requires a ControlClient to be configured (via WithClientControlAddr).
Example:
client, _ := tornago.NewClient(cfg)
listener, _ := client.Listen(ctx, 80, 8080) // onion:80 -> local:8080
defer listener.Close()
fmt.Printf("Listening at: %s\n", listener.OnionAddress())
for {
conn, _ := listener.Accept()
go handleConnection(conn)
}
func (*Client) ListenWithConfig ¶ added in v0.2.0
func (c *Client) ListenWithConfig(ctx context.Context, hsCfg HiddenServiceConfig, localPort int) (*TorListener, error)
ListenWithConfig creates a TorListener using a custom HiddenServiceConfig. This allows for advanced configurations like persistent keys or client authorization.
The HiddenServiceConfig must have exactly one port mapping, and its target port must match the localPort parameter.
Example:
hsCfg, _ := tornago.NewHiddenServiceConfig(
tornago.WithHiddenServicePrivateKey(savedKey),
tornago.WithHiddenServicePort(80, 8080),
)
listener, _ := client.ListenWithConfig(ctx, hsCfg, 8080)
func (*Client) Metrics ¶ added in v0.2.0
func (c *Client) Metrics() *MetricsCollector
Metrics returns the metrics collector, which may be nil if not configured.
func (*Client) RelayPerformanceStats ¶ added in v0.4.0
func (c *Client) RelayPerformanceStats() (RelayPerformanceStats, bool)
RelayPerformanceStats returns statistics about relay performance tracking. The second return value indicates whether slow relay avoidance is enabled. If not enabled, returns a zero-value RelayPerformanceStats and false.
The returned struct is a copy and can be safely modified without affecting internal state.
Example:
stats, ok := client.RelayPerformanceStats()
if ok {
fmt.Printf("Tracked: %d, Blocked: %d\n", stats.TrackedRelays, stats.BlockedRelays)
}
func (*Client) VerifyTorConnection ¶ added in v0.3.0
func (c *Client) VerifyTorConnection(ctx context.Context) (TorConnectionStatus, error)
VerifyTorConnection checks if the client is actually routing traffic through Tor by connecting to check.torproject.org. This service returns whether the connection came from a known Tor exit node.
This is useful for:
- Verifying Tor configuration is working correctly
- Detecting if traffic is leaking outside Tor
- Getting the current exit node IP address
Example:
client, _ := tornago.NewClient(cfg)
status, err := client.VerifyTorConnection(context.Background())
if err != nil {
log.Fatalf("Verification failed: %v", err)
}
if !status.UsingTor {
log.Printf("WARNING: Not using Tor! Exit IP: %s", status.ExitIP)
}
type ClientConfig ¶
type ClientConfig struct {
// contains filtered or unexported fields
}
ClientConfig bundles all knobs for creating a Client. It is immutable after construction via NewClientConfig.
func NewClientConfig ¶
func NewClientConfig(opts ...ClientOption) (ClientConfig, error)
NewClientConfig returns a validated, immutable client config.
func (ClientConfig) ControlAddr ¶
func (c ClientConfig) ControlAddr() string
ControlAddr is the ControlPort address used for optional control commands.
func (ClientConfig) ControlAuth ¶
func (c ClientConfig) ControlAuth() ControlAuth
ControlAuth carries credentials for the ControlPort.
func (ClientConfig) DialTimeout ¶
func (c ClientConfig) DialTimeout() time.Duration
DialTimeout is the timeout for establishing TCP connections via SOCKS5.
func (ClientConfig) Logger ¶ added in v0.3.0
func (c ClientConfig) Logger() Logger
Logger returns the optional logger instance.
func (ClientConfig) Metrics ¶ added in v0.2.0
func (c ClientConfig) Metrics() *MetricsCollector
Metrics returns the optional metrics collector.
func (ClientConfig) PerformanceTracker ¶ added in v0.4.0
func (c ClientConfig) PerformanceTracker() *RelayPerformanceTracker
PerformanceTracker returns the optional relay performance tracker.
func (ClientConfig) RateLimiter ¶ added in v0.2.0
func (c ClientConfig) RateLimiter() *RateLimiter
RateLimiter returns the optional rate limiter.
func (ClientConfig) RequestTimeout ¶
func (c ClientConfig) RequestTimeout() time.Duration
RequestTimeout sets the overall timeout for HTTP requests.
func (ClientConfig) RetryAttempts ¶
func (c ClientConfig) RetryAttempts() uint
RetryAttempts is the maximum number of retries when RetryOnError returns true.
func (ClientConfig) RetryDelay ¶
func (c ClientConfig) RetryDelay() time.Duration
RetryDelay is the initial backoff delay used by retry-go.
func (ClientConfig) RetryMaxDelay ¶
func (c ClientConfig) RetryMaxDelay() time.Duration
RetryMaxDelay caps backoff delay used by retry-go.
func (ClientConfig) RetryOnError ¶
func (c ClientConfig) RetryOnError() func(error) bool
RetryOnError decides whether an error should trigger a retry.
func (ClientConfig) SlowRelayAvoidanceEnabled ¶ added in v0.4.0
func (c ClientConfig) SlowRelayAvoidanceEnabled() bool
SlowRelayAvoidanceEnabled returns whether slow relay avoidance is enabled.
func (ClientConfig) SlowRelayOptions ¶ added in v0.4.0
func (c ClientConfig) SlowRelayOptions() []SlowRelayOption
SlowRelayOptions returns the options for slow relay avoidance.
func (ClientConfig) SocksAddr ¶
func (c ClientConfig) SocksAddr() string
SocksAddr is the target SocksPort address used for outbound traffic.
type ClientOption ¶
type ClientOption func(*ClientConfig)
ClientOption customizes ClientConfig creation.
func WithClientControlAddr ¶
func WithClientControlAddr(addr string) ClientOption
WithClientControlAddr sets the ControlPort address for the client.
func WithClientControlCookie ¶
func WithClientControlCookie(path string) ClientOption
WithClientControlCookie sets cookie-based ControlPort authentication.
func WithClientControlCookieBytes ¶ added in v0.2.0
func WithClientControlCookieBytes(data []byte) ClientOption
WithClientControlCookieBytes sets cookie-based ControlPort authentication using raw cookie bytes.
func WithClientControlPassword ¶
func WithClientControlPassword(password string) ClientOption
WithClientControlPassword sets password-based ControlPort authentication.
func WithClientDialTimeout ¶
func WithClientDialTimeout(timeout time.Duration) ClientOption
WithClientDialTimeout sets the timeout for dialing via SOCKS5.
func WithClientLogger ¶ added in v0.3.0
func WithClientLogger(logger Logger) ClientOption
WithClientLogger sets a structured logger for debugging and monitoring.
Example with slog:
logger := slog.New(slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{
Level: slog.LevelDebug,
}))
cfg, _ := tornago.NewClientConfig(
tornago.WithClientSocksAddr("127.0.0.1:9050"),
tornago.WithClientLogger(tornago.NewSlogAdapter(logger)),
)
func WithClientMetrics ¶ added in v0.2.0
func WithClientMetrics(m *MetricsCollector) ClientOption
WithClientMetrics sets the metrics collector for the client.
func WithClientPerformanceTracker ¶ added in v0.4.0
func WithClientPerformanceTracker(tracker *RelayPerformanceTracker) ClientOption
WithClientPerformanceTracker sets a RelayPerformanceTracker for slow relay avoidance. When set, the client can automatically track relay performance and avoid slow relays.
Example with default settings (recommended for most users):
tracker := tornago.NewRelayPerformanceTracker()
client, err := tornago.NewClient(
tornago.WithClientPerformanceTracker(tracker),
)
Example with custom thresholds:
threshold := tornago.NewRelayThreshold().
WithMaxLatency(3 * time.Second).
WithMinSuccessRate(0.9)
tracker := tornago.NewRelayPerformanceTracker(
tornago.WithTrackerThreshold(threshold),
)
client, err := tornago.NewClient(
tornago.WithClientPerformanceTracker(tracker),
)
func WithClientRateLimiter ¶ added in v0.2.0
func WithClientRateLimiter(r *RateLimiter) ClientOption
WithClientRateLimiter sets the rate limiter for the client.
func WithClientRequestTimeout ¶
func WithClientRequestTimeout(timeout time.Duration) ClientOption
WithClientRequestTimeout sets the overall HTTP request timeout.
func WithClientSocksAddr ¶
func WithClientSocksAddr(addr string) ClientOption
WithClientSocksAddr sets the SocksPort address for the client.
func WithRetryAttempts ¶
func WithRetryAttempts(attempts uint) ClientOption
WithRetryAttempts sets the maximum number of retries.
func WithRetryDelay ¶
func WithRetryDelay(delay time.Duration) ClientOption
WithRetryDelay sets the initial backoff delay.
func WithRetryMaxDelay ¶
func WithRetryMaxDelay(delay time.Duration) ClientOption
WithRetryMaxDelay caps the backoff delay.
func WithRetryOnError ¶
func WithRetryOnError(fn func(error) bool) ClientOption
WithRetryOnError registers a predicate to decide retry eligibility.
func WithSlowRelayAvoidance ¶ added in v0.4.0
func WithSlowRelayAvoidance(opts ...SlowRelayOption) ClientOption
WithSlowRelayAvoidance enables automatic slow relay avoidance in the Client. When enabled, the Client automatically tracks relay performance during requests, blocks slow or unreliable relays, and triggers circuit rotation when needed.
This is the recommended way to enable slow relay avoidance for most users. The feature works transparently - just make requests normally and the Client handles everything internally.
Options can be provided to customize behavior:
- SlowRelayMaxLatency: Maximum acceptable latency (default: 5s)
- SlowRelayMinSuccessRate: Minimum required success rate (default: 0.8)
- SlowRelayBlockDuration: How long to block slow relays (default: 30m)
- SlowRelayMinSamples: Samples needed before judging (default: 3)
- SlowRelayMonitorInterval: Background check interval (default: 30s)
- SlowRelayAutoExclude: Auto-update Tor's ExcludeNodes (default: true)
Note: This feature requires ControlPort access. Use WithClientControlAddr() to specify the Tor ControlPort address.
Example:
// Enable with defaults
client, err := tornago.NewClient(
tornago.WithClientSocksAddr(torProcess.SocksAddr()),
tornago.WithClientControlAddr(torProcess.ControlAddr()),
tornago.WithSlowRelayAvoidance(),
)
// Enable with custom settings
client, err := tornago.NewClient(
tornago.WithClientSocksAddr(torProcess.SocksAddr()),
tornago.WithClientControlAddr(torProcess.ControlAddr()),
tornago.WithSlowRelayAvoidance(
tornago.SlowRelayMaxLatency(3*time.Second),
tornago.SlowRelayMinSuccessRate(0.9),
),
)
// Get performance statistics
stats, ok := client.RelayPerformanceStats()
if ok {
fmt.Printf("Tracked relays: %d, Blocked: %d\n", stats.TrackedRelays(), stats.BlockedRelays())
}
type ControlAuth ¶
type ControlAuth struct {
// contains filtered or unexported fields
}
ControlAuth holds ControlPort authentication values. It is immutable after creation via the helper functions below.
func ControlAuthFromCookie ¶
func ControlAuthFromCookie(path string) ControlAuth
ControlAuthFromCookie builds ControlAuth for cookie-based auth. ControlAuthFromCookie constructs ControlAuth for cookie-based auth.
func ControlAuthFromCookieBytes ¶
func ControlAuthFromCookieBytes(data []byte) ControlAuth
ControlAuthFromCookieBytes constructs ControlAuth from raw cookie data.
func ControlAuthFromPassword ¶
func ControlAuthFromPassword(password string) ControlAuth
ControlAuthFromPassword builds ControlAuth for password-based auth. ControlAuthFromPassword constructs ControlAuth for password-based auth.
func ControlAuthFromTor ¶
ControlAuthFromTor queries Tor for the control cookie path and returns the ControlAuth that uses the corresponding cookie bytes.
func (ControlAuth) CookieBytes ¶
func (a ControlAuth) CookieBytes() []byte
CookieBytes returns the raw cookie data if configured.
func (ControlAuth) CookiePath ¶
func (a ControlAuth) CookiePath() string
CookiePath returns the configured control cookie path.
func (ControlAuth) Password ¶
func (a ControlAuth) Password() string
Password returns the configured control password.
type ControlClient ¶
type ControlClient struct {
// contains filtered or unexported fields
}
ControlClient talks to Tor's ControlPort (a text-based management interface where Tor accepts commands like AUTHENTICATE/GETINFO/SIGNAL NEWNYM). It is provided as a standalone client so tools that only need ControlPort access (e.g. circuit rotation or Hidden Service management) can use it without constructing the higher-level HTTP/TCP Client.
The ControlPort allows you to:
- Rotate circuits to get new exit IPs (NewIdentity)
- Create and manage hidden services (CreateHiddenService)
- Query Tor's internal state (GetInfo)
- Monitor Tor events and status
Authentication is required before most commands. Use either cookie-based authentication (automatic with StartTorDaemon) or password authentication (for existing Tor instances).
Example usage:
auth := tornago.ControlAuthFromCookie("/var/lib/tor/control_auth_cookie")
ctrl, _ := tornago.NewControlClient("127.0.0.1:9051", auth, 5*time.Second)
defer ctrl.Close()
ctrl.Authenticate()
ctrl.NewIdentity(context.Background()) // Request new circuits
func NewControlClient ¶
func NewControlClient(addr string, auth ControlAuth, timeout time.Duration) (*ControlClient, error)
NewControlClient dials the ControlPort at addr with the given timeout.
func (*ControlClient) Authenticate ¶
func (c *ControlClient) Authenticate() error
Authenticate performs AUTHENTICATE using ControlAuth credentials.
func (*ControlClient) ClearExcludeNodes ¶ added in v0.4.0
func (c *ControlClient) ClearExcludeNodes(ctx context.Context) error
ClearExcludeNodes removes all entries from the ExcludeNodes configuration.
func (*ControlClient) Close ¶
func (c *ControlClient) Close() error
Close closes the underlying ControlPort connection.
func (*ControlClient) CreateHiddenService ¶
func (c *ControlClient) CreateHiddenService(ctx context.Context, cfg HiddenServiceConfig) (HiddenService, error)
CreateHiddenService issues ADD_ONION and returns a HiddenService handle.
func (*ControlClient) ExcludeNodes ¶ added in v0.4.0
func (c *ControlClient) ExcludeNodes(ctx context.Context, fingerprints []string) error
ExcludeNodes sets the ExcludeNodes configuration to avoid specific relays. The fingerprints should be relay fingerprints (40-character hex strings), optionally prefixed with '$'.
Example:
err := ctrl.ExcludeNodes(ctx, []string{"$AAAA...", "$BBBB..."})
func (*ControlClient) GetCircuitStatus ¶ added in v0.2.0
func (c *ControlClient) GetCircuitStatus(ctx context.Context) ([]CircuitInfo, error)
GetCircuitStatus retrieves information about all current Tor circuits. This is useful for monitoring circuit health and debugging connectivity issues.
func (*ControlClient) GetConf ¶ added in v0.2.0
GetConf retrieves the current value of a Tor configuration option. The key should be a valid Tor configuration option name (e.g., "SocksPort", "ORPort").
Example:
socksPort, err := ctrl.GetConf(ctx, "SocksPort")
func (*ControlClient) GetHiddenServiceStatus ¶ added in v0.2.0
func (c *ControlClient) GetHiddenServiceStatus(ctx context.Context) ([]HiddenServiceStatus, error)
GetHiddenServiceStatus retrieves information about all active hidden services. This is useful for monitoring and debugging hidden service configurations.
func (*ControlClient) GetInfoNoAuth ¶
GetInfoNoAuth runs GETINFO without authenticating first.
func (*ControlClient) GetStreamStatus ¶ added in v0.2.0
func (c *ControlClient) GetStreamStatus(ctx context.Context) ([]StreamInfo, error)
GetStreamStatus retrieves information about all current Tor streams. This is useful for monitoring active connections through Tor.
func (*ControlClient) MapAddress ¶ added in v0.2.0
MapAddress creates a mapping from a virtual address to a target address. This allows you to access services using custom addresses through Tor.
Example:
// Map "mysite" to an onion address mapped, err := ctrl.MapAddress(ctx, "mysite.virtual", "abcdef...onion")
func (*ControlClient) NewIdentity ¶
func (c *ControlClient) NewIdentity(ctx context.Context) error
NewIdentity issues SIGNAL NEWNYM to rotate Tor circuits, causing Tor to close existing circuits and build new ones. This effectively gives you a new exit IP address for subsequent requests.
This is useful for:
- Avoiding rate limiting or IP-based blocks
- Getting a fresh identity for privacy reasons
- Testing behavior with different exit nodes
Note: Tor rate-limits NEWNYM requests to once per 10 seconds by default. Calling this more frequently will not create new circuits.
func (*ControlClient) ResetConf ¶ added in v0.2.0
func (c *ControlClient) ResetConf(ctx context.Context, key string) error
ResetConf resets a Tor configuration option to its default value.
Example:
err := ctrl.ResetConf(ctx, "MaxCircuitDirtiness")
func (*ControlClient) SaveConf ¶ added in v0.2.0
func (c *ControlClient) SaveConf(ctx context.Context) error
SaveConf saves the current configuration to the torrc file. This persists any changes made with SetConf.
func (*ControlClient) SetConf ¶ added in v0.2.0
func (c *ControlClient) SetConf(ctx context.Context, key, value string) error
SetConf sets a Tor configuration option to the specified value. The change takes effect immediately but is not persisted to the torrc file. To persist changes, call SaveConf after SetConf.
Example:
err := ctrl.SetConf(ctx, "MaxCircuitDirtiness", "600")
type DNSLeakCheck ¶ added in v0.3.0
type DNSLeakCheck struct {
// contains filtered or unexported fields
}
DNSLeakCheck represents the result of a DNS leak detection test. It is an immutable value object that provides methods to query leak status.
func (DNSLeakCheck) HasLeak ¶ added in v0.3.0
func (d DNSLeakCheck) HasLeak() bool
HasLeak returns true if DNS queries are leaking outside Tor.
func (DNSLeakCheck) Latency ¶ added in v0.3.0
func (d DNSLeakCheck) Latency() time.Duration
Latency returns how long the check took.
func (DNSLeakCheck) Message ¶ added in v0.3.0
func (d DNSLeakCheck) Message() string
Message provides human-readable details about the check.
func (DNSLeakCheck) ResolvedIPs ¶ added in v0.3.0
func (d DNSLeakCheck) ResolvedIPs() []string
ResolvedIPs returns a defensive copy of the IP addresses returned by DNS resolution.
func (DNSLeakCheck) String ¶ added in v0.3.0
func (d DNSLeakCheck) String() string
String returns a human-readable representation of the DNS leak check.
type ErrorKind ¶
type ErrorKind string
ErrorKind classifies Tornago errors for easier handling and retry decisions.
const ( // ErrInvalidConfig indicates user-supplied configuration is invalid. ErrInvalidConfig ErrorKind = "invalid_config" // ErrTorBinaryNotFound indicates the tor executable could not be located. ErrTorBinaryNotFound ErrorKind = "tor_binary_not_found" // ErrTorLaunchFailed indicates tor failed to launch or exited unexpectedly. ErrTorLaunchFailed ErrorKind = "tor_launch_failed" // ErrSocksDialFailed indicates SOCKS5 dialing failed. ErrSocksDialFailed ErrorKind = "socks_dial_failed" // ErrControlAuthFailed indicates ControlPort authentication failed. ErrControlAuthFailed ErrorKind = "control_auth_failed" // ErrControlRequestFail indicates a ControlPort request returned an error. ErrControlRequestFail ErrorKind = "control_request_failed" // ErrHTTPFailed indicates an HTTP request via Tor failed. ErrHTTPFailed ErrorKind = "http_failed" // ErrTimeout indicates an operation exceeded its deadline. ErrTimeout ErrorKind = "timeout" // ErrIO wraps generic I/O errors. ErrIO ErrorKind = "io_error" // ErrHiddenServiceFailed indicates Hidden Service creation/removal failed. ErrHiddenServiceFailed ErrorKind = "hidden_service_failed" // ErrListenerClosed indicates an operation was attempted on a closed listener. ErrListenerClosed ErrorKind = "listener_closed" // ErrListenerCloseFailed indicates the listener failed to close properly. ErrListenerCloseFailed ErrorKind = "listener_close_failed" // ErrAcceptFailed indicates Accept() failed on a listener. ErrAcceptFailed ErrorKind = "accept_failed" // ErrUnknown is used when no specific classification is available. ErrUnknown ErrorKind = "unknown" )
ErrorKind values classify tornago errors by their category.
type HealthCheck ¶ added in v0.3.0
type HealthCheck struct {
// contains filtered or unexported fields
}
HealthCheck contains the result of a health check operation. It is an immutable value object that provides methods to query health status.
func CheckTorDaemon ¶ added in v0.3.0
func CheckTorDaemon(ctx context.Context, proc *TorProcess) HealthCheck
CheckTorDaemon performs a health check on a TorProcess. It verifies that:
- The Tor process is running
- SOCKS and ControlPort are responsive
Example:
torProcess, _ := tornago.StartTorDaemon(cfg)
health := tornago.CheckTorDaemon(context.Background(), torProcess)
if !health.IsHealthy() {
log.Printf("Tor daemon unhealthy: %s", health.Message())
}
func (HealthCheck) IsDegraded ¶ added in v0.3.0
func (h HealthCheck) IsDegraded() bool
IsDegraded returns true if the service is operational but experiencing issues.
func (HealthCheck) IsHealthy ¶ added in v0.3.0
func (h HealthCheck) IsHealthy() bool
IsHealthy returns true if all components are functioning normally.
func (HealthCheck) IsUnhealthy ¶ added in v0.3.0
func (h HealthCheck) IsUnhealthy() bool
IsUnhealthy returns true if the service is not functioning.
func (HealthCheck) Latency ¶ added in v0.3.0
func (h HealthCheck) Latency() time.Duration
Latency returns how long the health check took.
func (HealthCheck) Message ¶ added in v0.3.0
func (h HealthCheck) Message() string
Message provides human-readable context about the health status.
func (HealthCheck) Status ¶ added in v0.3.0
func (h HealthCheck) Status() HealthStatus
Status returns the overall health status.
func (HealthCheck) String ¶ added in v0.3.0
func (h HealthCheck) String() string
String returns a human-readable representation of the health check.
func (HealthCheck) Timestamp ¶ added in v0.3.0
func (h HealthCheck) Timestamp() time.Time
Timestamp returns when the health check was performed.
type HealthStatus ¶ added in v0.3.0
type HealthStatus string
HealthStatus represents the health state of a Tor connection or service.
const ( // HealthStatusHealthy indicates the service is functioning normally. HealthStatusHealthy HealthStatus = "healthy" // HealthStatusDegraded indicates the service is operational but experiencing issues. HealthStatusDegraded HealthStatus = "degraded" // HealthStatusUnhealthy indicates the service is not functioning. HealthStatusUnhealthy HealthStatus = "unhealthy" )
type HiddenService ¶
type HiddenService interface {
// OnionAddress returns the .onion address where the service is accessible.
OnionAddress() string
// PrivateKey returns the private key in Tor's format for re-registering this service.
PrivateKey() string
// Ports returns the virtual port to local port mapping.
Ports() map[int]int
// ClientAuth returns the client authorization entries if configured.
ClientAuth() []HiddenServiceAuth
// Remove deletes this hidden service from Tor. The .onion address becomes inaccessible.
Remove(ctx context.Context) error
// SavePrivateKey saves the private key to a file for later reuse.
SavePrivateKey(path string) error
}
HiddenService represents a provisioned Hidden Service (also known as an onion service). A hidden service allows you to host a server that's accessible only through the Tor network, identified by a .onion address.
Benefits of hidden services:
- No need for public IP address or DNS registration
- Server location and IP remain anonymous
- End-to-end encryption through Tor network
- Censorship resistance (difficult to block .onion addresses)
Example usage:
// Create hidden service mapping port 80 to local port 8080
cfg, _ := tornago.NewHiddenServiceConfig(
tornago.WithHiddenServicePort(80, 8080),
)
hs, _ := controlClient.CreateHiddenService(context.Background(), cfg)
defer hs.Remove(context.Background())
fmt.Printf("Your service is at: %s\n", hs.OnionAddress())
// Example output: "abc123xyz456.onion"
type HiddenServiceAuth ¶
type HiddenServiceAuth struct {
// contains filtered or unexported fields
}
HiddenServiceAuth describes Tor v3 client authorization information.
func NewHiddenServiceAuth ¶
func NewHiddenServiceAuth(clientName, key string) HiddenServiceAuth
NewHiddenServiceAuth returns a client auth entry.
func (HiddenServiceAuth) ClientName ¶
func (a HiddenServiceAuth) ClientName() string
ClientName returns the configured auth client name.
func (HiddenServiceAuth) Key ¶
func (a HiddenServiceAuth) Key() string
Key returns the authorization key.
type HiddenServiceConfig ¶
type HiddenServiceConfig struct {
// contains filtered or unexported fields
}
HiddenServiceConfig describes the desired onion service to create via Tor.
func NewHiddenServiceConfig ¶
func NewHiddenServiceConfig(opts ...HiddenServiceOption) (HiddenServiceConfig, error)
NewHiddenServiceConfig returns a validated, immutable configuration.
func (HiddenServiceConfig) ClientAuth ¶
func (c HiddenServiceConfig) ClientAuth() []HiddenServiceAuth
ClientAuth returns a copy of the configured client authorization entries.
func (HiddenServiceConfig) KeyType ¶
func (c HiddenServiceConfig) KeyType() string
KeyType returns the key type (e.g. "ED25519-V3").
func (HiddenServiceConfig) Ports ¶
func (c HiddenServiceConfig) Ports() map[int]int
Ports returns a copy of the configured virtual -> target port mapping.
func (HiddenServiceConfig) PrivateKey ¶
func (c HiddenServiceConfig) PrivateKey() string
PrivateKey returns the optional private key blob.
type HiddenServiceOption ¶
type HiddenServiceOption func(*HiddenServiceConfig)
HiddenServiceOption customizes HiddenServiceConfig creation.
func WithHiddenServiceClientAuth ¶
func WithHiddenServiceClientAuth(auth ...HiddenServiceAuth) HiddenServiceOption
WithHiddenServiceClientAuth appends client authorization entries.
func WithHiddenServiceHTTP ¶ added in v0.2.0
func WithHiddenServiceHTTP(localPort int) HiddenServiceOption
WithHiddenServiceHTTP maps port 80 to the specified local port. This is a convenience for hosting HTTP services.
func WithHiddenServiceHTTPS ¶ added in v0.2.0
func WithHiddenServiceHTTPS(localPort int) HiddenServiceOption
WithHiddenServiceHTTPS maps port 443 to the specified local port. This is a convenience for hosting HTTPS services.
func WithHiddenServiceKeyType ¶
func WithHiddenServiceKeyType(keyType string) HiddenServiceOption
WithHiddenServiceKeyType sets the key type (default: "ED25519-V3").
func WithHiddenServicePort ¶
func WithHiddenServicePort(virtualPort, targetPort int) HiddenServiceOption
WithHiddenServicePort maps a virtual port to a local target port.
func WithHiddenServicePorts ¶
func WithHiddenServicePorts(ports map[int]int) HiddenServiceOption
WithHiddenServicePorts sets the entire virtual -> target port mapping.
func WithHiddenServicePrivateKey ¶
func WithHiddenServicePrivateKey(privateKey string) HiddenServiceOption
WithHiddenServicePrivateKey uses an existing private key blob.
func WithHiddenServicePrivateKeyFile ¶ added in v0.2.0
func WithHiddenServicePrivateKeyFile(path string) HiddenServiceOption
WithHiddenServicePrivateKeyFile loads a private key from a file and uses it. This is a convenience option that combines LoadPrivateKey and WithHiddenServicePrivateKey.
func WithHiddenServiceSamePort ¶ added in v0.2.0
func WithHiddenServiceSamePort(port int) HiddenServiceOption
WithHiddenServiceSamePort maps a port to itself (virtualPort == targetPort). This is a convenience for common cases where you don't need port translation.
type HiddenServiceStatus ¶ added in v0.2.0
type HiddenServiceStatus struct {
// ServiceID is the onion address without .onion suffix.
ServiceID string
// Ports lists the configured port mappings.
Ports []string
}
HiddenServiceStatus represents the status of a hidden service.
type Latency ¶ added in v0.4.0
type Latency struct {
// contains filtered or unexported fields
}
Latency represents a duration measurement for relay performance.
func NewLatency ¶ added in v0.4.0
NewLatency creates a new Latency from a duration.
func (Latency) ExceedsThreshold ¶ added in v0.4.0
ExceedsThreshold returns true if this latency exceeds the given threshold.
type Logger ¶ added in v0.3.0
type Logger interface {
// Log logs a message at the specified level with optional key-value pairs.
// Level should be one of: "debug", "info", "warn", "error".
// The keysAndValues are interpreted as alternating key-value pairs.
Log(level string, msg string, keysAndValues ...any)
}
Logger defines a minimal structured logging interface for tornago. This interface is intentionally simple to support various logging libraries (slog, logrus, zap, zerolog, etc.) through adapters.
The default logger discards all log messages. Users can provide their own logger implementation using WithLogger configuration option.
Example with slog:
logger := slog.New(slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{
Level: slog.LevelDebug,
}))
adapter := tornago.NewSlogAdapter(logger)
cfg, _ := tornago.NewClientConfig(
tornago.WithClientSocksAddr("127.0.0.1:9050"),
tornago.WithLogger(adapter),
)
For other logging libraries, implement this interface by wrapping your preferred logger. The keysAndValues parameter should be interpreted as alternating key-value pairs (e.g., "key1", value1, "key2", value2).
func NewSlogAdapter ¶ added in v0.3.0
NewSlogAdapter creates a Logger from *slog.Logger.
Example:
logger := slog.New(slog.NewTextHandler(os.Stderr, nil))
adapter := tornago.NewSlogAdapter(logger)
cfg, _ := tornago.NewClientConfig(
tornago.WithClientSocksAddr("127.0.0.1:9050"),
tornago.WithLogger(adapter),
)
type Metrics ¶ added in v0.2.0
type Metrics interface {
// RequestCount returns the total number of requests made.
RequestCount() uint64
// SuccessCount returns the number of successful requests.
SuccessCount() uint64
// ErrorCount returns the number of failed requests.
ErrorCount() uint64
// TotalLatency returns the sum of all request latencies.
TotalLatency() time.Duration
// AverageLatency returns the average request latency.
AverageLatency() time.Duration
// Reset clears all metrics.
Reset()
}
Metrics provides access to client operation statistics. All methods are safe for concurrent use.
type MetricsCollector ¶ added in v0.2.0
type MetricsCollector struct {
// contains filtered or unexported fields
}
MetricsCollector tracks request statistics for the Client. It is thread-safe and can be shared across goroutines.
func NewMetricsCollector ¶ added in v0.2.0
func NewMetricsCollector() *MetricsCollector
NewMetricsCollector creates a new MetricsCollector.
func (*MetricsCollector) AverageLatency ¶ added in v0.2.0
func (m *MetricsCollector) AverageLatency() time.Duration
AverageLatency returns the average request latency. Returns 0 if no requests have been made.
func (*MetricsCollector) ConnectionReuseCount ¶ added in v0.3.0
func (m *MetricsCollector) ConnectionReuseCount() uint64
ConnectionReuseCount returns the number of times an existing connection was reused. This is calculated as the difference between total requests and total dials.
func (*MetricsCollector) ConnectionReuseRate ¶ added in v0.3.0
func (m *MetricsCollector) ConnectionReuseRate() float64
ConnectionReuseRate returns the percentage of requests that reused existing connections. Returns 0.0 if no requests have been made. A higher rate (closer to 1.0) indicates better connection pooling efficiency.
func (*MetricsCollector) DialCount ¶ added in v0.3.0
func (m *MetricsCollector) DialCount() uint64
DialCount returns the total number of dial operations performed. This includes both new connections and connection reuse attempts.
func (*MetricsCollector) ErrorCount ¶ added in v0.2.0
func (m *MetricsCollector) ErrorCount() uint64
ErrorCount returns the number of failed requests.
func (*MetricsCollector) ErrorsByKind ¶ added in v0.3.0
func (m *MetricsCollector) ErrorsByKind() map[ErrorKind]uint64
ErrorsByKind returns a copy of error counts grouped by error kind.
func (*MetricsCollector) MaxLatency ¶ added in v0.3.0
func (m *MetricsCollector) MaxLatency() time.Duration
MaxLatency returns the maximum request latency observed. Returns 0 if no requests have been made.
func (*MetricsCollector) MinLatency ¶ added in v0.3.0
func (m *MetricsCollector) MinLatency() time.Duration
MinLatency returns the minimum request latency observed. Returns 0 if no requests have been made.
func (*MetricsCollector) RequestCount ¶ added in v0.2.0
func (m *MetricsCollector) RequestCount() uint64
RequestCount returns the total number of requests made.
func (*MetricsCollector) Reset ¶ added in v0.2.0
func (m *MetricsCollector) Reset()
Reset clears all metrics to zero.
func (*MetricsCollector) SuccessCount ¶ added in v0.2.0
func (m *MetricsCollector) SuccessCount() uint64
SuccessCount returns the number of successful requests.
func (*MetricsCollector) TotalLatency ¶ added in v0.2.0
func (m *MetricsCollector) TotalLatency() time.Duration
TotalLatency returns the sum of all request latencies.
type OnionAddr ¶ added in v0.2.0
type OnionAddr struct {
// contains filtered or unexported fields
}
OnionAddr represents a .onion address that implements net.Addr.
type RateLimiter ¶ added in v0.2.0
type RateLimiter struct {
// contains filtered or unexported fields
}
RateLimiter controls the rate of requests to prevent overloading Tor circuits. It implements a token bucket algorithm.
func NewRateLimiter ¶ added in v0.2.0
func NewRateLimiter(rate float64, burst int) *RateLimiter
NewRateLimiter creates a rate limiter with the specified rate (requests/second) and burst size.
func (*RateLimiter) Allow ¶ added in v0.2.0
func (r *RateLimiter) Allow() bool
Allow returns true if a request can proceed immediately without waiting.
func (*RateLimiter) Burst ¶ added in v0.2.0
func (r *RateLimiter) Burst() int
Burst returns the configured burst size.
func (*RateLimiter) Rate ¶ added in v0.2.0
func (r *RateLimiter) Rate() float64
Rate returns the configured rate (requests per second).
type RelayFingerprint ¶ added in v0.4.0
type RelayFingerprint struct {
// contains filtered or unexported fields
}
RelayFingerprint represents a Tor relay's unique identifier. It is a 40-character hexadecimal string (SHA-1 hash of the relay's identity key).
func NewRelayFingerprint ¶ added in v0.4.0
func NewRelayFingerprint(fingerprint string) RelayFingerprint
NewRelayFingerprint creates a new RelayFingerprint from a string. The fingerprint should be a 40-character hexadecimal string, optionally prefixed with '$'.
func (RelayFingerprint) Equal ¶ added in v0.4.0
func (f RelayFingerprint) Equal(other RelayFingerprint) bool
Equal returns true if two fingerprints are equal.
func (RelayFingerprint) IsEmpty ¶ added in v0.4.0
func (f RelayFingerprint) IsEmpty() bool
IsEmpty returns true if the fingerprint is empty.
func (RelayFingerprint) String ¶ added in v0.4.0
func (f RelayFingerprint) String() string
String returns the fingerprint as a string.
type RelayMeasurement ¶ added in v0.4.0
type RelayMeasurement struct {
// contains filtered or unexported fields
}
RelayMeasurement represents a single performance measurement for a relay.
func NewRelayMeasurement ¶ added in v0.4.0
func NewRelayMeasurement(latency time.Duration, success bool) RelayMeasurement
NewRelayMeasurement creates a new measurement.
func (RelayMeasurement) IsExpired ¶ added in v0.4.0
func (m RelayMeasurement) IsExpired(window time.Duration) bool
IsExpired returns true if the measurement is older than the given window.
func (RelayMeasurement) Latency ¶ added in v0.4.0
func (m RelayMeasurement) Latency() Latency
Latency returns the measured latency.
func (RelayMeasurement) Success ¶ added in v0.4.0
func (m RelayMeasurement) Success() bool
Success returns whether the measurement was successful.
func (RelayMeasurement) Timestamp ¶ added in v0.4.0
func (m RelayMeasurement) Timestamp() time.Time
Timestamp returns when the measurement was taken.
type RelayPerformanceStats ¶ added in v0.4.0
type RelayPerformanceStats struct {
// contains filtered or unexported fields
}
RelayPerformanceStats provides detailed statistics about relay performance. This is an immutable Value Object - use accessor methods to retrieve values.
func (RelayPerformanceStats) BlockedRelayList ¶ added in v0.4.0
func (s RelayPerformanceStats) BlockedRelayList() []string
BlockedRelayList returns a copy of the blocked relay fingerprints.
func (RelayPerformanceStats) BlockedRelays ¶ added in v0.4.0
func (s RelayPerformanceStats) BlockedRelays() int
BlockedRelays returns the number of currently blocked relays.
func (RelayPerformanceStats) Enabled ¶ added in v0.4.0
func (s RelayPerformanceStats) Enabled() bool
Enabled returns true if slow relay avoidance is active.
func (RelayPerformanceStats) Threshold ¶ added in v0.4.0
func (s RelayPerformanceStats) Threshold() RelayThresholdStats
Threshold returns the current threshold configuration.
func (RelayPerformanceStats) TrackedRelays ¶ added in v0.4.0
func (s RelayPerformanceStats) TrackedRelays() int
TrackedRelays returns the number of relays being monitored.
type RelayPerformanceTracker ¶ added in v0.4.0
type RelayPerformanceTracker struct {
// contains filtered or unexported fields
}
RelayPerformanceTracker tracks relay performance and manages slow relay exclusion.
func NewRelayPerformanceTracker ¶ added in v0.4.0
func NewRelayPerformanceTracker(opts ...RelayTrackerOption) *RelayPerformanceTracker
NewRelayPerformanceTracker creates a new tracker with optional configuration.
func (*RelayPerformanceTracker) BlockedRelays ¶ added in v0.4.0
func (t *RelayPerformanceTracker) BlockedRelays() []RelayFingerprint
BlockedRelays returns a list of currently blocked relay fingerprints.
func (*RelayPerformanceTracker) Clear ¶ added in v0.4.0
func (t *RelayPerformanceTracker) Clear()
Clear removes all tracked statistics and blocks.
func (*RelayPerformanceTracker) ClearExcludeNodes ¶ added in v0.4.0
func (t *RelayPerformanceTracker) ClearExcludeNodes(ctx context.Context) error
ClearExcludeNodes removes all ExcludeNodes from Tor configuration.
func (*RelayPerformanceTracker) GetStats ¶ added in v0.4.0
func (t *RelayPerformanceTracker) GetStats(fingerprint RelayFingerprint) *RelayStats
GetStats returns statistics for a specific relay.
func (*RelayPerformanceTracker) IsBlocked ¶ added in v0.4.0
func (t *RelayPerformanceTracker) IsBlocked(fingerprint RelayFingerprint) bool
IsBlocked returns true if the relay is currently blocked.
func (*RelayPerformanceTracker) RecordCircuitMeasurement ¶ added in v0.4.0
func (t *RelayPerformanceTracker) RecordCircuitMeasurement(path []string, latency time.Duration, success bool)
RecordCircuitMeasurement records a measurement for all relays in a circuit path.
func (*RelayPerformanceTracker) RecordMeasurement ¶ added in v0.4.0
func (t *RelayPerformanceTracker) RecordMeasurement(fingerprint RelayFingerprint, latency time.Duration, success bool)
RecordMeasurement records a performance measurement for a relay in a circuit.
func (*RelayPerformanceTracker) Stats ¶ added in v0.4.0
func (t *RelayPerformanceTracker) Stats() TrackerStats
Stats returns current tracker statistics.
type RelayStats ¶ added in v0.4.0
type RelayStats struct {
// contains filtered or unexported fields
}
RelayStats aggregates performance statistics for a single relay.
func NewRelayStats ¶ added in v0.4.0
func NewRelayStats(fingerprint RelayFingerprint, measureWindow time.Duration) *RelayStats
NewRelayStats creates a new RelayStats for the given fingerprint.
func (*RelayStats) AddMeasurement ¶ added in v0.4.0
func (s *RelayStats) AddMeasurement(m RelayMeasurement)
AddMeasurement adds a new measurement and recalculates statistics.
func (*RelayStats) AverageLatency ¶ added in v0.4.0
func (s *RelayStats) AverageLatency() Latency
AverageLatency returns the average latency.
func (*RelayStats) Fingerprint ¶ added in v0.4.0
func (s *RelayStats) Fingerprint() RelayFingerprint
Fingerprint returns the relay's fingerprint.
func (*RelayStats) IsSlow ¶ added in v0.4.0
func (s *RelayStats) IsSlow(threshold RelayThreshold) bool
IsSlow returns true if the relay is considered slow based on the threshold.
func (*RelayStats) SampleCount ¶ added in v0.4.0
func (s *RelayStats) SampleCount() int
SampleCount returns the number of samples in the current window.
func (*RelayStats) SuccessRate ¶ added in v0.4.0
func (s *RelayStats) SuccessRate() SuccessRate
SuccessRate returns the success rate.
type RelayThreshold ¶ added in v0.4.0
type RelayThreshold struct {
// contains filtered or unexported fields
}
RelayThreshold defines thresholds for determining slow relays. All fields are immutable after creation.
func NewRelayThreshold ¶ added in v0.4.0
func NewRelayThreshold() RelayThreshold
NewRelayThreshold creates a RelayThreshold with default values. Use With* methods to customize.
func (RelayThreshold) BlockDuration ¶ added in v0.4.0
func (t RelayThreshold) BlockDuration() time.Duration
BlockDuration returns how long slow relays are blocked.
func (RelayThreshold) MaxLatency ¶ added in v0.4.0
func (t RelayThreshold) MaxLatency() Latency
MaxLatency returns the maximum acceptable latency.
func (RelayThreshold) MinSamples ¶ added in v0.4.0
func (t RelayThreshold) MinSamples() int
MinSamples returns the minimum number of samples required for evaluation.
func (RelayThreshold) MinSuccessRate ¶ added in v0.4.0
func (t RelayThreshold) MinSuccessRate() SuccessRate
MinSuccessRate returns the minimum acceptable success rate.
func (RelayThreshold) WithBlockDuration ¶ added in v0.4.0
func (t RelayThreshold) WithBlockDuration(d time.Duration) RelayThreshold
WithBlockDuration returns a new RelayThreshold with the given block duration.
func (RelayThreshold) WithMaxLatency ¶ added in v0.4.0
func (t RelayThreshold) WithMaxLatency(d time.Duration) RelayThreshold
WithMaxLatency returns a new RelayThreshold with the given max latency.
func (RelayThreshold) WithMinSamples ¶ added in v0.4.0
func (t RelayThreshold) WithMinSamples(n int) RelayThreshold
WithMinSamples returns a new RelayThreshold with the given minimum sample count.
func (RelayThreshold) WithMinSuccessRate ¶ added in v0.4.0
func (t RelayThreshold) WithMinSuccessRate(rate float64) RelayThreshold
WithMinSuccessRate returns a new RelayThreshold with the given min success rate.
type RelayThresholdStats ¶ added in v0.4.0
type RelayThresholdStats struct {
// contains filtered or unexported fields
}
RelayThresholdStats provides threshold configuration details. This is an immutable Value Object - use accessor methods to retrieve values.
func (RelayThresholdStats) BlockDuration ¶ added in v0.4.0
func (s RelayThresholdStats) BlockDuration() time.Duration
BlockDuration returns how long slow relays remain blocked.
func (RelayThresholdStats) MaxLatency ¶ added in v0.4.0
func (s RelayThresholdStats) MaxLatency() time.Duration
MaxLatency returns the maximum acceptable latency.
func (RelayThresholdStats) MinSamples ¶ added in v0.4.0
func (s RelayThresholdStats) MinSamples() int
MinSamples returns the minimum measurements needed before evaluation.
func (RelayThresholdStats) MinSuccessRate ¶ added in v0.4.0
func (s RelayThresholdStats) MinSuccessRate() float64
MinSuccessRate returns the minimum acceptable success rate.
type RelayTrackerOption ¶ added in v0.4.0
type RelayTrackerOption func(*RelayPerformanceTracker)
RelayTrackerOption configures a RelayPerformanceTracker.
func WithTrackerAutoExclude ¶ added in v0.4.0
func WithTrackerAutoExclude(enabled bool) RelayTrackerOption
WithTrackerAutoExclude enables/disables automatic relay exclusion via Tor.
func WithTrackerControl ¶ added in v0.4.0
func WithTrackerControl(control *ControlClient) RelayTrackerOption
WithTrackerControl sets the control client for automatic ExcludeNodes.
func WithTrackerLogger ¶ added in v0.4.0
func WithTrackerLogger(logger Logger) RelayTrackerOption
WithTrackerLogger sets the logger.
func WithTrackerMeasureWindow ¶ added in v0.4.0
func WithTrackerMeasureWindow(d time.Duration) RelayTrackerOption
WithTrackerMeasureWindow sets the measurement window.
func WithTrackerThreshold ¶ added in v0.4.0
func WithTrackerThreshold(threshold RelayThreshold) RelayTrackerOption
WithTrackerThreshold sets the threshold configuration.
type Server ¶
type Server interface {
// SocksAddr returns the Tor SocksPort address.
SocksAddr() string
// ControlAddr returns the Tor ControlPort address.
ControlAddr() string
}
Server exposes Tor SocksPort and ControlPort addresses for clients to use.
func NewServer ¶
func NewServer(cfg ServerConfig) (Server, error)
NewServer builds a Server from the given configuration.
type ServerConfig ¶
type ServerConfig struct {
// contains filtered or unexported fields
}
ServerConfig represents addresses of an existing Tor instance. It is immutable after construction via NewServerConfig.
func NewServerConfig ¶
func NewServerConfig(opts ...ServerOption) (ServerConfig, error)
NewServerConfig returns a validated, immutable server config.
func (ServerConfig) ControlAddr ¶
func (c ServerConfig) ControlAddr() string
ControlAddr is the address of an already running Tor ControlPort.
func (ServerConfig) SocksAddr ¶
func (c ServerConfig) SocksAddr() string
SocksAddr is the address of an already running Tor SocksPort.
type ServerOption ¶
type ServerOption func(*ServerConfig)
ServerOption customizes ServerConfig creation.
func WithServerControlAddr ¶
func WithServerControlAddr(addr string) ServerOption
WithServerControlAddr sets the ControlPort address. WithServerControlAddr sets the ControlPort address on ServerConfig.
func WithServerSocksAddr ¶
func WithServerSocksAddr(addr string) ServerOption
WithServerSocksAddr sets the SocksPort address. WithServerSocksAddr sets the SocksPort address on ServerConfig.
type SlowRelayOption ¶ added in v0.4.0
type SlowRelayOption func(*slowRelayConfig)
SlowRelayOption configures slow relay avoidance behavior.
func SlowRelayAutoExclude ¶ added in v0.4.0
func SlowRelayAutoExclude(enabled bool) SlowRelayOption
SlowRelayAutoExclude enables/disables automatic Tor ExcludeNodes updates. When enabled, blocked relays are added to Tor's ExcludeNodes configuration. Default: true.
func SlowRelayBlockDuration ¶ added in v0.4.0
func SlowRelayBlockDuration(d time.Duration) SlowRelayOption
SlowRelayBlockDuration sets how long slow relays remain blocked. Default: 30 minutes.
func SlowRelayMaxLatency ¶ added in v0.4.0
func SlowRelayMaxLatency(d time.Duration) SlowRelayOption
SlowRelayMaxLatency sets the maximum acceptable latency. Relays with average latency exceeding this will be blocked. Default: 5 seconds.
func SlowRelayMinSamples ¶ added in v0.4.0
func SlowRelayMinSamples(n int) SlowRelayOption
SlowRelayMinSamples sets the minimum measurements needed before evaluation. Default: 3.
func SlowRelayMinSuccessRate ¶ added in v0.4.0
func SlowRelayMinSuccessRate(rate float64) SlowRelayOption
SlowRelayMinSuccessRate sets the minimum acceptable success rate (0.0-1.0). Relays with lower success rates will be blocked. Default: 0.8 (80%).
func SlowRelayMonitorInterval ¶ added in v0.4.0
func SlowRelayMonitorInterval(d time.Duration) SlowRelayOption
SlowRelayMonitorInterval sets how often to check for slow circuits. Default: 30 seconds.
type StreamInfo ¶ added in v0.2.0
type StreamInfo struct {
// ID is the stream identifier.
ID string
// Status is the stream status (e.g., "SUCCEEDED", "NEW", "SENTCONNECT").
Status string
// CircuitID is the circuit this stream is attached to.
CircuitID string
// Target is the destination address:port.
Target string
// Purpose is the stream purpose.
Purpose string
}
StreamInfo represents information about a Tor stream.
type SuccessRate ¶ added in v0.4.0
type SuccessRate struct {
// contains filtered or unexported fields
}
SuccessRate represents a success rate between 0.0 and 1.0.
func NewSuccessRate ¶ added in v0.4.0
func NewSuccessRate(rate float64) SuccessRate
NewSuccessRate creates a new SuccessRate, clamping to [0.0, 1.0].
func (SuccessRate) BelowThreshold ¶ added in v0.4.0
func (s SuccessRate) BelowThreshold(threshold SuccessRate) bool
BelowThreshold returns true if this rate is below the given threshold.
func (SuccessRate) Float64 ¶ added in v0.4.0
func (s SuccessRate) Float64() float64
Float64 returns the success rate as a float64.
type TestServer ¶
type TestServer struct {
// Process points to the TorProcess launched for tests.
Process *TorProcess
// Server exposes the Socks/Control addresses of the launched Tor instance.
Server Server
// contains filtered or unexported fields
}
TestServer wraps a TorProcess and Server for integration tests.
func StartTestServer ¶
func StartTestServer(t *testing.T) *TestServer
StartTestServer launches a Tor daemon for tests using a project-local DataDirectory and dedicated ports, skipping if tor is unavailable.
func (*TestServer) Client ¶
func (ts *TestServer) Client(t *testing.T) *Client
Client returns a Client configured to use the started Tor instance.
func (*TestServer) Close ¶
func (ts *TestServer) Close()
Close shuts down the client and Tor process launched for tests.
func (*TestServer) ControlAuth ¶
func (ts *TestServer) ControlAuth(t *testing.T) ControlAuth
ControlAuth returns ControlPort credentials for this TestServer.
type TorConnectionStatus ¶ added in v0.3.0
type TorConnectionStatus struct {
// contains filtered or unexported fields
}
TorConnectionStatus represents the result of verifying Tor connectivity. It is an immutable value object that provides methods to query connection status.
func (TorConnectionStatus) ExitIP ¶ added in v0.3.0
func (s TorConnectionStatus) ExitIP() string
ExitIP returns the IP address as seen by the target server (Tor exit node IP).
func (TorConnectionStatus) IsUsingTor ¶ added in v0.3.0
func (s TorConnectionStatus) IsUsingTor() bool
IsUsingTor returns true if the connection is going through Tor.
func (TorConnectionStatus) Latency ¶ added in v0.3.0
func (s TorConnectionStatus) Latency() time.Duration
Latency returns how long the verification took.
func (TorConnectionStatus) Message ¶ added in v0.3.0
func (s TorConnectionStatus) Message() string
Message provides human-readable details about the check.
func (TorConnectionStatus) String ¶ added in v0.3.0
func (s TorConnectionStatus) String() string
String returns a human-readable representation of the Tor connection status.
type TorLaunchConfig ¶
type TorLaunchConfig struct {
// contains filtered or unexported fields
}
TorLaunchConfig controls how the Tor daemon is started by Tornago. It is immutable after construction via NewTorLaunchConfig.
func NewTorLaunchConfig ¶
func NewTorLaunchConfig(opts ...TorLaunchOption) (TorLaunchConfig, error)
NewTorLaunchConfig returns a validated, immutable launch config.
func (TorLaunchConfig) ControlAddr ¶
func (c TorLaunchConfig) ControlAddr() string
ControlAddr is the address for Tor's ControlPort; ":0" lets Tor pick a free port.
func (TorLaunchConfig) DataDir ¶
func (c TorLaunchConfig) DataDir() string
DataDir is the Tor DataDirectory path when explicitly configured.
func (TorLaunchConfig) ExtraArgs ¶
func (c TorLaunchConfig) ExtraArgs() []string
ExtraArgs are passed through to the tor process at launch.
func (TorLaunchConfig) LogReporter ¶
func (c TorLaunchConfig) LogReporter() func(string)
LogReporter returns the callback registered for Tor log output.
func (TorLaunchConfig) Logger ¶ added in v0.3.0
func (c TorLaunchConfig) Logger() Logger
Logger returns the structured logger for Tor daemon operations.
func (TorLaunchConfig) SocksAddr ¶
func (c TorLaunchConfig) SocksAddr() string
SocksAddr is the address for Tor's SocksPort; ":0" lets Tor pick a free port.
func (TorLaunchConfig) StartupTimeout ¶
func (c TorLaunchConfig) StartupTimeout() time.Duration
StartupTimeout bounds how long Tornago waits for tor to become ready.
func (TorLaunchConfig) TorBinary ¶
func (c TorLaunchConfig) TorBinary() string
TorBinary is the tor executable path; defaults to LookPath("tor") when empty.
func (TorLaunchConfig) TorConfigFile ¶
func (c TorLaunchConfig) TorConfigFile() string
TorConfigFile is the optional tor configuration file path passed with "-f".
type TorLaunchOption ¶
type TorLaunchOption func(*TorLaunchConfig)
TorLaunchOption customizes TorLaunchConfig creation.
func WithTorBinary ¶
func WithTorBinary(path string) TorLaunchOption
WithTorBinary sets the tor executable path.
func WithTorConfigFile ¶
func WithTorConfigFile(path string) TorLaunchOption
WithTorConfigFile sets the torrc path passed to tor via "-f".
func WithTorControlAddr ¶
func WithTorControlAddr(addr string) TorLaunchOption
WithTorControlAddr sets the ControlPort listen address.
func WithTorDataDir ¶
func WithTorDataDir(path string) TorLaunchOption
WithTorDataDir forces Tor to use the provided DataDirectory path.
func WithTorExtraArgs ¶
func WithTorExtraArgs(args ...string) TorLaunchOption
WithTorExtraArgs appends additional CLI args passed to tor.
func WithTorLogReporter ¶
func WithTorLogReporter(fn func(string)) TorLaunchOption
WithTorLogReporter registers a callback to receive Tor startup logs.
func WithTorLogger ¶ added in v0.3.0
func WithTorLogger(logger Logger) TorLaunchOption
WithTorLogger sets the structured logger for Tor daemon operations.
func WithTorSocksAddr ¶
func WithTorSocksAddr(addr string) TorLaunchOption
WithTorSocksAddr sets the SocksPort listen address.
func WithTorStartupTimeout ¶
func WithTorStartupTimeout(timeout time.Duration) TorLaunchOption
WithTorStartupTimeout sets how long Tornago waits for tor to start.
type TorListener ¶ added in v0.2.0
type TorListener struct {
// contains filtered or unexported fields
}
TorListener implements net.Listener for Tor Hidden Services. It wraps a local TCP listener and exposes it as a Tor onion service.
Example usage:
client, _ := tornago.NewClient(tornago.NewClientConfig(...))
listener, _ := client.Listen(ctx, 80, 8080) // onion:80 -> local:8080
defer listener.Close()
for {
conn, err := listener.Accept()
if err != nil {
break
}
go handleConnection(conn)
}
func (*TorListener) Accept ¶ added in v0.2.0
func (l *TorListener) Accept() (net.Conn, error)
Accept waits for and returns the next connection to the listener. This implements net.Listener.
func (*TorListener) Addr ¶ added in v0.2.0
func (l *TorListener) Addr() net.Addr
Addr returns the .onion address of the listener. This implements net.Listener.
func (*TorListener) Close ¶ added in v0.2.0
func (l *TorListener) Close() error
Close stops listening and removes the hidden service from Tor. This implements net.Listener.
func (*TorListener) HiddenService ¶ added in v0.2.0
func (l *TorListener) HiddenService() HiddenService
HiddenService returns the underlying HiddenService. This can be used to access the private key or other hidden service details.
func (*TorListener) OnionAddress ¶ added in v0.2.0
func (l *TorListener) OnionAddress() string
OnionAddress returns the full .onion address (e.g., "abc123.onion").
func (*TorListener) VirtualPort ¶ added in v0.2.0
func (l *TorListener) VirtualPort() int
VirtualPort returns the port exposed on the .onion address.
type TorProcess ¶
type TorProcess struct {
// contains filtered or unexported fields
}
TorProcess represents a running tor daemon launched by Tornago. It is immutable and exposes read-only accessors for its properties.
func StartTorDaemon ¶
func StartTorDaemon(cfg TorLaunchConfig) (_ *TorProcess, err error)
StartTorDaemon launches the tor binary as a child process using the provided configuration. It waits until both the SocksPort and ControlPort become reachable or until StartupTimeout elapses.
This function is useful when you want your application to manage its own Tor instance rather than relying on a system-wide Tor daemon. StartTorDaemon handles:
- Finding the tor binary in PATH (install via: apt install tor, brew install tor, choco install tor)
- Allocating free ports when using ":0" addresses
- Configuring cookie authentication automatically
- Waiting for Tor to become ready before returning
- Creating/managing the Tor DataDirectory
The returned TorProcess must be stopped via Stop() to cleanly terminate Tor and clean up resources. Use defer torProc.Stop() to ensure cleanup.
Example usage:
cfg, _ := tornago.NewTorLaunchConfig(
tornago.WithTorSocksAddr(":0"), // Auto-select free port
tornago.WithTorControlAddr(":0"), // Auto-select free port
)
torProc, err := tornago.StartTorDaemon(cfg)
if err != nil {
log.Fatalf("failed to start tor: %v", err)
}
defer torProc.Stop()
// Use torProc.SocksAddr() and torProc.ControlAddr() to connect
clientCfg, _ := tornago.NewClientConfig(
tornago.WithClientSocksAddr(torProc.SocksAddr()),
)
client, _ := tornago.NewClient(clientCfg)
defer client.Close()
func (TorProcess) ControlAddr ¶
func (p TorProcess) ControlAddr() string
ControlAddr returns the resolved ControlPort address of the launched tor daemon.
func (TorProcess) DataDir ¶
func (p TorProcess) DataDir() string
DataDir returns the Tor data directory path used by this process.
func (TorProcess) PID ¶
func (p TorProcess) PID() int
PID returns the process identifier of the launched tor daemon.
func (TorProcess) SocksAddr ¶
func (p TorProcess) SocksAddr() string
SocksAddr returns the resolved SocksPort address of the launched tor daemon.
func (*TorProcess) Stop ¶
func (p *TorProcess) Stop() error
Stop terminates the tor process and cleans up temporary resources.
type TornagoError ¶
type TornagoError struct {
// Kind classifies the error for programmatic handling.
Kind ErrorKind
// Op names the operation during which the error occurred.
Op string
// Msg carries an optional human-readable description.
Msg string
// Err stores the wrapped underlying error.
Err error
}
TornagoError wraps an underlying error with a Kind and an optional operation label so callers can branch on error type while retaining context.
func (*TornagoError) Error ¶
func (e *TornagoError) Error() string
Error returns a formatted string that includes Kind, Op, and the wrapped error.
func (*TornagoError) Is ¶
func (e *TornagoError) Is(target error) bool
Is reports whether target has the same ErrorKind, enabling errors.Is checks.
func (*TornagoError) Unwrap ¶
func (e *TornagoError) Unwrap() error
Unwrap exposes the underlying error for errors.Is / errors.As compatibility.
type TrackerStats ¶ added in v0.4.0
type TrackerStats struct {
// TrackedRelays is the number of relays being tracked.
TrackedRelays int
// BlockedRelays is the number of currently blocked relays.
BlockedRelays int
// Threshold is the current threshold configuration.
Threshold RelayThreshold
}
TrackerStats provides statistics about the tracker.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
examples
|
|
|
circuit_management
command
Package main demonstrates advanced circuit management features including automatic circuit rotation, manual rotation, and circuit prewarming.
|
Package main demonstrates advanced circuit management features including automatic circuit rotation, manual rotation, and circuit prewarming. |
|
circuit_rotation
command
Package main demonstrates Tor circuit rotation using NEWNYM signal.
|
Package main demonstrates Tor circuit rotation using NEWNYM signal. |
|
error_handling
command
Package main demonstrates proper error handling with tornago.
|
Package main demonstrates proper error handling with tornago. |
|
existing_tor
command
Package main demonstrates connecting to an existing Tor daemon.
|
Package main demonstrates connecting to an existing Tor daemon. |
|
metrics_ratelimit
command
Package main demonstrates metrics collection and rate limiting.
|
Package main demonstrates metrics collection and rate limiting. |
|
observability
command
Package main demonstrates observability features: logging, metrics, and health checks.
|
Package main demonstrates observability features: logging, metrics, and health checks. |
|
onion_client
command
Package main provides an example client that connects to an onion service through Tor.
|
Package main provides an example client that connects to an onion service through Tor. |
|
onion_server
command
Package main provides an example HTTP server accessible via Tor hidden service.
|
Package main provides an example HTTP server accessible via Tor hidden service. |
|
persistent_onion
command
Package main demonstrates creating a Hidden Service with a persistent private key.
|
Package main demonstrates creating a Hidden Service with a persistent private key. |
|
security
command
Package main demonstrates security features: Tor connection verification, DNS leak detection, and Hidden Service client authentication.
|
Package main demonstrates security features: Tor connection verification, DNS leak detection, and Hidden Service client authentication. |
|
simple_client
command
Package main provides a simple example of making HTTP requests through Tor.
|
Package main provides a simple example of making HTTP requests through Tor. |
|
slow_relay_avoidance
command
Package main demonstrates the slow relay avoidance feature.
|
Package main demonstrates the slow relay avoidance feature. |