These 64 commits are when the Protocol Buffers files have changed:
| Commit: | a77273f | |
|---|---|---|
| Author: | eric | |
| Committer: | eric | |
feat(plugins): run plugins compiled into the client, named by builtin iOS will not load code from a file, and Android will not from anywhere an app can write, so there a plugin is linked in at build time instead. It is registered under a name with register_builtin_plugin, and a config refers to it with `builtin`, in conf ([Plugin] builtin=) and JSON alike. A registered builtin wins over path and url, which are then only the fallback for a client without it: nothing is downloaded and no cache directory is needed. A client with none of the three fails to start and lists the builtins it has. A builtin's descriptor goes through the same validation as a library's; only the file's checks -- path, permissions, sha256 -- do not apply, since there is no file. Loaded plugins are now keyed by source, so two outbounds on one builtin share it. Only plugins written in other languages are linked in. Plugins exist for protocols written in something other than Rust; one written in Rust belongs in leaf as an outbound of its own. Linking a Rust plugin in would also merge its dependencies' features with leaf's -- the TLS plugin's rustls with ring on top of leaf's aws-lc-rs, for one, which leaves rustls with no default provider and panics the DoH client. The in-tree Rust plugins stay loadable libraries only. For C, defining LEAF_PLUGIN_STATIC_NAME renames the descriptor function to leaf_plugin_<name>_get_descriptor and drops its export, through the canonical header, so the plugin's source does not change and any number of C plugins can be linked into one binary. leaf-ffi's plugin-socks5-c feature links the SOCKS5 C plugin into the library (compiled by build.rs) and registers it as the builtin socks5-c on the first call that reads a config. leaf_register_plugin registers one the app links itself. Its unit tests load the linked-in plugin through the host. The builtin/ e2e cases register a fixture's descriptor function and show that it carries TCP and UDP to a stock leaf server, wins over a path and over a url (with no cache directory to fall back on), gives way to the url on a client without it, fails clearly with nothing to fall back on, and is held to the same descriptor validation as a library. The READMEs describe builtins and how to link a plugin in, and plugin-test and CI run the linked-in tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| Commit: | 488ff34 | |
|---|---|---|
| Author: | eric | |
| Committer: | eric | |
feat(plugins): download the plugins a config names by url A plugin outbound can now give a url instead of a path. With the new plugin-fetch feature, a start downloads what the cache is missing into <cache>/<sha256>/<file> before any outbound is built, and points the outbounds at it; a reload, and testing an outbound, resolve from the cache only and refuse what they would have to download. - https only, redirects included, and only together with a sha256 pin. - Downloads go to a temporary file, are hashed as they arrive, and are renamed into place only once the digest matches, under the url's own name, with the platform's library suffix added when it has no extension, which is what Windows needs to load it. A download past the declared size, or past 64 MiB without one, is stopped. - The cache directory comes from FetchOptions or PLUGIN_CACHE_DIR, with no default: whether a directory is safe to load code from is the embedding app's call. - prefetch() reports QUEUED/CACHED for every plugin before any download, then STARTED, PROGRESS (at most every 100 ms) and exactly one DONE or FAILED each, on the calling thread; the callback can cancel. A download that has not finished gets a PROGRESS heartbeat at least once a second, before STARTED too, so that one stuck connecting or in the handshake can be cancelled as well as one stuck mid-body. conf gains a [Plugin] section that declares each plugin once (path, url, sha256, size) and a `plugin` proxy protocol that refers to it by name, with args= or args-b64= for arguments that contain commas. Proxy parameters are now split at the first `=` only, which used to drop any value that contained one. leaf-ffi gains leaf_prefetch_plugins, so that an app can download the plugins as soon as it has the config, and show progress, and the start that follows finds everything in the cache. Events arrive as a LeafFetchEvent whose first field is its size, on the calling thread and never after the call returns. Adds ERR_PLUGIN_FETCH, ERR_CANCELLED and ERR_UNSUPPORTED, and the plugin and plugin-fetch features. It is tested by unit tests rather than end to end: the library is a Rust dylib, which does not link in a Windows debug build (LNK1189). Twenty-three fetch/ e2e cases download from a per-case https server whose routes can announce a wrong length, omit it, fail, redirect, or hold a body at a gate until the case opens it. Every case checks its events against one statement of the progress contract, and every failure, cancel and timeout case checks that the cache is left empty. One checks that testing an outbound reads the cache, including a file put there by hand, and never downloads. The READMEs describe plugins in conf files and downloading them, and plugin-test and CI run the new unit tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| Commit: | b6a63ac | |
|---|---|---|
| Author: | eric | |
| Committer: | eric | |
feat(plugin)!: replace the in-process plugin API with a C ABI host The old API handed dynamic libraries Rust trait objects, tying every plugin to leaf's exact compiler and crate versions and ruling out other languages. It is removed, along with its shadowsocks sample, which returns on the new ABI in a later commit. The host loads plugins over leaf-plugin-abi instead. It validates the descriptor, dials the endpoint, and drives the engines as sans-io codecs over its own transport, exposing them as ordinary outbound handlers. Datagram engines are either unreliable, with a UDP socket of their own, or reliable, framed over the stream transport. Plugin failures carry the plugin's last error string, and plugin logs join the session's tracing span. Everything crossing the boundary is treated as untrusted: counts are checked against the buffers they describe, reported strings are bounded and escaped, engines get an opaque id rather than a pointer for host_ctx, and an engine that takes no input is backpressure rather than failure. A poll does a bounded amount of work, and a datagram the receiver cannot take is dropped instead of the session. An outbound names its path, host and port, and may pin the sha256 of the library it loads -- the only check on this path that still holds against someone who can write the file. `leaf --verify-plugin <path>` runs the same checks without a config file and prints what the plugin declares: its ABI version, its engines, whether the outbound must carry host and port, and the digest to pin it to. A build can then be vetted before it is in the path of any traffic.
| Commit: | 1d20301 | |
|---|---|---|
| Author: | eric | |
Revert "feat(inbound): limit data transfer and concurrent connections per IP" This reverts commit 05e872ac0aa85d9514125be2393afc87a672cd06.
| Commit: | 05e872a | |
|---|---|---|
| Author: | eric | |
feat(inbound): limit data transfer and concurrent connections per IP
| Commit: | a3459cc | |
|---|---|---|
| Author: | eric | |
| Committer: | eric | |
Support ECH config DNS lookup
| Commit: | 822889c | |
|---|---|---|
| Author: | eric | |
Support ECH
| Commit: | 428f448 | |
|---|---|---|
| Author: | eric | |
Support raw certificate configuration for JSON
| Commit: | f7b288e | |
|---|---|---|
| Author: | eric | |
| Committer: | eric | |
Add MPTP protocol
| Commit: | 1303e3e | |
|---|---|---|
| Author: | eric | |
Add wintun support
| Commit: | 8f43c2b | |
|---|---|---|
| Author: | eric | |
Refine Socks and tests
| Commit: | b1b64d5 | |
|---|---|---|
| Author: | eric | |
| Committer: | eric | |
Add VLess + Reality (experimental)
| Commit: | 1d0e982 | |
|---|---|---|
| Author: | eric | |
Add netstack-smoltcp tun2socks backend
| Commit: | a86f91a | |
|---|---|---|
| Author: | eric | |
Support compact log format
| Commit: | d764286 | |
|---|---|---|
| Author: | eric | |
| Committer: | eric | |
Added hc inbound for management purposes
| Commit: | 033213d | |
|---|---|---|
| Author: | eric | |
| Committer: | eric | |
Support PROCESS-NAME rule
The documentation is generated from this commit.
| Commit: | ea912cc | |
|---|---|---|
| Author: | eric | |
| Committer: | eric | |
Support PROCESS-NAME rule
The documentation is generated from this commit.
| Commit: | 93000df | |
|---|---|---|
| Author: | eric | |
| Committer: | eric | |
Support NetFilter inbound
| Commit: | 49aa8f8 | |
|---|---|---|
| Author: | eric | |
Added NONE loglevel to skip logger setup
| Commit: | a6070a7 | |
|---|---|---|
| Author: | eric | |
| Committer: | eric | |
Support multiple health check requests for the failover outbound
| Commit: | 09d1a97 | |
|---|---|---|
| Author: | eric | |
Added healthCheckWait option for failover outbound
| Commit: | b1ef030 | |
|---|---|---|
| Author: | eric | |
Added healthCheckOnStart option to failover outbound
| Commit: | ed261b6 | |
|---|---|---|
| Author: | eric | |
| Committer: | eric | |
Added healthCheckPrefers parameter for failover outbound
| Commit: | 6f9d426 | |
|---|---|---|
| Author: | eric | |
outbound/direct: allow to specify an outbound interface
| Commit: | 8517bb3 | |
|---|---|---|
| Author: | eric | |
outbound/amux: new parameters max-recv-bytes and max-lifetime to control connection behavior
| Commit: | af24da9 | |
|---|---|---|
| Author: | eric | |
| Committer: | eric | |
outbound/shadowsocks: support customizable salt prefix Note the prefix must specify in percent-encoded form and the length must less than the used cipher key length.
| Commit: | 1de877a | |
|---|---|---|
| Author: | eric | |
| Committer: | eric | |
outbound/tls: added an option to disable certificate verification
| Commit: | 85cfa4c | |
|---|---|---|
| Author: | bdbai | |
| Committer: | eycorsican | |
Add http obfs outbound
| Commit: | a358f7e | |
|---|---|---|
| Author: | eric | |
| Committer: | eric | |
inbound/cat: a new inbound makes leaf act as netcat Running leaf with the following config: ```json { "inbounds": [ { "protocol": "cat", "settings": { "address": "1.1.1.1", "network": "tcp", "port": 80 }, "tag": "cat" } ], "log": { "level": "warn" }, "outbounds": [ { "protocol": "socks", "settings": { "address": "127.0.0.1", "port": 1080 }, "tag": "socks" } ] } ``` is similar to the following `nc` command: ```shell nc -X5 -x127.0.0.1:1080 1.1.1.1 80 ``` Which establishes a TCP connection to 1.1.1.1:80 via a local SOCKS5 proxy. But leaf supports sending UDP over SOCKS5 as well as other supported outbounds.
| Commit: | a70d98d | |
|---|---|---|
| Author: | lemos | |
| Committer: | GitHub | |
outbound/socks: add authentication support for socks (#356)
| Commit: | 5fa702d | |
|---|---|---|
| Author: | eric | |
| Committer: | eric | |
quic: configurable ALPN
| Commit: | b291177 | |
|---|---|---|
| Author: | eric | |
| Committer: | eric | |
outbound/failover: skip health checking at inactivity
| Commit: | 09775d6 | |
|---|---|---|
| Author: | eric | |
| Committer: | eric | |
outbound/failover: configurable health check delay
| Commit: | aad085f | |
|---|---|---|
| Author: | eric | |
| Committer: | eric | |
outbound/vmess: re-introduce
| Commit: | 96294a6 | |
|---|---|---|
| Author: | eric | |
| Committer: | eric | |
Added statistics manager
| Commit: | c3afb38 | |
|---|---|---|
| Author: | eric | |
| Committer: | eric | |
outbound/random, outbound/rr, outbound/static: combined random and rr into static
| Commit: | cbef2f9 | |
|---|---|---|
| Author: | eric | |
outbound/retry: removed
| Commit: | 290831c | |
|---|---|---|
| Author: | eric | |
| Committer: | eric | |
outbound/failover: configurable health check timeout
| Commit: | 769c48d | |
|---|---|---|
| Author: | eric | |
| Committer: | eric | |
outbound/failover: allows a single outbound as a last resort
| Commit: | ae32f7a | |
|---|---|---|
| Author: | eric | |
| Committer: | eric | |
inbound/trojan: accept multiple passwords
| Commit: | ed8b128 | |
|---|---|---|
| Author: | eric | |
conf: support logoutput
| Commit: | 8e7c0b4 | |
|---|---|---|
| Author: | eric | |
| Committer: | eric | |
router, conf: support INBOUND-TAG rule
| Commit: | 028f294 | |
|---|---|---|
| Author: | eric | |
| Committer: | eric | |
conf: support NETWORK rule
| Commit: | fbe3a5a | |
|---|---|---|
| Author: | eric | |
| Committer: | eric | |
inbound/tls: new inbound
| Commit: | d35e649 | |
|---|---|---|
| Author: | eric | |
| Committer: | eric | |
Experimental plugin system
| Commit: | 489d80f | |
|---|---|---|
| Author: | eric | |
outbound/rr: new outbound to dispatch requests in a round-robin manner
| Commit: | 5dfbcaa | |
|---|---|---|
| Author: | eric | |
| Committer: | eric | |
config, router: make doman-resolve option reloadable
| Commit: | c1d6852 | |
|---|---|---|
| Author: | eric | |
| Committer: | eric | |
outbound/tun: automate tun setup
| Commit: | 47071b8 | |
|---|---|---|
| Author: | eric | |
| Committer: | eric | |
outbound/select: persists selector state
| Commit: | f8163d1 | |
|---|---|---|
| Author: | eric | |
config/json, test: enable api on json config and fix tests
| Commit: | a2dadff | |
|---|---|---|
| Author: | eric | |
outbound/select: new outbound
| Commit: | ae5f0f6 | |
|---|---|---|
| Author: | eric | |
| Committer: | eric | |
proxy/quic: a UDP-based multiplexed and secure transport
| Commit: | 8b1268b | |
|---|---|---|
| Author: | eric | |
| Committer: | eric | |
amux: a multiplexing transport
| Commit: | 5b1582f | |
|---|---|---|
| Author: | eric | |
| Committer: | eric | |
proxy: elementary support for multiplexing transports This adds an `Incoming` transport to represent a `futures::stream::Stream` of incoming transports from a multiplexing handler which accepts a single stream as input and returns multiple streams as output. A work in progress `amux` handler is also included.
| Commit: | 6ef895a | |
|---|---|---|
| Author: | eric | |
inbound/shadowsocks: new inbound
| Commit: | 99680ab | |
|---|---|---|
| Author: | eric | |
dns: support DNS static hosts
| Commit: | f764670 | |
|---|---|---|
| Author: | eric | |
outbound/ws: support custom headers
| Commit: | 0ac84b7 | |
|---|---|---|
| Author: | eric | |
outbound/retry: added retry outbound retry outbound allows multiple attempts on a list of outbounds.
| Commit: | 87d52fb | |
|---|---|---|
| Author: | eric | |
router: support port range matching
| Commit: | 82545d4 | |
|---|---|---|
| Author: | eric | |
Refactor
| Commit: | d52a49e | |
|---|---|---|
| Author: | eric | |
failover: Add the option to cache fallback actors
| Commit: | 807ad5a | |
|---|---|---|
| Author: | eric | |
| Committer: | eric | |
Added several inbounds * Added WebSocket inbound * Added trojan inbound * Added chain inbound Similar to the chain outbound, chain inbound can be used to chain multiple inbounds. The Nginx/CDN (TLS) + WebSocket + trojan setup is tested. There are also breaking changes to the JSON config format. Fake DNS now can operate in either Include or Exclude mode. SOCKS inbound settings no longer has the `bind` option, the local_addr of the TCP socket is used as the UDP relay address.
| Commit: | d1112c0 | |
|---|---|---|
| Author: | eric | |
add h2 support
| Commit: | 897fc87 | |
|---|---|---|
| Author: | eric | |
initial commit