Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c7722ef3da |
@@ -87,6 +87,9 @@ docker run -d \
|
|||||||
webhooker
|
webhooker
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The first-boot password goes to the container's log. Read it with `docker logs`
|
||||||
|
and the container's name.
|
||||||
|
|
||||||
In production, put a reverse proxy in front of webhooker: a server that accepts
|
In production, put a reverse proxy in front of webhooker: a server that accepts
|
||||||
the public connections and passes them on. Read
|
the public connections and passes them on. Read
|
||||||
[Behind a reverse proxy](#behind-a-reverse-proxy) first.
|
[Behind a reverse proxy](#behind-a-reverse-proxy) first.
|
||||||
@@ -182,7 +185,8 @@ creates every SQLite file with mode `0600`.
|
|||||||
from this repository's `Dockerfile` and runs it. Add no port mapping, because
|
from this repository's `Dockerfile` and runs it. Add no port mapping, because
|
||||||
upaas publishes every mapped port on all interfaces of the host. Put the app on
|
upaas publishes every mapped port on all interfaces of the host. Put the app on
|
||||||
your reverse proxy's Docker network instead, and mount one host directory at
|
your reverse proxy's Docker network instead, and mount one host directory at
|
||||||
`/var/lib/webhooker`.
|
`/var/lib/webhooker`. The first-boot password goes to the container's log. Read
|
||||||
|
it with `docker logs` and the name upaas gave the container.
|
||||||
|
|
||||||
### Behind a reverse proxy
|
### Behind a reverse proxy
|
||||||
|
|
||||||
@@ -190,7 +194,7 @@ webhooker speaks plain HTTP. It does not handle TLS, the encryption behind
|
|||||||
HTTPS: it holds no certificate and accepts no HTTPS connections. The reverse
|
HTTPS: it holds no certificate and accepts no HTTPS connections. The reverse
|
||||||
proxy holds the certificate and reaches webhooker over a private address. On a
|
proxy holds the certificate and reaches webhooker over a private address. On a
|
||||||
bare host that is loopback, the address only this host can reach. For the image
|
bare host that is loopback, the address only this host can reach. For the image
|
||||||
it is the Docker bridge.
|
it is the Docker bridge, the private network Docker puts containers on.
|
||||||
|
|
||||||
Four things must be right.
|
Four things must be right.
|
||||||
|
|
||||||
@@ -202,10 +206,10 @@ Four things must be right.
|
|||||||
from any connecting machine, so the proxy must overwrite whatever the client
|
from any connecting machine, so the proxy must overwrite whatever the client
|
||||||
sent.
|
sent.
|
||||||
3. **Cover the proxy in `TRUSTED_PROXIES`.** Otherwise every client shares one
|
3. **Cover the proxy in `TRUSTED_PROXIES`.** Otherwise every client shares one
|
||||||
rate-limit bucket, the count a limit keeps per client. The default list
|
rate-limit bucket, the count a limit keeps per client. A proxy on the host
|
||||||
covers the Docker bridge address, such as `172.17.0.1`, that the image sees a
|
reaches the container from the Docker bridge address, such as `172.17.0.1`.
|
||||||
proxy at. It does not cover loopback, so on a bare host set
|
The default list covers it. The list does not cover loopback, so on a bare
|
||||||
`TRUSTED_PROXIES=127.0.0.1`.
|
host set `TRUSTED_PROXIES=127.0.0.1`.
|
||||||
4. **Pass on the client's `Host` header with its port.** webhooker checks a
|
4. **Pass on the client's `Host` header with its port.** webhooker checks a
|
||||||
form's `Origin` against the `Host` header it receives. A `Host` without the
|
form's `Origin` against the `Host` header it receives. A `Host` without the
|
||||||
port makes every form submission fail with `403` on any port other than 443.
|
port makes every form submission fail with `403` on any port other than 443.
|
||||||
@@ -233,7 +237,9 @@ server {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The block matches webhooker's 1 MB body cap and its 60 second request timeout.
|
The block matches webhooker's 1 MB body cap. Its `proxy_read_timeout` is longer
|
||||||
|
than webhooker's 60 second request timeout, so webhooker's own `504` reaches the
|
||||||
|
client first.
|
||||||
|
|
||||||
### HSTS
|
### HSTS
|
||||||
|
|
||||||
@@ -375,12 +381,13 @@ SSRF guard refuses these ranges:
|
|||||||
The SSRF guard runs when a target is saved and again when each delivery
|
The SSRF guard runs when a target is saved and again when each delivery
|
||||||
connects, so a hostname that changes its address later is still checked.
|
connects, so a hostname that changes its address later is still checked.
|
||||||
Redirects are followed up to ten hops, and each hop is checked. A hop to another
|
Redirects are followed up to ten hops, and each hop is checked. A hop to another
|
||||||
host or port, or from `https` to `http`, carries none of the configured or
|
host or port, or from `https` to `http`, drops every configured or forwarded
|
||||||
forwarded headers, so a redirect cannot pass a credential to another host.
|
header except `Content-Type`. So a redirect cannot pass a credential to another
|
||||||
|
host.
|
||||||
|
|
||||||
Egress means the connections webhooker opens outward to deliver.
|
Egress means the connections webhooker opens outward to deliver.
|
||||||
[`ALLOWED_EGRESS_CIDRS`](#allowing-egress-to-your-own-network) opens named
|
[`ALLOWED_EGRESS_CIDRS`](#allowing-egress-to-your-own-network) lets deliveries
|
||||||
networks to it.
|
reach networks you name.
|
||||||
|
|
||||||
### What the logs contain
|
### What the logs contain
|
||||||
|
|
||||||
@@ -394,8 +401,8 @@ The `admin` password is printed in the clear on the first boot and by
|
|||||||
query string, headers and body.
|
query string, headers and body.
|
||||||
|
|
||||||
When `SENTRY_DSN` is set, error reports go to Sentry, an error reporting
|
When `SENTRY_DSN` is set, error reports go to Sentry, an error reporting
|
||||||
service. A report carries no query string, body or cookies, and the route
|
service. A report carries no query string, body or cookies. In place of the path
|
||||||
pattern (the route as registered, such as `/h/{uuid}`) in place of the path.
|
it carries the route pattern, the route as registered, such as `/h/{uuid}`.
|
||||||
|
|
||||||
## Design
|
## Design
|
||||||
|
|
||||||
@@ -410,8 +417,9 @@ delivery.
|
|||||||
|
|
||||||
The main database holds configuration. Each webhook has its own event database,
|
The main database holds configuration. Each webhook has its own event database,
|
||||||
so writes for one webhook never wait on another webhook's database. The program
|
so writes for one webhook never wait on another webhook's database. The program
|
||||||
starts in `cmd/webhooker/main.go`, and its packages are under `internal/`. The
|
starts in `cmd/webhooker/main.go`, and its logic is under `internal/`. The
|
||||||
pages' HTML, CSS and JavaScript are embedded in the binary.
|
`static` and `templates` packages embed the pages' HTML, CSS and JavaScript in
|
||||||
|
the binary.
|
||||||
|
|
||||||
## Configuration reference
|
## Configuration reference
|
||||||
|
|
||||||
@@ -432,7 +440,10 @@ is allowed. In `prod`, no CORS headers are sent.
|
|||||||
|
|
||||||
### `PORT`
|
### `PORT`
|
||||||
|
|
||||||
The TCP port the listener binds. Default `8080`.
|
The TCP port the listener binds. Default `8080`. Docker marks the image's
|
||||||
|
container healthy by a check every 30 seconds. The check requests port `8080`
|
||||||
|
whatever `PORT` says, so a container started with another `PORT` reports
|
||||||
|
unhealthy.
|
||||||
|
|
||||||
### `BIND_ADDRESS`
|
### `BIND_ADDRESS`
|
||||||
|
|
||||||
@@ -522,8 +533,10 @@ you list, and read the responses in the event log. List the smallest blocks that
|
|||||||
cover your destinations, and never `0.0.0.0/0` or `::/0`.
|
cover your destinations, and never `0.0.0.0/0` or `::/0`.
|
||||||
|
|
||||||
These addresses stay blocked whatever you list. They are link-local space, the
|
These addresses stay blocked whatever you list. They are link-local space, the
|
||||||
unspecified addresses, and cloud metadata endpoints, the addresses a cloud gives
|
unspecified addresses and cloud metadata endpoints. The unspecified addresses
|
||||||
each virtual machine for its own credentials:
|
are `0.0.0.0` and `::`, which name no host. A cloud metadata endpoint is the
|
||||||
|
address a cloud gives each virtual machine for its own credentials. The blocked
|
||||||
|
addresses are:
|
||||||
|
|
||||||
- `169.254.0.0/16` and `fe80::/10`;
|
- `169.254.0.0/16` and `fe80::/10`;
|
||||||
- `fd00:ec2::254/128` and `fd00:ec2::23/128`;
|
- `fd00:ec2::254/128` and `fd00:ec2::23/128`;
|
||||||
@@ -545,11 +558,11 @@ default but is reopened by a list that covers it.
|
|||||||
An `http` target posts the event body to its URL with the event's `Content-Type`
|
An `http` target posts the event body to its URL with the event's `Content-Type`
|
||||||
and headers, then the target's configured **Headers**, which replace event
|
and headers, then the target's configured **Headers**, which replace event
|
||||||
headers of the same name. Every `http` and `slack` request carries
|
headers of the same name. Every `http` and `slack` request carries
|
||||||
`User-Agent: webhooker/{version}`, replacing the sender's `User-Agent` and any
|
`User-Agent: webhooker/{version}`. The **Headers** field refuses `User-Agent`. A
|
||||||
configured one. A `2xx` response is a success. The first 4 KiB of the response
|
`2xx` response is a success. The first 4 KiB of the response body is stored with
|
||||||
body is stored with the attempt. **Timeout** is at most 300 seconds, and blank
|
the attempt. **Timeout** is at most 300 seconds, and blank means the 30 second
|
||||||
means the 30 second default. **Pass the query string on to this target** appends
|
default. **Pass the query string on to this target** appends the event's query
|
||||||
the event's query string to the URL.
|
string to the URL.
|
||||||
|
|
||||||
A `slack` target posts a message that describes the event and shows its body in
|
A `slack` target posts a message that describes the event and shows its body in
|
||||||
a code block, cut at 3500 bytes. An archive target, whose stored type is
|
a code block, cut at 3500 bytes. An archive target, whose stored type is
|
||||||
|
|||||||
Reference in New Issue
Block a user