CLI tool
shadowsocks/shadowsocks-c avatar
shadowsocks/shadowsocks-c

shadowsocks-c: the C Shadowsocks implementation rebuilt on libuv

Self-contained Shadowsocks implementation in C with libuv, asynchronous DNS, and portable static builds for Linux, macOS, Windows, and FreeBSD.

16,174 stars6,217 forksCGPL-3.0

At a glance

What is it?
A port of shadowsocks-libev that swapped libev for libuv and now ships pinned, statically linked builds for Linux, macOS, Windows and FreeBSD. It is aimed at embedded boxes and low-end servers, and the README is candid that new feature work lives in shadowsocks-rust.
Who is it for?
Adopt shadowsocks-c if you need a small C proxy that keeps the ss-local and ss-server command names, the shadowsocks.h API and the old configuration paths working, and you want static binaries or the ghcr.io/shadowsocks/shadowsocks-c:latest image. Do not adopt it expecting new protocol features: the README directs new development to shadowsocks-rust and describes this repository as a pure C implementation.
Can I use it commercially?
Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 17 days ago.
What is it written in?
Mainly C, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What shadowsocks-c replaces, and why the C implementation still exists

The README describes shadowsocks-c as a lightweight secured SOCKS5 proxy for embedded devices and low-end boxes. That audience explains most of the design. A router, a small VPS, or a container with a tight memory budget does not want a runtime and a package manager dragged along with it. The project is a port of the original Shadowsocks created by @clowwindy, maintained by @madeye and @linusyang, and the repository retains the commit history and releases of shadowsocks-libev.

The history matters more than the feature list here. The README states that shadowsocks-libev later entered a bug-fix-only maintenance phase, with new development directed toward shadowsocks-rust. In September 2026 the C implementation was modernized instead of abandoned: pinned dependency sources were bundled, several external dependencies were removed, and static-build validation was added across platforms. A second change replaced libev with libuv, added Windows IOCP and macOS kqueue support, and expanded asynchronous runtime DNS coverage. The project and repository were renamed shadowsocks-c to reflect that it is a pure C implementation.

So the pitch is not "faster than the alternatives". It is "the same protocol, same commands, fewer moving parts". If you already run shadowsocks-libev on constrained hardware, this is the continuation of that line rather than a new product.

libuv, IOCP, kqueue: what the event loop swap actually changes

The original C implementation was built around libev. The modernization replaced it with libuv, and that single change has visible consequences in the repository. libuv gives the project a cross-platform event loop with a Windows backend, which is why the README can list Windows IOCP and macOS kqueue support as part of the same migration rather than as separate ports. On Windows, IOCP is the completion-port model; on macOS and the BSDs, kqueue is the kernel event notification interface. Neither was reachable through the same abstraction before.

The same migration expanded asynchronous runtime DNS coverage. In a SOCKS5 proxy, name resolution is on the critical path: a client hands over a hostname, and the proxy has to resolve it before it can connect. Doing that synchronously blocks the event loop for every request. The README presents the async DNS work as part of the libuv migration, which is consistent with libuv's own DNS facilities.

The build side is the second half of the story. The default build uses pinned sources included in the repository, and the README states that no Git submodules, dependency package installations, or network access are needed for configuration or build. That is a deliberate trade: the repository carries vendored dependency code, which you have to audit and update yourself, in exchange for builds that work on a machine with no package mirror. The third_party/ directory at the repository root is where that code lives.

Installing shadowsocks-c with Docker and a first server config

Docker is the recommended way to run a server, according to the README. The image contains the bundled, fully static C binaries and supports Linux AMD64 and ARM64, including Linux containers under Docker Desktop on macOS and Windows. Start with a configuration file. The README's example uses port 8388, aes-256-gcm, and a mode that covers both transports; replace the password with your own long random value.

json
{
  "server": "0.0.0.0",
  "server_port": 8388,
  "password": "replace-with-a-long-random-password",
  "method": "aes-256-gcm",
  "mode": "tcp_and_udp"
}

Then pull the image and run it with the config mounted read-only. The README's command runs the container as your own user ID so it can read a file you own, drops all capabilities, and disables privilege escalation.

