Merge branch v3.4 into master
This commit is contained in:
commit
289d6e5dca
195 changed files with 1963 additions and 892 deletions
|
|
@ -15,8 +15,6 @@ A Use Case Using Docker
|
|||
Create a `docker-compose.yml` file where you will define a `reverse-proxy` service that uses the official Traefik image:
|
||||
|
||||
```yaml
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
reverse-proxy:
|
||||
# The official v3 Traefik docker image
|
||||
|
|
@ -50,8 +48,6 @@ Now that you have a Traefik instance up and running, you will deploy new service
|
|||
Edit your `docker-compose.yml` file and add the following at the end of your file.
|
||||
|
||||
```yaml
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
|
||||
...
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ You can configure Traefik to use an ACME provider (like Let's Encrypt) for autom
|
|||
!!! warning "Let's Encrypt and Rate Limiting"
|
||||
Note that Let's Encrypt API has [rate limiting](https://letsencrypt.org/docs/rate-limits). These last up to **one week**, and cannot be overridden.
|
||||
|
||||
When running Traefik in a container this file should be persisted across restarts.
|
||||
When running Traefik in a container the `acme.json` file should be persisted across restarts.
|
||||
If Traefik requests new certificates each time it starts up, a crash-looping container can quickly reach Let's Encrypt's ratelimits.
|
||||
To configure where certificates are stored, please take a look at the [storage](#storage) configuration.
|
||||
|
||||
|
|
@ -795,6 +795,8 @@ docker run -v "/my/host/acme:/etc/traefik/acme" traefik
|
|||
|
||||
_Optional, Default=2160_
|
||||
|
||||
`certificatesDuration` specifies the duration (in hours) of the certificates issued by the CA server. It is used to determine when to renew the certificate, but it **doesn't** define the duration of the certificates, that is up to the CA server.
|
||||
|
||||
`certificatesDuration` is used to calculate two durations:
|
||||
|
||||
- `Renew Period`: the period before the end of the certificate duration, during which the certificate should be renewed.
|
||||
|
|
|
|||
|
|
@ -677,3 +677,32 @@ it can lead to unsafe routing when the `sanitizePath` option is set to `false`.
|
|||
|
||||
Setting the `sanitizePath` option to `false` is not safe.
|
||||
Ensure every request is properly url encoded instead.
|
||||
|
||||
## v2.11.25
|
||||
|
||||
### Request Path Normalization
|
||||
|
||||
Since `v2.11.25`, the request path is now normalized by decoding unreserved characters in the request path,
|
||||
and also uppercasing the percent-encoded characters.
|
||||
This follows [RFC 3986 percent-encoding normalization](https://datatracker.ietf.org/doc/html/rfc3986#section-6.2.2.2),
|
||||
and [RFC 3986 case normalization](https://datatracker.ietf.org/doc/html/rfc3986#section-6.2.2.1).
|
||||
|
||||
The normalization happens before the request path is sanitized,
|
||||
and cannot be disabled.
|
||||
This notably helps with encoded dots characters (which are unreserved characters) to be sanitized properly.
|
||||
|
||||
### Routing Path
|
||||
|
||||
Since `v2.11.25`, the reserved characters [(as per RFC 3986)](https://datatracker.ietf.org/doc/html/rfc3986#section-2.2) are kept encoded in the request path when matching the router rules.
|
||||
Those characters, when decoded, change the meaning of the request path for routing purposes,
|
||||
and Traefik now keeps them encoded to avoid any ambiguity.
|
||||
|
||||
### Request Path Matching Examples
|
||||
|
||||
| Request Path | Router Rule | Traefik v2.11.24 | Traefik v2.11.25 |
|
||||
|-------------------|------------------------|------------------|------------------|
|
||||
| `/foo%2Fbar` | PathPrefix(`/foo/bar`) | Match | No match |
|
||||
| `/foo/../bar` | PathPrefix(`/foo`) | No match | No match |
|
||||
| `/foo/../bar` | PathPrefix(`/bar`) | Match | Match |
|
||||
| `/foo/%2E%2E/bar` | PathPrefix(`/foo`) | Match | No match |
|
||||
| `/foo/%2E%2E/bar` | PathPrefix(`/bar`) | No match | Match |
|
||||
|
|
|
|||
|
|
@ -290,3 +290,32 @@ and to help with the migration from v2 to v3.
|
|||
The `ruleSyntax` router's option was used to override the default rule syntax for a specific router.
|
||||
|
||||
In preparation for the next major release, please remove any use of these two options and use the v3 syntax for writing the router's rules.
|
||||
|
||||
## v3.4.1
|
||||
|
||||
### Request Path Normalization
|
||||
|
||||
Since `v3.4.1`, the request path is now normalized by decoding unreserved characters in the request path,
|
||||
and also uppercasing the percent-encoded characters.
|
||||
This follows [RFC 3986 percent-encoding normalization](https://datatracker.ietf.org/doc/html/rfc3986#section-6.2.2.2),
|
||||
and [RFC 3986 case normalization](https://datatracker.ietf.org/doc/html/rfc3986#section-6.2.2.1).
|
||||
|
||||
The normalization happens before the request path is sanitized,
|
||||
and cannot be disabled.
|
||||
This notably helps with encoded dots characters (which are unreserved characters) to be sanitized properly.
|
||||
|
||||
### Routing Path
|
||||
|
||||
Since `v3.4.1`, the reserved characters [(as per RFC 3986)](https://datatracker.ietf.org/doc/html/rfc3986#section-2.2) are kept encoded in the request path when matching the router rules.
|
||||
Those characters, when decoded, change the meaning of the request path for routing purposes,
|
||||
and Traefik now keeps them encoded to avoid any ambiguity.
|
||||
|
||||
### Request Path Matching Examples
|
||||
|
||||
| Request Path | Router Rule | Traefik v3.4.0 | Traefik v3.4.1 |
|
||||
|-------------------|------------------------|----------------|----------------|
|
||||
| `/foo%2Fbar` | PathPrefix(`/foo/bar`) | Match | No match |
|
||||
| `/foo/../bar` | PathPrefix(`/foo`) | No match | No match |
|
||||
| `/foo/../bar` | PathPrefix(`/bar`) | Match | Match |
|
||||
| `/foo/%2E%2E/bar` | PathPrefix(`/foo`) | Match | No match |
|
||||
| `/foo/%2E%2E/bar` | PathPrefix(`/bar`) | No match | Match |
|
||||
|
|
|
|||
|
|
@ -288,8 +288,6 @@ It is possible to configure the Traefik to timestamp in a specific timezone by e
|
|||
Example utilizing Docker Compose:
|
||||
|
||||
```yaml
|
||||
version: "3.7"
|
||||
|
||||
services:
|
||||
traefik:
|
||||
image: traefik:v3.4
|
||||
|
|
|
|||
|
|
@ -40,7 +40,6 @@ This provider works with [Docker (standalone) Engine](https://docs.docker.com/en
|
|||
Attaching labels to containers (in your docker compose file)
|
||||
|
||||
```yaml
|
||||
version: "3"
|
||||
services:
|
||||
my-container:
|
||||
# ...
|
||||
|
|
@ -162,8 +161,6 @@ See the [Docker API Access](#docker-api-access) section for more information.
|
|||
The docker-compose file shares the docker sock with the Traefik container
|
||||
|
||||
```yaml
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
traefik:
|
||||
image: traefik:v3.4 # The official v3 Traefik docker image
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@ This provider works with [Docker Swarm Mode](https://docs.docker.com/engine/swar
|
|||
then that service is automatically assigned to the router.
|
||||
|
||||
```yaml
|
||||
version: "3"
|
||||
services:
|
||||
my-container:
|
||||
deploy:
|
||||
|
|
@ -176,8 +175,6 @@ docker service create \
|
|||
```
|
||||
|
||||
```yml tab="With Docker Compose"
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
traefik:
|
||||
# ...
|
||||
|
|
@ -208,8 +205,6 @@ See the [Docker Swarm API Access](#docker-api-access) section for more informati
|
|||
The docker-compose file shares the docker sock with the Traefik container
|
||||
|
||||
```yaml
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
traefik:
|
||||
image: traefik:v3.4 # The official v3 Traefik docker image
|
||||
|
|
|
|||
|
|
@ -2291,7 +2291,7 @@ spec:
|
|||
type: object
|
||||
x-kubernetes-validations:
|
||||
- message: RootCA cannot have both Secret and ConfigMap defined.
|
||||
rule: has(self.secret) && has(self.configMap)
|
||||
rule: '!has(self.secret) || !has(self.configMap)'
|
||||
type: array
|
||||
rootCAsSecrets:
|
||||
description: |-
|
||||
|
|
@ -2436,7 +2436,7 @@ spec:
|
|||
type: object
|
||||
x-kubernetes-validations:
|
||||
- message: RootCA cannot have both Secret and ConfigMap defined.
|
||||
rule: has(self.secret) && has(self.configMap)
|
||||
rule: '!has(self.secret) || !has(self.configMap)'
|
||||
type: array
|
||||
rootCAsSecrets:
|
||||
description: |-
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ spec:
|
|||
type: object
|
||||
x-kubernetes-validations:
|
||||
- message: RootCA cannot have both Secret and ConfigMap defined.
|
||||
rule: has(self.secret) && has(self.configMap)
|
||||
rule: '!has(self.secret) || !has(self.configMap)'
|
||||
type: array
|
||||
rootCAsSecrets:
|
||||
description: |-
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ spec:
|
|||
type: object
|
||||
x-kubernetes-validations:
|
||||
- message: RootCA cannot have both Secret and ConfigMap defined.
|
||||
rule: has(self.secret) && has(self.configMap)
|
||||
rule: '!has(self.secret) || !has(self.configMap)'
|
||||
type: array
|
||||
rootCAsSecrets:
|
||||
description: |-
|
||||
|
|
|
|||
|
|
@ -199,8 +199,6 @@ It is possible to configure the Traefik to timestamp in a specific timezone by e
|
|||
Example utilizing Docker Compose:
|
||||
|
||||
```yaml
|
||||
version: "3.7"
|
||||
|
||||
services:
|
||||
traefik:
|
||||
image: traefik:v3.4
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ providers:
|
|||
Attach labels to containers (in your Docker compose file)
|
||||
|
||||
```yaml
|
||||
version: "3"
|
||||
services:
|
||||
my-container:
|
||||
# ...
|
||||
|
|
@ -67,8 +66,6 @@ See the [Docker API Access](#docker-api-access) section for more information.
|
|||
The docker-compose file shares the docker sock with the Traefik container
|
||||
|
||||
```yaml
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
traefik:
|
||||
image: traefik:v3.1 # The official v3 Traefik docker image
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ When there is only one service, and the router does not specify a service,
|
|||
then that service is automatically assigned to the router.
|
||||
|
||||
```yaml tab="Labels"
|
||||
version: "3"
|
||||
services:
|
||||
my-container:
|
||||
deploy:
|
||||
|
|
@ -73,8 +72,6 @@ See the [Docker Swarm API Access](#docker-api-access) section for more informati
|
|||
The docker-compose file shares the docker sock with the Traefik container
|
||||
|
||||
```yaml
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
traefik:
|
||||
image: traefik:v3.1 # The official v3 Traefik docker image
|
||||
|
|
@ -405,8 +402,6 @@ docker service create \
|
|||
```
|
||||
|
||||
```yml tab="With Docker Compose"
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
traefik:
|
||||
# ...
|
||||
|
|
|
|||
|
|
@ -72,8 +72,6 @@ When using Docker or Amazon ECS, you can define routing configuration using cont
|
|||
When deploying a Docker container, you can specify labels to define routing rules and services:
|
||||
|
||||
```yaml
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
my-service:
|
||||
image: my-image
|
||||
|
|
|
|||
|
|
@ -202,109 +202,6 @@ spec:
|
|||
- `X-Forwarded-Tls-Client-Cert-Info` header value is a string that has been escaped in order to be a valid URL query.
|
||||
- These options only work accordingly to the MutualTLS configuration. i.e, only the certificates that match the `clientAuth.clientAuthType` policy are passed.
|
||||
|
||||
??? example "Example of a complete certificate and explaining each of the middleware options"
|
||||
|
||||
```txt
|
||||
Certificate:
|
||||
Data:
|
||||
Version: 3 (0x2)
|
||||
Serial Number: 1 (0x1)
|
||||
Signature Algorithm: sha1WithRSAEncryption
|
||||
Issuer: DC=org, DC=cheese, O=Cheese, O=Cheese 2, OU=Simple Signing Section, OU=Simple Signing Section 2, CN=Simple Signing CA, CN=Simple Signing CA 2, C=FR, C=US, L=TOULOUSE, L=LYON, ST=Signing State, ST=Signing State 2/emailAddress=simple@signing.com/emailAddress=simple2@signing.com
|
||||
Validity
|
||||
Not Before: Dec 6 11:10:16 2018 GMT
|
||||
Not After : Dec 5 11:10:16 2020 GMT
|
||||
Subject: DC=org, DC=cheese, O=Cheese, O=Cheese 2, OU=Simple Signing Section, OU=Simple Signing Section 2, CN=*.example.org, CN=*.example.com, C=FR, C=US, L=TOULOUSE, L=LYON, ST=Cheese org state, ST=Cheese com statemailAddress=cert@example.org/emailAddress=cert@sexample.com
|
||||
Subject Public Key Info:
|
||||
Public Key Algorithm: rsaEncryption
|
||||
RSA Public-Key: (2048 bit)
|
||||
Modulus:
|
||||
00:de:77:fa:8d:03:70:30:39:dd:51:1b:cc:60:db:
|
||||
a9:5a:13:b1:af:fe:2c:c6:38:9b:88:0a:0f:8e:d9:
|
||||
1b:a1:1d:af:0d:66:e4:13:5b:bc:5d:36:92:d7:5e:
|
||||
d0:fa:88:29:d3:78:e1:81:de:98:b2:a9:22:3f:bf:
|
||||
8a:af:12:92:63:d4:a9:c3:f2:e4:7e:d2:dc:a2:c5:
|
||||
39:1c:7a:eb:d7:12:70:63:2e:41:47:e0:f0:08:e8:
|
||||
dc:be:09:01:ec:28:09:af:35:d7:79:9c:50:35:d1:
|
||||
6b:e5:87:7b:34:f6:d2:31:65:1d:18:42:69:6c:04:
|
||||
11:83:fe:44:ae:90:92:2d:0b:75:39:57:62:e6:17:
|
||||
2f:47:2b:c7:53:dd:10:2d:c9:e3:06:13:d2:b9:ba:
|
||||
63:2e:3c:7d:83:6b:d6:89:c9:cc:9d:4d:bf:9f:e8:
|
||||
a3:7b:da:c8:99:2b:ba:66:d6:8e:f8:41:41:a0:c9:
|
||||
d0:5e:c8:11:a4:55:4a:93:83:87:63:04:63:41:9c:
|
||||
fb:68:04:67:c2:71:2f:f2:65:1d:02:5d:15:db:2c:
|
||||
d9:04:69:85:c2:7d:0d:ea:3b:ac:85:f8:d4:8f:0f:
|
||||
c5:70:b2:45:e1:ec:b2:54:0b:e9:f7:82:b4:9b:1b:
|
||||
2d:b9:25:d4:ab:ca:8f:5b:44:3e:15:dd:b8:7f:b7:
|
||||
ee:f9
|
||||
Exponent: 65537 (0x10001)
|
||||
X509v3 extensions:
|
||||
X509v3 Key Usage: critical
|
||||
Digital Signature, Key Encipherment
|
||||
X509v3 Basic Constraints:
|
||||
CA:FALSE
|
||||
X509v3 Extended Key Usage:
|
||||
TLS Web Server Authentication, TLS Web Client Authentication
|
||||
X509v3 Subject Key Identifier:
|
||||
94:BA:73:78:A2:87:FB:58:28:28:CF:98:3B:C2:45:70:16:6E:29:2F
|
||||
X509v3 Authority Key Identifier:
|
||||
keyid:1E:52:A2:E8:54:D5:37:EB:D5:A8:1D:E4:C2:04:1D:37:E2:F7:70:03
|
||||
|
||||
X509v3 Subject Alternative Name:
|
||||
DNS:*.example.org, DNS:*.example.net, DNS:*.example.com, IP Address:10.0.1.0, IP Address:10.0.1.2, email:test@example.org, email:test@example.net
|
||||
Signature Algorithm: sha1WithRSAEncryption
|
||||
76:6b:05:b0:0e:34:11:b1:83:99:91:dc:ae:1b:e2:08:15:8b:
|
||||
16:b2:9b:27:1c:02:ac:b5:df:1b:d0:d0:75:a4:2b:2c:5c:65:
|
||||
ed:99:ab:f7:cd:fe:38:3f:c3:9a:22:31:1b:ac:8c:1c:c2:f9:
|
||||
5d:d4:75:7a:2e:72:c7:85:a9:04:af:9f:2a:cc:d3:96:75:f0:
|
||||
8e:c7:c6:76:48:ac:45:a4:b9:02:1e:2f:c0:15:c4:07:08:92:
|
||||
cb:27:50:67:a1:c8:05:c5:3a:b3:a6:48:be:eb:d5:59:ab:a2:
|
||||
1b:95:30:71:13:5b:0a:9a:73:3b:60:cc:10:d0:6a:c7:e5:d7:
|
||||
8b:2f:f9:2e:98:f2:ff:81:14:24:09:e3:4b:55:57:09:1a:22:
|
||||
74:f1:f6:40:13:31:43:89:71:0a:96:1a:05:82:1f:83:3a:87:
|
||||
9b:17:25:ef:5a:55:f2:2d:cd:0d:4d:e4:81:58:b6:e3:8d:09:
|
||||
62:9a:0c:bd:e4:e5:5c:f0:95:da:cb:c7:34:2c:34:5f:6d:fc:
|
||||
60:7b:12:5b:86:fd:df:21:89:3b:48:08:30:bf:67:ff:8c:e6:
|
||||
9b:53:cc:87:36:47:70:40:3b:d9:90:2a:d2:d2:82:c6:9c:f5:
|
||||
d1:d8:e0:e6:fd:aa:2f:95:7e:39:ac:fc:4e:d4:ce:65:b3:ec:
|
||||
c6:98:8a:31
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIGWjCCBUKgAwIBAgIBATANBgkqhkiG9w0BAQUFADCCAYQxEzARBgoJkiaJk/Is
|
||||
ZAEZFgNvcmcxFjAUBgoJkiaJk/IsZAEZFgZjaGVlc2UxDzANBgNVBAoMBkNoZWVz
|
||||
ZTERMA8GA1UECgwIQ2hlZXNlIDIxHzAdBgNVBAsMFlNpbXBsZSBTaWduaW5nIFNl
|
||||
Y3Rpb24xITAfBgNVBAsMGFNpbXBsZSBTaWduaW5nIFNlY3Rpb24gMjEaMBgGA1UE
|
||||
AwwRU2ltcGxlIFNpZ25pbmcgQ0ExHDAaBgNVBAMME1NpbXBsZSBTaWduaW5nIENB
|
||||
IDIxCzAJBgNVBAYTAkZSMQswCQYDVQQGEwJVUzERMA8GA1UEBwwIVE9VTE9VU0Ux
|
||||
DTALBgNVBAcMBExZT04xFjAUBgNVBAgMDVNpZ25pbmcgU3RhdGUxGDAWBgNVBAgM
|
||||
D1NpZ25pbmcgU3RhdGUgMjEhMB8GCSqGSIb3DQEJARYSc2ltcGxlQHNpZ25pbmcu
|
||||
Y29tMSIwIAYJKoZIhvcNAQkBFhNzaW1wbGUyQHNpZ25pbmcuY29tMB4XDTE4MTIw
|
||||
NjExMTAxNloXDTIwMTIwNTExMTAxNlowggF2MRMwEQYKCZImiZPyLGQBGRYDb3Jn
|
||||
MRYwFAYKCZImiZPyLGQBGRYGY2hlZXNlMQ8wDQYDVQQKDAZDaGVlc2UxETAPBgNV
|
||||
BAoMCENoZWVzZSAyMR8wHQYDVQQLDBZTaW1wbGUgU2lnbmluZyBTZWN0aW9uMSEw
|
||||
HwYDVQQLDBhTaW1wbGUgU2lnbmluZyBTZWN0aW9uIDIxFTATBgNVBAMMDCouY2hl
|
||||
ZXNlLm9yZzEVMBMGA1UEAwwMKi5jaGVlc2UuY29tMQswCQYDVQQGEwJGUjELMAkG
|
||||
A1UEBhMCVVMxETAPBgNVBAcMCFRPVUxPVVNFMQ0wCwYDVQQHDARMWU9OMRkwFwYD
|
||||
VQQIDBBDaGVlc2Ugb3JnIHN0YXRlMRkwFwYDVQQIDBBDaGVlc2UgY29tIHN0YXRl
|
||||
MR4wHAYJKoZIhvcNAQkBFg9jZXJ0QGNoZWVzZS5vcmcxHzAdBgkqhkiG9w0BCQEW
|
||||
EGNlcnRAc2NoZWVzZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
|
||||
AQDed/qNA3AwOd1RG8xg26laE7Gv/izGOJuICg+O2RuhHa8NZuQTW7xdNpLXXtD6
|
||||
iCnTeOGB3piyqSI/v4qvEpJj1KnD8uR+0tyixTkceuvXEnBjLkFH4PAI6Ny+CQHs
|
||||
KAmvNdd5nFA10Wvlh3s09tIxZR0YQmlsBBGD/kSukJItC3U5V2LmFy9HK8dT3RAt
|
||||
yeMGE9K5umMuPH2Da9aJycydTb+f6KN72siZK7pm1o74QUGgydBeyBGkVUqTg4dj
|
||||
BGNBnPtoBGfCcS/yZR0CXRXbLNkEaYXCfQ3qO6yF+NSPD8VwskXh7LJUC+n3grSb
|
||||
Gy25JdSryo9bRD4V3bh/t+75AgMBAAGjgeAwgd0wDgYDVR0PAQH/BAQDAgWgMAkG
|
||||
A1UdEwQCMAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMB0GA1UdDgQW
|
||||
BBSUunN4oof7WCgoz5g7wkVwFm4pLzAfBgNVHSMEGDAWgBQeUqLoVNU369WoHeTC
|
||||
BB034vdwAzBhBgNVHREEWjBYggwqLmNoZWVzZS5vcmeCDCouY2hlZXNlLm5ldIIM
|
||||
Ki5jaGVlc2UuY29thwQKAAEAhwQKAAECgQ90ZXN0QGNoZWVzZS5vcmeBD3Rlc3RA
|
||||
Y2hlZXNlLm5ldDANBgkqhkiG9w0BAQUFAAOCAQEAdmsFsA40EbGDmZHcrhviCBWL
|
||||
FrKbJxwCrLXfG9DQdaQrLFxl7Zmr983+OD/DmiIxG6yMHML5XdR1ei5yx4WpBK+f
|
||||
KszTlnXwjsfGdkisRaS5Ah4vwBXEBwiSyydQZ6HIBcU6s6ZIvuvVWauiG5UwcRNb
|
||||
CppzO2DMENBqx+XXiy/5Lpjy/4EUJAnjS1VXCRoidPH2QBMxQ4lxCpYaBYIfgzqH
|
||||
mxcl71pV8i3NDU3kgVi2440JYpoMveTlXPCV2svHNCw0X238YHsSW4b93yGJO0gI
|
||||
-----END CERTIFICATE-----
|
||||
```
|
||||
|
||||
## Configuration Options
|
||||
|
||||
| Field | Description | Default | Required |
|
||||
|
|
@ -362,5 +259,5 @@ If there are more than one certificate, they are separated by a `,`.
|
|||
The following example shows such a concatenation, when all the available fields are selected:
|
||||
|
||||
```text
|
||||
Subject="DC=org,DC=cheese,C=FR,C=US,ST=Cheese org state,ST=Cheese com state,L=TOULOUSE,L=LYON,O=Cheese,O=Cheese 2,CN=*.example.com";Issuer="DC=org,DC=cheese,C=FR,C=US,ST=Signing State,ST=Signing State 2,L=TOULOUSE,L=LYON,O=Cheese,O=Cheese 2,CN=Simple Signing CA 2";NB="1544094616";NA="1607166616";SAN="*.example.org,*.example.net,*.example.com,test@example.org,test@example.net,10.0.1.0,10.0.1.2"
|
||||
Subject="DC=org,DC=cheese,C=FR,C=US,ST=Cheese org state,ST=Cheese com state,L=TOULOUSE,L=LYON,O=Cheese,O=Cheese 2,CN=*.example.com";Issuer="DC=org,DC=cheese,C=FR,C=US,ST=Signing State,ST=Signing State 2,L=TOULOUSE,L=LYON,O=Cheese,O=Cheese 2,CN=Simple Signing CA 2";NB="1747282426";NA="1778818426"SAN="*.example.org,*.example.net,*.example.com,test@example.org,test@example.net,10.0.1.0,10.0.1.2"
|
||||
```
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@ With Docker, Traefik can leverage labels attached to a container to generate rou
|
|||
Attaching labels to containers (in your docker compose file)
|
||||
|
||||
```yaml
|
||||
version: "3"
|
||||
services:
|
||||
my-container:
|
||||
# ...
|
||||
|
|
@ -48,7 +47,6 @@ With Docker, Traefik can leverage labels attached to a container to generate rou
|
|||
Forward requests for `http://example.com` to `http://<private IP of container>:12345`:
|
||||
|
||||
```yaml
|
||||
version: "3"
|
||||
services:
|
||||
my-container:
|
||||
# ...
|
||||
|
|
@ -71,7 +69,6 @@ With Docker, Traefik can leverage labels attached to a container to generate rou
|
|||
In this example, requests are forwarded for `http://example-a.com` to `http://<private IP of container>:8000` in addition to `http://example-b.com` forwarding to `http://<private IP of container>:9000`:
|
||||
|
||||
```yaml
|
||||
version: "3"
|
||||
services:
|
||||
my-container:
|
||||
# ...
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@ With Docker Swarm, Traefik can leverage labels attached to a service to generate
|
|||
then that service is automatically assigned to the router.
|
||||
|
||||
```yaml
|
||||
version: "3"
|
||||
services:
|
||||
my-container:
|
||||
deploy:
|
||||
|
|
@ -67,7 +66,6 @@ With Docker Swarm, Traefik can leverage labels attached to a service to generate
|
|||
Forward requests for `http://example.com` to `http://<private IP of container>:12345`:
|
||||
|
||||
```yaml
|
||||
version: "3"
|
||||
services:
|
||||
my-container:
|
||||
# ...
|
||||
|
|
@ -93,7 +91,6 @@ With Docker Swarm, Traefik can leverage labels attached to a service to generate
|
|||
In this example, requests are forwarded for `http://example-a.com` to `http://<private IP of container>:8000` in addition to `http://example-b.com` forwarding to `http://<private IP of container>:9000`:
|
||||
|
||||
```yaml
|
||||
version: "3"
|
||||
services:
|
||||
my-container:
|
||||
# ...
|
||||
|
|
|
|||
|
|
@ -42,7 +42,6 @@ With Docker, Traefik can leverage labels attached to a container to generate rou
|
|||
Attaching labels to containers (in your docker compose file)
|
||||
|
||||
```yaml
|
||||
version: "3"
|
||||
services:
|
||||
my-container:
|
||||
# ...
|
||||
|
|
@ -55,7 +54,6 @@ With Docker, Traefik can leverage labels attached to a container to generate rou
|
|||
Forward requests for `http://example.com` to `http://<private IP of container>:12345`:
|
||||
|
||||
```yaml
|
||||
version: "3"
|
||||
services:
|
||||
my-container:
|
||||
# ...
|
||||
|
|
@ -78,7 +76,6 @@ With Docker, Traefik can leverage labels attached to a container to generate rou
|
|||
In this example, requests are forwarded for `http://example-a.com` to `http://<private IP of container>:8000` in addition to `http://example-b.com` forwarding to `http://<private IP of container>:9000`:
|
||||
|
||||
```yaml
|
||||
version: "3"
|
||||
services:
|
||||
my-container:
|
||||
# ...
|
||||
|
|
|
|||
|
|
@ -55,7 +55,6 @@ With Docker Swarm, Traefik can leverage labels attached to a service to generate
|
|||
then that service is automatically assigned to the router.
|
||||
|
||||
```yaml
|
||||
version: "3"
|
||||
services:
|
||||
my-container:
|
||||
deploy:
|
||||
|
|
@ -74,7 +73,6 @@ With Docker Swarm, Traefik can leverage labels attached to a service to generate
|
|||
Forward requests for `http://example.com` to `http://<private IP of container>:12345`:
|
||||
|
||||
```yaml
|
||||
version: "3"
|
||||
services:
|
||||
my-container:
|
||||
# ...
|
||||
|
|
@ -100,7 +98,6 @@ With Docker Swarm, Traefik can leverage labels attached to a service to generate
|
|||
In this example, requests are forwarded for `http://example-a.com` to `http://<private IP of container>:8000` in addition to `http://example-b.com` forwarding to `http://<private IP of container>:9000`:
|
||||
|
||||
```yaml
|
||||
version: "3"
|
||||
services:
|
||||
my-container:
|
||||
# ...
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ description: "Enforce strict Content‑Length validation in Traefik by streaming
|
|||
|
||||
Traefik acts as a streaming proxy. By default, it checks each chunk of data against the `Content-Length` header as it passes it on to the backend or client. This live check blocks truncated or over‑long streams without holding the entire message.
|
||||
|
||||
If you need Traefik to read and verify the full body before any data moves on, add the [buffering middleware](../../reference/routing-configuration/http/middlewares/buffering.md):
|
||||
If you need Traefik to read and verify the full body before any data moves on, add the [buffering middleware](../middlewares/http/buffering.md):
|
||||
|
||||
```yaml
|
||||
http:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
version: "3.3"
|
||||
|
||||
services:
|
||||
|
||||
traefik:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
version: "3.3"
|
||||
|
||||
secrets:
|
||||
ovh_endpoint:
|
||||
file: "./secrets/ovh_endpoint.secret"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
version: "3.3"
|
||||
|
||||
services:
|
||||
|
||||
traefik:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
version: "3.3"
|
||||
|
||||
services:
|
||||
|
||||
traefik:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
version: "3.3"
|
||||
|
||||
services:
|
||||
|
||||
traefik:
|
||||
|
|
|
|||
|
|
@ -23,8 +23,6 @@ Create a `docker-compose.yml` file with the following content:
|
|||
You can use a [pre-existing network](https://docs.docker.com/compose/networking/#use-a-pre-existing-network "Link to Docker Compose networking docs") too.
|
||||
|
||||
```yaml
|
||||
version: "3.3"
|
||||
|
||||
networks:
|
||||
traefiknet: {}
|
||||
|
||||
|
|
|
|||
355
docs/content/user-guides/websocket.md
Normal file
355
docs/content/user-guides/websocket.md
Normal file
|
|
@ -0,0 +1,355 @@
|
|||
---
|
||||
title: "Traefik WebSocket Documentation"
|
||||
description: "How to configure WebSocket and WebSocket Secure (WSS) connections with Traefik Proxy."
|
||||
---
|
||||
|
||||
# WebSocket
|
||||
|
||||
Configuring Traefik to handle WebSocket and WebSocket Secure (WSS) connections.
|
||||
{: .subtitle }
|
||||
|
||||
## Overview
|
||||
|
||||
WebSocket is a communication protocol that provides full-duplex communication channels over a single TCP connection.
|
||||
WebSocket Secure (WSS) is the encrypted version of WebSocket, using TLS/SSL encryption.
|
||||
|
||||
Traefik supports WebSocket and WebSocket Secure (WSS) out of the box. This guide will walk through examples of how to configure Traefik for different WebSocket scenarios.
|
||||
|
||||
## Basic WebSocket Configuration
|
||||
|
||||
A basic WebSocket configuration only requires defining a router and a service that points to your WebSocket server.
|
||||
|
||||
```yaml tab="Docker & Swarm"
|
||||
labels:
|
||||
- "traefik.http.routers.my-websocket.rule=Host(`ws.example.com`)"
|
||||
- "traefik.http.routers.my-websocket.service=my-websocket-service"
|
||||
- "traefik.http.services.my-websocket-service.loadbalancer.server.port=8000"
|
||||
```
|
||||
|
||||
```yaml tab="Kubernetes"
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: IngressRoute
|
||||
metadata:
|
||||
name: my-websocket-route
|
||||
spec:
|
||||
entryPoints:
|
||||
- web
|
||||
routes:
|
||||
- match: Host(`ws.example.com`)
|
||||
kind: Rule
|
||||
services:
|
||||
- name: my-websocket-service
|
||||
port: 8000
|
||||
```
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
http:
|
||||
routers:
|
||||
my-websocket:
|
||||
rule: "Host(`ws.example.com`)"
|
||||
service: my-websocket-service
|
||||
|
||||
services:
|
||||
my-websocket-service:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- url: "http://my-websocket-server:8000"
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
[http.routers]
|
||||
[http.routers.my-websocket]
|
||||
rule = "Host(`ws.example.com`)"
|
||||
service = "my-websocket-service"
|
||||
|
||||
[http.services]
|
||||
[http.services.my-websocket-service]
|
||||
[http.services.my-websocket-service.loadBalancer]
|
||||
[[http.services.my-websocket-service.loadBalancer.servers]]
|
||||
url = "http://my-websocket-server:8000"
|
||||
```
|
||||
|
||||
## WebSocket Secure (WSS) Configuration
|
||||
|
||||
WebSocket Secure (WSS) requires TLS configuration.
|
||||
The client connects using the `wss://` protocol instead of `ws://`.
|
||||
|
||||
```yaml tab="Docker & Swarm"
|
||||
labels:
|
||||
- "traefik.http.routers.my-websocket-secure.rule=Host(`wss.example.com`)"
|
||||
- "traefik.http.routers.my-websocket-secure.service=my-websocket-service"
|
||||
- "traefik.http.routers.my-websocket-secure.tls=true"
|
||||
- "traefik.http.services.my-websocket-service.loadbalancer.server.port=8000"
|
||||
```
|
||||
|
||||
```yaml tab="Kubernetes"
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: IngressRoute
|
||||
metadata:
|
||||
name: my-websocket-secure-route
|
||||
spec:
|
||||
entryPoints:
|
||||
- websecure
|
||||
routes:
|
||||
- match: Host(`wss.example.com`)
|
||||
kind: Rule
|
||||
services:
|
||||
- name: my-websocket-service
|
||||
port: 8000
|
||||
tls: {}
|
||||
```
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
http:
|
||||
routers:
|
||||
my-websocket-secure:
|
||||
rule: "Host(`wss.example.com`)"
|
||||
service: my-websocket-service
|
||||
tls: {}
|
||||
|
||||
services:
|
||||
my-websocket-service:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- url: "http://my-websocket-server:8000"
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
[http.routers]
|
||||
[http.routers.my-websocket-secure]
|
||||
rule = "Host(`wss.example.com`)"
|
||||
service = "my-websocket-service"
|
||||
[http.routers.my-websocket-secure.tls]
|
||||
|
||||
[http.services]
|
||||
[http.services.my-websocket-service]
|
||||
[http.services.my-websocket-service.loadBalancer]
|
||||
[[http.services.my-websocket-service.loadBalancer.servers]]
|
||||
url = "http://my-websocket-server:8000"
|
||||
```
|
||||
|
||||
## SSL Termination for WebSockets
|
||||
|
||||
In this scenario, clients connect to Traefik using WSS (encrypted), but Traefik connects to your backend server using WS (unencrypted).
|
||||
This is called SSL termination.
|
||||
|
||||
```yaml tab="Docker & Swarm"
|
||||
labels:
|
||||
- "traefik.http.routers.my-wss-termination.rule=Host(`wss.example.com`)"
|
||||
- "traefik.http.routers.my-wss-termination.service=my-ws-service"
|
||||
- "traefik.http.routers.my-wss-termination.tls=true"
|
||||
- "traefik.http.services.my-ws-service.loadbalancer.server.port=8000"
|
||||
```
|
||||
|
||||
```yaml tab="Kubernetes"
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: IngressRoute
|
||||
metadata:
|
||||
name: my-wss-termination-route
|
||||
spec:
|
||||
entryPoints:
|
||||
- websecure
|
||||
routes:
|
||||
- match: Host(`wss.example.com`)
|
||||
kind: Rule
|
||||
services:
|
||||
- name: my-ws-service
|
||||
port: 8000
|
||||
tls: {}
|
||||
```
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
http:
|
||||
routers:
|
||||
my-wss-termination:
|
||||
rule: "Host(`wss.example.com`)"
|
||||
service: my-ws-service
|
||||
tls: {}
|
||||
|
||||
services:
|
||||
my-ws-service:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- url: "http://my-ws-server:8000"
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
[http.routers]
|
||||
[http.routers.my-wss-termination]
|
||||
rule = "Host(`wss.example.com`)"
|
||||
service = "my-ws-service"
|
||||
[http.routers.my-wss-termination.tls]
|
||||
|
||||
[http.services]
|
||||
[http.services.my-ws-service]
|
||||
[http.services.my-ws-service.loadBalancer]
|
||||
[[http.services.my-ws-service.loadBalancer.servers]]
|
||||
url = "http://my-ws-server:8000"
|
||||
```
|
||||
|
||||
## End-to-End WebSocket Secure (WSS)
|
||||
|
||||
For end-to-end encryption, Traefik can be configured to connect to your backend using HTTPS.
|
||||
|
||||
```yaml tab="Docker & Swarm"
|
||||
labels:
|
||||
- "traefik.http.routers.my-wss-e2e.rule=Host(`wss.example.com`)"
|
||||
- "traefik.http.routers.my-wss-e2e.service=my-wss-service"
|
||||
- "traefik.http.routers.my-wss-e2e.tls=true"
|
||||
- "traefik.http.services.my-wss-service.loadbalancer.server.port=8443"
|
||||
# If the backend uses a self-signed certificate
|
||||
- "traefik.http.serversTransports.insecureTransport.insecureSkipVerify=true"
|
||||
- "traefik.http.services.my-wss-service.loadBalancer.serversTransport=insecureTransport"
|
||||
```
|
||||
|
||||
```yaml tab="Kubernetes"
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: ServersTransport
|
||||
metadata:
|
||||
name: insecure-transport
|
||||
spec:
|
||||
insecureSkipVerify: true
|
||||
|
||||
---
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: IngressRoute
|
||||
metadata:
|
||||
name: my-wss-e2e-route
|
||||
spec:
|
||||
entryPoints:
|
||||
- websecure
|
||||
routes:
|
||||
- match: Host(`wss.example.com`)
|
||||
kind: Rule
|
||||
services:
|
||||
- name: my-wss-service
|
||||
port: 8443
|
||||
serversTransport: insecure-transport
|
||||
tls: {}
|
||||
```
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
http:
|
||||
serversTransports:
|
||||
insecureTransport:
|
||||
insecureSkipVerify: true
|
||||
|
||||
routers:
|
||||
my-wss-e2e:
|
||||
rule: "Host(`wss.example.com`)"
|
||||
service: my-wss-service
|
||||
tls: {}
|
||||
|
||||
services:
|
||||
my-wss-service:
|
||||
loadBalancer:
|
||||
serversTransport: insecureTransport
|
||||
servers:
|
||||
- url: "https://my-wss-server:8443"
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
[http.serversTransports]
|
||||
[http.serversTransports.insecureTransport]
|
||||
insecureSkipVerify = true
|
||||
|
||||
[http.routers]
|
||||
[http.routers.my-wss-e2e]
|
||||
rule = "Host(`wss.example.com`)"
|
||||
service = "my-wss-service"
|
||||
[http.routers.my-wss-e2e.tls]
|
||||
|
||||
[http.services]
|
||||
[http.services.my-wss-service]
|
||||
[http.services.my-wss-service.loadBalancer]
|
||||
serversTransport = "insecureTransport"
|
||||
[[http.services.my-wss-service.loadBalancer.servers]]
|
||||
url = "https://my-wss-server:8443"
|
||||
```
|
||||
|
||||
## EntryPoints Configuration for WebSockets
|
||||
|
||||
In your Traefik static configuration, you'll need to define entryPoints for both WS and WSS:
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
entryPoints:
|
||||
web:
|
||||
address: ":80"
|
||||
websecure:
|
||||
address: ":443"
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
[entryPoints]
|
||||
[entryPoints.web]
|
||||
address = ":80"
|
||||
[entryPoints.websecure]
|
||||
address = ":443"
|
||||
```
|
||||
|
||||
## Testing WebSocket Connections
|
||||
|
||||
You can test your WebSocket configuration using various tools:
|
||||
|
||||
1. Browser Developer Tools: Most modern browsers include WebSocket debugging in their developer tools.
|
||||
2. WebSocket client tools like [wscat](https://github.com/websockets/wscat) or online tools like [Piesocket's WebSocket Tester](https://www.piesocket.com/websocket-tester).
|
||||
|
||||
Example wscat commands:
|
||||
|
||||
```bash
|
||||
# Test standard WebSocket
|
||||
wscat -c ws://ws.example.com
|
||||
|
||||
# Test WebSocket Secure
|
||||
wscat -c wss://wss.example.com
|
||||
```
|
||||
|
||||
## Common Issues and Solutions
|
||||
|
||||
### Headers and Origin Checks
|
||||
|
||||
Some WebSocket servers implement origin checking. Traefik passes the original headers to your backend, including the `Origin` header.
|
||||
|
||||
If you need to manipulate headers for WebSocket connections, you can use Traefik's Headers middleware:
|
||||
|
||||
```yaml tab="Docker & Swarm"
|
||||
labels:
|
||||
- "traefik.http.middlewares.my-headers.headers.customrequestheaders.Origin=https://allowed-origin.com"
|
||||
- "traefik.http.routers.my-websocket.middlewares=my-headers"
|
||||
```
|
||||
|
||||
```yaml tab="Kubernetes"
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: Middleware
|
||||
metadata:
|
||||
name: my-headers
|
||||
spec:
|
||||
headers:
|
||||
customRequestHeaders:
|
||||
Origin: "https://allowed-origin.com"
|
||||
|
||||
---
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: IngressRoute
|
||||
metadata:
|
||||
name: my-websocket-route
|
||||
spec:
|
||||
routes:
|
||||
- match: Host(`ws.example.com`)
|
||||
kind: Rule
|
||||
middlewares:
|
||||
- name: my-headers
|
||||
services:
|
||||
- name: my-websocket-service
|
||||
port: 8000
|
||||
```
|
||||
|
||||
### Certificate Issues with WSS
|
||||
|
||||
If you're experiencing certificate issues with WSS:
|
||||
|
||||
1. Ensure your certificates are valid and not expired
|
||||
2. For testing with self-signed certificates, configure your clients to accept them
|
||||
3. When using Let's Encrypt, ensure your domain is properly configured
|
||||
|
||||
For backends with self-signed certificates, use the `insecureSkipVerify` option in the ServersTransport configuration as shown in the examples above.
|
||||
|
|
@ -171,6 +171,7 @@ nav:
|
|||
- 'Kubernetes and Let''s Encrypt': 'user-guides/crd-acme/index.md'
|
||||
- 'Kubernetes and cert-manager': 'user-guides/cert-manager.md'
|
||||
- 'gRPC Examples': 'user-guides/grpc.md'
|
||||
- 'WebSocket Examples': 'user-guides/websocket.md'
|
||||
- 'Docker':
|
||||
- 'Basic Example': 'user-guides/docker-compose/basic-example/index.md'
|
||||
- 'HTTPS with Let''s Encrypt':
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue