中文版: README.zh-CN.md
Minimal SDK-only Sangfor aTrust runtime. A Rust supervisor wraps the aTrust SDK login flow, starts Core/Xtunnel on demand, and exposes an embedded SOCKS5 listener only after the VPN tunnel is connected.
This repository does not redistribute Sangfor aTrust binaries, SDK libraries,
licenses, credentials, or prebuilt images containing them. Both supported setup
paths initialize the aTrust runtime locally from a user-provided official
.deb file or HTTPS download URL.
scripts/atrust-lite-supervisor.rs: Rust supervisor, helper API, SMS flow, aTrust Core/Xtunnel lifecycle, stale-session watchdog, optional in-tunnel keepalive, and embedded SOCKS5.scripts/init-atrust-runtime.sh: local-only initializer that extracts a licensed upstream aTrust.debinto a minimal runtime root.scripts/build-runtime-image.sh: local Docker image build wrapper.scripts/install-host-native.sh: host-native installer without Docker.scripts/Dockerfile.scratchandscripts/Dockerfile.slim: optional image recipes that consume a locally generatedatrust-lite-root/.scripts/atrust-vpn-run.sh: optional Docker runtime launcher.scripts/atrust-socks-gate-sync.sh: host-side fail-closed SOCKS gate.scripts/*-atrust-lite*.ps1: Windows-side deploy, connect, SMS, disconnect, image-build, and live-check commands.docs/design.md: implementation notes and verification rules.
Stable data path:
operator script -> Rust supervisor API -> aTrust SDK/Core/Xtunnel -> embedded SOCKS5
- A Linux gateway host with systemd, iptables, and
/dev/net/tun. - Licensed access to the upstream Sangfor aTrust Linux
.deb. - Rust
rustcplus a C linker on the build/install host, unless you pass a prebuiltatrust-lite-supervisorbinary. The prebuilt path leaves no compiler toolchain on the gateway. - For scratch or host-native runtime roots, the build/install host must provide
common aTrust shared-library dependencies such as
libx11-6,libxtst6,libproxy1v5,libharfbuzz0b, andlibgl1. The host-native installer installs these automatically on apt-based systems. URL-based initialization additionally needs host-sidecurlorwget. - Docker only if you choose the image deployment path.
- PowerShell and OpenSSH only if you use the Windows-side operator scripts.
Run the doctor on the target Linux gateway before installing:
sudo bash scripts/doctor-atrust-lite.sh \
--atrust-deb ./aTrustInstaller_amd64.deb \
--sha256 <expected-sha256>For URL-based local initialization:
sudo bash scripts/doctor-atrust-lite.sh \
--atrust-url https://example.invalid/aTrustInstaller_amd64.deb \
--sha256 <expected-sha256>The URL is intentionally user-supplied. This project does not hard-code a Sangfor download URL or mirror aTrust packages.
For a local --atrust-deb, the doctor checks that the file exists, optionally
matches --sha256, is a readable Debian package, and contains the expected
aTrust SDK/Core payload paths:
/usr/share/sangfor/aTrust/resources/bin/aTrustAgent/usr/share/sangfor/aTrust/resources/bin/aTrustXtunnel-64/usr/share/sangfor/aTrust/resources/bin/libaTrustSDK.so/usr/share/sangfor/aTrust/resources/bin/plugins/aTrustCore/libaTrustCore.so
For --atrust-url, the doctor does not download the package. It only validates
that the URL is HTTPS, a downloader exists, and the provided SHA-256 is shaped
correctly. The install and image-build flows then download locally, verify the
SHA-256, extract the package, fail if the required aTrust files are missing,
prune GUI resources, and check shared-library completeness before producing a
runtime root.
GitHub Releases may provide atrust-lite-supervisor binaries built from this
repository's Rust source. These artifacts contain only the open source
supervisor; they do not contain Sangfor aTrust binaries, SDK libraries,
credentials, runtime roots, or images.
Use a prebuilt supervisor to avoid installing Rust on the gateway:
sudo bash scripts/install-host-native.sh \
--atrust-deb ./aTrustInstaller_amd64.deb \
--sha256 <expected-sha256> \
--supervisor-bin ./atrust-lite-supervisor \
--accept-upstream-licenseInstall directly on the gateway without Docker:
sudo bash scripts/install-host-native.sh \
--atrust-deb ./aTrustInstaller_amd64.deb \
--sha256 <expected-sha256> \
--accept-upstream-licenseEquivalent URL-based local initialization:
sudo bash scripts/install-host-native.sh \
--atrust-url https://example.invalid/aTrustInstaller_amd64.deb \
--sha256 <expected-sha256> \
--accept-upstream-licenseFill the root-only helper config on the gateway:
sudoedit /srv/atrust-vpn/root/.atrust-lite/helper.env
sudo systemctl restart atrust-lite-host.serviceMinimum helper.env:
ATRUST_SERVER=https://connect.example:443
ATRUST_USERNAME=alice
ATRUST_PASSWORD=change-me
ATRUST_HELPER_TOKEN=change-meOptional keepalive traffic can be configured in /etc/atrust-vpn/runtime.env.
Use an internal endpoint that is safe to receive an unauthenticated GET
periodically. After the data plane is healthy, the Rust supervisor opens a SOCKS
tunnel, sends the request, and requires a valid HTTP status line. HTTPS endpoints
are verified against the runtime CA bundle. Redirects are not followed, and curl
is not required in the runtime.
ATRUST_KEEPALIVE_URLS=https://internal.example.com/
ATRUST_KEEPALIVE_INTERVAL_SECONDS=60
ATRUST_KEEPALIVE_TIMEOUT_SECONDS=8The embedded SOCKS server defaults to 256 external clients, a 10-second
incomplete-handshake timeout, and a 120-second idle relay timeout. These can be
overridden with ATRUST_SOCKS_MAX_CLIENTS,
ATRUST_SOCKS_HANDSHAKE_TIMEOUT_SECONDS, and
ATRUST_SOCKS_IO_TIMEOUT_SECONDS in the same runtime environment file.
If aTrust's resolver intentionally returns no address for a company hostname that is nevertheless reachable through the tunnel, the embedded SOCKS server can use an allowlisted DNS-over-TLS fallback. The normal aTrust answer always wins; fallback runs only for an empty or failed lookup, only for the configured domain suffixes, and verifies the resolver certificate.
ATRUST_SOCKS_FALLBACK_DNS=223.5.5.5:853
ATRUST_SOCKS_FALLBACK_TLS_NAME=dns.alidns.com
ATRUST_SOCKS_FALLBACK_DOMAINS=internal.example.com,corp.example.netWhen the gateway has a local DNS facade on a non-standard port, keep the chroot resolver off LAN DNS interception and install an idempotent OUTPUT DNAT before the supervisor starts:
ATRUST_BOOTSTRAP_DNS_PRIMARY=192.0.2.10
ATRUST_BOOTSTRAP_DNS_SECONDARY=192.0.2.10
ATRUST_DNS_FACADE_PORT=5354Both resolver addresses should be the facade host. The redirect is disabled
when ATRUST_DNS_FACADE_PORT is unset.
The host installer also enables an hourly log-prune timer. Closed aTrust logs
are retained for at most 7 days and capped at 256 MiB; supervisor state logs
are capped at 64 MiB. Recently modified and open files are never removed.
Persistent journald storage is capped at 64 MiB. Override the file caps with
ATRUST_VENDOR_LOG_MAX_BYTES, ATRUST_STATE_LOG_MAX_BYTES, and
ATRUST_LOG_MAX_AGE_DAYS in /etc/atrust-vpn/runtime.env.
Build an image on a machine that is allowed to access the upstream aTrust package:
bash scripts/build-runtime-image.sh \
--atrust-deb ./aTrustInstaller_amd64.deb \
--sha256 <expected-sha256> \
--accept-upstream-license \
--tag atrust-lite-runtime:localEquivalent URL-based initialization:
bash scripts/build-runtime-image.sh \
--atrust-url https://example.invalid/aTrustInstaller_amd64.deb \
--sha256 <expected-sha256> \
--accept-upstream-licenseRun the local image:
sudo env ATRUST_IMAGE=atrust-lite-runtime:local bash scripts/atrust-vpn-run.shConfigure the gateway SSH target on your workstation:
$env:ATRUST_LITE_HOST = "<gateway-host>"
$env:ATRUST_LITE_SSH_USER = "root"
$env:ATRUST_LITE_SSH_IDENTITY = "<path-to-key>"Request SMS, submit the received code, validate, and disconnect:
npm run request-sms
npm run submit-sms -- -SmsCode <sms-code>
npm run live -- -Expect Connected
npm run disconnectDirect helper API calls are also supported from any shell on the gateway:
token="$(awk -F= '/^ATRUST_HELPER_TOKEN=/{print $2}' /srv/atrust-vpn/root/.atrust-lite/helper.env)"
curl -fsS -H "Authorization: Bearer ${token}" http://127.0.0.1:54680/status
curl -fsS -X POST -H "Authorization: Bearer ${token}" http://127.0.0.1:54680/connect
curl -fsS -X POST -H "Authorization: Bearer ${token}" \
-d '{"smsCode":"123456"}' http://127.0.0.1:54680/submit-smsRemote image build from Windows:
npm run build-image -- -HostName <gateway-host> -User <ssh-user> `
-AtrustDeb .\aTrustInstaller_amd64.deb `
-Sha256 <expected-sha256> `
-AcceptAtrustLicenseone of --atrust-deb or --atrust-url is required: provide an official aTrust Linux package locally or as a user-supplied HTTPS URL.rustc is required: install Rust on the build host or pass--supervisor-binwith a compatible prebuilt supervisor.compiled supervisor requires GLIBC_*: rebuild the supervisor on an older compatible userspace, or use a release binary built for your runtime root.- keepalive failures: verify that each configured URL uses
http://orhttps://, resolves inside aTrust, accepts an HTTPGET, and (for HTTPS) has a certificate trusted by the runtime CA bundle. - Docker starts unexpectedly in host-native mode: disable legacy local units
that reference Docker, especially
atrust-openclash-route-sync.*. dataPlane.statusisunhealthy: check the configured DNS/SOCKS health probe hosts and verify that the aTrust tunnel device is up.
- MFA is not bypassed or weakened.
- OTP values are accepted only as explicit user input and are not stored.
- SOCKS is exposed only after connected state is verified.
/statusmust not wake the SDK or start aTrust processes while idle.- Keepalive URLs are local runtime settings and are never committed by this project.
- Credentials, tokens, internal domains, and routing policy stay in local runtime configuration.
npm testMIT