# tcptun

tcptun is a configuration-driven multi-inbound, multi-outbound proxy runtime written in Go. One process loads one strict JSON file, compiles its outbound graph and routing rules, prepares every inbound, then serves them together.

The Go module is also an embeddable networking library at `pkg.tcptun.com/net`.

[Reverse Subnet / home network access](docs/reverse-subnet.md) routes IPv4/IPv6 TCP/UDP
to a home LAN through an outbound-only connector, with independent Edge and home
network, CIDR, and destination-port ACLs.

[Reverse Subnet direct QUIC](docs/reverse-subnet-p2p.md) optionally keeps Edge authorization and per-flow permits while moving successful application payload to an authenticated Remote-to-Home QUIC path, with automatic relay fallback.

New programmatic integrations should compose the focused `flow`, `endpoint`,
`route`, `outbound`, `discovery`, `transport`, and `engine` packages rather than
starting from JSON configuration. See [the library architecture](docs/library-architecture.md).
Stream connections use `net.Conn`; `endpoint.Dialer` exposes TCP and UDP through
the standard `Dial`/`DialContext` contracts, and packet sessions adapt to both
connected `net.Conn` and unconnected `net.PacketConn`. Reusable transport
sessions can also be exposed as `net.Listener`.
The public `engine.PacketForwarder` provides bounded UDP routing through Direct
or SOCKS5 UDP ASSOCIATE packet outbounds.

## Run

```sh
tcptun --config config.json
tcptun -c config.json
```

tcptun reads a configuration file only when `--config/-c` explicitly names it. It never searches the current directory for a default configuration.

```sh
tcptun
```

Without `--config`, tcptun builds the equivalent formal `FileConfig` in memory, reserves `127.0.0.1:1080`, discovers the first SOCKS5 service reachable on port 1080 across the local private IPv4 networks, and then starts a mixed SOCKS/HTTP proxy. Reserving the listener first reports port conflicts immediately, but no traffic is accepted before discovery succeeds. Discovery performs a real SOCKS5 handshake and stops remaining probes after the first success; if it finds no upstream, startup fails and releases the listener. Use `tcptun --retry` to retry discovery forever while retaining the listener reservation. `--retry` is specific to this automatic mode and cannot be combined with `--config`.

The automatic LAN mode can authenticate its discovered SOCKS5 upstream with command-line credentials:

```sh
tcptun --username alice --password 'secret'
tcptun --retry --username alice --password 'secret'
```

The same values can come from the environment:

```sh
TCPTUN_USERNAME=alice \
TCPTUN_PASSWORD='secret' \
tcptun
```

`--username` independently overrides `TCPTUN_USERNAME`, and `--password` independently overrides `TCPTUN_PASSWORD`; an empty environment value is treated as unset. These credentials apply only to the automatic `lan-socks5` outbound. They do not authenticate the local mixed proxy on `127.0.0.1:1080`, and environment values never override credentials loaded by `--config`. Explicit `--username` or `--password` flags cannot be combined with `--config`. The generated outbound leaves `auth_mode` unset so the existing credentialed SOCKS5 default remains secure authentication.

Passing `--password` can expose the secret in shell history or the process list. For scripts, containers, and service managers, prefer `TCPTUN_PASSWORD`; environment variables reduce command-line exposure but are not an absolute secret-storage mechanism.

The root command exposes `--config/-c`, `--verbose/-v`, and the no-config automatic-mode flags `--retry`, `--username`, and `--password`. Other protocol, listener, authentication, transport, TLS, REALITY, mux, and routing options belong in JSON.

## Configuration model

```json
{
  "log": { "level": "info" },
  "inbounds": [
    {
      "tag": "local",
      "type": "mixed",
      "address": ["127.0.0.1:1080"],
      "network": ["tcp", "udp"]
    }
  ],
  "outbounds": [
    {
      "tag": "proxy",
      "type": "native",
      "address": ["proxy.example.com:9443"],
      "token": "change-me",
      "transport": { "type": "raw" },
      "mux": { "enabled": true }
    }
  ],
  "route": { "default_outbound": "proxy", "rules": [] },
  "dns": {
    "servers": ["1.1.1.1", "[2606:4700:4700::1111]:53"],
    "strategy": "prefer_ipv4",
    "outbound": "proxy",
    "fake_ip": {
      "enabled": true,
      "ipv4_range": "198.18.0.0/15",
      "ipv6_range": "fc00::/18",
      "capacity": 65536,
      "ttl": "10m"
    }
  },
  "resources": {
    "mux_receive_buffer_budget": 268435456,
    "resumable_buffer_budget": 1073741824
  }
}
```

