Skip to content

xrdavies/light-ss

Repository files navigation

Light Shadowsocks Client

A lightweight shadowsocks client written in Go that provides local HTTP/HTTPS and SOCKS5 proxy servers. Forward all your traffic through a shadowsocks server with ease.

Features

  • Shadowsocks Client: Connect to any shadowsocks server with AEAD cipher support
  • Server Testing: Test SS servers without starting the daemon - measure latency and speed (latency-only mode available for bandwidth savings)
  • Unified Proxy Mode: Single port for HTTP/HTTPS and SOCKS5 (like Clash)
  • Separate Proxy Mode: Dedicated ports for HTTP and SOCKS5
  • Simple-obfs Plugin: HTTP and TLS obfuscation support
  • Command-line Parameters: Run without config files - perfect for automation
  • Config Converters: Import from ss-local and Clash configurations
  • Statistics Monitoring: Track connections and bandwidth usage
  • Management API: REST API for monitoring, speed testing (with latency-only mode), and hot-reload
  • Graceful Shutdown: Proper cleanup on exit signals
  • Flexible Configuration: YAML/JSON config files, environment variables, or CLI params

Installation

From Source

git clone https://github.com/xrdavies/light-ss.git
cd light-ss
make build

The binary will be available at ./bin/light-ss.

Manual Build

go build -o light-ss ./cmd/light-ss

Quick Start

Using Configuration File

  1. Create a configuration file:
cp config.yaml.example config.yaml
  1. Edit config.yaml with your shadowsocks server details:
shadowsocks:
  server: "example.com:8388"
  password: "your-strong-password"
  cipher: "AEAD_CHACHA20_POLY1305"
  timeout: 300

# Unified mode - single port for both HTTP and SOCKS5
proxies: "127.0.0.1:1080"

Or use JSON format (config.json):

{
  "shadowsocks": {
    "server": "example.com",
    "port": 8388,
    "method": "aes-128-gcm",
    "password": "your-password",
    "timeout": 300
  },
  "proxies": "127.0.0.1:1080"
}
  1. Start the client:
./light-ss start -c config.yaml
  1. Configure your applications to use the proxy at 127.0.0.1:1080

Using Command-line Parameters (No Config File)

./light-ss start \
  --server example.com \
  --port 8388 \
  --password your-strong-password \
  --method aes-128-gcm \
  --proxies 127.0.0.1:1080

With Simple-obfs Plugin

./light-ss start \
  --server example.com \
  --port 8388 \
  --password your-strong-password \
  --method aes-128-gcm \
  --plugin simple-obfs \
  --plugin-obfs http \
  --plugin-host www.bing.com \
  --proxies 127.0.0.1:1080

Usage

Start the Client

# With config file
./light-ss start -c config.yaml

# With CLI parameters only
./light-ss start -s server.com -p 8388 --password pass -m aes-128-gcm

# Override config file values
./light-ss start -c config.yaml --log-level debug --proxies 0.0.0.0:1080

# View all available flags
./light-ss start --help

Convert Existing Configurations

# Convert from ss-local format
./light-ss convert --from ss-local --input ss-local.json --output config.json

# Convert from Clash format
./light-ss convert --from clash --input clash.yaml --output config.yaml

# Print to stdout (JSON format)
./light-ss convert --from ss-local --input ss-local.json

Test Shadowsocks Servers

Test a shadowsocks server without starting the full daemon. This is useful for:

  • Validating server credentials before use
  • Testing server availability and performance
  • Benchmarking multiple servers
  • Integration with automation tools

Basic Test:

# Test with command-line parameters
./light-ss test \
  -s server.com:8388 \
  --password your-password \
  -m aes-128-gcm

# Output:
# ✅ Test successful
# Server:   server.com:8388
# Cipher:   aes-128-gcm
# Latency:  45ms
# Speed:    127.78 Mbps

Test from Config File:

./light-ss test -c config.yaml

Quick Latency Check (Skip Speed Test):

./light-ss test \
  -s server.com:8388 \
  --password your-password \
  -m aes-128-gcm \
  --latency-only

JSON Output (For Automation):

./light-ss test \
  -s server.com:8388 \
  --password your-password \
  -m aes-128-gcm \
  --json

# Output:
# {
#   "server": "server.com:8388",
#   "cipher": "aes-128-gcm",
#   "success": true,
#   "latency_ms": 45,
#   "download_speed_bps": 16777216,
#   "download_speed_mbps": 127.78,
#   "timestamp": "2025-12-02T10:30:00Z"
# }