sh
docker pull ghcr.io/shadowsocks/shadowsocks-c:latest
docker run -d --name shadowsocks-c --restart unless-stopped \
  --user "$(id -u):$(id -g)" --read-only --cap-drop=ALL \
  --security-opt=no-new-privileges:true \
  -p 8388:8388/tcp -p 8388:8388/udp \
  --mount type=bind,src="$PWD/config.json",dst=/etc/shadowsocks-c/config.json,readonly \
  ghcr.io/shadowsocks/shadowsocks-c:latest

The README says to check the result with docker logs shadowsocks-c and to stop the container with docker stop shadowsocks-c. Then point your Shadowsocks client at the server address, port, password and method from the config. Two tags matter: latest follows master, while version tags and sha-<full-commit> tags identify specific published builds. If the registry image is not available yet, the README gives a local build path.

sh
docker build -f docker/static/Dockerfile --target runtime \
  -t ghcr.io/shadowsocks/shadowsocks-c:latest .

For a source build instead, the README requires a C11 compiler, CMake 3.20+, and Make or Ninja, with no network access needed for configuration or build. Python is used by tests, and optional documentation builds need Doxygen 1.9.4 or later.

sh
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --parallel

If you prefer flags over a config file, the README points at --help for grouped CLI options and --version for version information, with CLI conventions documented on the project's generated site.

Compatibility promises and what they commit you to

The rename is the part most likely to break a deployment, and the README addresses it directly. Commands such as ss-local and ss-server, the shadowsocks.h API, and the embedding library ABI remain compatible. New builds provide libshadowsocks-c along with the CMake and pkg-config package named shadowsocks-c, while legacy library filenames and the shadowsocks-libev package lookup name remain available as compatibility aliases. Existing configuration paths, distribution package names, and service names are retained.

That is a stronger compatibility story than most renames offer, but read the wording carefully. The README says references to shadowsocks-libev in the installation examples refer to those existing integrations. In other words, the documentation deliberately mixes old and new names because the packaging layer has not been renamed everywhere. The same caveat appears for Snap: existing Snap packages still use the shadowsocks-libev name and may predate this modernization.

One more boundary is worth noting. The README's homepage field points at the shadowsocks-rust repository, not at a standalone site for this project, and the README itself frames shadowsocks-rust as the destination for new development. The generated CLI and configuration documentation lives on a GitHub Pages site built with Doxygen from the source and published after updates to master. If you need documentation that matches a tag rather than master, you are reading source or building the docs yourself.

Where shadowsocks-c is the wrong choice

The README is unusually clear that this is not where the ecosystem's new work happens. It states that shadowsocks-libev entered a bug-fix-only maintenance phase with new development directed toward shadowsocks-rust, and that the September 2026 work was a modernization focused on self-contained builds and portability. Nothing in the README promises new protocol features. If your roadmap depends on features that only exist in newer implementations, this repository is not the one to track.

The vendored dependency model is the second trade-off. Pinned sources mean the build works offline and reproducibly, but they also mean dependency updates arrive when the project updates them, not when an upstream CVE fix lands. The README does not describe a policy for refreshing third_party/. That is a question for whoever maintains your deployment, and the answer is not in the documentation.

Platform support is the third. The README's installation guide covers Debian and Ubuntu, Fedora and RHEL, Arch and Manjaro, NixOS, Nix, FreeBSD, OpenWRT, macOS, Windows via MinGW, and Docker, so coverage is broad. But the README does not document rollback, downgrade, or migration procedures between versions. If you are moving an existing shadowsocks-libev deployment, plan the rollback yourself. The release history is also uneven: v3.3.4 landed in January 2020, v3.3.5 in September 2020, and v3.3.6 in February 2026, so the modernization arrives after a long quiet period rather than as a steady cadence.

Shadowsocks-rust, shadowsocks-libev and the Android question

The natural comparison is shadowsocks-rust, and the README makes the difference explicit rather than leaving you to infer it. shadowsocks-rust is where the project directs new development. shadowsocks-c is the C implementation, kept for embedded and low-end targets and now rebuilt around libuv with pinned, static dependencies. The choice is not about protocol support, which both implement; it is about what you are willing to run on the box. A Rust binary and toolchain is a different footprint from a static C binary, and the README's framing of this project as lightweight for embedded devices is the whole argument.

