Skip to content

⚠️ This is NOT the official shadowsocks website ⚠️

The official shadowsocks site is at shadowsocks.org

Under the condition of MIT License of the original project, this forked site is used ONLY for non-commercial and personal study purposes. The official shadowsocks site is at shadowsocks.org. In addition, the SEO indexing has been turned off on this site in order to protect the exposure of the official shadowsocks.org on the internet

The official shadowsocks site is at shadowsocks.org

Setting Up shadowsocks on Ubuntu Server and Client on Mac

This is a robust, modern guide to deploying a Shadowsocks-Rust server on an AWS EC2 instance using Podman, and connecting to it from macOS.

Part 1: Server Setup (AWS EC2 Ubuntu)

We will use the Rust implementation of Shadowsocks (shadowsocks-rust) because it is actively maintained, memory-safe, and highly performant compared to the older Python or C (libev) versions.

Step 1: Install Podman or Docker

TIP

OpenML prefer Podman over Docker, so we install Podman on our Ubuntu instance as an example. But it doesn't stop anyone who would rather use Docker instead

bash
sudo apt-get update
sudo apt-get install -y podman

Step 2: Prepare Configuration

Create a directory to store shadowsocks configuration so it persists across container restarts.

bash
mkdir -p ~/shadowsocks
nano ~/shadowsocks/config.json

Paste the following configuration. Replace <MY_PASSWORD> with a strong password.

json
{
    "server": "0.0.0.0",
    "server_port": 8388,
    "password": "<YOUR_PASSWORD>",
    "timeout": 300,
    "method": "aes-256-gcm",
    "fast_open": true
}
  • Method: aes-256-gcm is the industry standard for speed and security on modern hardware (AES-NI).
  • Server: Must be 0.0.0.0 to allow the container to accept external connections.

Step 3: Run the Server with Podman

Run the container in detached mode (-d). We use --network host for performance efficiency, or we can map ports manually. Here is the standard port-mapping approach for better isolation:

bash
podman run -d \
  --name ss-server \
  --restart always \
  -p 8388:8388/tcp \
  -p 8388:8388/udp \
  -v ~/shadowsocks/config.json:/etc/shadowsocks-rust/config.json \
  ghcr.io/shadowsocks/ssserver-rust:latest

WARNING

If we specified a different port in shadowsocks configuration earlier, we must adjust the port forwarding -p 8388:8388/tcp and -p 8388:8388/udp as well.

Step 4: Configure AWS Security Group

The server is running, but AWS needs to let the traffic in.

  1. Go to the AWS Console > EC2 > Security Groups.

  2. Select the Security Group attached to our instance.

  3. Edit Inbound rules.

  4. Add a Custom TCP rule:

    • Port range: 8388
    • Source: 0.0.0.0/0 (or some specific IP for better security).
  5. (Optional but recommended) Add a Custom UDP rule for the same port 8388 if you plan to use UDP relaying.

(If Podman was Used) Step 5:

There is a classic behavior of rootless containers on systemd-based Linux distros (like Ubuntu). When we run a container as a regular user (rootless) inside an SSH session, that container is a child process of our login session. The Systemd creates a "session scope" for us upon session is initiated. The container would live inside this scope. When we exit the SSH session, systemd detects the session has ended and, to keep the system clean, sends a SIGTERM (which also gets printed in the container logs) to all processes in that scope, effectively killing our shadowsocks server.

To avoid this, we need to tell systemd to "linger" for our user. This promotes our user to a "long-running" status, allowing our processes to survive even after we disconnect. To do that, run this command on the EC2 instance:

bash
sudo loginctl enable-linger $USER

INFO

The $USER automatically picks our current username, usually ubuntu on AWS.

Part 2: Client Setup (macOS as an example)

For macOS, the standard, reliable client is ShadowsocksX-NG which supports both modern macOS versions and Apple Silicon. In addition, it has out-of-the box for HTTP proxy support as well.

  1. Download

  2. Install

    • Open the .dmg and drag the app to our Applications folder.
    • Open the app. It will appear as a paper airplane icon in our menu bar.
  3. Configure:

    • Click the paper airplane icon in the menu bar.
    • Select Server Preferences.
    • Click the + button to add a new server.
    • Address: Our AWS EC2 Public IP.
    • Port: 8388
    • Encryption: aes-256-gcm
    • Password: The password we set in config.json.
    • Click OK.
  4. Activate:

    • Click the menu bar icon again.
    • Ensure Shadowsocks: On is checked.
    • Select Global Mode (proxies everything) or PAC Mode (proxies only blocked sites based on a list). Global Mode is easier for testing.
  5. Verification

    To verify the traffic is routing through our EC2:

    • Open a terminal on Mac.
    • Run: curl ifconfig.me
    • If the setup is working, it should return the IP address of the AWS EC2 instance, not our home IP.

Getting Started

First, you need to pick a shadowsocks server and client implementation. Any implementation below is compatible with each other.

CLI implementations

  • shadowsocks-libev: Lightweight C implementation for embedded devices and low end boxes. Very small footprint (several megabytes) for thousands of connections.
  • go-shadowsocks2: Go implementation focusing on core features and code reusability.
  • shadowsocks-rust: A rust port of shadowsocks.

Feature comparison

ss-libevgo-ss2ss-rust
TCP Fast Open
Multiuser
Management API
Redirect mode
Tunnel mode
UDP Relay
MPTCP
AEAD ciphers
Plugin
Plugin UDP (Experimental)

GUI Clients

Feature comparison

ss-winssx-ngss-qt5ss-android
System Proxy
CHNRoutes
PAC Configuration
Profile Switching
QR Code Scan
QR Code Generation

This website is released under the MIT License.