`FileConfig` is decoded with unknown-field rejection and is separate from the compiled `RuntimeConfig`. Inbound and outbound tags must be unique. Every inbound reference, route reference, chain hop, TCP/UDP capability, protocol credential, transport, TLS, and REALITY configuration is checked before listeners are opened.

Platform-injected TUN inbounds use gVisor netstack for IPv4/IPv6 TCP and UDP and
enter the same compiled router as ordinary endpoint inbounds; they never loop
through a local mixed/SOCKS listener. For TUN DNS on TCP or UDP port 53,
`dns.servers` optionally replaces the client-selected resolver. `dns.outbound`
can pin intercepted DNS to one TCP/UDP-capable outbound, bypassing ordinary
route rules and fallback; an unavailable pinned outbound fails closed instead
of leaking DNS through another route. With
`dns.fake_ip.enabled`, A and AAAA queries receive bounded in-memory fake
addresses and later TCP/UDP flows to those addresses are restored to the domain
before route selection. Non-A/AAAA DNS messages continue through the configured
packet or stream outbound. Fake-IP ranges, capacity, and TTL are validated at
startup; mappings are per-runtime and are cleared on stop.

`resources.mux_receive_buffer_budget` bounds payload queued across every Native
TCP mux carrier in one Runtime. It defaults to 256 MiB and accepts 1–256 MiB;
the existing 256 MiB process hard limit still bounds multiple Runtimes
together. `Runtime.Stats` exposes the limit, current and peak usage, and
rejections. Memory-sensitive Android embedders should lower it according to
the host memory class.

Embedders can use `tun.NewWithOptions` to bound the packet queue, in-flight and
active TCP flows, active UDP flows, and UDP idle lifetime. `tun.New` retains the
same production defaults. `tun.Inbound.Stats` and `Runtime.Stats` expose active
platform flows, cumulative admission results, packet/byte totals, and rejected
packet classifications without parsing logs. Malformed IP envelopes and
transports other than TCP/UDP are counted and dropped without terminating the
TUN; they are not silently passed to a direct route.

Platforms that do not expose a Unix TUN file descriptor can implement
`tun.PacketDevice` and use `tun.NewPacketDevice` or
`tun.NewPacketDeviceWithOptions`. Reads and writes carry exactly one complete IP
packet, and `Close` must unblock pending I/O. The existing `tun.New` file API is
unchanged and retains the Linux fd-backed gVisor fast path; on Windows it still
returns `tun.ErrUnsupported`, while a Wintun-style adapter can use the packet
device API.

### Windows Wintun packet device