The other comparison is with shadowsocks-libev itself, which is really a comparison with the past. The README notes that this repository retains the shadowsocks-libev commit history and releases, and that commands, the shadowsocks.h API, and the embedding ABI remain compatible. If you are already on shadowsocks-libev, the migration is closer to a rebuild than a rewrite, provided you account for the library and package naming aliases.

On Android, the documentation is thin. The README does not describe an Android client, and the installation guide stops at OpenWRT for embedded Linux targets. The related searches people run around "Shadowsocks c android" are not answered by anything in this repository's documentation. Treat Android as out of scope for this project until the docs say otherwise.

On safety and detection, the README documents configuration and deployment, not threat models. It gives no claim about whether traffic is detectable, and it gives no cost information because the software is free under GPL-3.0. Those questions belong to the protocol and to your network, not to this repository.

Licence and upgrade cost

shadowsocks-c is licensed under GPL-3.0, and the repository carries a COPYING file at the top level. That is a copyleft licence, which matters most if you link the embedding library into your own product rather than running the binaries as separate processes. The README advertises the shadowsocks.h API and a stable embedding library ABI, so embedding is an intended use, and embedding GPL-3.0 code has consequences for how you distribute the result. This is a description of the licence, not legal advice; talk to someone qualified about your specific distribution model.

The upgrade cost is mostly the naming transition. Because the project keeps legacy library filenames and the shadowsocks-libev package lookup name as compatibility aliases, a package built from this source can satisfy dependencies that still ask for the old name. That reduces breakage but also means a build script can silently pick up either. The README explicitly warns that existing Snap packages may predate the modernization, so a Snap install is not evidence that you are running the libuv build.

On version pinning, the README distinguishes latest, which follows master, from version tags and sha-<full-commit> tags that identify specific published builds. For anything you intend to keep running, the commit-addressed tag is the one that tells you what you deployed. The documentation does not describe an upgrade procedure or a rollback path between these tags.

Editorial conclusion

Adopt shadowsocks-c if you need a small C proxy that keeps the ss-local and ss-server command names, the shadowsocks.h API and the old configuration paths working, and you want static binaries or the ghcr.io/shadowsocks/shadowsocks-c:latest image. Do not adopt it expecting new protocol features: the README directs new development to shadowsocks-rust and describes this repository as a pure C implementation. Before rollout, confirm which build you are actually running, since the README warns that existing Snap packages still use the shadowsocks-libev name and may predate the modernization, and check the pinned dependency sources in third_party/ against your own audit requirements.

Frequently asked questions

Is shadowsocks-c safe to use?

The README documents configuration and deployment rather than threat models, so it makes no claim about safety or detectability. On the operational side it recommends running the Docker image with --read-only, --cap-drop=ALL, and --security-opt=no-new-privileges:true, which is a hardened default. Whether the traffic itself is safe depends on the protocol and your network, not on this repository.

Can Shadowsocks be detected?

The README does not address detection. It describes the protocol implementation, the libuv event loop, and how to build and run the server and client, and it points to a feature comparison wiki page for differences between versions. Any question about traffic analysis or blocking is outside what this documentation covers.

Does shadowsocks-c still work in China?

Nothing in the README discusses regional availability or network conditions. It covers installation on Debian, Ubuntu, Fedora, RHEL, Arch, Manjaro, NixOS, Nix, FreeBSD, OpenWRT, macOS, Windows via MinGW, and Docker, which says nothing about whether a given network path works.

How much does shadowsocks-c cost?

The software is free. It is licensed under GPL-3.0, and the repository includes a COPYING file. Your costs are the hardware or container you run it on, not a licence fee.

Official sources

  1. License: GPL-3.0
  2. Project website
  3. README
  4. Releases
  5. shadowsocks/shadowsocks-c on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/shadowsocks-shadowsocks-c.svg)](https://hysenlabs.com/projects/shadowsocks-shadowsocks-c)