1
0
mirror of https://github.com/containous/traefik.git synced 2026-01-19 04:32:51 +03:00

Compare commits

...

29 Commits

Author SHA1 Message Date
Kevin Pollet
9e5d4ba5a1 Prepare release v2.11.35 2026-01-14 10:28:04 +01:00
Gina A.
adf47fba31 Make encoded character options opt-in 2026-01-14 10:16:04 +01:00
Sheddy
ee265a8509 Add Scarf Analytics to documentation 2026-01-13 11:16:05 +01:00
Barbara Soraggi
fc67185987 Replace markdown-include dependency with mkdocs-include-markdown-plugin 2026-01-13 10:08:04 +01:00
Michel Loiseleur
e8067f4e01 Refactor CI on documentation 2026-01-09 17:24:04 +01:00
LBF38
e9f3089e90 Add timeout to ACME-TLS/1 challenge handshake
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2026-01-08 16:16:05 +01:00
Michael
47d7094dfb Welcome 2026 2026-01-02 09:58:04 +01:00
Michael
d1765c7768 Prepare release v2.11.34 2025-12-29 15:56:04 +01:00
Romain
90ce858347 Fix deny encoded characters
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2025-12-23 16:00:05 +01:00
Jesper Noordsij
8ebab1b243 Update Dockerfiles to Alpine 3.23 2025-12-17 15:26:06 +01:00
Romain
5fe10e2098 Prepare release v2.11.33 2025-12-17 10:56:04 +01:00
Jesper Noordsij
fd36de5a0a Bump webui to NodeJS v24 2025-12-17 10:36:05 +01:00
Romain
60b19b7b81 Print access logs for rejected requests and warn about new behavior 2025-12-16 16:20:05 +01:00
Romain
e0e49533ab Clarify doc about encodedCharacters rejection 2025-12-09 15:28:04 +01:00
Romain
351dcbd186 Fix encodedCharacters entryPoint option documentation 2025-12-08 10:44:04 +01:00
Kevin Pollet
7f40f3cd58 Fix encoded characters option documentation 2025-12-05 15:06:04 +01:00
Michael
c63be08b07 Github action release split 2025-12-05 09:44:04 +01:00
Kevin Pollet
e931a71660 Fix migration guide indentation 2025-12-04 16:40:04 +01:00
Romain
63a6172ec4 Prepare release v2.11.32 2025-12-04 15:26:04 +01:00
Romain
4d7d627319 Reject suspicious encoded characters
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2025-12-04 15:10:05 +01:00
GreyXor
0b6438b7c0 Bump github.com/quic-go/quic-go to v0.57.1 2025-12-02 09:04:05 +01:00
Michel Loiseleur
e15c11961f Protect CI against supply chain attack on nodejs 2025-12-01 14:58:05 +01:00
Emile Vauge
042feacf3e Update SECURITY.md to streamline information 2025-11-24 15:32:04 +01:00
Chris Wayne
759e82c3c8 Update SECURITY.md 2025-11-24 11:56:04 +01:00
GreyXor
2d7262515d Bump github.com/quic-go/quic-go to v0.57.0 2025-11-24 10:44:04 +01:00
Kevin Pollet
f3e199cd47 Bump golang.org/x/crypto to v0.45.0 2025-11-20 11:30:05 +01:00
Kevin Pollet
9232535cf6 Validate plugin module name
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2025-11-20 10:50:04 +01:00
Kevin Pollet
79bb320f4c Prepare release v2.11.31 2025-11-13 10:42:16 +01:00
Kevin Pollet
058b194604 Auto-negotiate Docker API version 2025-11-12 16:32:06 +01:00
197 changed files with 1755 additions and 310 deletions

63
.github/workflows/check_doc.yaml vendored Normal file
View File

@@ -0,0 +1,63 @@
name: Check Documentation
on:
pull_request:
branches:
- '*'
paths:
- '.github/workflows/check_doc.yaml'
- 'docs/**'
jobs:
docs:
name: lint, build and verify
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Install markdownlint
run: |
npm install --global markdownlint@0.29.0 markdownlint-cli@0.35.0
- name: Lint
run: ./docs/scripts/lint.sh docs
- name: Setup python
uses: actions/setup-python@v6
with:
python-version: '3.12'
cache: 'pip'
cache-dependency-path: "./docs/requirements.txt"
- name: Build documentation
working-directory: ./docs
run: |
pip install -r requirements.txt
mkdocs build --strict
- name: Setup ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.4'
- name: Install html-proofer
run: |
gem install nokogiri --version 1.18.6 --no-document -- --use-system-libraries
gem install html-proofer --version 5.0.10 --no-document -- --use-system-libraries
env:
NOKOGIRI_USE_SYSTEM_LIBRARIES: "true"
# Comes from https://github.com/gjtorikian/html-proofer?tab=readme-ov-file#caching-with-continuous-integration
- name: Cache HTMLProofer
uses: actions/cache@v4
with:
path: tmp/.htmlproofer
key: ${{ runner.os }}-htmlproofer
- name: Verify
run: ./docs/scripts/verify.sh docs/site

View File

@@ -1,25 +0,0 @@
name: Check Documentation
on:
pull_request:
branches:
- '*'
jobs:
docs:
name: Check, verify and build documentation
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Check documentation
run: make docs-pull-images docs
env:
# These variables are not passed to workflows that are triggered by a pull request from a fork.
DOCS_VERIFY_SKIP: ${{ vars.DOCS_VERIFY_SKIP }}
DOCS_LINT_SKIP: ${{ vars.DOCS_LINT_SKIP }}

View File

@@ -24,7 +24,7 @@ jobs:
strategy:
matrix:
os: [ linux-amd64, linux-386, linux-arm, linux-arm64, linux-ppc64le, linux-s390x, linux-riscv64, darwin, windows-amd64, windows-arm64, windows-386, freebsd, openbsd ]
os: [ linux-amd64, linux-386, linux-arm, linux-arm64, linux-ppc64le, linux-s390x, linux-riscv64, darwin-amd64, darwin-arm64, windows-amd64, windows-arm64, windows-386, freebsd-amd64, freebsd-386, openbsd-amd64, openbsd-386, openbsd-riscv64 ]
needs:
- build-webui

View File

@@ -1,6 +1,8 @@
name: Build Web UI
on:
workflow_call: {}
env:
SAFE_CHAIN_MINIMUM_PACKAGE_AGE_HOURS: 360 # 15 days
jobs:
build-webui:
@@ -19,10 +21,16 @@ jobs:
cache: yarn
cache-dependency-path: webui/yarn.lock
- name: Setup safe-chain
working-directory: ./webui
run: |
npm i -g @aikidosec/safe-chain
safe-chain setup-ci
- name: Build webui
working-directory: ./webui
run: |
yarn install
yarn install --ignore-scripts
yarn build
- name: Package webui

View File

@@ -80,7 +80,12 @@ jobs:
cache: 'yarn'
cache-dependency-path: webui/yarn.lock
- name: Setup safe-chain
run: |
npm i -g @aikidosec/safe-chain
safe-chain setup-ci
- name: UI unit tests
run: |
yarn --cwd webui install
yarn --cwd webui install --ignore-scripts
yarn --cwd webui test:unit:ci

View File

@@ -54,10 +54,12 @@ changelog:
archives:
- id: traefik
name_template: '{{ .ProjectName }}_v{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}'
format: tar.gz
formats:
- tar.gz
format_overrides:
- goos: windows
format: zip
formats:
- zip
files:
- LICENSE.md
- CHANGELOG.md

View File