With Plugin:

./light-ss test \
  -s server.com:8388 \
  --password your-password \
  -m aes-128-gcm \
  --plugin simple-obfs \
  --plugin-obfs http \
  --plugin-host www.bing.com

Test Flags:

  • -s, --server - Server address (with or without port)
  • -p, --port - Server port (if not in server address)
  • --password - Server password
  • -m, --method - Encryption method
  • -c, --config - Load from config file
  • --timeout - Connection timeout in seconds (default: 10)
  • --duration - Speed test duration in seconds (default: 10)
  • --latency-only - Only test connection latency, skip download speed test. Saves bandwidth (~10MB per test). Uses www.google.com:80 for faster testing.
  • --json - Output result as JSON
  • --plugin - Plugin name (e.g., simple-obfs)
  • --plugin-obfs - Obfuscation mode (http or tls)
  • --plugin-host - Obfuscation host header

Use Cases:

# Test multiple servers and compare
for server in server1.com:8388 server2.com:8388; do
  ./light-ss test -s $server --password pass -m aes-128-gcm --json
done

# Validate subscription servers
cat servers.txt | while read server; do
  ./light-ss test -s $server --password pass -m aes-128-gcm --latency-only
done

# CI/CD health check
./light-ss test -c config.yaml --json | jq -e '.success == true'

Testing the Proxies

# Unified mode (single port for both protocols)
curl -x socks5://127.0.0.1:1080 https://www.google.com
curl -x http://127.0.0.1:1080 https://www.google.com

# Separate mode
curl -x socks5://127.0.0.1:1080 https://www.google.com
curl -x http://127.0.0.1:8080 https://www.google.com

Browser Configuration

Firefox

  1. Settings → Network Settings → Manual proxy configuration
  2. SOCKS Host: 127.0.0.1, Port: 1080
  3. Check "SOCKS v5" and "Proxy DNS when using SOCKS v5"

Note: With unified mode, both HTTP and SOCKS5 work on the same port!

Chrome/Chromium

# Unified mode - use either SOCKS5 or HTTP on same port
chromium --proxy-server="socks5://127.0.0.1:1080"
chromium --proxy-server="http://127.0.0.1:1080"

# Separate mode
chromium --proxy-server="socks5://127.0.0.1:1080"
chromium --proxy-server="http://127.0.0.1:8080"

Configuration

Configuration File

The configuration file supports both YAML and JSON formats. See config.yaml.example or config.json.example for complete examples.

Instance Identification

# Optional: Instance name for identification
name: "my-hk-proxy"

The instance name helps identify your light-ss instance in:

  • Log messages (stats output)
  • API responses (health, version, stats, config endpoints)
  • Monitoring and debugging across multiple instances

This is especially useful when running multiple light-ss instances and need to distinguish between them.

Shadowsocks Settings

shadowsocks:
  server: "example.com:8388"          # Server address and port
  password: "your-strong-password"    # Server password
  cipher: "AEAD_CHACHA20_POLY1305"   # Encryption cipher
  timeout: 300                        # Connection timeout (seconds)

  # Optional: Simple-obfs plugin
  plugin: "simple-obfs"
  plugin_opts:
    obfs: "http"                      # or "tls"
    obfs-host: "www.bing.com"

Supported Ciphers:

  • AEAD_CHACHA20_POLY1305 (recommended)
  • AEAD_AES_256_GCM
  • AEAD_AES_192_GCM
  • AEAD_AES_128_GCM
  • AEAD_XCHACHA20_POLY1305

Alternative formats (auto-normalized):

  • aes-128-gcm, aes-192-gcm, aes-256-gcm
  • chacha20-poly1305, chacha20-ietf-poly1305
  • xchacha20-poly1305

Proxy Settings

Unified Mode (Recommended): Single port for both HTTP/HTTPS and SOCKS5

# YAML format
proxies: "127.0.0.1:1080"
// JSON format
{
  "proxies": "127.0.0.1:1080"
}

Separate Mode: Dedicated ports for each protocol

# YAML format
proxies:
  http: "127.0.0.1:8080"
  socks5: "127.0.0.1:1080"
// JSON format
{
  "proxies": {
    "http": "127.0.0.1:8080",
    "socks5": "127.0.0.1:1080"
  }
}

SOCKS5 with Authentication:

proxies:
  socks5: "user:pass@127.0.0.1:1080"

Statistics

stats:
  enabled: true     # Enable stats collection
  interval: 60      # Report interval in seconds

