Skip to content

Commit

Permalink
docs: reverse_proxy: Add guide for Caddy
Browse files Browse the repository at this point in the history
Closes snikket-im#82
Based on snikket-im#87 and discussion in Caddy forums,
consolidate information into basic and advanced configuration. The
basic set up is easy to use, and only forwards HTTP/S traffic. The
advanced set up requires additional plugins, and allows Caddy to be
used in place of `sslh` with the added advantage of forwarding port 80
- allowing Snikket to obtain certificates by itself.
  • Loading branch information
Rijul-A committed Dec 19, 2021
1 parent 705949b commit ac730b2
Showing 1 changed file with 139 additions and 1 deletion.
140 changes: 139 additions & 1 deletion docs/advanced/reverse_proxy.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ to proxy over SSL.
ProxyPreserveHost On
ProxyPass / http://chat.example.com/
ProxyPass / http://chat.example.com/
ProxyPassReverse / http://chat.example.com/
ErrorLog ${APACHE_LOG_DIR}/chat.example.com_error.log
Expand All @@ -238,3 +238,141 @@ to proxy over SSL.
```

### Caddy
#### Basic
For a simple configuration that only proxies the Snikket web portal, the following Caddyfile can be used.
```
http://example.com,
http://groups.example.com,
http://share.example.com {
reverse_proxy localhost:5080
}
example.com,
groups.example.com,
share.example.com {
reverse_proxy https://localhost:5443 {
transport http {
tls_insecure_skip_verify
}
}
}
```

#### Advanced
The advanced configuration allows for Caddy to be used as a "multiplexer", that is, serving HTTPS and encrypted XMPP traffic through the same port. This can be used to get around some very restrictive firewalls, similar to [`sslh`](#sslh). The configuration also forwards port 80 to 5080 (which `sslh` cannot do). However, since Caddy, by design is a layer 7 proxy, an additional layer4 plugin is needed.

Download [xcaddy](https://github.com/caddyserver/xcaddy) and build Caddy with the [layer4](https://github.com/mholt/caddy-l4) plugin. Also include the [YAML plugin](https://github.com/abiosoft/caddy-yaml), since the layer4 plugin does not support Caddyfile ([yet](https://github.com/mholt/caddy-l4/issues/16)).
```bash
xcaddy build \
--with github.com/mholt/caddy-l4 \
--with github.com/abiosoft/caddy-yaml
```
Run Caddy with
```bash
caddy run --config config.yaml --adapter yaml
```
Alternatively, if you use Caddy with Docker, use the following Dockerfile with the folder containing `config.yaml` mounted as `/etc/caddy` in the container.
```dockerfile
FROM caddy:builder AS builder

RUN xcaddy build \
--with github.com/mholt/caddy-l4 \
--with github.com/abiosoft/caddy-yaml

FROM caddy:latest

COPY --from=builder /usr/bin/caddy /usr/bin/caddy

CMD ["caddy", "run", "--config", "/etc/caddy/config.yaml", "--adapter", "yaml"]
```
The `config.yaml` needs to
1. Forward HTTP traffic (on port 80) with Snikket hostnames to port 5080.
1. Forward HTTPS traffic (on port 443) with Snikket hostnames to port 5443 *without* terminating TLS, since Snikket obtains certificates by itself.
1. Forward encrypted XMPP traffic on port 443 to 5223.
1. Forward unencrypted XMPP traffic on port 443 to 5222 (which uses STARTTLS).
1. Forward any other traffic to Caddy's standard HTTP/S proxy on layer 7.

```yaml
apps:
layer4: # layer4 plugin
servers:
srv0:
listen:
- ":80" # listens on port 80
- ":443" # and port 443
routes:
- match:
- http: # match HTTP traffic containing Snikket hostnames
- host:
- xmpp.example.com
- groups.xmpp.example.com
- share.xmpp.example.com
handle:
- handler: proxy
upstreams:
- dial: # and send to Snikket's HTTP port
- localhost:5080
- match:
- tls: # match encrypted XMPP traffic
alpn:
- xmpp-client
handle:
- handler: proxy
upstreams:
- dial: # and send to Snikket's encrypted XMPP port
- localhost:5223
- match:
- tls:
sni: # match HTTPS traffic containing Snikket hostnames
- xmpp.example.com
- groups.xmpp.example.com
- share.xmpp.example.com
handle:
- handler: proxy
upstreams:
- dial: # and send to Snikket's HTTPS port
- localhost:5443
- match:
- xmpp: {} # match unencrypted XMPP traffic
handle:
- handler: proxy
upstreams:
- dial: # and send to Snikket (will use STARTLS)
- localhost:5222
- handle: # no `match` here, so it matches all leftover traffic
- handler: proxy
upstreams:
- dial: # send it to Caddy's HTTP/S proxy, defined below
- 127.0.0.1:1337
http:
https_port: 1337 # needed for HTTPS to work
servers:
srv1:
listen:
- ":1337"
routes: # replace the below with your regular Caddy config (two standard examples are provided below)
- match: # this host will proxy to port 1025
- host:
- reverse-proxy-1025.example.com
handle:
- handler: subroute
routes:
- handle:
- handler: reverse_proxy
upstreams:
- dial: localhost:1025
terminal: true
- match: # this host will proxy to port 1026
- host:
- reverse-proxy-1026.example.com
handle:
- handler: subroute
routes:
- handle:
- handler: reverse_proxy
upstreams:
- dial: localhost:1026
terminal: true
```
In case you are using Docker, don't forget to [add the `host.docker.internal` extra host](https://stackoverflow.com/questions/48546124/what-is-linux-equivalent-of-host-docker-internal/61001152) and replace `localhost` with `host.docker.internal` in `config.yaml`.

0 comments on commit ac730b2

Please sign in to comment.