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.