When enabled, statistics will be logged periodically showing:

  • Total and active connections
  • HTTP and SOCKS5 connection counts
  • Bytes sent and received
  • Uptime

Logging

logging:
  level: "info"     # debug, info, warn, error
  format: "text"    # json, text

Command-line Parameters

All configuration can be specified via command-line flags:

./light-ss start [flags]

Shadowsocks Flags:

  • -s, --server string - Shadowsocks server address
  • -p, --port int - Shadowsocks server port
  • --password string - Shadowsocks password
  • -m, --method string - Encryption method (aes-128-gcm, aes-256-gcm, chacha20-poly1305)
  • --timeout int - Connection timeout in seconds

Plugin Flags:

  • --plugin string - Plugin name (e.g., simple-obfs)
  • --plugin-obfs string - Obfuscation mode: http or tls
  • --plugin-host string - Obfuscation host header

Proxy Flags:

  • --proxies string - Unified proxy listen address (e.g., 127.0.0.1:1080)
  • --http-proxy string - HTTP/HTTPS proxy listen address
  • --socks5-proxy string - SOCKS5 proxy listen address (supports user:pass@host:port)

Other Flags:

  • -c, --config string - Path to configuration file (optional)
  • --log-level string - Log level (debug, info, warn, error)

Examples:

# Minimal setup
./light-ss start -s server.com -p 8388 --password pass -m aes-128-gcm

# With plugin
./light-ss start \
  -s server.com -p 8388 --password pass -m aes-128-gcm \
  --plugin simple-obfs --plugin-obfs http --plugin-host www.bing.com

# Separate proxy ports
./light-ss start -s server.com -p 8388 --password pass -m aes-128-gcm \
  --http-proxy 127.0.0.1:8080 --socks5-proxy 127.0.0.1:1080

# Override config file
./light-ss start -c config.yaml --log-level debug --proxies 0.0.0.0:1080

Environment Variables

You can override configuration values using environment variables:

export LIGHT_SS_SERVER="example.com:8388"
export LIGHT_SS_PASSWORD="your-strong-password"
export LIGHT_SS_CIPHER="AEAD_CHACHA20_POLY1305"
export LIGHT_SS_HTTP_LISTEN="127.0.0.1:8080"
export LIGHT_SS_SOCKS5_LISTEN="127.0.0.1:1080"
export LIGHT_SS_LOG_LEVEL="debug"

Priority: CLI flags > Environment variables > Config file > Defaults

Architecture

Unified Mode (Default)

Single port handles both HTTP/HTTPS and SOCKS5 through protocol detection:

Client Apps → Unified Proxy:1080 → Stats → Shadowsocks+Plugin → Server → Internet
              (HTTP or SOCKS5)

Separate Mode (Optional)

Dedicated ports for each protocol:

Client Apps → HTTP:8080 ────┐
              SOCKS5:1080 ───┴→ Stats → Shadowsocks → Server → Internet

Management API

Light-ss provides a REST API for monitoring, configuration management, and control operations.

Enabling the API

Via Config File:

api:
  enabled: true
  listen: "127.0.0.1:8090"
  token: "your-secret-token"  # Optional bearer token for authentication

Via CLI Flags:

./light-ss start -c config.yaml \
  --api-enabled \
  --api-listen 127.0.0.1:8090 \
  --api-token secret123

API Endpoints

GET /health

Health check endpoint - always returns 200 OK when running

curl http://127.0.0.1:8090/health
# Response: {"name": "my-hk-proxy", "status": "ok", "uptime": "2h30m15s"}
# Note: "name" field only included if instance name is configured

GET /version

Get version and build information

curl http://127.0.0.1:8090/version
# Response: {"name": "my-hk-proxy", "version": "1.0.0", "commit": "abc123", "build_time": "2024-01-01"}
# Note: "name" field only included if instance name is configured

GET /stats

Get current statistics (connections, bandwidth, real-time speed)

curl http://127.0.0.1:8090/stats
# With authentication:
curl -H "Authorization: Bearer secret123" http://127.0.0.1:8090/stats

Response includes:

  • Instance name (if configured)
  • Connection counts (total, active, HTTP, SOCKS5)
  • Bandwidth (bytes sent/received)
  • Current speed (download/upload in bytes/sec)
  • Uptime

GET /speedtest

Run active speed test through SS connection

# Default 10-second test
curl http://127.0.0.1:8090/speedtest

# Custom duration
curl "http://127.0.0.1:8090/speedtest?duration=30"

# Latency-only test (saves bandwidth, no download test)
curl "http://127.0.0.1:8090/speedtest?latency_only=true"

# Combined parameters
curl "http://127.0.0.1:8090/speedtest?duration=5&latency_only=true"

# Response: {"download_speed": 1234567, "latency_ms": 45, "test_duration_sec": 30}
# Note: download_speed will be 0 when latency_only=true

Query Parameters:

  • duration - Test duration in seconds (1-300, default: 10). Only used for download speed test.
  • latency_only - If true or 1, only measures connection latency without downloading test data. Uses www.google.com:80 for faster testing. If false or omitted, performs full speed test using speed.cloudflare.com.

GET /config

Get current configuration (passwords sanitized)

curl http://127.0.0.1:8090/config
# Response includes instance name (if configured), server, cipher, plugin settings, and proxy configuration
# Passwords replaced with "***"

POST /reload

Hot-reload shadowsocks configuration without restart

# Reload server configuration
curl -X POST http://127.0.0.1:8090/reload \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer secret123" \
  -d '{"server": "new-server.com:8388", "password": "newpass", "cipher": "aes-256-gcm"}'

# Reload with plugin
curl -X POST http://127.0.0.1:8090/reload \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer secret123" \
  -d '{
    "server": "new-server.com:8388",
    "password": "newpass",
    "cipher": "aes-256-gcm",
    "plugin": "simple-obfs",
    "plugin_opts": {
      "obfs": "http",
      "obfs-host": "www.bing.com"
    }
  }'

Behavior: Graceful reload - new connections use new config immediately, existing connections continue with old config until they close naturally.

POST /stop

Graceful shutdown of all servers

curl -X POST http://127.0.0.1:8090/stop \
  -H "Authorization: Bearer secret123"

API Security

  • Bearer Token: Optional authentication (disabled by default)
  • Localhost Binding: Binds to 127.0.0.1 by default for security
  • Password Sanitization: Passwords never exposed in API responses
  • HTTPS: Use a reverse proxy (nginx/caddy) for HTTPS if needed

Config Converters

Light-ss can import configurations from other shadowsocks clients:

From ss-local (shadowsocks-libev)

# Convert and save
./light-ss convert --from ss-local --input ss-local.json --output config.json

# Print to stdout
./light-ss convert --from ss-local --input ss-local.json

ss-local format (JSON):

{
  "server": "example.com",
  "server_port": 8388,
  "password": "password",
  "method": "aes-128-gcm",
  "plugin": "obfs-local",
  "plugin_opts": "obfs=http;obfs-host=www.bing.com"
}

From Clash

# Convert to YAML
./light-ss convert --from clash --input clash.yaml --output config.yaml

# Convert to JSON
./light-ss convert --from clash --input clash.yaml --output config.json

Clash format (YAML):

proxies:
  - name: "ss-server"
    type: ss
    server: example.com
    port: 8388
    cipher: aes-128-gcm
    password: "password"
    plugin: obfs
    plugin-opts:
      mode: http
      host: www.bing.com

Security Considerations

  1. Cipher Selection: Always use AEAD ciphers (ChaCha20-Poly1305 or AES-GCM)
  2. Plugin Obfuscation: Use simple-obfs to disguise traffic as HTTP/TLS
  3. Local Only: Proxies bind to 127.0.0.1 by default - don't expose them publicly
  4. Config File: Protect your config file permissions: chmod 600 config.yaml
  5. No Logging: Sensitive data like passwords are never logged
  6. HTTPS: The client doesn't inspect HTTPS traffic - it only tunnels it

Troubleshooting

Enable Debug Logging

./light-ss start -c config.yaml --log-level debug

Connection Issues

  • Verify shadowsocks server is running and accessible
  • Check cipher matches server configuration
  • Ensure password is correct
  • Test server connectivity: telnet example.com 8388

Proxy Not Working

  • Verify the proxy server started (check logs)
  • Test local connectivity: curl http://127.0.0.1:8080
  • Check firewall rules
  • Ensure no other service is using the same port

Statistics Not Showing

  • Enable stats in config: stats.enabled: true
  • Check stats interval setting
  • View logs for statistics output

Building

Build for Current Platform

make build

Build for All Platforms

make build-all

This creates binaries for:

  • Linux (amd64)
  • macOS (amd64, arm64)
  • Windows (amd64)

Dependencies

License

MIT License

Contributing

Contributions are welcome! Please feel free to submit issues or pull requests.

Author

xrdavies

About

A light-weight SS client, currently MacOS only, later will be ported to all platform.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published