1
0
mirror of https://github.com/shadowsocks/shadowsocks-libev.git synced 2026-09-24 00:45:06 +00:00

2443 Commits

Author SHA1 Message Date
Max Lv
d52ddf2bce Merge pull request #3062 from shadowsocks/feature/server-endpoints
Combine server host and port with strict IPv6 endpoint parsing
2026-09-13 07:23:22 +08:00
Max Lv
454bdc0a67 Accept combined server endpoints with strict IPv6 parsing 2026-09-13 07:15:28 +08:00
Max Lv
243f1f92ec Merge pull request #3061 from shadowsocks/feature/redesigned-cli
Redesign CLI flags, help, and argument validation
2026-09-12 21:25:11 +08:00
Max Lv
ea951e6bd1 Redesign CLI flags, help, and argument validation 2026-09-12 21:17:38 +08:00
Max Lv
7bcb3d7dee Merge pull request #3060 from shadowsocks/madeye/cmake-build-test-error-on-macos
Raise the file descriptor limit for descriptor-heavy tests
2026-09-12 15:30:51 +08:00
Max Lv
8773939dce Raise the file descriptor limit for descriptor-heavy tests
test_event opens 256 UDP receivers plus a sender on top of the loop's own
descriptors. macOS starts processes with a soft RLIMIT_NOFILE of 256, so
socket() eventually returned -1 and the unchecked descriptor tripped the
bind() assertion when running ctest from a stock terminal (#3058).

Wrap every registered unit test in a small sh launcher that raises the soft
limit to 1024 before exec'ing the binary, and have test_event raise its own
limit as well so it also passes when run directly. Assert on socket()
failures so a limit problem is reported as such instead of as a bind error.

Fixes #3058

Claude-Session: https://claude.ai/code/session_01PSG4XV3jiqitDgdgFSGATx
2026-09-12 15:23:43 +08:00
Max Lv
36a5cc6b8d Merge pull request #3059 from shadowsocks/feature/publish-doxygen-pages
Publish native Doxygen documentation with GitHub Pages
2026-09-12 15:01:38 +08:00
Max Lv
6b11c7a632 Include downloadable man pages in the published documentation 2026-09-12 14:55:13 +08:00
Max Lv
f5d5bf0be1 Publish native Doxygen documentation with GitHub Pages 2026-09-12 14:46:42 +08:00
Max Lv
b281b739c7 Merge pull request #3057 from shadowsocks/feature/generated-cli-docs
Generate CLI manual sections from source option declarations
2026-09-12 10:57:59 +08:00
Max Lv
146818c182 Generate CLI manual sections from source option declarations 2026-09-12 10:51:25 +08:00
Max Lv
463ff72ca0 Merge pull request #3056 from shadowsocks/docs/add-contribution-guide
docs: add contribution guide
2026-09-12 10:31:55 +08:00
Max Lv
00ea8dec77 docs: add contribution guide 2026-09-12 10:31:30 +08:00
Max Lv
dce4aaaa7e Merge pull request #3055 from shadowsocks/docs/add-code-of-conduct
docs: add community code of conduct
2026-09-12 10:19:58 +08:00
Max Lv
0d58d15e99 docs: add community code of conduct 2026-09-12 10:14:24 +08:00
Max Lv
bff687bd34 Add Docker publishing, recommended installation and project history (#3052)
Document the shadowsocks-libev history and shadowsocks-c rename, and recommend Docker installation with mounted configuration and TCP/UDP port mappings.

Add native AMD64/ARM64 builds of the unprivileged static runtime image, real container relay and shutdown tests, and GHCR publication after both architecture checks pass. All 24 build/test checks pass at reviewed head 3f3f6bf8e01e5614821d1e15fda3ad8f07812902; publication is intentionally skipped on pull requests.
2026-09-11 16:22:30 +08:00
Max Lv
bdc77408cb Rename to shadowsocks-c with libuv, async DNS and CI lint (#3051)
Rename the project to shadowsocks-c while retaining ss-* commands, the embedding ABI, and legacy library/package lookup compatibility.

Replace libev with bundled libuv for IOCP/kqueue event backends, expand asynchronous runtime DNS coverage, and add actionlint/Ruff with strict clang-tidy failure handling. Validate native platforms, static builds, packaging, interoperability, sanitizers, and canonical/legacy consumers.

All 22 hosted checks pass at reviewed head a8493250eb.
2026-09-11 14:18:37 +08:00
Max Lv
201e70c4bd Modernize C builds with offline dependencies and portable runtime helpers (#3050)
Bundle pinned offline dependencies, remove libcork/libipset and submodule requirements, and add portable runtime helpers with relocatable static/shared library installations.

Add Clang static build validation for Linux/musl, macOS and Windows, real TCP/UDP and SIP003 interoperability coverage, and recorded performance tradeoffs. All 21 hosted checks pass at the reviewed PR head 8d504e6218.
2026-09-11 13:42:11 +08:00
Max Lv
8fe386b5c2 Merge pull request #3049 from shadowsocks/feature/aead-2022
Add Shadowsocks 2022 (SIP022) ciphers and ss:// URL support
2026-08-20 09:18:27 +08:00
Max Lv
fdde2c7cee Release the bloom filter in the AEAD-2022 tests
crypto_init() initializes the nonce bloom filter on every call, so a test
that builds a crypto_t per case has to tear it down per case as well.
Freeing only once at the end leaked a pair of filters for every crypto_t
after the first, which the valgrind memcheck job caught.

test_crypto.c already frees it alongside each crypto_t; do the same here
by folding it into the local free_crypto() helper.
2026-08-20 09:14:04 +08:00
Max Lv
8cc58cea95 Accept an ss:// server URL on the ss-local command line
shadowsocks-rust takes a whole server definition as a URL; libev could
only be given the pieces separately, so importing a server meant taking a
URL apart by hand. ss-local now accepts --server-url and reads the
address, port, cipher, password and SIP003 plugin from it.

Both encodings are handled: the SIP002 form with the userinfo in
base64url, and the older form where the whole body is one base64 blob.
The userinfo is also accepted in the clear, because that is what
shadowsocks-rust's `ssurl` emits for the 2022 ciphers, whose base64
pre-shared keys it percent-encodes instead. IPv6 literals, a trailing
slash, the plugin query and the '#' tag are all covered.

Options given later on the command line still win, since they are applied
as getopt reaches them.

ssurl.c sits with the ss-local sources rather than the shared ones: it
depends on base64.c, which ss-manager does not link.

The tests include URLs copied verbatim from `ssurl --encode` output, so
the parser is pinned against what another implementation really produces
rather than only against my reading of the spec. Verified end to end by
pointing ss-local at a rust-generated URL and proxying through their
ssserver.
2026-08-19 20:15:38 +08:00
Max Lv
3728a993a7 Add an interoperability test against shadowsocks-rust
A cipher can round-trip perfectly against our own implementation and
still be wrong: header layout, padding rules, and nonce ordering are only
pinned down by talking to another implementation. This drives ss-local
against rust's ssserver and rust's sslocal against ss-server, over a
local origin server so it needs no network access.

Covers the three SIP022 methods plus aes-256-gcm, so a regression in the
legacy path shows up here too. Skips itself when shadowsocks-rust or the
built binaries are absent, so it is safe to run anywhere.
2026-08-19 18:42:39 +08:00
Max Lv
06bbf3d86c Use snprintf for port formatting
The buffers were all large enough for a uint16, so none of these could
actually overflow, but sprintf gives the compiler and the linters nothing
to check. Passing the destination size makes that guarantee explicit and
survives any later change to the buffers.

parse_udprelay_header writes through a caller-supplied pointer, so it
uses the MAX_PORT_STR_LEN contract its callers already allocate to.
2026-08-19 18:27:19 +08:00
Max Lv
98915c7828 Build as C11 and remove input-sized VLAs from key parsing
crypto_parse_key sized a stack array from strlen() of the key given on
the command line or in the config file, so a long enough key string
overflowed the stack before any validation ran. Only the first key_len
bytes were ever used, and base64_decode already stops at the size it is
given, so a fixed MAX_KEY_LENGTH buffer is enough. crypto_parse_psk
needs one byte of slack to tell an over-long key from an exact-size one.

The two "here is a valid key instead" error paths were identical; they
are now one helper, which also drops the last input-sized VLA.

Switch the standard from gnu99 to C11 via CMAKE_C_STANDARD rather than a
hand-written -std flag, so CMake picks the right spelling per compiler.
2026-08-19 18:24:33 +08:00
Max Lv
46791234c0 Add Shadowsocks 2022 (SIP022) ciphers
shadowsocks-rust has supported the 2022 edition for years while libev was
stuck on the 2017 AEAD construction, the largest functional gap between
the two implementations. This adds the three SIP022 methods:

  2022-blake3-aes-128-gcm
  2022-blake3-aes-256-gcm
  2022-blake3-chacha20-poly1305

TCP uses BLAKE3 derive_key for session subkeys, standalone header chunks
carrying a type byte and timestamp, request padding, and a response header
echoing the request salt. Replay protection uses an exact-match salt pool
with 60s retention rather than the bloom filter, which SIP022 forbids
because false positives are unacceptable there.

UDP is session-based: an AES-ECB separate header for the AES methods and a
merged XChaCha20-Poly1305 construction for ChaCha, with a per-session
sliding window replay filter. Servers must route by client session ID,
which is only known after decryption, so the crypto layer owns the
server-side session table and hands the session back to udprelay for the
reply path.

The 2022 code lives in aead2022.c and aead2022_udp.c so aead.c keeps its
current size, with aead_internal.h carrying what they share. BLAKE3 is
vendored (portable backend only) as its own build target.

Keys are base64 pre-shared keys of exactly the cipher's key size; per
SIP022 a password is never stretched into a key.

Verified interoperable in both directions against shadowsocks-rust 1.24.0
for all three ciphers over TCP and UDP, including an 8MB transfer checked
by digest, plus unit tests for header framing, partial delivery, tamper
detection, and UDP replay rejection.
2026-08-19 18:15:35 +08:00
Max Lv
ab6e49381f Accept the standard base64 alphabet when decoding keys
The decode table only mapped the URL-safe alphabet, so '+' and '/' were
rejected as invalid characters. Keys are commonly generated with
`openssl rand -base64`, which emits standard base64, and shadowsocks-rust
accepts either form; a key containing '+' or '/' was refused outright
while the same key worked elsewhere.

Map both alphabets. The affected table entries previously decoded as
"invalid", so no input that used to decode changes meaning.
2026-08-19 18:15:24 +08:00
Max Lv
93b12ec7af Fix mbedTLS headers and libraries being drawn from different installs
find_library's search order puts CMAKE_PREFIX_PATH ahead of HINTS, so on
a Homebrew machine with both mbedtls (4.x) and the keg-only mbedtls@3,
the headers resolved to mbedtls@3 while the libraries resolved to 4.x.

That is not a link error but memory corruption at runtime:
mbedtls_cipher_context_t grew between the two versions, so every context
allocated with ss_malloc(sizeof(cipher_evp_t)) from the 3.x headers was
overrun by 4.x's mbedtls_cipher_init. It corrupted the heap in every
binary that sets up a cipher, and made the unit tests segfault inside an
unrelated malloc.

Pick a prefix that provides both the headers and libmbedcrypto and pin
every component to it, then verify at configure time that the header
version string matches what the linked library reports, so a mismatch
fails the build instead of corrupting memory.
2026-08-19 18:15:16 +08:00
Max Lv
dd2704c857 Fix bugs found by clang-tidy triage; ratchet warning budget to zero (#3047)
Real bugs fixed:
- manager.c: kill_server/stop_server checked fscanf() != EOF, so malformed
  pid file content left pid uninitialized and passed it to kill(). Parse
  with fgets + ss_parse_int and require pid > 0.
- utils.c: get_default_conf() crashed on strlen(NULL) when HOME is unset
  (e.g. daemons started by init) and left a dangling static pointer after
  free(), a latent use-after-free on repeated calls. Use a static buffer
  and fall back to the system config when HOME is missing.
- local.c: in UDP_ONLY mode, start_ss_local_server() passed uninitialized
  listen_ctx.fd to the library callback. Initialize it to -1.

Improvements:
- Replace rand()/srand(time(NULL)) upstream-server selection in ss-local,
  ss-redir and ss-tunnel with libsodium randombytes_uniform(): unbiased,
  unpredictable, and no seeding required (cert-msc30/msc32).
- Mark FATAL() noreturn so both the compiler and analyzers understand
  control flow (removes a family of analyzer false positives).
- Drop two dead stores (manager.c restore_sigchld, udprelay.c src_addr_len).

All remaining findings were verified as false positives and carry NOLINT
comments with rationale (uthash macro internals, symmetric back-pointer
cleanup, analyzer-invisible postconditions). clang-tidy-18 on Linux now
reports zero warnings, so MAX_WARNINGS drops from 29 to 0.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 13:02:58 +08:00
Max Lv
ba7b9ad4cc Add code quality tooling: clang-tidy, sanitizers, coverage (#3046)
- Export compile_commands.json for tooling
- .clang-tidy: clang-analyzer + bugprone + cert checks scoped to src/,
  with stylistic/false-positive-prone checks disabled
- ENABLE_SANITIZERS CMake option (ASan + UBSan)
- ENABLE_COVERAGE CMake option with an lcov/genhtml 'coverage' target
- CI: asan job (ctest + stress test under ASan/UBSan), clang-tidy job
  (warning-count ratchet, baseline 29 with pinned clang-tidy-18),
  coverage job (lcov summary + HTML report artifact)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 12:24:57 +08:00
Max Lv
5559eec939 Harden security-sensitive input handling (#3045)
* harden security-sensitive input handling

* enable ctest failure checks in ci

* add valgrind leak smoke tests

* split tests into separate workflow
2026-07-15 11:10:24 +08:00
notsure2
fc8750f329 Fix mishandling of incoming socket buffer. It must be set on the listening socket not the accepted socket. 2026-06-17 17:19:00 +08:00
dependabot[bot]
244af7d35c Bump actions/checkout from 4 to 6
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-17 16:47:35 +08:00
Max Lv
19e681fd8c Merge pull request #2986 from xwjdsh/master
[ss-manager] Fall back to /tmp if workdir is /
2026-06-17 11:26:53 +08:00
Max Lv
6f73c823a9 Merge pull request #3034 from vndroid/patch1
Fix CMake Warning
2026-06-17 11:26:48 +08:00
Max Lv
7ae92ee2cd Merge pull request #3038 from hillwoodroc/master
Fix build with gcc13
2026-06-17 11:26:43 +08:00
Max Lv
acf55e495f Merge pull request #3025 from shadowsocks/fix/cares-static-lib-name
Fix static c-ares detection for c-ares >= 1.27
2026-06-17 11:26:39 +08:00
Max Lv
9292a30225 Merge pull request #3017 from ayuusweetfish/mbedtls3-aesgcm
Fix failed assertion with Mbed TLS 3
2026-06-17 11:26:35 +08:00
Max Lv
7b507caf9e Merge pull request #3039 from TurboTheTurtle/fix-udp-json-bounds-checks
Fix truncated UDP and JSON bounds checks
2026-06-17 11:26:32 +08:00
Andy Ye
835f653df8 Fix truncated UDP and JSON bounds checks 2026-05-12 00:50:59 -07:00
Hillwood Yang
59a6aca759 Fix build with gcc13 2026-05-05 14:39:10 +08:00
Pain
95b8a2ca7a Fix CMake Warning 2026-04-16 07:39:14 -07:00
Pain
fb3d4a5fb2 Fix CMake Deprecation Warning 2026-04-16 07:35:27 -07:00
Max Lv
8ad3036f29 Update snap packaging for v3.3.6 with CMake and core22
Migrate from autotools to cmake plugin, upgrade base from core18 to
core22, point source to local git repo instead of stale v3.3.5 tarball,
update PCRE3 to PCRE2, and update runtime library packages for Ubuntu
22.04.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 18:56:17 +08:00
Max Lv
5c47b80f4e Update README with CMake build instructions and ss-setup/ss-nat docs
Modernize build instructions to focus on CMake (the sole build system),
remove outdated autotools/backports references, and add documentation
for the ss-setup interactive TUI tool and the ss-nat transparent proxy
helper script with practical usage examples.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 08:59:58 +08:00
Max Lv
716269d020 CI: enable static build to catch static-linking issues
WITH_STATIC defaults to ON in CMakeLists.txt but CI was explicitly
disabling it. Remove -DWITH_STATIC=OFF so the static targets are
also built and linked, catching issues like the c-ares static
library rename (#3024).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 16:13:44 +08:00
Max Lv
7ac8694aae Fix static c-ares detection for newer Debian/Ubuntu releases
c-ares >= 1.27 renamed the static library from libcares.a to
libcares_static.a. Search for both names so the static build works
on older distros (libcares.a) and newer ones (libcares_static.a).

Fixes #3024

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 15:43:42 +08:00
Max Lv
c5e8788013 Bump version to 3.3.6
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v3.3.6
2026-02-09 09:15:12 +08:00
Max Lv
2981f65e20 Merge pull request #3023 from shadowsocks/fix/aead-decrypt-chunk-compaction
Fix unbounded buffer growth in aead_decrypt chunk reassembly
2026-02-09 09:12:12 +08:00
Max Lv
ff44361f5d Fix unbounded buffer growth in aead_decrypt chunk reassembly
The idx-tracking optimization in aead_decrypt skipped memmove when
partial AEAD chunks spanned multiple calls, but never compacted the
dead space before idx. This caused the chunk buffer to grow
proportionally to total data transferred (~10 MB growth per 10 MB
transferred), tripping the stress test memory leak threshold.

Compact residual data to the front when appending new ciphertext,
keeping the buffer bounded to the size of the residual plus new data.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 09:04:58 +08:00
Max Lv
31731baa44 Reduce memory copies in crypto encrypt/decrypt paths
Add bswap_data() to swap buffer pointers instead of copying, replace
brealloc+memcpy with pointer swaps in aead and stream codecs, add
in-place fast paths for non-Salsa20 stream ciphers, and use index
tracking instead of memmove in aead_decrypt chunked reassembly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 08:53:28 +08:00