diff --git a/docs/vpn/advanced/prefixing.md b/docs/vpn/advanced/prefixing.md index ef26f6bb..27a47adb 100644 --- a/docs/vpn/advanced/prefixing.md +++ b/docs/vpn/advanced/prefixing.md @@ -7,7 +7,7 @@ sidebar_label: "Connection Prefixes" As of Outline Client version 1.9.0, access keys support the "prefix" option. The "prefix" is a list of bytes used as the first bytes of the -[salt](https://shadowsocks.org/doc/aead.html) of a Shadowsocks TCP connection. +[salt](https://shadowsocks.org/doc/aead.html) of a Shadowsocks connection. This can make the connection look like a protocol that is allowed in the network, circumventing firewalls that reject protocols they don't recognize. @@ -27,9 +27,9 @@ The port you use should match the protocol that your prefix is pretending to be. IANA keeps a [transport protocol port number registry](https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml) that maps protocols and port numbers. -Some examples of effective prefixes look like common protocols: +Some examples of effective TCP prefixes that look like common protocols: -| | Recommended Port | JSON-encoded | URL-encoded | +| | Recommended Port | YAML-encoded | URL-encoded | |----------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------|--------------------------| | HTTP request | 80 (http) | `"POST "` | `POST%20` | | HTTP response | 80 (http) | `"HTTP/1.1 "` | `HTTP%2F1.1%20` | @@ -39,22 +39,35 @@ Some examples of effective prefixes look like common protocols: | TLS ServerHello | 443 (https), 463 (smtps), 563 (nntps), 636 (ldaps), 989 (ftps-data), 990 (ftps), 993 (imaps), 995 (pop3s), 5223 (Apple APN), 5228 (Play Store), 5349 (turns) | `"\u0016\u0003\u0003\u0040\u0000\u0002"` | `%16%03%03%40%00%02` | | SSH | 22 (ssh), 830 (netconf-ssh), 4334 (netconf-ch-ssh), 5162 (snmpssh-trap) | `"SSH-2.0\r\n"` | `SSH-2.0%0D%0A` | +Some examples of effective UDP prefixes that look like common protocols: + +| | Recommended Port | YAML-encoded | +|----------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------| +| DNS request | 53 (dns) | `"\u006b\u007b\u0001\u0020"` (note: randomize the first two bytes) | +| DNS response | 53 (dns) | `"\u006b\u007b\u0081\u00a0\u0000\u0001"` (note: randomize the first two bytes) | +| QUIC Client Initial | 443 (https) | `"\u00cd\u0000\u0000\u0000\u0001"` | + ### Dynamic Access Keys To use the prefix feature with [Dynamic Access Keys](../management/dynamic-access-keys.md) (`ssconf://`), -add a "prefix" key to the JSON object, with a **JSON-encoded** value -representing the prefix you want (see examples in the table above). You can +add a "prefix" key to the YAML object, with a **YAML-encoded** value +representing the prefix you want_ (see examples in the table above)_. You can use escape codes (like \u00FF) to represent non-printable Unicode codepoints in the `U+0` to `U+FF` range. For example: -```json -{ - "server": "example.com", - "server_port": 8388, - "password": "example", - "method": "chacha20-ietf-poly1305", - "prefix": "\u0005\u00DC\u005F\u00E0\u0001\u0020" -} +```yaml +transport: + $type: tcpudp + tcp: + <<: &shared + $type: shadowsocks + endpoint: 147.182.248.224:20478 + secret: cqXYJ2BtMyNHneQHjpIXyg + cipher: chacha20-ietf-poly1305 + prefix: "\u0013\u0003\u0003\u003F" + udp: + <<: *shared + prefix: "\u006b\u007b\u0001\u0020" ``` ### Static Access Keys @@ -66,6 +79,8 @@ of these in the table above) and add it to the end of the access key like so: `ss://Z34nthataITHiTNIHTohithITHbVBqQ1o3bkk@127.0.0.1:33142/?outline=1&prefix=` +Prefixes in the URL format only work for TCP connections. + For advanced users, you can use your browser's `encodeURIComponent()` function to convert your **JSON-encoded** prefix to a **URL-encoded** one. To do this, open your web inspector console @@ -80,4 +95,4 @@ Press enter. The value produced will be the *URL-encoded *version. For example: ```js encodeURIComponent("\u0016\u0003\u0001\u0000\u00a8\u0001\u0001") '%16%03%01%00%C2%A8%01%01' -``` \ No newline at end of file +``` diff --git a/docs/vpn/reference/access-key-config.md b/docs/vpn/reference/access-key-config.md index 19889a45..0ec2d1b3 100644 --- a/docs/vpn/reference/access-key-config.md +++ b/docs/vpn/reference/access-key-config.md @@ -5,6 +5,157 @@ sidebar_label: "Access Key Config" # Config +Outline uses a YAML-based configuration to define VPN parameters and handle +TCP/UDP traffic. The configuration supports composability at multiple levels, +enabling flexible and extensible setups. + +The top-level configuration specifies a [TunnelConfig](#tunnelconfig). + +## Examples + +A typical Shadowsocks configuration will look like this: + +```yaml +transport: + $type: tcpudp + + tcp: + $type: shadowsocks + endpoint: ss.example.com:4321 + cipher: chacha20-ietf-poly1305 + secret: SECRET + prefix: "POST " + + udp: + $type: shadowsocks + endpoint: ss.example.com:4321 + cipher: chacha20-ietf-poly1305 + secret: SECRET +``` + +Note how we can now have TCP and UDP running on different ports or endpoints. + +You can take advantage of YAML anchors and the `<<` merge key to avoid +duplication: + +```yaml +transport: + $type: tcpudp + + tcp: + <<: &shared + $type: shadowsocks + endpoint: ss.example.com:4321 + cipher: chacha20-ietf-poly1305 + secret: SECRET + prefix: "POST " + + udp: *shared +``` + +It's now possible to compose strategies and do multi-hops: + +```yaml +transport: + $type: tcpudp + + tcp: + $type: shadowsocks + + endpoint: + $type: dial + address: exit.example.com:4321 + dialer: + $type: shadowsocks + address: entry.example.com:4321 + cipher: chacha20-ietf-poly1305 + secret: ENTRY_SECRET + + cipher: chacha20-ietf-poly1305 + secret: EXIT_SECRET + + udp: *shared +``` + +In case of blocking of "look-like-nothing" protocols like Shadowsocks, you +can use Shadowsocks over Websockets. See the +[server example configuration](https://github.com/Jigsaw-Code/outline-ss-server/blob/master/cmd/outline-ss-server/config_example.yml) +on how to deploy it. A client configuration will look like: + +```yaml +transport: + $type: tcpudp + tcp: + $type: shadowsocks + endpoint: + $type: websocket + url: wss://legendary-faster-packs-und.trycloudflare.com/SECRET_PATH/tcp + cipher: chacha20-ietf-poly1305 + secret: SS_SECRET + + udp: + $type: shadowsocks + endpoint: + $type: websocket + url: wss://legendary-faster-packs-und.trycloudflare.com/SECRET_PATH/udp + cipher: chacha20-ietf-poly1305 + secret: SS_SECRET +``` + +Note that the Websocket endpoint can, in turn, take an endpoint, which can be +used to bypass DNS-based blocking: + +```yaml +transport: + $type: tcpudp + tcp: + $type: shadowsocks + endpoint: + $type: websocket + url: wss://legendary-faster-packs-und.trycloudflare.com/SECRET_PATH/tcp + endpoint: cloudflare.net:443 + cipher: chacha20-ietf-poly1305 + secret: SS_SECRET + + udp: + $type: shadowsocks + endpoint: + $type: websocket + url: wss://legendary-faster-packs-und.trycloudflare.com/SECRET_PATH/udp + endpoint: cloudflare.net:443 + cipher: chacha20-ietf-poly1305 + secret: SS_SECRET +``` + +Note that Websockets is not yet supported on Windows. In order to have a single +config for all platforms, use a `first-supported` for backwards-compatibility: + +```yaml +transport: + $type: tcpudp + tcp: + $type: shadowsocks + endpoint: + $type: first-supported + options: + - $type: websocket + url: wss://legendary-faster-packs-und.trycloudflare.com/SECRET_PATH/tcp + - ss.example.com:4321 + cipher: chacha20-ietf-poly1305 + secret: SS_SECRET + + udp: + $type: shadowsocks + endpoint: + $type: first-supported + options: + - $type: websocket + url: wss://legendary-faster-packs-und.trycloudflare.com/SECRET_PATH/udp + - ss.example.com:4321 + cipher: chacha20-ietf-poly1305 + secret: SS_SECRET +``` + ## Tunnels ### TunnelConfig @@ -155,11 +306,17 @@ Packet Dialers. The _null_ (absent) Dialer means the default Dialer, which uses direct TCP connections for Stream and direct UDP connections for Packets. -Supported Interface types for Stream and Packer Dialers: +Supported Interface types for Stream and Packet dialers: - `first-supported`: [FirstSupportedConfig](#firstsupportedconfig) - `shadowsocks`: [ShadowsocksConfig](#shadowsocksconfig) +Supported Interface types for Stream dialers: + +- `iptable`: [IPTableConfig](#iptableconfig) +- `direct`: [Direct](#direct) +- `block`: [Block](#block) + ## Packet Listeners A Packet Listener establishes an unbounded packet connection that can be used to @@ -253,6 +410,79 @@ secret: SECRET prefix: "POST " ``` +### Selective Routing + +#### IPTableConfig + +Represents a Stream Dialer that routes connections based on the +destination IP address. It matches the destination IP against a list of rules +in the `table`. If a rule matches, the connection is handled by the `dialer` +specified in that rule. If no rules match, the connection is handled by the +`fallback` dialer. + +This is a Stream-only dialer and should be used for `tcp` transports. + +**Format:** _struct_ + +**Fields:** + + - `table` (*list*): A list of routing rules. + - `ips` (*list*): A list of IP addresses or CIDR ranges (e.g., `192.0.2.0/24`). + - `dialer` ([DialerConfig](#dialerconfig)): The dialer to use if the destination IP matches an entry in `ips`. + - `fallback` ([DialerConfig](#dialerconfig)): The dialer to use if the + destination IP does not match any rule in the `table`. + +Example: + +```yaml +# This config blocks TCP connections to 192.0.2.0/24 and sends all +# other TCP traffic directly. +transport: + $type: tcpudp + tcp: + $type: iptable + table: + - ips: + - 192.0.2.0/24 + dialer: + $type: block + fallback: + $type: direct + udp: + $type: shadowsocks + # ... udp config +``` + +## Utility Dialers + +### Direct + +Represents a direct Stream dialer. + +This is a Stream-only dialer and should be used for `tcp` transports. + +Example: + +```yaml +dialer: + $type: direct +``` + +### Block + +Represents a dialer that blocks all connection attempts. This can be useful +for explicitly denying traffic to specific destinations, especially when +used with [IPTableConfig](#iptableconfig). + +This is a Stream-only dialer and should be used for `tcp` transports. + +Example: + +```yaml +dialer: + $type: block +``` + ## Meta Definitions ### FirstSupportedConfig @@ -290,4 +520,4 @@ $type: shadowsocks endpoint: example.com:4321 cipher: chacha20-ietf-poly1305 secret: SECRET -``` \ No newline at end of file +```