18230 / shadowsocks-local
Pure PHP Shadowsocks client with a SOCKS5 frontend.
Requires
- php: ^8.2
- ext-json: *
- ext-openssl: *
- ext-sockets: *
- monolog/monolog: ^3.6
- symfony/console: ^7.2
- symfony/yaml: ^7.2
- workerman/workerman: ^5.1
Requires (Dev)
- phpunit/phpunit: ^11.4
Suggests
- ext-curl: Required if your application wants to apply SOCKS5 options directly to PHP curl handles.
- guzzlehttp/guzzle: Optional if you want to use the provided proxy settings with Guzzle.
- illuminate/support: Optional for Laravel service-provider integration.
- topthink/framework: Optional for ThinkPHP service-provider integration.
README
php-shadowsocks-client is a pure-PHP Shadowsocks client package. It exposes a local SOCKS5 endpoint through the bundled ss-local runtime and relays TCP traffic to a remote Shadowsocks server by using Workerman as the long-running runtime.
Features
- PHP 8.2+
- Windows, Linux, and macOS
- Composer package with a CLI entrypoint
- Pure PHP SOCKS5 frontend and Shadowsocks TCP relay
aes-256-gcm- YAML, JSON, and
ss://node parsing - Reusable
ProxyServicehelpers for application code - Laravel and ThinkPHP integration entry points
- Cross-platform startup scripts for development and production
- GitHub Actions Ubuntu CI workflow for Linux validation
Current Scope
Implemented:
- SOCKS5
CONNECT - Shadowsocks TCP relay
- CLI startup command
- TLS helper objects for PHP
curland Guzzle - Structured logging and basic runtime guards
Not implemented yet:
- UDP relay
- SIP003 plugins
- AEAD-2022 methods
- Additional ciphers beyond
aes-256-gcm
Installation
Install from Packagist:
composer require 18230/php-shadowsocks-client
For local development in this repository:
composer install
Quick Start
Start with explicit options:
php bin/ss-local \ --server=your-node.example.com \ --port=18001 \ --cipher=aes-256-gcm \ --password=your-password \ --listen=127.0.0.1:1080
Start with inline YAML:
php bin/ss-local --node="{ name: 'SG 01', type: ss, server: your-node.example.com, port: 18001, cipher: aes-256-gcm, password: your-password, udp: true }"
Start with a config file:
php bin/ss-local --config=examples/node.example.yaml
Validate the runtime and configuration before you start:
php bin/ss-local doctor --config=examples/node.example.yaml
Check available options:
php bin/ss-local --help
Application Usage
PHP curl
<?php use SsLocal\Support\ProxyService; use SsLocal\Support\TlsSettings; $proxy = ProxyService::fromListenAddress( '127.0.0.1:1080', TlsSettings::fromIni() ); $ch = curl_init('https://api.ipify.org?format=json'); $proxy->applyToCurlHandle($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 30, ]); $result = curl_exec($ch); curl_close($ch);
Guzzle
<?php use GuzzleHttp\Client; use SsLocal\Support\ProxyService; use SsLocal\Support\TlsSettings; $proxy = ProxyService::fromListenAddress('127.0.0.1:1080', TlsSettings::fromIni()); $client = new Client($proxy->guzzleOptions()); $response = $client->get('https://api.ipify.org?format=json'); echo $response->getBody()->getContents();
CLI curl
curl --proxy socks5h://127.0.0.1:1080 https://api.ipify.org?format=json
Configuration
The CLI accepts configuration from:
--server,--port,--cipher,--password--nodewith inline YAML, JSON, orss://--configwith YAML or JSON files
Recommended config file structure:
node: name: "SG 01" type: ss server: your-node.example.com port: 18001 cipher: aes-256-gcm password: your-password udp: true runtime: listen: 127.0.0.1:1080 worker_count: 1 max_connections: 1024 allow_ips: - 127.0.0.1 - ::1 connect_timeout: 10 connect_retries: 1 retry_delay_ms: 250 idle_timeout: 900 max_send_buffer: 4194304 status_file: runtime/ss-local.status.json status_interval: 10 log_file: runtime/ss-local.log pid_file: runtime/ss-local.pid daemon: false
Useful runtime options:
--listen=127.0.0.1:1080--worker-count=1--max-connections=1024--allow-ip=127.0.0.1,::1--connect-timeout=10--connect-retries=1--retry-delay-ms=250--idle-timeout=900--max-send-buffer=4194304--status-file=/path/to/ss-local.status.json--status-interval=10--log-file=/path/to/ss-local.log--pid-file=/path/to/ss-local.pid--daemonon non-Windows platforms--verbose-log
What these production-oriented runtime options do:
worker_count: number of Workerman worker processes on Unix-like platforms. Windows always runs a single worker.max_connections: per-worker cap for active client sessions. New clients are rejected after the cap is reached.allow_ips: optional client IP allowlist. Supports exact IPs and CIDR ranges.connect_retriesandretry_delay_ms: simple retry policy for the initial upstream Shadowsocks connect phase.status_file: periodic JSON status snapshot for ops checks or sidecar monitoring.status_interval: write interval for the status snapshot in seconds.
See node.example.yaml for a file-based example.
TLS / CA Configuration
The proxy itself does not need a CA file. Your PHP application needs one when it accesses https:// endpoints and wants certificate verification to succeed.
If curl.cainfo and openssl.cafile are not configured, PHP curl can fail even when the proxy works correctly.
Template:
Framework Integration
Production Deployment
Recommended minimum production posture:
- Keep the local listen address on loopback unless you explicitly need LAN access
- Use
--allow-ipif you bind beyond loopback - Run
php bin/ss-local doctor ...before deploying - Keep
worker_count=1unless you have validated your workload on Unix - Enable
status_fileandlog_fileso operational failures are visible
Release Notes
Examples
Testing
composer test
Notes for Publishing
- The Packagist package name for this repository is
18230/php-shadowsocks-client. - The first tag intended for the renamed package is
v0.2.0. - The previous package name
18230/shadowsocks-localshould be treated as a legacy package name. - Run
composer validate --strictandcomposer testbefore tagging a release. - To keep Packagist in sync after every push, add the
PACKAGIST_API_TOKENrepository secret and optionally thePACKAGIST_USERNAMErepository variable. - To remove the "not auto-updated" warning on Packagist, run the native GitHub hook setup script once:
scripts/setup-packagist-github-hook.ps1orscripts/setup-packagist-github-hook.sh.