@@ -1,3 +1,47 @@
## [v2.11.35](https://github.com/traefik/traefik/tree/v2.11.35) (2026-01-14)
[All Commits](https://github.com/traefik/traefik/compare/v2.11.34...v2.11.35)
**Bug fixes:**
- **[acme]** Add timeout to ACME-TLS/1 challenge handshake ([#12516](https://github.com/traefik/traefik/pull/12516) by [LBF38](https://github.com/LBF38))
- **[server]** Make encoded character options opt-in ([#12540](https://github.com/traefik/traefik/pull/12540) by [gndz07](https://github.com/gndz07))
## [v2.11.34](https://github.com/traefik/traefik/tree/v2.11.34) (2025-12-23)
[All Commits](https://github.com/traefik/traefik/compare/v2.11.33...v2.11.34)
**Bug fixes:**
- **[server]** Fix deny encoded characters ([#12457](https://github.com/traefik/traefik/pull/12457) by [rtribotte](https://github.com/rtribotte))
## [v2.11.33](https://github.com/traefik/traefik/tree/v2.11.33) (2025-12-17)
[All Commits](https://github.com/traefik/traefik/compare/v2.11.32...v2.11.33)
**Bug fixes:**
- **[server]** Print access logs for rejected requests and warn about new behavior ([#12426](https://github.com/traefik/traefik/pull/12426) by [rtribotte](https://github.com/rtribotte))
**Documentation:**
- Clarify doc about encoded characters rejection ([#12391](https://github.com/traefik/traefik/pull/12391) by [rtribotte](https://github.com/rtribotte))
- Fix encoded characters entryPoint option documentation ([#12384](https://github.com/traefik/traefik/pull/12384) by [rtribotte](https://github.com/rtribotte))
- Fix encoded characters option documentation ([#12373](https://github.com/traefik/traefik/pull/12373) by [kevinpollet](https://github.com/kevinpollet))
## [v2.11.32](https://github.com/traefik/traefik/tree/v2.11.32) (2025-12-04)
[All Commits](https://github.com/traefik/traefik/compare/v2.11.31...v2.11.32)
**Bug fixes:**
- **[server]** Reject suspicious encoded characters ([#12360](https://github.com/traefik/traefik/pull/12360) by [rtribotte](https://github.com/rtribotte))
- **[plugins]** Validate plugin module name ([#12291](https://github.com/traefik/traefik/pull/12291) by [kevinpollet](https://github.com/kevinpollet))
- **[http3]** Bump github.com/quic-go/quic-go to v0.57.1 ([#12319](https://github.com/traefik/traefik/pull/12319) by [GreyXor](https://github.com/GreyXor))
- **[http3]** Bump github.com/quic-go/quic-go to v0.57.0 ([#12308](https://github.com/traefik/traefik/pull/12308) by [GreyXor](https://github.com/GreyXor))
- **[server]** Bump golang.org/x/crypto to v0.45.0 ([#12296](https://github.com/traefik/traefik/pull/12296) by [kevinpollet](https://github.com/kevinpollet))
**Documentation:**
- Update SECURITY.md to streamline information ([#12310](https://github.com/traefik/traefik/pull/12310) by [emilevauge](https://github.com/emilevauge))
- Update SECURITY.md ([#12304](https://github.com/traefik/traefik/pull/12304) by [cwayne18](https://github.com/cwayne18))
## [v2.11.31](https://github.com/traefik/traefik/tree/v2.11.31) (2025-11-13)
[All Commits](https://github.com/traefik/traefik/compare/v2.11.30...v2.11.31)
**Bug fixes:**
- **[docker,docker/swarm]** Auto-negotiate Docker API version ([#12262](https://github.com/traefik/traefik/pull/12262) by [kevinpollet](https://github.com/kevinpollet))
## [v2.11.30](https://github.com/traefik/traefik/tree/v2.11.30) (2025-10-28)
[All Commits](https://github.com/traefik/traefik/compare/v2.11.29...v2.11.30)

View File

@@ -1,5 +1,5 @@
# syntax=docker/dockerfile:1.2
FROM alpine:3.22
FROM alpine:3.23
RUN apk add --no-cache --no-progress ca-certificates tzdata

View File

@@ -1,10 +1,5 @@
# Security Policy
You can join our security mailing list to be aware of the latest announcements from our security team.
You can subscribe by sending an email to security+subscribe@traefik.io or on [the online viewer](https://groups.google.com/a/traefik.io/forum/#!forum/security).
Reported vulnerabilities can be found on [cve.mitre.org](https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=traefik).
## Supported Versions
- We usually release 3/4 new versions (e.g. 1.1.0, 1.2.0, 1.3.0) per year.
@@ -17,10 +12,10 @@ We use [Semantic Versioning](https://semver.org/).
| Version | Supported |
|-----------|--------------------|
| `2.2.x` | :white_check_mark: |
| `< 2.2.x` | :x: |
| `1.7.x` | :white_check_mark: |
| `< 1.7.x` | :x: |
| `3.6.x` | :white_check_mark: |
| `< 3.6.x` | :x: |
| `2.11.x` | :white_check_mark: |
| `< 2.11.x` | :x: |
## Reporting a Vulnerability
@@ -28,3 +23,5 @@ We want to keep Traefik safe for everyone.
If you've discovered a security vulnerability in Traefik,
we appreciate your help in disclosing it to us in a responsible manner,
by creating a [security advisory](https://github.com/traefik/traefik/security/advisories).
Reported vulnerabilities can be found on [cve.mitre.org](https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=traefik).

View File

@@ -87,6 +87,11 @@ Complete documentation is available at https://traefik.io`,
func runCmd(staticConfiguration *static.Configuration) error {
configureLogging(staticConfiguration)
log.WithoutContext().Warn("Traefik can reject some encoded characters in the request path." +
"When your backend is not fully compliant with [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986)," +
"it is recommended to set these options to `false` to avoid split-view situation." +
"Refer to the documentation for more details: https://doc.traefik.io/traefik/v2.11/migration/v2/#encoded-characters-configuration-default-values")
http.DefaultTransport.(*http.Transport).Proxy = http.ProxyFromEnvironment
if err := roundrobin.SetDefaultWeight(0); err != nil {

View File

@@ -1,4 +1,4 @@
FROM alpine:3.22
FROM alpine:3.23
RUN apk --no-cache --no-progress add \
build-base \

View File

@@ -1,4 +1,14 @@
/* Highlight */
(function(hljs) {
hljs.initHighlightingOnLoad();
})(hljs);
})(hljs);
/* Scarf Analytics - cookieless, anonymous company-level intelligence */
(function() {
var img = document.createElement('img');
img.src = 'https://static.scarf.sh/a.png?x-pxid=1a49232a-b165-4015-8ed2-a1092f1f0d83';
img.referrerPolicy = 'no-referrer-when-downgrade';
img.loading = 'eager';
img.style.cssText = 'visibility:hidden;position:absolute;width:1px;height:1px;';
document.body.appendChild(img);
})();

View File

@@ -34,7 +34,7 @@ Below is a non-exhaustive list of versions and their maintenance status:
This page is maintained and updated periodically to reflect our roadmap and any decisions affecting the end of support for Traefik Proxy.
Please refer to our migration guides for specific instructions on upgrading between versions, an example is the [v2 to v3 migration guide](../migration/v2-to-v3.md).
Please refer to our migration guides for specific instructions on upgrading between versions.
!!! important "All target dates for end of support or feature removal announcements may be subject to change."

View File

@@ -57,4 +57,4 @@ You no longer need to create and synchronize configuration files cluttered with
Traefik is able to use your cluster API to discover the services and read the attached information.
In Traefik, these connectors are called [providers](../providers/overview.md "Link to overview about Traefik providers") because they *provide* the configuration to Traefik.
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -94,4 +94,4 @@ All the configuration options are documented in their related section.
You can browse the available features in the menu, the [providers](../providers/overview.md), or the [routing section](../routing/overview.md) to see them in action.
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -252,4 +252,4 @@ In which case, you should make sure your infrastructure is properly set up for a
LEGO_DISABLE_CNAME_SUPPORT=true
```
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -144,4 +144,4 @@ And run it:
All the details are available in the [Contributing Guide](../contributing/building-testing.md)
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -334,4 +334,4 @@ curl -v http://localhost/
- Use [IngressRoute CRD](../providers/kubernetes-crd.md)
- Protect [ingresses with TLS](../routing/providers/kubernetes-ingress.md#enabling-tls-via-annotations)
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -121,4 +121,4 @@ IP: 172.27.0.4
Now that you have a basic understanding of how Traefik can automatically create the routes to your services and load balance them, it is time to dive into [the user guides](../../user-guides/docker-compose/basic-example/ "Link to the user guides") and [the documentation](/ "Link to the docs landing page") and let Traefik work for you!
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -797,4 +797,4 @@ If Let's Encrypt is not reachable, the following certificates will apply:
!!! important
For new (sub)domains which need Let's Encrypt authentication, the default Traefik certificate will be used until Traefik is restarted.
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -20,4 +20,4 @@ That is to say, how to obtain [TLS certificates](./tls.md#certificates-definitio
either through a definition in the dynamic configuration, or through [Let's Encrypt](./acme.md) (ACME).
And how to configure [TLS options](./tls.md#tls-options), and [certificates stores](./tls.md#certificates-stores).
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -561,4 +561,4 @@ spec:
clientAuthType: RequireAndVerifyClientCert
```
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -404,4 +404,4 @@ http:
[http.middlewares.test-auth.basicAuth]
removeHeader = true
```
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -637,4 +637,4 @@ http:
[http.middlewares.test-auth.forwardAuth.tls]
insecureSkipVerify: true
```
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -480,4 +480,4 @@ Set `isDevelopment` to `true` when developing to mitigate the unwanted effects o
Usually testing takes place using HTTP, not HTTPS, and on `localhost`, not your production domain.
If you would like your development environment to mimic production with complete Host blocking, SSL redirects, and STS headers, leave this as `false`.
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -158,4 +158,4 @@ http:
Please take a look at the community-contributed plugins in the [plugin catalog](https://plugins.traefik.io/plugins).
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -100,4 +100,4 @@ The `replacement` option defines how to modify the URL to have the new target UR
Care should be taken when defining replacement expand variables: `$1x` is equivalent to `${1x}`, not `${1}x` (see [Regexp.Expand](https://golang.org/pkg/regexp/#Regexp.Expand)), so use `${1}` syntax.
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -171,4 +171,4 @@ http:
forceSlash = false
```
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -130,4 +130,4 @@ A list of HTTP middlewares can be found [here](http/overview.md).
A list of TCP middlewares can be found [here](tcp/overview.md).
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -714,3 +714,53 @@ It appears that enabling MPTCP on some platforms can cause Traefik to stop with
- `set tcp X.X.X.X:X->X.X.X.X:X: setsockopt: operation not supported`
However, it can be re-enabled by setting the `multipathtcp` variable in the GODEBUG environment variable, see the related [go documentation](https://go.dev/doc/godebug#go-124).
## v2.11.32
### Encoded Characters in Request Path
Since `v2.11.32`, for security reasons Traefik now rejects requests with a path containing a specific set of encoded characters by default.
When such a request is received, Traefik responds with a `400 Bad Request` status code.
Here is the list of the encoded characters that are rejected by default, along with the corresponding configuration option to allow them:
| Encoded Character | Character | Config option to allow the encoded character |
|-------------------|-------------------------|--------------------------------------------------------------------------------------|
| `%2f` or `%2F` | `/` (slash) | `entryPoints.<name>`<br/>`.http.encodedCharacters`<br/>`.allowEncodedSlash` |
| `%5c` or `%5C` | `\` (backslash) | `entryPoints.<name>.`<br/>`.http.encodedCharacters`<br/>`.allowEncodedBackSlash` |
| `%00` | `NULL` (null character) | `entryPoints.<name>.`<br/>`.http.encodedCharacters`<br/>`.allowEncodedNullCharacter` |
| `%3b` or `%3B` | `;` (semicolon) | `entryPoints.<name>.`<br/>`.http.encodedCharacters`<br/>`.allowEncodedSemicolon` |
| `%25` | `%` (percent) | `entryPoints.<name>.`<br/>`.http.encodedCharacters`<br/>`.allowEncodedPercent` |
| `%3f` or `%3F` | `?` (question mark) | `entryPoints.<name>.`<br/>`.http.encodedCharacters`<br/>`.allowEncodedQuestionMark` |
| `%23` | `#` (hash) | `entryPoints.<name>.`<br/>`.http.encodedCharacters`<br/>`.allowEncodedHash` |
Note: This check is not done against query parameters,
but only against the request path as defined in [RFC3986 section-3](https://datatracker.ietf.org/doc/html/rfc3986#section-3).
Please check out the entrypoint [encodedCharacters option](../routing/entrypoints.md#encoded-characters) documentation for more details.
## v2.11.35
### Encoded Characters Configuration Default Values
Since `v2.11.35`, the options for encoded characters now have a `true` default value.
This means that Traefik will not reject requests with a path containing a specific set of encoded characters by default.
It is now up to the users to configure the security hardening of encoded characters.
Here is the list of the encoded characters that can be configured to `false` to disallow them:
| Encoded Character | Character | Config options | Default value |
|-------------------|-------------------------|--------------------------------------------------------------------------------------|---------------|
| `%2f` or `%2F` | `/` (slash) | `entryPoints.<name>`<br/>`.http.encodedCharacters`<br/>`.allowEncodedSlash` | `true` |
| `%5c` or `%5C` | `\` (backslash) | `entryPoints.<name>.`<br/>`.http.encodedCharacters`<br/>`.allowEncodedBackSlash` | `true` |
| `%00` | `NULL` (null character) | `entryPoints.<name>.`<br/>`.http.encodedCharacters`<br/>`.allowEncodedNullCharacter` | `true` |
| `%3b` or `%3B` | `;` (semicolon) | `entryPoints.<name>.`<br/>`.http.encodedCharacters`<br/>`.allowEncodedSemicolon` | `true` |
| `%25` | `%` (percent) | `entryPoints.<name>.`<br/>`.http.encodedCharacters`<br/>`.allowEncodedPercent` | `true` |
| `%3f` or `%3F` | `?` (question mark) | `entryPoints.<name>.`<br/>`.http.encodedCharacters`<br/>`.allowEncodedQuestionMark` | `true` |
| `%23` | `#` (hash) | `entryPoints.<name>.`<br/>`.http.encodedCharacters`<br/>`.allowEncodedHash` | `true` |
Note: This check is not done against query parameters,
but only against the request path as defined
in [RFC3986 section-3](https://datatracker.ietf.org/doc/html/rfc3986#section-3).
Please check out the entrypoint [encodedCharacters option](../routing/entrypoints.md#encoded-characters) documentation
for more details.

View File

@@ -281,4 +281,4 @@ services:
- /var/run/docker.sock:/var/run/docker.sock
```
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -90,4 +90,4 @@ This allows the logs to be rotated and processed by an external program, such as
!!! warning
This does not work on Windows due to the lack of USR signals.
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -175,4 +175,4 @@ All the following endpoints must be accessed with a `GET` HTTP request.
| `/debug/pprof/symbol` | See the [pprof Symbol](https://golang.org/pkg/net/http/pprof/#Symbol) Go documentation. |
| `/debug/pprof/trace` | See the [pprof Trace](https://golang.org/pkg/net/http/pprof/#Trace) Go documentation. |
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -132,4 +132,4 @@ api:
--api.dashboard=false
```
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -31,4 +31,4 @@ The experience of implementing a Traefik plugin is comparable to writing a web b
To learn more about Traefik plugin creation, please refer to the [developer documentation](https://plugins.traefik.io/create).
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -764,4 +764,4 @@ providers:
--providers.docker.allowEmptyServices=true
```
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -292,4 +292,4 @@ To illustrate, it is possible to easily define multiple routers, services, and T
{{ end }}
```
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -345,4 +345,4 @@ providers:
For additional information, refer to the [full example](../user-guides/crd-acme/index.md) with Let's Encrypt.
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -269,4 +269,4 @@ providers:
--providers.kubernetesgateway.throttleDuration=10s
```
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -504,4 +504,4 @@ providers:
To learn more about the various aspects of the Ingress specification that Traefik supports,
many examples of Ingresses definitions are located in the test [examples](https://github.com/traefik/traefik/tree/v2.11/pkg/provider/kubernetes/ingress/fixtures) of the Traefik repository.
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -233,4 +233,4 @@ List of providers that support constraints:
- [Kubernetes Ingress](./kubernetes-ingress.md#labelselector)
- [Kubernetes Gateway](./kubernetes-gateway.md#labelselector)
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -36,4 +36,4 @@ Dynamic configuration with Kubernetes Custom Resource
--8<-- "content/reference/dynamic-configuration/kubernetes-crd-rbac.yml"
```
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -30,4 +30,4 @@ Dynamic configuration with Kubernetes Gateway provider.
--8<-- "content/reference/dynamic-configuration/kubernetes-gateway-rbac.yml"
```
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -123,6 +123,27 @@ Trust only forwarded headers from selected IPs.
`--entrypoints.<name>.http`:
HTTP configuration.
`--entrypoints.<name>.http.encodedcharacters.allowencodedbackslash`:
Defines whether requests with encoded back slash characters in the path are allowed. (Default: ```true```)
`--entrypoints.<name>.http.encodedcharacters.allowencodedhash`:
Defines whether requests with encoded hash characters in the path are allowed. (Default: ```true```)
`--entrypoints.<name>.http.encodedcharacters.allowencodednullcharacter`:
Defines whether requests with encoded null characters in the path are allowed. (Default: ```true```)
`--entrypoints.<name>.http.encodedcharacters.allowencodedpercent`:
Defines whether requests with encoded percent characters in the path are allowed. (Default: ```true```)
`--entrypoints.<name>.http.encodedcharacters.allowencodedquestionmark`:
Defines whether requests with encoded question mark characters in the path are allowed. (Default: ```true```)
`--entrypoints.<name>.http.encodedcharacters.allowencodedsemicolon`:
Defines whether requests with encoded semicolon characters in the path are allowed. (Default: ```true```)
`--entrypoints.<name>.http.encodedcharacters.allowencodedslash`:
Defines whether requests with encoded slash characters in the path are allowed. (Default: ```true```)
`--entrypoints.<name>.http.encodequerysemicolons`:
Defines whether request query semicolons should be URLEncoded. (Default: ```false```)

View File

@@ -132,6 +132,27 @@ HTTP/3 configuration. (Default: ```false```)
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP3_ADVERTISEDPORT`:
UDP port to advertise, on which HTTP/3 is available. (Default: ```0```)
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_ENCODEDCHARACTERS_ALLOWENCODEDBACKSLASH`:
Defines whether requests with encoded back slash characters in the path are allowed. (Default: ```true```)
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_ENCODEDCHARACTERS_ALLOWENCODEDHASH`:
Defines whether requests with encoded hash characters in the path are allowed. (Default: ```true```)
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_ENCODEDCHARACTERS_ALLOWENCODEDNULLCHARACTER`:
Defines whether requests with encoded null characters in the path are allowed. (Default: ```true```)
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_ENCODEDCHARACTERS_ALLOWENCODEDPERCENT`:
Defines whether requests with encoded percent characters in the path are allowed. (Default: ```true```)
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_ENCODEDCHARACTERS_ALLOWENCODEDQUESTIONMARK`:
Defines whether requests with encoded question mark characters in the path are allowed. (Default: ```true```)
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_ENCODEDCHARACTERS_ALLOWENCODEDSEMICOLON`:
Defines whether requests with encoded semicolon characters in the path are allowed. (Default: ```true```)
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_ENCODEDCHARACTERS_ALLOWENCODEDSLASH`:
Defines whether requests with encoded slash characters in the path are allowed. (Default: ```true```)
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_ENCODEQUERYSEMICOLONS`:
Defines whether request query semicolons should be URLEncoded. (Default: ```false```)

View File

@@ -55,6 +55,14 @@
[[entryPoints.EntryPoint0.http.tls.domains]]
main = "foobar"
sans = ["foobar", "foobar"]
[entryPoints.EntryPoint0.http.encodedCharacters]
allowEncodedSlash = true
allowEncodedBackSlash = true
allowEncodedNullCharacter = true
allowEncodedSemicolon = true
allowEncodedPercent = true
allowEncodedQuestionMark = true
allowEncodedHash = true
[entryPoints.EntryPoint0.http2]
maxConcurrentStreams = 42
[entryPoints.EntryPoint0.http3]

View File

@@ -62,6 +62,14 @@ entryPoints:
sans:
- foobar
- foobar
encodedCharacters:
allowEncodedSlash: true
allowEncodedBackSlash: true
allowEncodedNullCharacter: true
allowEncodedSemicolon: true
allowEncodedPercent: true
allowEncodedQuestionMark: true
allowEncodedHash: true
encodeQuerySemicolons: true
sanitizePath: true
http2:

View File

@@ -127,6 +127,15 @@ They can be defined by using a file (YAML or TOML) or CLI arguments.
trustedIPs:
- "127.0.0.1"
- "192.168.0.1"
http:
encodedCharacters:
allowEncodedSlash: false
allowEncodedBackSlash: false
allowEncodedNullCharacter: false
allowEncodedSemicolon: false
allowEncodedPercent: false
allowEncodedQuestionMark: false
allowEncodedHash: false
```
```toml tab="File (TOML)"
@@ -152,6 +161,14 @@ They can be defined by using a file (YAML or TOML) or CLI arguments.
[entryPoints.name.forwardedHeaders]
insecure = true
trustedIPs = ["127.0.0.1", "192.168.0.1"]
[entryPoints.name.http.encodedCharacters]
allowEncodedSlash = false
allowEncodedBackSlash = false
allowEncodedNullCharacter = false
allowEncodedSemicolon = false
allowEncodedPercent = false
allowEncodedQuestionMark = false
allowEncodedHash = false
```
```bash tab="CLI"
@@ -168,6 +185,13 @@ They can be defined by using a file (YAML or TOML) or CLI arguments.
--entryPoints.name.proxyProtocol.trustedIPs=127.0.0.1,192.168.0.1
--entryPoints.name.forwardedHeaders.insecure=true
--entryPoints.name.forwardedHeaders.trustedIPs=127.0.0.1,192.168.0.1
--entryPoints.name.http.encodedCharacters.allowEncodedSlash=false
--entryPoints.name.http.encodedCharacters.allowEncodedBackSlash=false
--entryPoints.name.http.encodedCharacters.allowEncodedNullCharacter=false
--entryPoints.name.http.encodedCharacters.allowEncodedSemicolon=false
--entryPoints.name.http.encodedCharacters.allowEncodedPercent=false
--entryPoints.name.http.encodedCharacters.allowEncodedQuestionMark=false
--entryPoints.name.http.encodedCharacters.allowEncodedHash=false
```
### Address
@@ -994,6 +1018,245 @@ entryPoints:
| false | foo=bar&baz=bar;foo | foo=bar&baz=bar&foo |
| true | foo=bar&baz=bar;foo | foo=bar&baz=bar%3Bfoo |
### Encoded Characters
You can configure Traefik to control the handling of encoded characters in request paths for security purposes.
By default, Traefik do not reject requests with path containing certain encoded characters that could be used in path traversal or other security attacks.
!!! info
This check is not done against the request query parameters,
but only against the request path as defined in [RFC3986 section-3](https://datatracker.ietf.org/doc/html/rfc3986#section-3).
!!! info "Security Considerations"
When your backend is not fully compliant with [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986) and notably decode encoded reserved characters in the requets path,
it is recommended to set these options to `false` to avoid split-view situation and helps prevent path traversal attacks or other malicious attempts to bypass security controls.
??? info "`encodedCharacters.allowEncodedSlash`"
_Optional, Default=true_
Controls whether requests with encoded slash characters (`%2F` or `%2f`) in the path are allowed.
```yaml tab="File (YAML)"
## Static configuration
entryPoints:
web:
address: ":80"
http:
encodedCharacters:
allowEncodedSlash: false
```
```toml tab="File (TOML)"
## Static configuration
[entryPoints]
[entryPoints.web]
address = ":80"
[entryPoints.web.http.encodedCharacters]
allowEncodedSlash = false
```
```bash tab="CLI"
## Static configuration
--entryPoints.web.address=:80
--entryPoints.web.http.encodedCharacters.allowEncodedSlash=false
```
??? info "`encodedCharacters.allowEncodedBackSlash`"
_Optional, Default=true_
Controls whether requests with encoded back slash characters (`%5C` or `%5c`) in the path are allowed.
```yaml tab="File (YAML)"
## Static configuration
entryPoints:
web:
address: ":80"
http:
encodedCharacters:
allowEncodedBackSlash: false
```
```toml tab="File (TOML)"
## Static configuration
[entryPoints]
[entryPoints.web]
address = ":80"
[entryPoints.web.http.encodedCharacters]
allowEncodedBackSlash = false
```
```bash tab="CLI"
## Static configuration
--entryPoints.web.address=:80
--entryPoints.web.http.encodedCharacters.allowEncodedBackSlash=false
```
??? info "`encodedCharacters.allowEncodedNullCharacter`"
_Optional, Default=true_
Controls whether requests with encoded null characters (`%00`) in the path are allowed.
```yaml tab="File (YAML)"
## Static configuration
entryPoints:
web:
address: ":80"
http:
encodedCharacters:
allowEncodedNullCharacter: false
```
```toml tab="File (TOML)"
## Static configuration
[entryPoints]
[entryPoints.web]
address = ":80"
[entryPoints.web.http.encodedCharacters]
allowEncodedNullCharacter = false
```
```bash tab="CLI"
## Static configuration
--entryPoints.web.address=:80
--entryPoints.web.http.encodedCharacters.allowEncodedNullCharacter=false
```
??? info "`encodedCharacters.allowEncodedSemicolon`"
_Optional, Default=true_
Controls whether requests with encoded semicolon characters (`%3B` or `%3b`) in the path are allowed.
```yaml tab="File (YAML)"
## Static configuration
entryPoints:
web:
address: ":80"
http:
encodedCharacters:
allowEncodedSemicolon: false
```
```toml tab="File (TOML)"
## Static configuration
[entryPoints]
[entryPoints.web]
address = ":80"
[entryPoints.web.http.encodedCharacters]
allowEncodedSemicolon = false
```
```bash tab="CLI"
## Static configuration
--entryPoints.web.address=:80
--entryPoints.web.http.encodedCharacters.allowEncodedSemicolon=false
```
??? info "`encodedCharacters.allowEncodedPercent`"
_Optional, Default=true_
Controls whether requests with encoded percent characters (`%25`) in the path are allowed.
```yaml tab="File (YAML)"
## Static configuration
entryPoints:
web:
address: ":80"
http:
encodedCharacters:
allowEncodedPercent: false
```
```toml tab="File (TOML)"
## Static configuration
[entryPoints]
[entryPoints.web]
address = ":80"
[entryPoints.web.http.encodedCharacters]
allowEncodedPercent = false
```
```bash tab="CLI"
## Static configuration
--entryPoints.web.address=:80
--entryPoints.web.http.encodedCharacters.allowEncodedPercent=false
```
??? info "`encodedCharacters.allowEncodedQuestionMark`"
_Optional, Default=true_
Controls whether requests with encoded question mark characters (`%3F` or `%3f`) in the path are allowed.
```yaml tab="File (YAML)"
## Static configuration
entryPoints:
web:
address: ":80"
http:
encodedCharacters:
allowEncodedQuestionMark: false
```
```toml tab="File (TOML)"
## Static configuration
[entryPoints]
[entryPoints.web]
address = ":80"
[entryPoints.web.http.encodedCharacters]
allowEncodedQuestionMark = false
```
```bash tab="CLI"
## Static configuration
--entryPoints.web.address=:80
--entryPoints.web.http.encodedCharacters.allowEncodedQuestionMark=false
```
??? info "`encodedCharacters.allowEncodedHash`"
_Optional, Default=true_
Controls whether requests with encoded hash characters (`%23`) in the path are allowed.
```yaml tab="File (YAML)"
## Static configuration
entryPoints:
web:
address: ":80"
http:
encodedCharacters:
allowEncodedHash: false
```
```toml tab="File (TOML)"
## Static configuration
[entryPoints]
[entryPoints.web]
address = ":80"
[entryPoints.web.http.encodedCharacters]
allowEncodedHash = false
```
```bash tab="CLI"
## Static configuration
--entryPoints.web.address=:80
--entryPoints.web.http.encodedCharacters.allowEncodedHash=false
```
### SanitizePath
_Optional, Default=true_
@@ -1179,4 +1442,4 @@ entryPoints:
--entryPoints.foo.udp.timeout=10s
```
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -412,4 +412,4 @@ serversTransport:
--serversTransport.forwardingTimeouts.idleConnTimeout=1s
```
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -1904,4 +1904,4 @@ If the ServersTransport CRD is defined in another provider the cross-provider fo
Also see the [full example](../../user-guides/crd-acme/index.md) with Let's Encrypt.
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -355,4 +355,4 @@ Kubernetes cluster before creating `TLSRoute` objects.
| [11] | `group` | Group is the group of the referent. Only `traefik.io`, `traefik.containo.us` and `gateway.networking.k8s.io` values are supported. |
| [12] | `kind` | Kind is kind of the referent. Only `TraefikService` and `Service` values are supported. |
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -969,4 +969,4 @@ This will allow users to create a "default router" that will match all unmatched
To do this, use the `traefik.ingress.kubernetes.io/router.priority` annotation (as seen in [Annotations on Ingress](#on-ingress)) on your ingresses accordingly.
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -1349,4 +1349,4 @@ Services are the target for the router.
!!! important "UDP routers can only target UDP services (and not HTTP or TCP services)."
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -1646,4 +1646,4 @@ udp:
address = "private-ip-server-2:8080/"
```
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -3,7 +3,8 @@ title: "Content-Length"
description: "Enforce strict ContentLength validation in Traefik by streaming or full buffering to prevent truncated or overlong requests and responses. Read the technical documentation."
---
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 overlong streams without holding the entire message.
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 overlong 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](../middlewares/http/buffering.md):
@@ -20,5 +21,7 @@ With buffering enabled, Traefik will:
- Compare the actual byte count to the `Content-Length` header.
- Reject the message if the counts do not match.
!!!warning
Buffering adds overhead. Every request and response is held in full before forwarding, which can increase memory use and latency. Use it when strict content validation is critical to your security posture.
!!! warning
Buffering adds overhead. Every request and response is held in full before forwarding, which can increase memory use and latency.
Use it when strict content validation is critical to your security posture.

View File

@@ -0,0 +1,135 @@
---
title: "Request Path"
description: "Learn how Traefik processes and secures request paths through sanitization and encoded character filtering to protect against path traversal and injection attacks."
---
# Request Path
Protecting Against Path-Based Attacks Through Sanitization and Filtering
{: .subtitle }
Traefik implements multiple layers of security when processing incoming request paths.
This includes path sanitization to normalize potentially dangerous sequences and encoded character filtering to prevent attack vectors that use URL encoding.
Understanding how Traefik handles request paths is crucial for maintaining a secure routing infrastructure.
## How Traefik Processes Request Paths
When Traefik receives an HTTP request, it processes the request path through several security-focused stages:
### 1. Encoded Character Filtering
Traefik inspects the path for potentially dangerous encoded characters and rejects requests containing them unless explicitly allowed.
Here is the list of the encoded characters that are allowed by default:
| Encoded Character | Character |
|-------------------|-------------------------|
| `%2f` or `%2F` | `/` (slash) |
| `%5c` or `%5C` | `\` (backslash) |
| `%00` | `NULL` (null character) |
| `%3b` or `%3B` | `;` (semicolon) |
| `%25` | `%` (percent) |
| `%3f` or `%3F` | `?` (question mark) |
| `%23` | `#` (hash) |
### 2. Path Normalization
Traefik normalizes the request path by decoding the unreserved percent-encoded characters,
as they are equivalent to their non-encoded form (according to [rfc3986#section-2.3](https://datatracker.ietf.org/doc/html/rfc3986#section-2.3)),
and capitalizing the percent-encoded characters (according to [rfc3986#section-6.2.2.1](https://datatracker.ietf.org/doc/html/rfc3986#section-6.2.2.1)).
### 3. Path Sanitization
Traefik sanitizes request paths to prevent common attack vectors,
by removing the `..`, `.` and duplicate slash segments from the URL (according to [rfc3986#section-6.2.2.3](https://datatracker.ietf.org/doc/html/rfc3986#section-6.2.2.3)).
## Path Security Configuration
Traefik provides two main mechanisms for path security that work together to protect your applications.
### Path Sanitization
Path sanitization is enabled by default and helps prevent directory traversal attacks by normalizing request paths.
Configure it in the [EntryPoints](../routing/entrypoints.md#sanitizepath) HTTP section:
```yaml tab="File (YAML)"
entryPoints:
websecure:
address: ":443"
http:
sanitizePath: true # Default: true (recommended)
```
```toml tab="File (TOML)"
[entryPoints.websecure]
address = ":443"
[entryPoints.websecure.http]
sanitizePath = true
```
```bash tab="CLI"
--entryPoints.websecure.address=:443
--entryPoints.websecure.http.sanitizePath=true
```
**Sanitization behavior:**
- `./foo/bar` → `/foo/bar` (removes relative current directory)
- `/foo/../bar` → `/bar` (resolves parent directory traversal)
- `/foo/bar//` → `/foo/bar/` (removes duplicate slashes)
- `/./foo/../bar//` → `/bar/` (combines all normalizations)
### Encoded Character Filtering
Encoded character filtering provides an additional security layer by rejecting potentially dangerous URL-encoded characters.
Configure it in the [EntryPoints](../routing/entrypoints.md#encoded-characters) HTTP section.
This filtering occurs before path sanitization and catches attack attempts that use encoding to bypass other security controls.
All encoded character filtering is disabled by default (`true` means encoded characters are allowed).
!!! info "Security Considerations"
When your backend is not fully compliant with [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986) and notably decode encoded reserved characters in the requets path,
it is recommended to set these options to `false` to avoid split-view situation and helps prevent path traversal attacks or other malicious attempts to bypass security controls.
```yaml tab="File (YAML)"
entryPoints:
websecure:
address: ":443"
http:
encodedCharacters:
allowEncodedSlash: false # %2F - Default: true
allowEncodedBackSlash: false # %5C - Default: true
allowEncodedNullCharacter: false # %00 - Default: true
allowEncodedSemicolon: false # %3B - Default: true
allowEncodedPercent: false # %25 - Default: true
allowEncodedQuestionMark: false # %3F - Default: true
allowEncodedHash: false # %23 - Default: true
```
```toml tab="File (TOML)"
[entryPoints.websecure]
address = ":443"
[entryPoints.websecure.http.encodedCharacters]
allowEncodedSlash = false
allowEncodedBackSlash = false
allowEncodedNullCharacter = false
allowEncodedSemicolon = false
allowEncodedPercent = false
allowEncodedQuestionMark = false
allowEncodedHash = false
```
```bash tab="CLI"
--entryPoints.websecure.address=:443
--entryPoints.websecure.http.encodedCharacters.allowEncodedSlash=false
--entryPoints.websecure.http.encodedCharacters.allowEncodedBackSlash=false
--entryPoints.websecure.http.encodedCharacters.allowEncodedNullCharacter=false
--entryPoints.websecure.http.encodedCharacters.allowEncodedSemicolon=false
--entryPoints.websecure.http.encodedCharacters.allowEncodedPercent=false
--entryPoints.websecure.http.encodedCharacters.allowEncodedQuestionMark=false
--entryPoints.websecure.http.encodedCharacters.allowEncodedHash=false
```

View File

@@ -187,4 +187,4 @@ environment:
- "OVH_CONSUMER_KEY_FILE=/run/secrets/ovh_consumer_key"
```
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -83,4 +83,4 @@ labels:
- "traefik.http.routers.whoami.tls.certresolver=myresolver"
```
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -133,4 +133,4 @@ whoami:
- "traefik.http.routers.whoami.entrypoints=web"
```
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -1,4 +1,4 @@
FROM alpine:3.22
FROM alpine:3.23
ENV PATH="${PATH}:/venv/bin"

View File

@@ -2,18 +2,19 @@ site_name: Traefik
site_description: Traefik Documentation
site_author: traefik.io
site_url: https://doc.traefik.io/traefik
dev_addr: 0.0.0.0:8000
dev_addr: localhost:8000
repo_name: 'GitHub'
repo_url: 'https://github.com/traefik/traefik'
docs_dir: 'content'
product: proxy
# https://squidfunk.github.io/mkdocs-material/
# Use custom version of mkdocs-material
# See https://github.com/traefik/mkdocs-material
theme:
name: 'traefik-labs'
product: proxy
language: en
include_sidebar: true
favicon: assets/img/traefikproxy-icon-color.png
@@ -38,6 +39,8 @@ plugins:
- exclude:
glob:
- "**/include-*.md"
- include-markdown:
encoding: utf-8
# https://squidfunk.github.io/mkdocs-material/extensions/admonition/
# https://facelessuser.github.io/pymdown-extensions/
@@ -55,9 +58,6 @@ markdown_extensions:
- pymdownx.tasklist
- pymdownx.snippets:
check_paths: true
- markdown_include.include:
base_path: content/includes/
encoding: utf-8
- toc:
permalink: true
@@ -165,8 +165,8 @@ nav:
- 'Instana': 'observability/tracing/instana.md'
- 'Haystack': 'observability/tracing/haystack.md'
- 'Elastic': 'observability/tracing/elastic.md'
- 'OpenTelemetry': 'observability/tracing/opentelemetry.md'
- 'Security':
- 'Request Path': 'security/request-path.md'
- 'Content-Length': 'security/content-length.md'
- 'TLS in Multi-Tenant Kubernetes': 'security/tls-certs-in-multi-tenant-kubernetes.md'
- 'User Guides':

View File

@@ -16,3 +16,15 @@
[pymdown-extensions]: https://facelessuser.github.io/pymdown-extensions "PyMdown Extensions"
[pymdown-extensions-src]: https://github.com/facelessuser/pymdown-extensions "PyMdown Extensions - Sources"
## Build locally without docker
```sh
# Pre-requisite: python3, pip and virtualenv
DOCS="/tmp/traefik-docs"
mkdir "$DOCS"
virtualenv "$DOCS"
source "$DOCS/bin/activate"
pip install -r requirements.txt
mkdocs serve # or mkdocs build
```

View File

@@ -1,5 +1,5 @@
markdown-include==0.5.1
mkdocs==1.2.4
mkdocs==1.4.3
mkdocs-include-markdown-plugin==7.2.0
mkdocs-exclude==1.0.2
mkdocs-traefiklabs>=100.0.7

View File

@@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
# This script will run a couple of linter on the documentation
set -eu
@@ -6,14 +6,14 @@ set -eu
# We want to run all linters before returning success (exit 0) or failure (exit 1)
# So this variable holds the global exit code
EXIT_CODE=0
readonly BASE_DIR=/app
readonly BASE_DIR="${1:-/app}"
echo "== Linting Markdown"
# Uses the file ".markdownlint.json" for setup
cd "${BASE_DIR}" || exit 1
LINTER_EXCLUSIONS="$(find "${BASE_DIR}/content" -type f -name '.markdownlint.json')"
GLOBAL_LINT_OPTIONS="--config ${BASE_DIR}/.markdownlint.json"
LINTER_EXCLUSIONS="$(find "content" -type f -name '.markdownlint.json')"
GLOBAL_LINT_OPTIONS="--config .markdownlint.json"
# Lint the specific folders (containing linter specific rulesets)
for LINTER_EXCLUSION in ${LINTER_EXCLUSIONS}
@@ -24,6 +24,6 @@ do
done
# Lint all the content, excluding the previously done`
eval markdownlint "${GLOBAL_LINT_OPTIONS}" "${BASE_DIR}/content/**/*.md" || EXIT_CODE=1
eval markdownlint "${GLOBAL_LINT_OPTIONS}" "content/**/*.md" || EXIT_CODE=1
exit "${EXIT_CODE}"

22
go.mod
View File

@@ -57,10 +57,10 @@ require (
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // No tag on the repo.
github.com/prometheus/client_golang v1.22.0
github.com/prometheus/client_model v0.6.1
github.com/quic-go/quic-go v0.55.0
github.com/quic-go/quic-go v0.57.1
github.com/rancher/go-rancher-metadata v0.0.0-20200311180630-7f4c936a06ac // No tag on the repo.
github.com/sirupsen/logrus v1.9.3
github.com/stretchr/testify v1.10.0
github.com/stretchr/testify v1.11.1
github.com/stvp/go-udp-testing v0.0.0-20191102171040-06b61409b154 // No tag on the repo.
github.com/testcontainers/testcontainers-go v0.32.0
github.com/traefik/paerser v0.2.2
@@ -73,11 +73,11 @@ require (
github.com/vulcand/predicate v1.2.0
go.elastic.co/apm/module/apmot/v2 v2.4.8
go.elastic.co/apm/v2 v2.4.8
golang.org/x/mod v0.28.0
golang.org/x/net v0.46.0
golang.org/x/text v0.30.0
golang.org/x/mod v0.29.0
golang.org/x/net v0.47.0
golang.org/x/text v0.31.0
golang.org/x/time v0.12.0
golang.org/x/tools v0.37.0
golang.org/x/tools v0.38.0
google.golang.org/grpc v1.73.0
gopkg.in/DataDog/dd-trace-go.v1 v1.74.6
gopkg.in/yaml.v3 v3.0.1
@@ -312,7 +312,7 @@ require (
github.com/prometheus/common v0.62.0 // indirect
github.com/prometheus/procfs v0.16.1 // indirect
github.com/puzpuzpuz/xsync/v3 v3.5.1 // indirect
github.com/quic-go/qpack v0.5.1 // indirect
github.com/quic-go/qpack v0.6.0 // indirect
github.com/redis/go-redis/v9 v9.8.0 // indirect
github.com/regfish/regfish-dnsapi-go v0.1.1 // indirect
github.com/sacloud/api-client-go v0.3.2 // indirect
@@ -380,12 +380,12 @@ require (
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/ratelimit v0.3.1 // indirect
go.uber.org/zap v1.27.0 // indirect
golang.org/x/crypto v0.43.0 // indirect
golang.org/x/crypto v0.45.0 // indirect
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 // indirect
golang.org/x/oauth2 v0.30.0 // indirect
golang.org/x/sync v0.17.0 // indirect
golang.org/x/sys v0.37.0 // indirect
golang.org/x/term v0.36.0 // indirect
golang.org/x/sync v0.18.0 // indirect
golang.org/x/sys v0.38.0 // indirect
golang.org/x/term v0.37.0 // indirect
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
google.golang.org/api v0.242.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7 // indirect

44
go.sum
View File

@@ -1252,10 +1252,10 @@ github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlT
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/puzpuzpuz/xsync/v3 v3.5.1 h1:GJYJZwO6IdxN/IKbneznS6yPkVC+c3zyY/j19c++5Fg=
github.com/puzpuzpuz/xsync/v3 v3.5.1/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA=
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
github.com/quic-go/quic-go v0.55.0 h1:zccPQIqYCXDt5NmcEabyYvOnomjs8Tlwl7tISjJh9Mk=
github.com/quic-go/quic-go v0.55.0/go.mod h1:DR51ilwU1uE164KuWXhinFcKWGlEjzys2l8zUl5Ss1U=
github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8=
github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII=
github.com/quic-go/quic-go v0.57.1 h1:25KAAR9QR8KZrCZRThWMKVAwGoiHIrNbT72ULHTuI10=
github.com/quic-go/quic-go v0.57.1/go.mod h1:ly4QBAjHA2VhdnxhojRsCUOeJwKYg+taDlos92xb1+s=
github.com/rancher/go-rancher-metadata v0.0.0-20200311180630-7f4c936a06ac h1:wBGhHdXKICZmvAPWS8gQoMyOWDH7QAi9bU4Z1nDWnFU=
github.com/rancher/go-rancher-metadata v0.0.0-20200311180630-7f4c936a06ac/go.mod h1:67sLWL17mVlO1HFROaTBmU71NB4R8UNCesFHhg0f6LQ=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
@@ -1392,8 +1392,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/stvp/go-udp-testing v0.0.0-20191102171040-06b61409b154 h1:XGopsea1Dw7ecQ8JscCNQXDGYAKDiWjDeXnpN/+BY9g=
github.com/stvp/go-udp-testing v0.0.0-20191102171040-06b61409b154/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
@@ -1647,8 +1647,8 @@ golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDf
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -1696,8 +1696,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U=
golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI=
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -1766,8 +1766,8 @@ golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4=
golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -1799,8 +1799,8 @@ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -1911,8 +1911,8 @@ golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
@@ -1930,8 +1930,8 @@ golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q=
golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss=
golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=
golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -1950,8 +1950,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -2033,8 +2033,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE=
golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w=
golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@@ -0,0 +1,20 @@
[global]
checkNewVersion = false
sendAnonymousUsage = false
[api]
insecure = true
[entryPoints]
[entryPoints.web]
address = ":8000"
[providers.file]
filename = "{{ .SelfFilename }}"
## dynamic configuration ##
[http.routers]
[http.routers.router]
service = "noop@internal"
rule = "Host(`deny.localhost`)"

View File

@@ -0,0 +1,40 @@
[global]
checkNewVersion = false
sendAnonymousUsage = false
[log]
level = "DEBUG"
[entryPoints]
[entryPoints.strict]
address = ":8000"
[entryPoints.strict.http.encodedCharacters]
allowEncodedSlash = false
[entryPoints.permissive]
address = ":8001"
# No config, default values should apply
[entryPoints.permissive2]
address = ":8002"
# No config for allowEncodedSlash, default value is effectively true
[entryPoints.permissive.http.encodedCharacters]
allowEncodedBackSlash = false
[api]
insecure = true
[providers.file]
filename = "{{ .SelfFilename }}"
## dynamic configuration ##
[http.routers]
[http.routers.sameRouter]
service = "service1"
rule = "Host(`test.localhost`)"
[http.services]
[http.services.service1.loadBalancer]
[[http.services.service1.loadBalancer.servers]]
url = "{{ .Server1 }}"

View File

@@ -1369,16 +1369,15 @@ func (s *SimpleSuite) TestDenyFragment() {
s.composeUp()
defer s.composeDown()
s.traefikCmd(withConfigFile("fixtures/simple_default.toml"))
s.traefikCmd(withConfigFile(s.adaptFile("fixtures/simple_deny.toml", struct{}{})))
// Expected a 404 as we did not configure anything
err := try.GetRequest("http://127.0.0.1:8000/", 1*time.Second, try.StatusCodeIs(http.StatusNotFound))
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1*time.Second, try.BodyContains("Host(`deny.localhost`)"))
require.NoError(s.T(), err)
conn, err := net.Dial("tcp", "127.0.0.1:8000")
require.NoError(s.T(), err)
_, err = conn.Write([]byte("GET /#/?bar=toto;boo=titi HTTP/1.1\nHost: other.localhost\n\n"))
_, err = conn.Write([]byte("GET /#/?bar=toto;boo=titi HTTP/1.1\nHost: deny.localhost\n\n"))
require.NoError(s.T(), err)
resp, err := http.ReadResponse(bufio.NewReader(conn), nil)
@@ -1482,3 +1481,84 @@ func (s *SimpleSuite) TestSanitizePath() {
}
}
}
// TestEncodedCharactersDifferentEntryPoints verifies that router handler caching does not interfere with
// per-entry-point encoded characters configuration.
// The same router should behave differently on different entry points.
func (s *SimpleSuite) TestEncodedCharactersDifferentEntryPoints() {
s.createComposeProject("base")
s.composeUp()
defer s.composeDown()
whoami1URL := "http://" + net.JoinHostPort(s.getComposeServiceIP("whoami1"), "80")
file := s.adaptFile("fixtures/simple_encoded_chars.toml", struct {
Server1 string
}{whoami1URL})
s.traefikCmd(withConfigFile(file))
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1*time.Second, try.BodyContains("Host(`test.localhost`)"))
require.NoError(s.T(), err)
testCases := []struct {
desc string
request string
target string
expected int
}{
{
desc: "Encoded slash should be REJECTED on strict entry point",
request: "GET /path%2Fwith%2Fslash HTTP/1.1\r\nHost: test.localhost\r\n\r\n",
target: "127.0.0.1:8000", // strict entry point
expected: http.StatusBadRequest,
},
{
desc: "Encoded slash should be ALLOWED on permissive entry point",
request: "GET /path%2Fwith%2Fslash HTTP/1.1\r\nHost: test.localhost\r\n\r\n",
target: "127.0.0.1:8001", // permissive entry point
expected: http.StatusOK,
},
{
desc: "Encoded slash should be ALLOWED on permissive2 entry point",
request: "GET /path%2Fwith%2Fslash HTTP/1.1\r\nHost: test.localhost\r\n\r\n",
target: "127.0.0.1:8002", // permissive2 entry point
expected: http.StatusOK,
},
{
desc: "Regular path should work on strict entry point",
request: "GET /regular/path HTTP/1.1\r\nHost: test.localhost\r\n\r\n",
target: "127.0.0.1:8000",
expected: http.StatusOK,
},
{
desc: "Regular path should work on permissive entry point",
request: "GET /regular/path HTTP/1.1\r\nHost: test.localhost\r\n\r\n",
target: "127.0.0.1:8001",
expected: http.StatusOK,
},
{
desc: "Regular path should work on permissive2 entry point",
request: "GET /regular/path HTTP/1.1\r\nHost: test.localhost\r\n\r\n",
target: "127.0.0.1:8002",
expected: http.StatusOK,
},
}
for _, test := range testCases {
conn, err := net.Dial("tcp", test.target)
require.NoError(s.T(), err)
_, err = conn.Write([]byte(test.request))
require.NoError(s.T(), err)
resp, err := http.ReadResponse(bufio.NewReader(conn), nil)
require.NoError(s.T(), err)
assert.Equalf(s.T(), test.expected, resp.StatusCode, "%s failed with %d instead of %d", test.desc, resp.StatusCode, test.expected)
err = conn.Close()
require.NoError(s.T(), err)
}
}

View File

@@ -2,4 +2,4 @@
"address": ":81",
"http": {},
"name": "bar"
}
}

View File

@@ -24,4 +24,4 @@
"http": {},
"name": "ep18"
}
]
]

View File

@@ -4,4 +4,4 @@
"http": {},
"name": "web2"
}
]
]

View File

@@ -24,8 +24,9 @@ type HTTPConfiguration struct {
// Model is a set of default router's values.
type Model struct {
Middlewares []string `json:"middlewares,omitempty" toml:"middlewares,omitempty" yaml:"middlewares,omitempty" export:"true"`
TLS *RouterTLSConfig `json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" label:"allowEmpty" file:"allowEmpty" kv:"allowEmpty" export:"true"`
Middlewares []string `json:"middlewares,omitempty" toml:"middlewares,omitempty" yaml:"middlewares,omitempty" export:"true"`
TLS *RouterTLSConfig `json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" label:"allowEmpty" file:"allowEmpty" kv:"allowEmpty" export:"true"`
DeniedEncodedPathCharacters *RouterDeniedEncodedPathCharacters `json:"-" toml:"-" yaml:"-" label:"-" file:"-" kv:"-" export:"true"`
}
// +k8s:deepcopy-gen=true
@@ -42,13 +43,60 @@ type Service struct {
// Router holds the router configuration.
type Router struct {
EntryPoints []string `json:"entryPoints,omitempty" toml:"entryPoints,omitempty" yaml:"entryPoints,omitempty" export:"true"`
Middlewares []string `json:"middlewares,omitempty" toml:"middlewares,omitempty" yaml:"middlewares,omitempty" export:"true"`
Service string `json:"service,omitempty" toml:"service,omitempty" yaml:"service,omitempty" export:"true"`
Rule string `json:"rule,omitempty" toml:"rule,omitempty" yaml:"rule,omitempty"`
Priority int `json:"priority,omitempty" toml:"priority,omitempty,omitzero" yaml:"priority,omitempty" export:"true"`
TLS *RouterTLSConfig `json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" label:"allowEmpty" file:"allowEmpty" kv:"allowEmpty" export:"true"`
DefaultRule bool `json:"-" toml:"-" yaml:"-" label:"-" file:"-"`
EntryPoints []string `json:"entryPoints,omitempty" toml:"entryPoints,omitempty" yaml:"entryPoints,omitempty" export:"true"`
Middlewares []string `json:"middlewares,omitempty" toml:"middlewares,omitempty" yaml:"middlewares,omitempty" export:"true"`
Service string `json:"service,omitempty" toml:"service,omitempty" yaml:"service,omitempty" export:"true"`
Rule string `json:"rule,omitempty" toml:"rule,omitempty" yaml:"rule,omitempty"`
Priority int `json:"priority,omitempty" toml:"priority,omitempty,omitzero" yaml:"priority,omitempty" export:"true"`
TLS *RouterTLSConfig `json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" label:"allowEmpty" file:"allowEmpty" kv:"allowEmpty" export:"true"`
DefaultRule bool `json:"-" toml:"-" yaml:"-" label:"-" file:"-"`
DeniedEncodedPathCharacters *RouterDeniedEncodedPathCharacters `json:"-" toml:"-" yaml:"-" label:"-" file:"-" kv:"-"`
}
// +k8s:deepcopy-gen=true
// RouterDeniedEncodedPathCharacters configures which encoded characters are allowed in the request path.
type RouterDeniedEncodedPathCharacters struct {
AllowEncodedSlash bool `description:"Defines whether requests with encoded slash characters in the path are allowed." json:"allowEncodedSlash,omitempty" toml:"allowEncodedSlash,omitempty" yaml:"allowEncodedSlash,omitempty" export:"true"`
AllowEncodedBackSlash bool `description:"Defines whether requests with encoded back slash characters in the path are allowed." json:"allowEncodedBackSlash,omitempty" toml:"allowEncodedBackSlash,omitempty" yaml:"allowEncodedBackSlash,omitempty" export:"true"`
AllowEncodedNullCharacter bool `description:"Defines whether requests with encoded null characters in the path are allowed." json:"allowEncodedNullCharacter,omitempty" toml:"allowEncodedNullCharacter,omitempty" yaml:"allowEncodedNullCharacter,omitempty" export:"true"`
AllowEncodedSemicolon bool `description:"Defines whether requests with encoded semicolon characters in the path are allowed." json:"allowEncodedSemicolon,omitempty" toml:"allowEncodedSemicolon,omitempty" yaml:"allowEncodedSemicolon,omitempty" export:"true"`
AllowEncodedPercent bool `description:"Defines whether requests with encoded percent characters in the path are allowed." json:"allowEncodedPercent,omitempty" toml:"allowEncodedPercent,omitempty" yaml:"allowEncodedPercent,omitempty" export:"true"`
AllowEncodedQuestionMark bool `description:"Defines whether requests with encoded question mark characters in the path are allowed." json:"allowEncodedQuestionMark,omitempty" toml:"allowEncodedQuestionMark,omitempty" yaml:"allowEncodedQuestionMark,omitempty" export:"true"`
AllowEncodedHash bool `description:"Defines whether requests with encoded hash characters in the path are allowed." json:"allowEncodedHash,omitempty" toml:"allowEncodedHash,omitempty" yaml:"allowEncodedHash,omitempty" export:"true"`
}
// Map returns a map of unallowed encoded characters.
func (r *RouterDeniedEncodedPathCharacters) Map() map[string]struct{} {
characters := make(map[string]struct{})
if !r.AllowEncodedSlash {
characters["%2F"] = struct{}{}
characters["%2f"] = struct{}{}
}
if !r.AllowEncodedBackSlash {
characters["%5C"] = struct{}{}
characters["%5c"] = struct{}{}
}
if !r.AllowEncodedNullCharacter {
characters["%00"] = struct{}{}
}
if !r.AllowEncodedSemicolon {
characters["%3B"] = struct{}{}
characters["%3b"] = struct{}{}
}
if !r.AllowEncodedPercent {
characters["%25"] = struct{}{}
}
if !r.AllowEncodedQuestionMark {
characters["%3F"] = struct{}{}
characters["%3f"] = struct{}{}
}
if !r.AllowEncodedHash {
characters["%23"] = struct{}{}
}
return characters
}
// +k8s:deepcopy-gen=true

View File

@@ -0,0 +1,165 @@
package dynamic
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestEncodedCharactersMap(t *testing.T) {
tests := []struct {
name string
config RouterDeniedEncodedPathCharacters
expected map[string]struct{}
}{
{
name: "Handles empty configuration",
expected: map[string]struct{}{
"%2F": {},
"%2f": {},
"%5C": {},
"%5c": {},
"%00": {},
"%3B": {},
"%3b": {},
"%25": {},
"%3F": {},
"%3f": {},
"%23": {},
},
},
{
name: "Exclude encoded slash when allowed",
config: RouterDeniedEncodedPathCharacters{
AllowEncodedSlash: true,
},
expected: map[string]struct{}{
"%5C": {},
"%5c": {},
"%00": {},
"%3B": {},
"%3b": {},
"%25": {},
"%3F": {},
"%3f": {},
"%23": {},
},
},
{
name: "Exclude encoded backslash when allowed",
config: RouterDeniedEncodedPathCharacters{
AllowEncodedBackSlash: true,
},
expected: map[string]struct{}{
"%2F": {},
"%2f": {},
"%00": {},
"%3B": {},
"%3b": {},
"%25": {},
"%3F": {},
"%3f": {},
"%23": {},
},
},
{
name: "Exclude encoded null character when allowed",
config: RouterDeniedEncodedPathCharacters{
AllowEncodedNullCharacter: true,
},
expected: map[string]struct{}{
"%2F": {},
"%2f": {},
"%5C": {},
"%5c": {},
"%3B": {},
"%3b": {},
"%25": {},
"%3F": {},
"%3f": {},
"%23": {},
},
},
{
name: "Exclude encoded semicolon when allowed",
config: RouterDeniedEncodedPathCharacters{
AllowEncodedSemicolon: true,
},
expected: map[string]struct{}{
"%2F": {},
"%2f": {},
"%5C": {},
"%5c": {},
"%00": {},
"%25": {},
"%3F": {},
"%3f": {},
"%23": {},
},
},
{
name: "Exclude encoded percent when allowed",
config: RouterDeniedEncodedPathCharacters{
AllowEncodedPercent: true,
},
expected: map[string]struct{}{
"%2F": {},
"%2f": {},
"%5C": {},
"%5c": {},
"%00": {},
"%3B": {},
"%3b": {},
"%3F": {},
"%3f": {},
"%23": {},
},
},
{
name: "Exclude encoded question mark when allowed",
config: RouterDeniedEncodedPathCharacters{
AllowEncodedQuestionMark: true,
},
expected: map[string]struct{}{
"%2F": {},
"%2f": {},
"%5C": {},
"%5c": {},
"%00": {},
"%3B": {},
"%3b": {},
"%25": {},
"%23": {},
},
},
{
name: "Exclude encoded hash when allowed",
config: RouterDeniedEncodedPathCharacters{
AllowEncodedHash: true,
},
expected: map[string]struct{}{
"%2F": {},
"%2f": {},
"%5C": {},
"%5c": {},
"%00": {},
"%3B": {},
"%3b": {},
"%25": {},
"%3F": {},
"%3f": {},
},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
t.Parallel()
result := test.config.Map()
require.Equal(t, test.expected, result)
})
}
}

View File

@@ -4,7 +4,7 @@
/*
The MIT License (MIT)
Copyright (c) 2016-2020 Containous SAS; 2020-2025 Traefik Labs
Copyright (c) 2016-2020 Containous SAS; 2020-2026 Traefik Labs
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -845,6 +845,11 @@ func (in *Model) DeepCopyInto(out *Model) {
*out = new(RouterTLSConfig)
(*in).DeepCopyInto(*out)
}
if in.DeniedEncodedPathCharacters != nil {
in, out := &in.DeniedEncodedPathCharacters, &out.DeniedEncodedPathCharacters
*out = new(RouterDeniedEncodedPathCharacters)
**out = **in
}
return
}
@@ -1030,6 +1035,11 @@ func (in *Router) DeepCopyInto(out *Router) {
*out = new(RouterTLSConfig)
(*in).DeepCopyInto(*out)
}
if in.DeniedEncodedPathCharacters != nil {
in, out := &in.DeniedEncodedPathCharacters, &out.DeniedEncodedPathCharacters
*out = new(RouterDeniedEncodedPathCharacters)
**out = **in
}
return
}
@@ -1043,6 +1053,22 @@ func (in *Router) DeepCopy() *Router {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *RouterDeniedEncodedPathCharacters) DeepCopyInto(out *RouterDeniedEncodedPathCharacters) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouterDeniedEncodedPathCharacters.
func (in *RouterDeniedEncodedPathCharacters) DeepCopy() *RouterDeniedEncodedPathCharacters {
if in == nil {
return nil
}
out := new(RouterDeniedEncodedPathCharacters)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *RouterTCPTLSConfig) DeepCopyInto(out *RouterTCPTLSConfig) {
*out = *in

View File

@@ -59,11 +59,12 @@ func (ep *EntryPoint) SetDefaults() {
// HTTPConfig is the HTTP configuration of an entry point.
type HTTPConfig struct {
Redirections *Redirections `description:"Set of redirection" json:"redirections,omitempty" toml:"redirections,omitempty" yaml:"redirections,omitempty" export:"true"`
Middlewares []string `description:"Default middlewares for the routers linked to the entry point." json:"middlewares,omitempty" toml:"middlewares,omitempty" yaml:"middlewares,omitempty" export:"true"`
TLS *TLSConfig `description:"Default TLS configuration for the routers linked to the entry point." json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"`
EncodeQuerySemicolons bool `description:"Defines whether request query semicolons should be URLEncoded." json:"encodeQuerySemicolons,omitempty" toml:"encodeQuerySemicolons,omitempty" yaml:"encodeQuerySemicolons,omitempty" export:"true"`
SanitizePath *bool `description:"Defines whether to enable request path sanitization (removal of /./, /../ and multiple slash sequences)." json:"sanitizePath,omitempty" toml:"sanitizePath,omitempty" yaml:"sanitizePath,omitempty" export:"true"`
Redirections *Redirections `description:"Set of redirection" json:"redirections,omitempty" toml:"redirections,omitempty" yaml:"redirections,omitempty" export:"true"`
Middlewares []string `description:"Default middlewares for the routers linked to the entry point." json:"middlewares,omitempty" toml:"middlewares,omitempty" yaml:"middlewares,omitempty" export:"true"`
TLS *TLSConfig `description:"Default TLS configuration for the routers linked to the entry point." json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"`
EncodedCharacters *EncodedCharacters `description:"Defines which encoded characters are allowed in the request path." json:"encodedCharacters,omitempty" toml:"encodedCharacters,omitempty" yaml:"encodedCharacters,omitempty" export:"true"`
EncodeQuerySemicolons bool `description:"Defines whether request query semicolons should be URLEncoded." json:"encodeQuerySemicolons,omitempty" toml:"encodeQuerySemicolons,omitempty" yaml:"encodeQuerySemicolons,omitempty" export:"true"`
SanitizePath *bool `description:"Defines whether to enable request path sanitization (removal of /./, /../ and multiple slash sequences)." json:"sanitizePath,omitempty" toml:"sanitizePath,omitempty" yaml:"sanitizePath,omitempty" export:"true"`
}
// SetDefaults sets the default values.
@@ -72,6 +73,27 @@ func (h *HTTPConfig) SetDefaults() {
h.SanitizePath = &sanitizePath
}
// EncodedCharacters configures which encoded characters are allowed in the request path.
type EncodedCharacters struct {
AllowEncodedSlash bool `description:"Defines whether requests with encoded slash characters in the path are allowed." json:"allowEncodedSlash,omitempty" toml:"allowEncodedSlash,omitempty" yaml:"allowEncodedSlash,omitempty" export:"true"`
AllowEncodedBackSlash bool `description:"Defines whether requests with encoded back slash characters in the path are allowed." json:"allowEncodedBackSlash,omitempty" toml:"allowEncodedBackSlash,omitempty" yaml:"allowEncodedBackSlash,omitempty" export:"true"`
AllowEncodedNullCharacter bool `description:"Defines whether requests with encoded null characters in the path are allowed." json:"allowEncodedNullCharacter,omitempty" toml:"allowEncodedNullCharacter,omitempty" yaml:"allowEncodedNullCharacter,omitempty" export:"true"`
AllowEncodedSemicolon bool `description:"Defines whether requests with encoded semicolon characters in the path are allowed." json:"allowEncodedSemicolon,omitempty" toml:"allowEncodedSemicolon,omitempty" yaml:"allowEncodedSemicolon,omitempty" export:"true"`
AllowEncodedPercent bool `description:"Defines whether requests with encoded percent characters in the path are allowed." json:"allowEncodedPercent,omitempty" toml:"allowEncodedPercent,omitempty" yaml:"allowEncodedPercent,omitempty" export:"true"`
AllowEncodedQuestionMark bool `description:"Defines whether requests with encoded question mark characters in the path are allowed." json:"allowEncodedQuestionMark,omitempty" toml:"allowEncodedQuestionMark,omitempty" yaml:"allowEncodedQuestionMark,omitempty" export:"true"`
AllowEncodedHash bool `description:"Defines whether requests with encoded hash characters in the path are allowed." json:"allowEncodedHash,omitempty" toml:"allowEncodedHash,omitempty" yaml:"allowEncodedHash,omitempty" export:"true"`
}
func (ec *EncodedCharacters) SetDefaults() {
ec.AllowEncodedSlash = true
ec.AllowEncodedBackSlash = true
ec.AllowEncodedNullCharacter = true
ec.AllowEncodedSemicolon = true
ec.AllowEncodedPercent = true
ec.AllowEncodedQuestionMark = true
ec.AllowEncodedHash = true
}
// HTTP2Config is the HTTP2 configuration of an entry point.
type HTTP2Config struct {
MaxConcurrentStreams int32 `description:"Specifies the number of concurrent streams per connection that each client is allowed to initiate." json:"maxConcurrentStreams,omitempty" toml:"maxConcurrentStreams,omitempty" yaml:"maxConcurrentStreams,omitempty" export:"true"`

View File

@@ -8,6 +8,7 @@ import (
"github.com/hashicorp/go-multierror"
"github.com/traefik/traefik/v2/pkg/log"
"golang.org/x/mod/module"
)
const localGoPath = "./plugins-local/"
@@ -68,24 +69,18 @@ func checkRemotePluginsConfiguration(plugins map[string]Descriptor) error {
var errs []string
for pAlias, descriptor := range plugins {
if descriptor.ModuleName == "" {
errs = append(errs, fmt.Sprintf("%s: plugin name is missing", pAlias))
if err := module.CheckPath(descriptor.ModuleName); err != nil {
errs = append(errs, fmt.Sprintf("%s: malformed plugin module name is missing: %s", pAlias, err))
}
if descriptor.Version == "" {
errs = append(errs, fmt.Sprintf("%s: plugin version is missing", pAlias))
}
if strings.HasPrefix(descriptor.ModuleName, "/") || strings.HasSuffix(descriptor.ModuleName, "/") {
errs = append(errs, fmt.Sprintf("%s: plugin name should not start or end with a /", pAlias))
continue
}
if _, ok := uniq[descriptor.ModuleName]; ok {
errs = append(errs, fmt.Sprintf("only one version of a plugin is allowed, there is a duplicate of %s", descriptor.ModuleName))
continue
}
uniq[descriptor.ModuleName] = struct{}{}
}

View File

@@ -0,0 +1,85 @@
package plugins
import (
"testing"
"github.com/stretchr/testify/assert"
)
func Test_checkRemotePluginsConfiguration(t *testing.T) {
testCases := []struct {
name string
plugins map[string]Descriptor
wantErr bool
}{
{
name: "nil plugins configuration returns no error",
plugins: nil,
wantErr: false,
},
{
name: "malformed module name returns error",
plugins: map[string]Descriptor{
"plugin1": {ModuleName: "invalid/module/name", Version: "v1.0.0"},
},
wantErr: true,
},
{
name: "malformed module name with path traversal returns error",
plugins: map[string]Descriptor{
"plugin1": {ModuleName: "github.com/module/../name", Version: "v1.0.0"},
},
wantErr: true,
},
{
name: "malformed module name with encoded path traversal returns error",
plugins: map[string]Descriptor{
"plugin1": {ModuleName: "github.com/module%2F%2E%2E%2Fname", Version: "v1.0.0"},
},
wantErr: true,
},
{
name: "malformed module name returns error",
plugins: map[string]Descriptor{
"plugin1": {ModuleName: "invalid/module/name", Version: "v1.0.0"},
},
wantErr: true,
},
{
name: "missing plugin version returns error",
plugins: map[string]Descriptor{
"plugin1": {ModuleName: "github.com/module/name", Version: ""},
},
wantErr: true,
},
{
name: "duplicate plugin module name returns error",
plugins: map[string]Descriptor{
"plugin1": {ModuleName: "github.com/module/name", Version: "v1.0.0"},
"plugin2": {ModuleName: "github.com/module/name", Version: "v1.1.0"},
},
wantErr: true,
},
{
name: "valid plugins configuration returns no error",
plugins: map[string]Descriptor{
"plugin1": {ModuleName: "github.com/module/name1", Version: "v1.0.0"},
"plugin2": {ModuleName: "github.com/module/name2", Version: "v1.1.0"},
},
wantErr: false,
},
}
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
t.Parallel()
err := checkRemotePluginsConfiguration(test.plugins)
if test.wantErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
})
}
}

View File

@@ -33,14 +33,6 @@ import (
"github.com/traefik/traefik/v2/pkg/version"
)
const (
// DockerAPIVersion is a constant holding the version of the Provider API traefik will use.
DockerAPIVersion = "1.24"
// SwarmAPIVersion is a constant holding the version of the Provider API traefik will use.
SwarmAPIVersion = "1.24"
)
// DefaultTemplateRule The default template for the default rule.
const DefaultTemplateRule = "Host(`{{ normalize .Name }}`)"
@@ -121,13 +113,10 @@ func (p *Provider) createClient() (client.APIClient, error) {
httpHeaders := map[string]string{
"User-Agent": "Traefik " + version.Version,
}
opts = append(opts, client.WithHTTPHeaders(httpHeaders))
apiVersion := DockerAPIVersion
if p.SwarmMode {
apiVersion = SwarmAPIVersion
}
opts = append(opts, client.WithVersion(apiVersion))
opts = append(opts,
client.FromEnv,
client.WithAPIVersionNegotiation(),
client.WithHTTPHeaders(httpHeaders))
return client.NewClientWithOpts(opts...)
}

View File

@@ -1,7 +1,7 @@
/*
The MIT License (MIT)
Copyright (c) 2016-2020 Containous SAS; 2020-2025 Traefik Labs
Copyright (c) 2016-2020 Containous SAS; 2020-2026 Traefik Labs
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,7 +1,7 @@
/*
The MIT License (MIT)
Copyright (c) 2016-2020 Containous SAS; 2020-2025 Traefik Labs
Copyright (c) 2016-2020 Containous SAS; 2020-2026 Traefik Labs
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,7 +1,7 @@
/*
The MIT License (MIT)
Copyright (c) 2016-2020 Containous SAS; 2020-2025 Traefik Labs
Copyright (c) 2016-2020 Containous SAS; 2020-2026 Traefik Labs
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,7 +1,7 @@
/*
The MIT License (MIT)
Copyright (c) 2016-2020 Containous SAS; 2020-2025 Traefik Labs
Copyright (c) 2016-2020 Containous SAS; 2020-2026 Traefik Labs
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,7 +1,7 @@
/*
The MIT License (MIT)
Copyright (c) 2016-2020 Containous SAS; 2020-2025 Traefik Labs
Copyright (c) 2016-2020 Containous SAS; 2020-2026 Traefik Labs
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,7 +1,7 @@
/*
The MIT License (MIT)
Copyright (c) 2016-2020 Containous SAS; 2020-2025 Traefik Labs
Copyright (c) 2016-2020 Containous SAS; 2020-2026 Traefik Labs
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,7 +1,7 @@
/*
The MIT License (MIT)
Copyright (c) 2016-2020 Containous SAS; 2020-2025 Traefik Labs
Copyright (c) 2016-2020 Containous SAS; 2020-2026 Traefik Labs
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,7 +1,7 @@
/*
The MIT License (MIT)
Copyright (c) 2016-2020 Containous SAS; 2020-2025 Traefik Labs
Copyright (c) 2016-2020 Containous SAS; 2020-2026 Traefik Labs
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,7 +1,7 @@
/*
The MIT License (MIT)
Copyright (c) 2016-2020 Containous SAS; 2020-2025 Traefik Labs
Copyright (c) 2016-2020 Containous SAS; 2020-2026 Traefik Labs
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,7 +1,7 @@
/*
The MIT License (MIT)
Copyright (c) 2016-2020 Containous SAS; 2020-2025 Traefik Labs
Copyright (c) 2016-2020 Containous SAS; 2020-2026 Traefik Labs
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,7 +1,7 @@
/*
The MIT License (MIT)
Copyright (c) 2016-2020 Containous SAS; 2020-2025 Traefik Labs
Copyright (c) 2016-2020 Containous SAS; 2020-2026 Traefik Labs
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,7 +1,7 @@
/*
The MIT License (MIT)
Copyright (c) 2016-2020 Containous SAS; 2020-2025 Traefik Labs
Copyright (c) 2016-2020 Containous SAS; 2020-2026 Traefik Labs
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,7 +1,7 @@
/*
The MIT License (MIT)
Copyright (c) 2016-2020 Containous SAS; 2020-2025 Traefik Labs
Copyright (c) 2016-2020 Containous SAS; 2020-2026 Traefik Labs
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,7 +1,7 @@
/*
The MIT License (MIT)
Copyright (c) 2016-2020 Containous SAS; 2020-2025 Traefik Labs
Copyright (c) 2016-2020 Containous SAS; 2020-2026 Traefik Labs
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,7 +1,7 @@
/*
The MIT License (MIT)
Copyright (c) 2016-2020 Containous SAS; 2020-2025 Traefik Labs
Copyright (c) 2016-2020 Containous SAS; 2020-2026 Traefik Labs
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,7 +1,7 @@
/*
The MIT License (MIT)
Copyright (c) 2016-2020 Containous SAS; 2020-2025 Traefik Labs
Copyright (c) 2016-2020 Containous SAS; 2020-2026 Traefik Labs
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,7 +1,7 @@
/*
The MIT License (MIT)
Copyright (c) 2016-2020 Containous SAS; 2020-2025 Traefik Labs
Copyright (c) 2016-2020 Containous SAS; 2020-2026 Traefik Labs
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,7 +1,7 @@
/*
The MIT License (MIT)
Copyright (c) 2016-2020 Containous SAS; 2020-2025 Traefik Labs
Copyright (c) 2016-2020 Containous SAS; 2020-2026 Traefik Labs
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,7 +1,7 @@
/*
The MIT License (MIT)
Copyright (c) 2016-2020 Containous SAS; 2020-2025 Traefik Labs
Copyright (c) 2016-2020 Containous SAS; 2020-2026 Traefik Labs
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,7 +1,7 @@
/*
The MIT License (MIT)
Copyright (c) 2016-2020 Containous SAS; 2020-2025 Traefik Labs
Copyright (c) 2016-2020 Containous SAS; 2020-2026 Traefik Labs
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

Some files were not shown because too many files have changed in this diff Show More