FillOutJson merges into the previously stored out_json, but naiveOut never
removed the old quic / quic_congestion_control keys. Clearing the QUIC
Congestion Control field on an existing naive inbound therefore left
"quic": true and the old algorithm in the generated config. Delete both
keys first, matching the other *Out helpers.
Closes#1243
Starts snell v5 and v6 inbounds, a snell outbound and an oom-killer service;
bridge gets construct-only coverage since creating its tun needs privileges.
Also bumps the frontend submodule to the UI for these protocols.
Adds every new 1.14 type to the registries, following upstream's include
package: the build-tagged ones get the same stub pair s-ui already uses for
naive and tailscale, so a build without the tag reports which tag is missing
instead of failing to parse.
- inbound: snell, cloudflared
- outbound: snell, bridge
- endpoint: openconnect, openvpn (client and server)
- dns transport: mdns, resolved, openconnect, openvpn
- service: api, oom-killer, usbip (server and client)
with_cloudflared, with_openconnect, with_openvpn and with_usbip are added to
build.sh, the Dockerfile and both release workflows. Verified the linux
amd64/arm64 and windows amd64 cross-builds CI ships.
Registry tests now assert the full expected type set rather than just
certificate providers, and the box tests write their cache file to a temp
directory instead of leaving core/cache.db behind.
One-shot migration over the stored config and TLS rows, guarded by a setting
so it runs once:
- dns.independent_cache is dropped (1.14 reads it only to warn; the value is
never passed to the DNS client)
- experimental.cache_file.store_rdrc becomes store_dns
- route.rule_set[].download_detour becomes the http_client 1.14 builds for it
- inline tls.acme becomes tls.certificate_provider with type "acme"
Legacy DNS address filters and the `strategy` DNS rule action are NOT migrated
automatically. Converting them means inserting evaluate rules and reordering,
which changes how names resolve, so they are logged with the upstream
migration link for the operator to handle.
Tests cover each rewrite, that unrelated options survive, that a config with
nothing to migrate is left byte-identical, and that the migrated shapes build
a box with no deprecation warning.
The 1.14 upgrade wired up a certificate provider registry with only
origin_ca, so `tls.certificate_provider: {"type": "acme"}` failed to parse
with "unknown certificate provider type". Register ACME and Tailscale too,
behind the same build tags upstream uses, with stubs that report a helpful
error when the tag is absent.
This is what `tls.acme` migrates to in 1.14: the same fields move under
certificate_provider with `type: "acme"`, which parses clean with no
deprecation warning.
Starts a real box for each config in testdata/configs and logs the
deprecation notes it triggers. Covers the eight re-copied protocol inbounds
plus the option shapes s-ui's UI can emit that 1.14 deprecates.
Confirms no config s-ui produces fails to start under 1.14; the deprecated
ones warn and keep working.
Re-sync core/protocol/* from upstream (they were verbatim copies), re-fork
core/box.go onto the new upstream box.go, and adapt to changed APIs:
- adapter.ConnectionTracker gained RoutedFlow; add no-op impls to both trackers
- log.ObservableFactory gained AttachPlatformWriter; add no-op impl
- box.Context now takes a CertificateProviderRegistry; wire one up with
the origin_ca provider
- box.go now depends on debug*.go; copy them from upstream
- hysteria inbound moved QUIC option building into quic.go; copy it
Deps: sing v0.9.0-beta.4, sing-quic v0.7.0-beta.4, sing-tun v0.9.0-beta.2.
Runtime behaviour is not yet validated and config migration for options
deprecated in 1.14 is not done, so this is not ready for main.
* fix(hysteria2): use stable user identity on hot updates
Replace Service[int] (position-based) with Service[string] (name-based)
so that existing sessions retain a correct stable identity when the user
list changes via UpdateUsers. Remove the now-redundant userNameList field.
Fixes panic: runtime error: index out of range after user deletion,
and wrong username attribution when list positions shift.
* fix(hysteria2): gofmt struct field alignment after userNameList removal
* fix: extend stable user identity fix to hysteria, tuic, trojan, vless, vmess
The same Service[int] → Service[string] bug fixed for hysteria2 in the
previous commit affects all five remaining inbound protocols. When users
are deleted or reordered, integer position-based identity causes panics
(index out of range) and wrong username attribution in logs and traffic
stats.
Apply the same fix across hysteria v1, tuic, trojan, vless, and vmess:
- Service[int] → Service[string] in all five inbound structs
- Pass user.Name as the stable identity instead of the list index
- Remove the now-unnecessary cached `users []option.*User` fields from
trojan, vless, and vmess structs (they existed solely to map indexes
back to names)
- UpdateUsers helpers rebuilt to pass names, keeping auth/password
fields unchanged
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* ci: add go vet + gofmt check for patched protocols
* fix: gofmt struct field alignment in hysteria and tuic inbound
* fix: address review feedback on stable-identity PR
Three fixes from maintainer review:
1. Logging regression (trojan/vless/vmess): when a client has no name,
the old code fell back to the index as a log label; the new code was
emitting `[] inbound connection`. Align with the hysteria2 pattern:
omit the `[name]` prefix entirely when name is empty.
2. Duplicate/empty client names: trojan's Service.UpdateUsers rejects a
repeated identity, so two clients with the same name on the same
inbound would make UpdateUsers fail. vmess silently overwrites the
earlier entry. vless misattributes flow. Add server-side validation
in ClientService.Save (new, edit, addbulk) that rejects empty names
and names already in use on any shared inbound within the same tx.
3. Remove .github/workflows/check.yml: the workflow only triggered on
the feature branch, so it would be permanently dead after merge.
* fix: make client name validation global and trim whitespace
* ci: temporarily re-add check workflow for CI verification
* ci: remove temporary check workflow
* validate client names on bulk save paths too
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Alireza Ahmadi <alireza7@gmail.com>