Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 29 additions & 14 deletions docs/vpn/advanced/prefixing.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand All @@ -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` |
Expand All @@ -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
Expand All @@ -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=<your url-encoded prefix goes here>`

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
Expand All @@ -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'
```
```
234 changes: 232 additions & 2 deletions docs/vpn/reference/access-key-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -290,4 +520,4 @@ $type: shadowsocks
endpoint: example.com:4321
cipher: chacha20-ietf-poly1305
secret: SECRET
```
```
Loading