Skip to content

A Tor-proxied HTTP client and ControlPort client for interacting with the Tor network in PHP.

License

Notifications You must be signed in to change notification settings

EdouardCourty/tor-php

Repository files navigation

TOR-PHP

PHP CI

TOR-PHP is a PHP library for Tor network integration. It provides two main components:

  • TorHttpClient - A Symfony HttpClient implementation that routes HTTP requests through the Tor SOCKS5 proxy for anonymous communication.
  • TorControlClient - A socket-based client implementing the Tor Control Protocol for managing circuits, configuration, and onion services.

Table of Contents


Quick Start

  1. Install and start Tor:

    # Debian/Ubuntu
    sudo apt install tor
    sudo systemctl start tor
    
    # macOS
    brew install tor
    brew services start tor
  2. Install TOR-PHP:

    composer require ecourty/tor-php
  3. Make your first request:

    <?php
    require 'vendor/autoload.php';
    
    use TorPHP\TorHttpClient;
    
    $client = new TorHttpClient();
    $response = $client->request('GET', 'https://api.ipify.org?format=json');
    echo $response->getContent(); // Your Tor exit IP

Installation

1. Install Tor

On Debian/Ubuntu

sudo apt install tor

On macOS (Homebrew)

brew install tor

2. Configure Tor ControlPort

Edit your Tor configuration file (/etc/tor/torrc or /usr/local/etc/tor/torrc):

ControlPort 9051

See the Authentication section for configuring authentication.

3. Install TOR-PHP via Composer

composer require ecourty/tor-php

Requirements

  • PHP 8.4 or higher
  • Tor daemon running locally
  • ControlPort enabled in Tor configuration (required for TorControlClient features)

Authentication

The Tor ControlPort should always be protected with authentication. TOR-PHP supports three authentication methods.

Password Authentication

Recommended for production environments.

  1. Generate a hashed password:

    tor --hash-password "your_secure_password"
  2. Add to /etc/tor/torrc:

    ControlPort 9051
    HashedControlPassword 16:872860B76453A77D60CA2BB8C1A7042072093276A3D701AD684053EC4C
  3. Use in PHP:

    use TorPHP\TorControlClient;
    
    $control = new TorControlClient(
        password: 'your_secure_password'
    );

Cookie Authentication

Recommended when the PHP process runs as the same user as Tor.

  1. Configure /etc/tor/torrc:

    ControlPort 9051
    CookieAuthentication 1
  2. Use in PHP:

    use TorPHP\TorControlClient;
    
    $control = new TorControlClient(
        authenticationCookie: '/var/run/tor/control.authcookie'
    );

    The cookie file path varies by system:

    • Linux: /var/run/tor/control.authcookie
    • macOS (Homebrew): /usr/local/var/run/tor/control.authcookie

No Authentication (Not Recommended)

Only use for local development on isolated systems.

Configure /etc/tor/torrc:

ControlPort 9051
CookieAuthentication 0

Use in PHP:

use TorPHP\TorControlClient;

$control = new TorControlClient(); // No credentials

Warning: Running Tor ControlPort without authentication is a security risk. Any process on the system can control your Tor instance.


Features

HTTP Client Features

  • HTTP/HTTPS requests through Tor SOCKS5 proxy (port 9050)
  • Request new identity (change Tor circuit)
  • Retrieve current Tor exit nodes
  • Compatible with Symfony HttpClient interface

Control Client Features

  • Circuit management and inspection
  • Signal new identity (NEWNYM)
  • Configuration management (GETCONF, SETCONF)
  • Onion service creation and deletion
  • ED25519-V3 keypair generation for onion services
  • Tor event subscription
  • Wait for circuit build completion

Security Baseline

Mandatory Authentication

Running Tor ControlPort without authentication is dangerous. An attacker with local access could:

  • Reconfigure your Tor instance
  • Create onion services
  • Monitor your traffic
  • Manipulate circuits

Always use password or cookie authentication in production.

Best Practices

  • Protect credentials: Never commit passwords or cookie files to version control
  • File permissions: Set restrictive permissions on sensitive files:
    chmod 600 /path/to/onion/private.key
    chmod 600 /path/to/.env
  • Environment variables: Store credentials in environment variables:
    $control = new TorControlClient(
        password: $_ENV['TOR_CONTROL_PASSWORD']
    );
  • Sensitive parameter protection: TOR-PHP uses #[\SensitiveParameter] to prevent credential leakage in stack traces

Usage Examples

Example 1: Get current IP via Tor

<?php

use TorPHP\TorHttpClient;
use Symfony\Component\HttpClient\HttpClient;

$torClient = new TorHttpClient();

$response = $torClient->request('GET', 'https://api.ipify.org?format=json');
$torIp = $response->toArray()['ip'];

$normalClient = HttpClient::create();
$normalIp = $normalClient->request('GET', 'https://api.ipify.org?format=json')->toArray()['ip'];

echo "Tor IP: $torIp" . PHP_EOL;
echo "Non-Tor IP: $normalIp" . PHP_EOL;

Example 2: Request a New Identity

<?php

use TorPHP\TorHttpClient;

$torClient = new TorHttpClient();
$torClient->request('GET', 'https://example.com');

// Change circuit when you need
$torClient->newIdentity();

$response = $torClient->request('GET', 'https://example.com/another-page');

Example 3: Manage Your Tor Node

<?php

use TorPHP\TorControlClient;
use TorPHP\Model\PortMapping;

$control = new TorControlClient();

// Get circuits
$circuits = $control->getCircuits();

// Change config
$control->setConfigValue('SocksPort', '9080');

// Add onion service
$onion = $control->addOnionService([
    new PortMapping(host: 'localhost', localPort: 3000, remotePort: 80),
]);

// List onion services
$services = $control->listOnionServices();

// Delete onion service
$control->deleteOnionService($onion->id);

Example 4: Generate Onion Service Keys

<?php

use TorPHP\Helper\KeyPairGenerator;
use TorPHP\TorControlClient;
use TorPHP\Model\PortMapping;

// Generate a new ED25519-V3 keypair
$keyPair = KeyPairGenerator::generate();

echo "Service ID: {$keyPair->serviceId}.onion\n";
echo "Private Key: {$keyPair->getPrivateKeyFormatted()}\n";

// Use the generated key to create an onion service
$control = new TorControlClient();
$onion = $control->addOnionService(
    portMappings: [new PortMapping('127.0.0.1', 8080, 80)],
    privateKey: $keyPair->getPrivateKeyBase64()
);

// The onion service ID will match the derived serviceId from the keypair
assert($onion->id === $keyPair->serviceId);

Other code examples can be found here.


Changelog

See CHANGELOG.md for details.


Contributing

See CONTRIBUTING.md for contribution guidelines.


License

Author: Edouard Courty
License: MIT - See LICENSE
Copyright © 2025


Need Help?

Feel free to open an issue or contribute via pull requests.

About

A Tor-proxied HTTP client and ControlPort client for interacting with the Tor network in PHP.

Resources

License

Contributing

Stars

Watchers

Forks

Packages

No packages published

Languages