Add support for ipv6 subnet in ipStrategy

This commit is contained in:
Michal Kralik 2024-09-24 18:04:05 +02:00 committed by GitHub
parent a398536688
commit 312ebb17ab
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 544 additions and 12 deletions

View file

@ -101,7 +101,7 @@ If none are set, the default is to use the `requestHost`.
#### `sourceCriterion.ipStrategy`
The `ipStrategy` option defines two parameters that configures how Traefik determines the client IP: `depth`, and `excludedIPs`.
The `ipStrategy` option defines three parameters that configures how Traefik determines the client IP: `depth`, `excludedIPs` and `ipv6Subnet`.
!!! important "As a middleware, InFlightReq happens before the actual proxying to the backend takes place. In addition, the previous network hop only gets appended to `X-Forwarded-For` during the last stages of proxying, i.e. after it has already passed through the middleware. Therefore, during InFlightReq, as the previous network hop is not yet present in `X-Forwarded-For`, it cannot be used and/or relied upon."
@ -112,6 +112,9 @@ The `depth` option tells Traefik to use the `X-Forwarded-For` header and select
- If `depth` is greater than the total number of IPs in `X-Forwarded-For`, then the client IP is empty.
- `depth` is ignored if its value is less than or equal to 0.
If `ipStrategy.ipv6Subnet` is provided and the selected IP is IPv6, the IP is transformed into the first IP of the subnet it belongs to.
See [ipStrategy.ipv6Subnet](#ipstrategyipv6subnet) for more details.
!!! example "Example of Depth & X-Forwarded-For"
If `depth` is set to 2, and the request `X-Forwarded-For` header is `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` then the "real" client IP is `"10.0.0.1"` (at depth 4) but the IP used as the criterion is `"12.0.0.1"` (`depth=2`).
@ -218,6 +221,63 @@ http:
excludedIPs = ["127.0.0.1/32", "192.168.1.7"]
```
##### `ipStrategy.ipv6Subnet`
This strategy applies to `Depth` and `RemoteAddr` strategy only.
If `ipv6Subnet` is provided and the selected IP is IPv6, the IP is transformed into the first IP of the subnet it belongs to.
This is useful for grouping IPv6 addresses into subnets to prevent bypassing this middleware by obtaining a new IPv6.
- `ipv6Subnet` is ignored if its value is outside of 0-128 interval
!!! example "Example of ipv6Subnet"
If `ipv6Subnet` is provided, the IP is transformed in the following way.
| `IP` | `ipv6Subnet` | clientIP |
|---------------------------|--------------|-----------------------|
| `"::abcd:1111:2222:3333"` | `64` | `"::0:0:0:0"` |
| `"::abcd:1111:2222:3333"` | `80` | `"::abcd:0:0:0:0"` |
| `"::abcd:1111:2222:3333"` | `96` | `"::abcd:1111:0:0:0"` |
```yaml tab="Docker & Swarm"
labels:
- "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.ipstrategy.ipv6Subnet=64"
```
```yaml tab="Kubernetes"
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: test-inflightreq
spec:
inFlightReq:
sourceCriterion:
ipStrategy:
ipv6Subnet: 64
```
```yaml tab="Consul Catalog"
- "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.ipstrategy.ipv6Subnet=64"
```
```yaml tab="File (YAML)"
http:
middlewares:
test-inflightreq:
inFlightReq:
sourceCriterion:
ipStrategy:
ipv6Subnet: 64
```
```toml tab="File (TOML)"
[http.middlewares]
[http.middlewares.test-inflightreq.inflightreq]
[http.middlewares.test-inflightreq.inFlightReq.sourceCriterion.ipStrategy]
ipv6Subnet = 64
```
#### `sourceCriterion.requestHeaderName`
Name of the header used to group incoming requests.

View file

@ -75,6 +75,9 @@ The `depth` option tells Traefik to use the `X-Forwarded-For` header and take th
- If `depth` is greater than the total number of IPs in `X-Forwarded-For`, then the client IP will be empty.
- `depth` is ignored if its value is less than or equal to 0.
If `ipStrategy.ipv6Subnet` is provided and the selected IP is IPv6, the IP is transformed into the first IP of the subnet it belongs to.
See [ipStrategy.ipv6Subnet](#ipstrategyipv6subnet) for more details.
!!! example "Examples of Depth & X-Forwarded-For"
If `depth` is set to 2, and the request `X-Forwarded-For` header is `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` then the "real" client IP is `"10.0.0.1"` (at depth 4) but the IP used is `"12.0.0.1"` (`depth=2`).
@ -204,3 +207,60 @@ http:
[http.middlewares.test-ipallowlist.ipAllowList.ipStrategy]
excludedIPs = ["127.0.0.1/32", "192.168.1.7"]
```
#### `ipStrategy.ipv6Subnet`
This strategy applies to `Depth` and `RemoteAddr` strategy only.
If `ipv6Subnet` is provided and the selected IP is IPv6, the IP is transformed into the first IP of the subnet it belongs to.
This is useful for grouping IPv6 addresses into subnets to prevent bypassing this middleware by obtaining a new IPv6.
- `ipv6Subnet` is ignored if its value is outside of 0-128 interval
!!! example "Example of ipv6Subnet"
If `ipv6Subnet` is provided, the IP is transformed in the following way.
| `IP` | `ipv6Subnet` | clientIP |
|---------------------------|--------------|-----------------------|
| `"::abcd:1111:2222:3333"` | `64` | `"::0:0:0:0"` |
| `"::abcd:1111:2222:3333"` | `80` | `"::abcd:0:0:0:0"` |
| `"::abcd:1111:2222:3333"` | `96` | `"::abcd:1111:0:0:0"` |
```yaml tab="Docker & Swarm"
labels:
- "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcecriterion.ipstrategy.ipv6Subnet=64"
```
```yaml tab="Kubernetes"
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: test-ipallowlist
spec:
ipallowlist:
sourceCriterion:
ipStrategy:
ipv6Subnet: 64
```
```yaml tab="Consul Catalog"
- "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcecriterion.ipstrategy.ipv6Subnet=64"
```
```yaml tab="File (YAML)"
http:
middlewares:
test-ipallowlist:
ipallowlist:
sourceCriterion:
ipStrategy:
ipv6Subnet: 64
```
```toml tab="File (TOML)"
[http.middlewares]
[http.middlewares.test-ipallowlist.ipallowlist]
[http.middlewares.test-ipallowlist.ipallowlist.sourceCriterion.ipStrategy]
ipv6Subnet = 64
```

View file

@ -81,6 +81,9 @@ The `depth` option tells Traefik to use the `X-Forwarded-For` header and take th
- If `depth` is greater than the total number of IPs in `X-Forwarded-For`, then the client IP will be empty.
- `depth` is ignored if its value is less than or equal to 0.
If `ipStrategy.ipv6Subnet` is provided and the selected IP is IPv6, the IP is transformed into the first IP of the subnet it belongs to.
See [ipStrategy.ipv6Subnet](#ipstrategyipv6subnet) for more details.
!!! example "Examples of Depth & X-Forwarded-For"
If `depth` is set to 2, and the request `X-Forwarded-For` header is `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` then the "real" client IP is `"10.0.0.1"` (at depth 4) but the IP used for the whitelisting is `"12.0.0.1"` (`depth=2`).
@ -210,3 +213,60 @@ http:
[http.middlewares.test-ipwhitelist.ipWhiteList.ipStrategy]
excludedIPs = ["127.0.0.1/32", "192.168.1.7"]
```
#### `ipStrategy.ipv6Subnet`
This strategy applies to `Depth` and `RemoteAddr` strategy only.
If `ipv6Subnet` is provided and the selected IP is IPv6, the IP is transformed into the first IP of the subnet it belongs to.
This is useful for grouping IPv6 addresses into subnets to prevent bypassing this middleware by obtaining a new IPv6.
- `ipv6Subnet` is ignored if its value is outside of 0-128 interval
!!! example "Example of ipv6Subnet"
If `ipv6Subnet` is provided, the IP is transformed in the following way.
| `IP` | `ipv6Subnet` | clientIP |
|---------------------------|--------------|-----------------------|
| `"::abcd:1111:2222:3333"` | `64` | `"::0:0:0:0"` |
| `"::abcd:1111:2222:3333"` | `80` | `"::abcd:0:0:0:0"` |
| `"::abcd:1111:2222:3333"` | `96` | `"::abcd:1111:0:0:0"` |
```yaml tab="Docker & Swarm"
labels:
- "traefik.http.middlewares.test-ipWhiteList.ipWhiteList.sourcecriterion.ipstrategy.ipv6Subnet=64"
```
```yaml tab="Kubernetes"
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: test-ipWhiteList
spec:
ipWhiteList:
sourceCriterion:
ipStrategy:
ipv6Subnet: 64
```
```yaml tab="Consul Catalog"
- "traefik.http.middlewares.test-ipWhiteList.ipWhiteList.sourcecriterion.ipstrategy.ipv6Subnet=64"
```
```yaml tab="File (YAML)"
http:
middlewares:
test-ipWhiteList:
ipWhiteList:
sourceCriterion:
ipStrategy:
ipv6Subnet: 64
```
```toml tab="File (TOML)"
[http.middlewares]
[http.middlewares.test-ipWhiteList.ipWhiteList]
[http.middlewares.test-ipWhiteList.ipWhiteList.sourceCriterion.ipStrategy]
ipv6Subnet = 64
```

View file

@ -211,7 +211,7 @@ If none are set, the default is to use the request's remote address field (as an
#### `sourceCriterion.ipStrategy`
The `ipStrategy` option defines two parameters that configures how Traefik determines the client IP: `depth`, and `excludedIPs`.
The `ipStrategy` option defines three parameters that configures how Traefik determines the client IP: `depth`, `excludedIPs` and `ipv6Subnet`.
!!! important "As a middleware, rate-limiting happens before the actual proxying to the backend takes place. In addition, the previous network hop only gets appended to `X-Forwarded-For` during the last stages of proxying, i.e. after it has already passed through rate-limiting. Therefore, during rate-limiting, as the previous network hop is not yet present in `X-Forwarded-For`, it cannot be found and/or relied upon."
@ -222,6 +222,9 @@ The `depth` option tells Traefik to use the `X-Forwarded-For` header and select
- If `depth` is greater than the total number of IPs in `X-Forwarded-For`, then the client IP is empty.
- `depth` is ignored if its value is less than or equal to 0.
If `ipStrategy.ipv6Subnet` is provided and the selected IP is IPv6, the IP is transformed into the first IP of the subnet it belongs to.
See [ipStrategy.ipv6Subnet](#ipstrategyipv6subnet) for more details.
!!! example "Example of Depth & X-Forwarded-For"
If `depth` is set to 2, and the request `X-Forwarded-For` header is `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` then the "real" client IP is `"10.0.0.1"` (at depth 4) but the IP used as the criterion is `"12.0.0.1"` (`depth=2`).
@ -355,6 +358,63 @@ http:
excludedIPs = ["127.0.0.1/32", "192.168.1.7"]
```
##### `ipStrategy.ipv6Subnet`
This strategy applies to `Depth` and `RemoteAddr` strategy only.
If `ipv6Subnet` is provided and the selected IP is IPv6, the IP is transformed into the first IP of the subnet it belongs to.
This is useful for grouping IPv6 addresses into subnets to prevent bypassing this middleware by obtaining a new IPv6.
- `ipv6Subnet` is ignored if its value is outside of 0-128 interval
!!! example "Example of ipv6Subnet"
If `ipv6Subnet` is provided, the IP is transformed in the following way.
| `IP` | `ipv6Subnet` | clientIP |
|---------------------------|--------------|-----------------------|
| `"::abcd:1111:2222:3333"` | `64` | `"::0:0:0:0"` |
| `"::abcd:1111:2222:3333"` | `80` | `"::abcd:0:0:0:0"` |
| `"::abcd:1111:2222:3333"` | `96` | `"::abcd:1111:0:0:0"` |
```yaml tab="Docker & Swarm"
labels:
- "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.ipstrategy.ipv6Subnet=64"
```
```yaml tab="Kubernetes"
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: test-ratelimit
spec:
ratelimit:
sourceCriterion:
ipStrategy:
ipv6Subnet: 64
```
```yaml tab="Consul Catalog"
- "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.ipstrategy.ipv6Subnet=64"
```
```yaml tab="File (YAML)"
http:
middlewares:
test-ratelimit:
ratelimit:
sourceCriterion:
ipStrategy:
ipv6Subnet: 64
```
```toml tab="File (TOML)"
[http.middlewares]
[http.middlewares.test-ratelimit.ratelimit]
[http.middlewares.test-ratelimit.ratelimit.sourceCriterion.ipStrategy]
ipv6Subnet = 64
```
#### `sourceCriterion.requestHeaderName`
Name of the header used to group incoming requests.

View file

@ -85,15 +85,18 @@
- "traefik.http.middlewares.middleware13.ipallowlist.ipstrategy=true"
- "traefik.http.middlewares.middleware13.ipallowlist.ipstrategy.depth=42"
- "traefik.http.middlewares.middleware13.ipallowlist.ipstrategy.excludedips=foobar, foobar"
- "traefik.http.middlewares.middleware13.ipallowlist.ipstrategy.ipv6subnet=42"
- "traefik.http.middlewares.middleware13.ipallowlist.rejectstatuscode=42"
- "traefik.http.middlewares.middleware13.ipallowlist.sourcerange=foobar, foobar"
- "traefik.http.middlewares.middleware14.ipwhitelist.ipstrategy=true"
- "traefik.http.middlewares.middleware14.ipwhitelist.ipstrategy.depth=42"
- "traefik.http.middlewares.middleware14.ipwhitelist.ipstrategy.excludedips=foobar, foobar"
- "traefik.http.middlewares.middleware14.ipwhitelist.ipstrategy.ipv6subnet=42"
- "traefik.http.middlewares.middleware14.ipwhitelist.sourcerange=foobar, foobar"
- "traefik.http.middlewares.middleware15.inflightreq.amount=42"
- "traefik.http.middlewares.middleware15.inflightreq.sourcecriterion.ipstrategy.depth=42"
- "traefik.http.middlewares.middleware15.inflightreq.sourcecriterion.ipstrategy.excludedips=foobar, foobar"
- "traefik.http.middlewares.middleware15.inflightreq.sourcecriterion.ipstrategy.ipv6subnet=42"
- "traefik.http.middlewares.middleware15.inflightreq.sourcecriterion.requestheadername=foobar"
- "traefik.http.middlewares.middleware15.inflightreq.sourcecriterion.requesthost=true"
- "traefik.http.middlewares.middleware16.passtlsclientcert.info.issuer.commonname=true"
@ -125,6 +128,7 @@
- "traefik.http.middlewares.middleware18.ratelimit.period=42s"
- "traefik.http.middlewares.middleware18.ratelimit.sourcecriterion.ipstrategy.depth=42"
- "traefik.http.middlewares.middleware18.ratelimit.sourcecriterion.ipstrategy.excludedips=foobar, foobar"
- "traefik.http.middlewares.middleware18.ratelimit.sourcecriterion.ipstrategy.ipv6subnet=42"
- "traefik.http.middlewares.middleware18.ratelimit.sourcecriterion.requestheadername=foobar"
- "traefik.http.middlewares.middleware18.ratelimit.sourcecriterion.requesthost=true"
- "traefik.http.middlewares.middleware19.redirectregex.permanent=true"

View file

@ -227,12 +227,14 @@
[http.middlewares.Middleware13.ipAllowList.ipStrategy]
depth = 42
excludedIPs = ["foobar", "foobar"]
ipv6Subnet = 42
[http.middlewares.Middleware14]
[http.middlewares.Middleware14.ipWhiteList]
sourceRange = ["foobar", "foobar"]
[http.middlewares.Middleware14.ipWhiteList.ipStrategy]
depth = 42
excludedIPs = ["foobar", "foobar"]
ipv6Subnet = 42
[http.middlewares.Middleware15]
[http.middlewares.Middleware15.inFlightReq]
amount = 42
@ -242,6 +244,7 @@
[http.middlewares.Middleware15.inFlightReq.sourceCriterion.ipStrategy]
depth = 42
excludedIPs = ["foobar", "foobar"]
ipv6Subnet = 42
[http.middlewares.Middleware16]
[http.middlewares.Middleware16.passTLSClientCert]
pem = true
@ -286,6 +289,7 @@
[http.middlewares.Middleware18.rateLimit.sourceCriterion.ipStrategy]
depth = 42
excludedIPs = ["foobar", "foobar"]
ipv6Subnet = 42
[http.middlewares.Middleware19]
[http.middlewares.Middleware19.redirectRegex]
regex = "foobar"

View file

@ -267,6 +267,7 @@ http:
excludedIPs:
- foobar
- foobar
ipv6Subnet: 42
rejectStatusCode: 42
Middleware14:
ipWhiteList:
@ -278,6 +279,7 @@ http:
excludedIPs:
- foobar
- foobar
ipv6Subnet: 42
Middleware15:
inFlightReq:
amount: 42
@ -287,6 +289,7 @@ http:
excludedIPs:
- foobar
- foobar
ipv6Subnet: 42
requestHeaderName: foobar
requestHost: true
Middleware16:
@ -333,6 +336,7 @@ http:
excludedIPs:
- foobar
- foobar
ipv6Subnet: 42
requestHeaderName: foobar
requestHost: true
Middleware19:

View file

@ -1458,6 +1458,12 @@ spec:
items:
type: string
type: array
ipv6Subnet:
description: IPv6Subnet configures Traefik to consider
all IPv6 addresses from the defined subnet as originating
from the same IP. Applies to RemoteAddrStrategy and
DepthStrategy.
type: integer
type: object
requestHeaderName:
description: RequestHeaderName defines the name of the header
@ -1491,6 +1497,11 @@ spec:
items:
type: string
type: array
ipv6Subnet:
description: IPv6Subnet configures Traefik to consider all
IPv6 addresses from the defined subnet as originating from
the same IP. Applies to RemoteAddrStrategy and DepthStrategy.
type: integer
type: object
rejectStatusCode:
description: |-
@ -1523,6 +1534,11 @@ spec:
items:
type: string
type: array
ipv6Subnet:
description: IPv6Subnet configures Traefik to consider all
IPv6 addresses from the defined subnet as originating from
the same IP. Applies to RemoteAddrStrategy and DepthStrategy.
type: integer
type: object
sourceRange:
description: SourceRange defines the set of allowed IPs (or ranges
@ -1691,6 +1707,12 @@ spec:
items:
type: string
type: array
ipv6Subnet:
description: IPv6Subnet configures Traefik to consider
all IPv6 addresses from the defined subnet as originating
from the same IP. Applies to RemoteAddrStrategy and
DepthStrategy.
type: integer
type: object
requestHeaderName:
description: RequestHeaderName defines the name of the header

View file

@ -103,18 +103,21 @@ THIS FILE MUST NOT BE EDITED BY HAND
| `traefik/http/middlewares/Middleware13/ipAllowList/ipStrategy/depth` | `42` |
| `traefik/http/middlewares/Middleware13/ipAllowList/ipStrategy/excludedIPs/0` | `foobar` |
| `traefik/http/middlewares/Middleware13/ipAllowList/ipStrategy/excludedIPs/1` | `foobar` |
| `traefik/http/middlewares/Middleware13/ipAllowList/ipStrategy/ipv6Subnet` | `42` |
| `traefik/http/middlewares/Middleware13/ipAllowList/rejectStatusCode` | `42` |
| `traefik/http/middlewares/Middleware13/ipAllowList/sourceRange/0` | `foobar` |
| `traefik/http/middlewares/Middleware13/ipAllowList/sourceRange/1` | `foobar` |
| `traefik/http/middlewares/Middleware14/ipWhiteList/ipStrategy/depth` | `42` |
| `traefik/http/middlewares/Middleware14/ipWhiteList/ipStrategy/excludedIPs/0` | `foobar` |
| `traefik/http/middlewares/Middleware14/ipWhiteList/ipStrategy/excludedIPs/1` | `foobar` |
| `traefik/http/middlewares/Middleware14/ipWhiteList/ipStrategy/ipv6Subnet` | `42` |
| `traefik/http/middlewares/Middleware14/ipWhiteList/sourceRange/0` | `foobar` |
| `traefik/http/middlewares/Middleware14/ipWhiteList/sourceRange/1` | `foobar` |
| `traefik/http/middlewares/Middleware15/inFlightReq/amount` | `42` |
| `traefik/http/middlewares/Middleware15/inFlightReq/sourceCriterion/ipStrategy/depth` | `42` |
| `traefik/http/middlewares/Middleware15/inFlightReq/sourceCriterion/ipStrategy/excludedIPs/0` | `foobar` |
| `traefik/http/middlewares/Middleware15/inFlightReq/sourceCriterion/ipStrategy/excludedIPs/1` | `foobar` |
| `traefik/http/middlewares/Middleware15/inFlightReq/sourceCriterion/ipStrategy/ipv6Subnet` | `42` |
| `traefik/http/middlewares/Middleware15/inFlightReq/sourceCriterion/requestHeaderName` | `foobar` |
| `traefik/http/middlewares/Middleware15/inFlightReq/sourceCriterion/requestHost` | `true` |
| `traefik/http/middlewares/Middleware16/passTLSClientCert/info/issuer/commonName` | `true` |
@ -147,6 +150,7 @@ THIS FILE MUST NOT BE EDITED BY HAND
| `traefik/http/middlewares/Middleware18/rateLimit/sourceCriterion/ipStrategy/depth` | `42` |
| `traefik/http/middlewares/Middleware18/rateLimit/sourceCriterion/ipStrategy/excludedIPs/0` | `foobar` |
| `traefik/http/middlewares/Middleware18/rateLimit/sourceCriterion/ipStrategy/excludedIPs/1` | `foobar` |
| `traefik/http/middlewares/Middleware18/rateLimit/sourceCriterion/ipStrategy/ipv6Subnet` | `42` |
| `traefik/http/middlewares/Middleware18/rateLimit/sourceCriterion/requestHeaderName` | `foobar` |
| `traefik/http/middlewares/Middleware18/rateLimit/sourceCriterion/requestHost` | `true` |
| `traefik/http/middlewares/Middleware19/redirectRegex/permanent` | `true` |

View file

@ -734,6 +734,12 @@ spec:
items:
type: string
type: array
ipv6Subnet:
description: IPv6Subnet configures Traefik to consider
all IPv6 addresses from the defined subnet as originating
from the same IP. Applies to RemoteAddrStrategy and
DepthStrategy.
type: integer
type: object
requestHeaderName:
description: RequestHeaderName defines the name of the header
@ -767,6 +773,11 @@ spec:
items:
type: string
type: array
ipv6Subnet:
description: IPv6Subnet configures Traefik to consider all
IPv6 addresses from the defined subnet as originating from
the same IP. Applies to RemoteAddrStrategy and DepthStrategy.
type: integer
type: object
rejectStatusCode:
description: |-
@ -799,6 +810,11 @@ spec:
items:
type: string
type: array
ipv6Subnet:
description: IPv6Subnet configures Traefik to consider all
IPv6 addresses from the defined subnet as originating from
the same IP. Applies to RemoteAddrStrategy and DepthStrategy.
type: integer
type: object
sourceRange:
description: SourceRange defines the set of allowed IPs (or ranges
@ -967,6 +983,12 @@ spec:
items:
type: string
type: array
ipv6Subnet:
description: IPv6Subnet configures Traefik to consider
all IPv6 addresses from the defined subnet as originating
from the same IP. Applies to RemoteAddrStrategy and
DepthStrategy.
type: integer
type: object
requestHeaderName:
description: RequestHeaderName defines the name of the header