`inbound/tun/wintun` adapts the
[official wintun-go bindings](https://git.zx2c4.com/wintun-go/about/) without
adding a Wintun dependency to the core `tun` package:

```go
device, err := wintun.Create("tcptun0", wintun.Options{})
if err != nil {
    return err
}
inbound, err := tun.NewPacketDevice("tun", device, 1500)
if err != nil {
    return errors.Join(err, device.Close())
}
```

The matching-architecture `wintun.dll` must be deployed where the official
binding can load it. `Device.LUID()` is available for Windows IP Helper calls;
the embedder must configure interface addresses, routes, and DNS before serving
the inbound. Closing the inbound ends the Wintun session and releases the
adapter handle. Ring capacity is bounded to Wintun's 128 KiB–64 MiB power-of-two
range and defaults to 8 MiB.

Both `inbound.address` and `outbound.address` are strict string arrays. Multiple addresses on one outbound must be alternate entrances to the same logical service with shared credentials and protocol settings; they are not load-balancing members. The first connection races complete transport handshakes (including TLS, REALITY, HTTP, and QUIC authentication) with a 150ms stagger, later connections prefer the last successful address, and failures restore configured-order racing. Configure independent services as separate outbounds under `balance` instead.

Supported inbounds:

- `mixed`, `socks5`
- `native`

Supported outbounds:

- `direct`, `blackhole`
- `balance`
- `socks5`, `mixed`
- `native`

### Mixed and SOCKS5 proxy authentication

Every authenticated inbound accepts a bounded `users` array (at most 256
entries). Fields are protocol-specific:

| inbound | allowed `users[]` fields |
| --- | --- |
| `mixed` | `username`, `password` |
| `socks5` | `username`, `password` |
| `native` | `id`, optional `flow` for existing REALITY/Vision configurations |

For example, one mixed listener can authenticate both accounts across SOCKS5,
HTTP, HTTPS `CONNECT`, and SOCKS5 UDP:

```json
{
  "tag": "local",
  "type": "mixed",
  "address": ["127.0.0.1:1080"],
  "users": [
    { "username": "alice", "password": "secret-a" },
    { "username": "bob", "password": "secret-b" }
  ]
}
```

The legacy top-level `username` and `password` remain supported for a
single-account `mixed` or `socks5` inbound, but cannot be combined with
`users`. An empty `users` array with no legacy credentials preserves no-auth
behavior. Tunnel inbounds require at least one user. Outbounds remain a single
client identity and do not use `users`.

Configured `socks5` users protect SOCKS5 TCP and UDP sessions. The same users
on a `mixed` inbound protect SOCKS5, ordinary HTTP proxy requests, and HTTPS
`CONNECT` requests. HTTP
clients use standard `Proxy-Authorization: Basic ...`; missing, malformed,
duplicate, or incorrect credentials receive `407 Proxy Authentication
Required`. The proxy consumes this header before routing, so it is never sent
to an origin or included in a raw-mixed HTTP handoff. `CONNECT` remains an
opaque byte tunnel and does not perform TLS interception.

An authenticated `socks5` or `mixed` outbound accepts an `auth_mode` policy:

- `secure` sends exactly `[05 01 80]` and permits only tcptun private method
  `0x80`. It never offers or sends RFC1929 credentials, rejects any other
  selection, and closes on proof failure. This prevents method-selection
  downgrade from exposing the password and is the default when credentials are
  configured and `auth_mode` is omitted.
- `standard` sends exactly `[05 01 02]` for explicit compatibility with a
  third-party RFC1929 server. Username and password are recoverable on the
  SOCKS5 wire; confidentiality requires an outer TLS, VPN, native tunnel, or
  other trusted secure transport. This mode does not provide tcptun secure auth.
- `auto` sends `[05 02 80 02]` and accepts either method. It is a downgradeable
  compatibility mode: an active attacker can force RFC1929. Use it only behind
  trusted outer encryption or while migrating an older deployment; it is not a
  secure mode.

With no configured outbound credentials, SOCKS5 continues to send only
`[05 01 00]`, and setting `auth_mode` is rejected. Inbound compatibility is
unchanged: an upgraded tcptun inbound prefers `0x80`, but standard SOCKS5
clients such as curl, Clash, and system clients that advertise only
`0x02` continue to use RFC1929. Ordinary HTTP proxy clients continue to use
Basic authentication, and HTTP remains unauthenticated when no credentials are
configured.

Secure Auth V2 keeps method `0x80` and uses version byte `0x02` in these bounded
frames:

```text
client -> server: version | username-length | username | client-nonce[32]
server -> client: version | status | salt[16] | server-nonce[32]
client -> server: version | client-proof[32]
server -> client: version | status | server-proof[32]
```

V2 derives a 32-byte authentication key with HKDF-SHA256 using the configured
`password` bytes as input keying material, the 16-byte server credential salt,
and info `tcptun-socks5-secure-auth-v2/auth-key`. Role-separated HMAC-SHA256
proofs bind `tcptun-socks5-secure-auth-v2`, version, length-delimited username,
both fresh 32-byte nonces, and salt. The server caches an independent salt and
derived key for every configured credential; the immutable client derives on every
connection without a lock or key cache. This removes V1's 64 MiB Argon2id cost.

V2 is authentication for a **high-entropy pre-shared secret**. Treat the public
`password` field as that secret when using private method `0x80`: use at least
128 bits of random entropy, preferably 192 or 256 bits (for example, encode 24
or 32 bytes from `crypto/rand` as Base64URL, Base64, or hex). String length does
not prove entropy. V2 does not send the raw secret and fresh nonces prevent
direct proof replay, but a passive capture permits offline verification of
guessed secrets. It is not TLS, transport encryption, or a PAKE, and weak human
passwords are unsuitable when credential secrecy matters. V1 (`0x01`,
Argon2id) and V2 (`0x02`, HKDF) peers are intentionally incompatible and fail
closed; there is no runtime V1 fallback. See the [Secure Auth V2 wire and test
vector](docs/socks5-secure-auth-v2.md).

HKDF V2 addresses authentication resource cost, not unauthenticated SOCKS5
method selection. `auth_mode: "secure"` provides the separate downgrade boundary
by never offering RFC1929; `auto` remains explicitly downgradeable. RFC1929 and
HTTP Basic still send recoverable credentials and require an outer secure
transport for confidentiality.

Native raw TCP-mux and QUIC-mux tunnels also support reverse TCP and UDP publishing. Configure
`publish` on the server tunnel inbound and matching `expose` entries on the
client tunnel outbound. See [Reverse service publishing](docs/reverse-publishing.md).

Tunnel endpoints retain TCP and UDP, mux, raw/WebSocket/HTTP2/HTTP3, TLS, and REALITY support. `via` chains are finite and cycle-checked. A blackhole route rejects TCP and discards UDP; it never falls through to direct.

For throughput-oriented tcptun-to-tcptun deployments, prefer native + raw + mux. Native TCP mux sends the destination in the stream OPEN frame and waits for the server's target-dial result before reporting proxy success. Its large-frame wire format requires both endpoints to run the same current release; disable mux during a rolling upgrade from an older build. See [the Native protocol guide](docs/protocol-native.md) for pooling, memory bounds, transport tradeoffs, benchmarks, and compatibility details.

## Configuration tools

Validate and compile without binding ports:

```sh
tcptun config check --config config.json
```

Apply stable, idempotent formatting:

```sh
tcptun config format --config config.json
```

## Diagnostics and observability

Compile a configuration and render a deterministic, redacted report without
binding listeners, dialing outbounds, or starting background work:

```sh
tcptun diagnostics --config config.json
tcptun diagnostics --config config.json --json
```

Embedders can poll `Runtime.Snapshot()` for a detached grouped lifecycle,
inbound/outbound, routing, DNS, TUN, mux, resource, and shutdown view.
`Runtime.ExplainRoute` evaluates the same ordered matcher used by live routing
but performs no DNS lookup, dial, health update, or state mutation.
`Runtime.Diagnostics` and `Runtime.DiagnosticsWithRoute` combine those views;
`RenderDiagnostics` and `WriteDiagnostics` produce the same text or versioned
JSON used by the CLI. These APIs redact compiled credentials and return no
mutable runtime maps or executable errors.

Control-plane failures support `errors.Is` with `ErrConfigInvalid`,
`ErrOutboundUnavailable`, `ErrNetworkUnavailable`, `ErrPermissionDenied`,
`ErrResourceLimit`, and `ErrStopped`. See [the error taxonomy](docs/error-taxonomy.md)
and [observability design](docs/observability.md).

Generate matching `server.json` and `client.json` artifacts with fresh credentials and matching REALITY keys. The optional Native ECH form instead uses raw TCP, `security.type: "none"`, and a fresh X25519 key pair to protect carried TLS 1.3 ClientHello SNI:

```sh
tcptun config native --server proxy.example.com --port 9443
tcptun config native --quic --server proxy.example.com --port 9443
tcptun config native --ech --server proxy.example.com --server-name public.example
```

The unified topology generator emits configurations that pass `Validate + Compile`. The `full` topology covers every file-config inbound, outbound, transport, security, carrier, mux, fallback, ECH, reverse-publishing, routing, DNS, and resource field; TUN/Android platform-injected inbounds still require embedder setup:

```sh
tcptun config generate full --output config.json --force
tcptun config generate client --protocol native --security tls --carrier auto --carrier-prefer quic --output client.json
tcptun config generate client --protocol native --security reality --carrier auto --resume --output client.json
tcptun config generate reverse-server --publish-service web --publish-address 0.0.0.0:8080 --output server.json
```

Available topologies are `full`, `client`, `server`, `relay`, `chain`, `reverse-server`, and `reverse-client`. The generator covers Native; `raw/ws/h2/h3`; `none/tls/reality`; TCP/QUIC/auto carriers; mux/resume; TLS fallback; TCP/UDP reverse publishing; DNS; and resource limits. The protocol shortcut command accepts the same transport, security, carrier, mux, fallback, reverse, and DNS options.

Value flags use `pkg.gostartkit.com/cmd` enum metadata and dynamic completion. The built-in command can generate Bash, Zsh, Fish, or PowerShell completion scripts:

```sh
tcptun completion zsh > "${fpath[1]}/_tcptun"
```

The server listens on `0.0.0.0:9443` by default and the client exposes a mixed proxy on `127.0.0.1:1080`. Native + raw + mux can set `carrier.mode: "auto"` with either TLS or REALITY security; the inbound then binds TCP and UDP on the same address and port. Outbound `carrier.prefer` accepts `adaptive` (also the omitted default), `quic`, or `tcp`. Strict preferences use the healthy preferred carrier regardless of relative load and fall back only while it is unavailable, degraded, or backing off. `adaptive` preserves the existing load/quality policy. Set `carrier.mode` to `tcp` or `quic` for one carrier. QUIC and auto require `"mux": {"enabled": true}`; `carrier.prefer` is outbound-only and valid only with auto mode. See `examples/server-native-auto.json` and `examples/client-native-auto.json`.

Generator flags also have short forms: `-S/-C` select server/client outputs, `-s/-p/-l` set server/port/listen, `-L/-P` set local listen/port, `-n` sets the REALITY server name or ECH public name, `-D` sets the REALITY fallback destination, `-q` selects native QUIC, and `-e` selects Native ECH ClientHello protection.

Native is tcptun-specific and is covered by tcptun-to-tcptun wire tests.

The top-level `uri` command supports Native endpoints using the `native://` scheme. Export defaults to every tunnel outbound; `-i, --inbound` switches it to every tunnel inbound/listen endpoint and emits one client URI for each configured user and address. This behavior is independent of the configuration filename. Multiple URIs are newline-separated:

```sh
tcptun uri export --config server.json --inbound --output server.uri
tcptun uri export --config client.json --output client.uri
tcptun uri export --config client.json --qr-output client.png
tcptun uri export --config client.json --qr-output client.png --qr-format t3
tcptun uri export --config client.json --qr-output client.png --qr-format t3 --qr-compact
tcptun uri export --config client.json --qr-output client.png --qr-level high --qr-module-size 8
tcptun uri import --input client.uri --output outbound.json
tcptun uri import --input client.uri --client --output client.json
cat client.uri | tcptun uri import --input - --client --output client.json
```

`--qr-output client.png` writes `client.png` for one URI. For multiple URIs it writes `client-1.png`, `client-2.png`, and so on. QR payloads use the ordinary protocol URI by default. `--qr-format t3` instead uses the current compact binary Base45 `T3:` profile. It preserves TCP-only/UDP-only endpoints, carrier selection, QUIC UDP modes, and receive-window overrides. T3 encoding is strict and never falls back to a URI. `--qr-format t2` remains available only for legacy interoperability; old Native T2 payloads remain importable.

QR rendering defaults to medium (15%) recovery and 8 pixels per module. `--qr-level` accepts `low`/`medium`/`high`/`highest` (QR L/M/Q/H, approximately 7%/15%/25%/30%), while `--qr-module-size` accepts 4 through 12 pixels. `--qr-compact` requires T3 and omits the cosmetic display name from the QR payload; the decoded profile uses its server host as the name, while separately exported URI text keeps the requested name. Short forms are `-R`, `-s`, and `-C` respectively. Keep the default medium level for general camera scanning; low recovery is intended only for controlled displays where reducing the QR version matters more than damage tolerance.

The Android gomobile bridge exposes stateless `EncodeProfile(profileJSON)`, `EncodeProfileQRCode(profileJSON, recoveryLevel, moduleSize, compact)`, and `DecodeProfile(payload)` functions. The generated QR API returns PNG bytes directly (Java/Kotlin `byte[]`/`ByteArray`); an empty recovery level and zero module size select medium recovery and 8 pixels per module. Encoding produces `T3:`, decoding remains compatible with legacy `T2:`, and prefix dispatch never falls back between formats or to a URI. QR scanning remains the Android application's responsibility. Decoded JSON omits the Android-local `id`, and unknown JSON fields are rejected.

Single local proxy credentials use the separate `A1:` format through `EncodeProxyAccount(accountJSON)`, `DecodeProxyAccount(payload)`, and `EncodeProxyAccountQRCode(accountJSON, recoveryLevel, moduleSize)`. One A1 payload always contains exactly one username/password pair. It uses the same binary-to-Base45 QR-alphanumeric outer strategy as T3 but an independent frozen wire schema; it is never decoded as a tunnel profile. A1 is not encrypted and must be handled as a bearer secret.

Non-tunnel endpoints such as `direct` are skipped, while an outbound with multiple addresses emits one URI or QR code per candidate. `--client` creates a runnable mixed inbound, route, and tunnel outbound from one URI. URI and QR files contain credentials; generated files use mode `0600` and must not be shared through an untrusted location. An individual URI cannot represent a candidate address array, custom routing, discovery, or outbound chains; use JSON for those features. URI mode query parameters are rejected. Legacy `tcptun://` native URIs remain importable.

URI flags provide short forms where available: export uses `-i` (inbound), `-n` (name), `-o` (output), `-q` (QR output), `-Q` (QR format), and `-f` (force). Import uses `-t` (tag), `-i` (input), `-o` (output), `-C` (client), `-f` (force), `-l` (local listen), and `-p` (local port). Uppercase `-C` avoids the global `-c, --config` flag.

Commands have short aliases: `config` is `c`/`cfg`; its children are `n` (native), `c` (check), and `f` (format). `uri` is `u`, with `i` (import) and `e` (export). `version` is `v`/`ver`. Root flags are `-c`, `-v`, and `-r` for config, verbose, and retry.

## Legacy concept mapping

| Previous concept | Unified topology |
| --- | --- |
| local topology | local mixed/SOCKS inbound + LAN SOCKS/mixed outbound |
| client topology | local mixed/SOCKS inbound + remote tunnel outbound |
| server topology | tunnel inbound + selected direct/SOCKS/mixed/tunnel outbound |

The runtime loader rejects the previous top-level `mode` format. There is no automatic mode inference or compatibility command.

## Examples

See [`examples/`](examples/) for a runnable minimal mixed-to-Direct proxy,
matching Native client/server pairs, reverse publishing, relay,
chain, blackhole, embedded Go, and platform-neutral TUN examples. JSON examples
are covered by load/validate/compile tests, and the Go examples are compiled by
the normal module test command.

## Development

```sh
go test ./...
go vet ./...
```

Run the repeatable, offline core performance matrix with allocation reporting:

```sh
make bench-core
```

Focused TCP, routing, fake-IP, mux, and UDP commands are documented in
[`benchmarks/`](benchmarks/).

The CLI uses `pkg.gostartkit.com/cmd` v0.2.1. The first termination signal cancels the runtime for graceful shutdown; a second signal exits immediately.

# Application-aware routing

Local platform integrations may supply a platform-neutral application identity
for a newly observed flow. tcptun does not discover Android UIDs, packages, or
processes itself. The identity is used only by the local router and is not added
to native, mux, or UDP protocol frames.

```json
"route": {
  "default_outbound": "proxy",
  "rules": [
    {
      "app": {
        "ids": ["com.example.reader"],
        "platforms": ["android"],
        "attributes": {"profile": ["work"]}
      },
      "outbound": "proxy"
    },
    {
      "app": {"id_prefixes": ["com.example.game."]},
      "outbound": "direct"
    }
  ]
}
```

Arrays within one condition are OR alternatives. IDs, platform, individual
attribute keys, and the rule's normal inbound/network/destination conditions
are combined with AND. Rules remain ordered. A rule containing `app` does not
match when identity metadata is unavailable, so ordinary routing continues.
Platform names and attribute keys are case-normalized; IDs and values are not.

Android should normally use the package name as `id`. Other information such
as UID, shared packages, profile, or category can be supplied as multi-valued
attributes. UIDs may change after installation and display names are not stable
routing keys. The Android bridge accepts an optional `AppIdentityProvider`;
the callback receives flow JSON and returns identity JSON. It is called once
per TCP connection or cached UDP flow, never once per packet.

## License

Original TcpTun Inc code is distributed under the [TcpTun Inc Proprietary
Free-Use License](LICENSE). Everyone may use an authorized copy free of charge,
including for commercial purposes. This license does not grant rights to modify,
redistribute, sublicense, or reuse the source code. Use is at the user's own
risk, without warranty or support. Bundled third-party components retain their
own license terms; see the license files in their respective directories.
