@@ -33,7 +33,7 @@ and **MAY** are to be interpreted as normative requirements.
3333The Portal is configured with one URL:
3434
3535``` text
36- portal://<shared-key>@<listen-host>:<listen-port>?tls=<mode>&spec=<spec>&alpn=<alpn >&net=<mode>&dial=<ip-or-auto>&rate=<mbps>&etar =<mbps>&crt=<path>&key=<path>&log=<level >
36+ portal://<shared-key>@<listen-host>:<listen-port>?log=<level>& tls=<mode>&crt=<path>&key=<path >&net=<mode>&spec=<spec>&alpn=<alpn>&rate =<mbps>&etar=<mbps>&dial=<ip-or-auto>&socks=<proxy >
3737```
3838
3939Minimal configuration:
@@ -50,28 +50,32 @@ Unknown query parameters are ignored.
5050
5151The shared key, ` spec ` , and ` alpn ` are percent-decoded as UTF-8. A literal ` + `
5252in ` spec ` or ` alpn ` remains ` + ` ; it is not converted to a space. If a query key
53- occurs more than once, the first occurrence is used.
53+ occurs more than once, the first occurrence is used. Duplicate ` socks `
54+ parameters MUST be rejected.
5455
5556| Input | Requirement | Decoded UTF-8 byte length |
5657| --- | --- | --- |
5758| Shared key | Required and non-empty | ` 1..255 ` |
5859| ` spec ` | Optional; empty is treated as omitted | ` 1..255 ` when non-empty |
5960| ` alpn ` | Optional; empty is treated as omitted | ` 1..255 ` when non-empty |
61+ | SOCKS username | Required when SOCKS authentication is configured | ` 1..255 ` |
62+ | SOCKS password | Required when SOCKS authentication is configured | ` 1..255 ` |
6063
6164### 3.2 Parameters
6265
6366| Parameter | Default | Semantics |
6467| --- | --- | --- |
68+ | ` log ` | ` info ` | ` none ` , ` debug ` , ` info ` , ` warn ` , ` error ` , or ` event ` . An unknown value selects ` info ` . |
6569| ` tls ` | ` 1 ` | ` 1 ` creates a self-signed certificate. ` 2 ` loads PEM files from ` crt ` and ` key ` . Other values are invalid. |
70+ | ` crt ` | Empty | PEM certificate chain used by ` tls=2 ` . |
71+ | ` key ` | Empty | PEM private key used by ` tls=2 ` . |
72+ | ` net ` | ` mix ` | Selects ingress transports. ` tcp ` enables TLS/TCP, ` udp ` enables QUIC/UDP, and ` mix ` enables both. Missing and empty values select ` mix ` ; other values are invalid. |
6673| ` spec ` | ` auto ` | Deterministic seed for v1 authentication, padding, and frame layouts. |
6774| ` alpn ` | ` now/1 ` | QUIC/TLS ALPN override. It does not alter any other protocol field. |
68- | ` net ` | ` mix ` | Selects ingress transports. ` tcp ` enables TLS/TCP, ` udp ` enables QUIC/UDP, and ` mix ` enables both. Missing and empty values select ` mix ` ; other values are invalid. |
69- | ` dial ` | ` auto ` | Local IP literal for outbound TCP and UDP sockets. Empty, invalid, hostname, and ` auto ` values select the operating-system default. |
7075| ` rate ` | ` 0 ` | Client-to-target rate limit in Mbps. |
7176| ` etar ` | ` 0 ` | Target-to-client rate limit in Mbps. |
72- | ` crt ` | Empty | PEM certificate chain used by ` tls=2 ` . |
73- | ` key ` | Empty | PEM private key used by ` tls=2 ` . |
74- | ` log ` | ` info ` | ` none ` , ` debug ` , ` info ` , ` warn ` , ` error ` , or ` event ` . An unknown value selects ` info ` . |
77+ | ` dial ` | ` auto ` | Local IP literal for outbound TCP and UDP sockets. Empty, invalid, hostname, and ` auto ` values select the operating-system default. |
78+ | ` socks ` | ` none ` | SOCKS5 proxy as ` host:port ` or ` user:pass@host:port ` . Missing, empty, and ` none ` disable proxying. |
7579
7680` rate ` and ` etar ` accept positive decimal integers. Zero, a negative value, an
7781invalid value, or omission disables the corresponding limit. The conversion is:
@@ -87,6 +91,12 @@ has independent client-to-target and target-to-client buckets.
8791relay and UoT. QUIC supports TCP relay on bidirectional streams and UDP relay
8892in DATAGRAM frames.
8993
94+ When ` socks ` is configured, every target MUST use that proxy. TCP uses SOCKS5
95+ CONNECT. Each UDP flow uses a separate UDP ASSOCIATE and retains its control
96+ connection for the flow lifetime. Target domain names are encoded in SOCKS5
97+ requests and resolved by the proxy. Proxy failure MUST NOT fall back to direct
98+ target access. ` dial ` binds connections and relay sockets toward the proxy.
99+
90100### 3.3 Listen Address
91101
92102An empty listen host binds separate IPv4 and IPv6 wildcard sockets on the same
@@ -359,10 +369,12 @@ The receiver MUST reject a version other than `1`, an invalid target, an
359369incorrect padding length, or incorrect padding bytes. The request padding is
360370not forwarded to the target.
361371
362- After parsing the request, the Portal resolves and connects to the target,
363- optionally binding the outbound socket to ` dial ` . It then relays bytes in both
364- directions. When one direction reaches EOF, the other direction may continue
365- for at most ` NOW_TCP_READ_TIMEOUT ` .
372+ After parsing the request, the Portal either resolves and connects directly to
373+ the target or sends the target unchanged in a configured SOCKS5 CONNECT
374+ request. ` dial ` binds the direct target socket or the connection to the SOCKS5
375+ server. The Portal then relays bytes in both directions. When one direction
376+ reaches EOF, the other direction may continue for at most
377+ ` NOW_TCP_READ_TIMEOUT ` .
366378
367379## 9. UDP Relay
368380
@@ -429,7 +441,9 @@ target_len_u16 || target_utf8
429441` target_len_u16 ` MUST be from 1 through 512, and ` target_utf8 ` MUST satisfy
430442Section 10. The Portal bounds reading the complete setup target by
431443` NOW_HANDSHAKE_TIMEOUT ` . It then resolves the target and opens one connected UDP
432- socket, optionally binding its source address according to ` dial ` .
444+ socket, optionally binding its source address according to ` dial ` . With SOCKS5
445+ enabled, it instead creates a per-flow UDP ASSOCIATE, keeps the associated TCP
446+ control connection open, and sends the target in each SOCKS5 UDP packet.
433447
434448After setup, both directions consist only of packet frames:
435449
0 commit comments