diff --git a/docs/content/middlewares/http/ipallowlist.md b/docs/content/middlewares/http/ipallowlist.md new file mode 100644 index 000000000..d62e253bb --- /dev/null +++ b/docs/content/middlewares/http/ipallowlist.md @@ -0,0 +1,195 @@ +--- +title: "Traefik HTTP Middlewares IPAllowList" +description: "Learn how to use IPAllowList in HTTP middleware for limiting clients to specific IPs in Traefik Proxy. Read the technical documentation." +--- + +# IPAllowList + +Limiting Clients to Specific IPs +{: .subtitle } + +IPAllowList accepts / refuses requests based on the client IP. + +## Configuration Examples + +```yaml tab="Docker & Swarm" +# Accepts request from defined IP +labels: + - "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7" +``` + +```yaml tab="Kubernetes" +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: test-ipallowlist +spec: + ipAllowList: + sourceRange: + - 127.0.0.1/32 + - 192.168.1.7 +``` + +```yaml tab="Consul Catalog" +# Accepts request from defined IP +- "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7" +``` + +```yaml tab="File (YAML)" +# Accepts request from defined IP +http: + middlewares: + test-ipallowlist: + ipAllowList: + sourceRange: + - "127.0.0.1/32" + - "192.168.1.7" +``` + +```toml tab="File (TOML)" +# Accepts request from defined IP +[http.middlewares] + [http.middlewares.test-ipallowlist.ipAllowList] + sourceRange = ["127.0.0.1/32", "192.168.1.7"] +``` + +## Configuration Options + +### `sourceRange` + +The `sourceRange` option sets the allowed IPs (or ranges of allowed IPs by using CIDR notation). + +### `ipStrategy` + +The `ipStrategy` option defines two parameters that set how Traefik determines the client IP: `depth`, and `excludedIPs`. +If no strategy is set, the default behavior is to match `sourceRange` against the Remote address found in the request. + +!!! important "As a middleware, whitelisting 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 whitelisting. Therefore, during whitelisting, as the previous network hop is not yet present in `X-Forwarded-For`, it cannot be matched against `sourceRange`." + +#### `ipStrategy.depth` + +The `depth` option tells Traefik to use the `X-Forwarded-For` header and take the IP located at the `depth` position (starting from the right). + +- 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. + +!!! 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`). + + | `X-Forwarded-For` | `depth` | clientIP | + |-----------------------------------------|---------|--------------| + | `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` | `1` | `"13.0.0.1"` | + | `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` | `3` | `"11.0.0.1"` | + | `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` | `5` | `""` | + +```yaml tab="Docker & Swarm" +# Allowlisting Based on `X-Forwarded-For` with `depth=2` +labels: + - "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7" + - "traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.depth=2" +``` + +```yaml tab="Kubernetes" +# Allowlisting Based on `X-Forwarded-For` with `depth=2` +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: test-ipallowlist +spec: + ipAllowList: + sourceRange: + - 127.0.0.1/32 + - 192.168.1.7 + ipStrategy: + depth: 2 +``` + +```yaml tab="Consul Catalog" +# Allowlisting Based on `X-Forwarded-For` with `depth=2` +- "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7" +- "traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.depth=2" +``` + +```yaml tab="File (YAML)" +# Allowlisting Based on `X-Forwarded-For` with `depth=2` +http: + middlewares: + test-ipallowlist: + ipAllowList: + sourceRange: + - "127.0.0.1/32" + - "192.168.1.7" + ipStrategy: + depth: 2 +``` + +```toml tab="File (TOML)" +# Allowlisting Based on `X-Forwarded-For` with `depth=2` +[http.middlewares] + [http.middlewares.test-ipallowlist.ipAllowList] + sourceRange = ["127.0.0.1/32", "192.168.1.7"] + [http.middlewares.test-ipallowlist.ipAllowList.ipStrategy] + depth = 2 +``` + +#### `ipStrategy.excludedIPs` + +`excludedIPs` configures Traefik to scan the `X-Forwarded-For` header and select the first IP not in the list. + +!!! important "If `depth` is specified, `excludedIPs` is ignored." + +!!! example "Example of ExcludedIPs & X-Forwarded-For" + + | `X-Forwarded-For` | `excludedIPs` | clientIP | + |-----------------------------------------|-----------------------|--------------| + | `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` | `"12.0.0.1,13.0.0.1"` | `"11.0.0.1"` | + | `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` | `"15.0.0.1,13.0.0.1"` | `"12.0.0.1"` | + | `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` | `"10.0.0.1,13.0.0.1"` | `"12.0.0.1"` | + | `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` | `"15.0.0.1,16.0.0.1"` | `"13.0.0.1"` | + | `"10.0.0.1,11.0.0.1"` | `"10.0.0.1,11.0.0.1"` | `""` | + +```yaml tab="Docker & Swarm" +# Exclude from `X-Forwarded-For` +labels: + - "traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7" +``` + +```yaml tab="Kubernetes" +# Exclude from `X-Forwarded-For` +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: test-ipallowlist +spec: + ipAllowList: + ipStrategy: + excludedIPs: + - 127.0.0.1/32 + - 192.168.1.7 +``` + +```yaml tab="Consul Catalog" +# Exclude from `X-Forwarded-For` +- "traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7" +``` + +```yaml tab="File (YAML)" +# Exclude from `X-Forwarded-For` +http: + middlewares: + test-ipallowlist: + ipAllowList: + ipStrategy: + excludedIPs: + - "127.0.0.1/32" + - "192.168.1.7" +``` + +```toml tab="File (TOML)" +# Exclude from `X-Forwarded-For` +[http.middlewares] + [http.middlewares.test-ipallowlist.ipAllowList] + [http.middlewares.test-ipallowlist.ipAllowList.ipStrategy] + excludedIPs = ["127.0.0.1/32", "192.168.1.7"] +``` diff --git a/docs/content/middlewares/http/ipwhitelist.md b/docs/content/middlewares/http/ipwhitelist.md index 979791de0..eaf761541 100644 --- a/docs/content/middlewares/http/ipwhitelist.md +++ b/docs/content/middlewares/http/ipwhitelist.md @@ -8,9 +8,13 @@ description: "Learn how to use IPWhiteList in HTTP middleware for limiting clien Limiting Clients to Specific IPs {: .subtitle } -![IpWhiteList](../../assets/img/middleware/ipwhitelist.png) +![IPWhiteList](../../assets/img/middleware/ipwhitelist.png) -IPWhitelist accepts / refuses requests based on the client IP. +IPWhiteList accepts / refuses requests based on the client IP. + +!!! warning + + This middleware is deprecated, please use the [IPAllowList](./ipallowlist.md) middleware instead. ## Configuration Examples diff --git a/docs/content/middlewares/tcp/ipallowlist.md b/docs/content/middlewares/tcp/ipallowlist.md new file mode 100644 index 000000000..e8466b94e --- /dev/null +++ b/docs/content/middlewares/tcp/ipallowlist.md @@ -0,0 +1,60 @@ +--- +title: "Traefik TCP Middlewares IPAllowList" +description: "Learn how to use IPAllowList in TCP middleware for limiting clients to specific IPs in Traefik Proxy. Read the technical documentation." +--- + +# IPAllowList + +Limiting Clients to Specific IPs +{: .subtitle } + +IPAllowList accepts / refuses connections based on the client IP. + +## Configuration Examples + +```yaml tab="Docker & Swarm" +# Accepts connections from defined IP +labels: + - "traefik.tcp.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7" +``` + +```yaml tab="Kubernetes" +apiVersion: traefik.io/v1alpha1 +kind: MiddlewareTCP +metadata: + name: test-ipallowlist +spec: + ipAllowList: + sourceRange: + - 127.0.0.1/32 + - 192.168.1.7 +``` + +```yaml tab="Consul Catalog" +# Accepts request from defined IP +- "traefik.tcp.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7" +``` + +```toml tab="File (TOML)" +# Accepts request from defined IP +[tcp.middlewares] + [tcp.middlewares.test-ipallowlist.ipAllowList] + sourceRange = ["127.0.0.1/32", "192.168.1.7"] +``` + +```yaml tab="File (YAML)" +# Accepts request from defined IP +tcp: + middlewares: + test-ipallowlist: + ipAllowList: + sourceRange: + - "127.0.0.1/32" + - "192.168.1.7" +``` + +## Configuration Options + +### `sourceRange` + +The `sourceRange` option sets the allowed IPs (or ranges of allowed IPs by using CIDR notation). diff --git a/docs/content/middlewares/tcp/ipwhitelist.md b/docs/content/middlewares/tcp/ipwhitelist.md index 5926cc65a..9133c5f37 100644 --- a/docs/content/middlewares/tcp/ipwhitelist.md +++ b/docs/content/middlewares/tcp/ipwhitelist.md @@ -8,7 +8,11 @@ description: "Learn how to use IPWhiteList in TCP middleware for limiting client Limiting Clients to Specific IPs {: .subtitle } -IPWhitelist accepts / refuses connections based on the client IP. +IPWhiteList accepts / refuses connections based on the client IP. + +!!! warning + + This middleware is deprecated, please use the [IPAllowList](./ipallowlist.md) middleware instead. ## Configuration Examples diff --git a/docs/content/migration/v2.md b/docs/content/migration/v2.md index fdf1f6aa2..9fc05c38f 100644 --- a/docs/content/migration/v2.md +++ b/docs/content/migration/v2.md @@ -523,3 +523,13 @@ kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.10/docs/co ### Traefik Hub In `v2.10`, Traefik Hub configuration has been removed because Traefik Hub v2 doesn't require this configuration. + +## v2.11 + +### IPWhiteList (HTTP) + +In `v2.11`, the `IPWhiteList` middleware is deprecated, please use the [IPAllowList](../middlewares/http/ipallowlist.md) middleware instead. + +### IPWhiteList (TCP) + +In `v2.11`, the `IPWhiteList` middleware is deprecated, please use the [IPAllowList](../middlewares/tcp/ipallowlist.md) middleware instead. diff --git a/docs/content/reference/dynamic-configuration/docker-labels.yml b/docs/content/reference/dynamic-configuration/docker-labels.yml index c413f27bd..723d4b049 100644 --- a/docs/content/reference/dynamic-configuration/docker-labels.yml +++ b/docs/content/reference/dynamic-configuration/docker-labels.yml @@ -121,6 +121,9 @@ - "traefik.http.middlewares.middleware21.stripprefix.forceslash=true" - "traefik.http.middlewares.middleware21.stripprefix.prefixes=foobar, foobar" - "traefik.http.middlewares.middleware22.stripprefixregex.regex=foobar, foobar" +- "traefik.http.middlewares.middleware23.ipallowlist.ipstrategy.depth=42" +- "traefik.http.middlewares.middleware23.ipallowlist.ipstrategy.excludedips=foobar, foobar" +- "traefik.http.middlewares.middleware23.ipallowlist.sourcerange=foobar, foobar" - "traefik.http.routers.router0.entrypoints=foobar, foobar" - "traefik.http.routers.router0.middlewares=foobar, foobar" - "traefik.http.routers.router0.priority=42" @@ -167,6 +170,7 @@ - "traefik.http.services.service01.loadbalancer.server.scheme=foobar" - "traefik.tcp.middlewares.tcpmiddleware00.ipwhitelist.sourcerange=foobar, foobar" - "traefik.tcp.middlewares.tcpmiddleware01.inflightconn.amount=42" +- "traefik.tcp.middlewares.tcpmiddleware02.ipallowlist.sourcerange=foobar, foobar" - "traefik.tcp.routers.tcprouter0.entrypoints=foobar, foobar" - "traefik.tcp.routers.tcprouter0.middlewares=foobar, foobar" - "traefik.tcp.routers.tcprouter0.rule=foobar" diff --git a/docs/content/reference/dynamic-configuration/file.toml b/docs/content/reference/dynamic-configuration/file.toml index 895a1f97f..7b00cffa2 100644 --- a/docs/content/reference/dynamic-configuration/file.toml +++ b/docs/content/reference/dynamic-configuration/file.toml @@ -284,6 +284,12 @@ [http.middlewares.Middleware22] [http.middlewares.Middleware22.stripPrefixRegex] regex = ["foobar", "foobar"] + [http.middlewares.Middleware23] + [http.middlewares.Middleware23.ipAllowList] + sourceRange = ["foobar", "foobar"] + [http.middlewares.Middleware23.ipAllowList.ipStrategy] + depth = 42 + excludedIPs = ["foobar", "foobar"] [http.serversTransports] [http.serversTransports.ServersTransport0] serverName = "foobar" diff --git a/docs/content/reference/dynamic-configuration/file.yaml b/docs/content/reference/dynamic-configuration/file.yaml index ec3081778..a19859e0b 100644 --- a/docs/content/reference/dynamic-configuration/file.yaml +++ b/docs/content/reference/dynamic-configuration/file.yaml @@ -323,6 +323,16 @@ http: regex: - foobar - foobar + Middleware23: + ipAllowList: + sourceRange: + - foobar + - foobar + ipStrategy: + depth: 42 + excludedIPs: + - foobar + - foobar serversTransports: ServersTransport0: serverName: foobar @@ -437,6 +447,11 @@ tcp: TCPMiddleware01: inFlightConn: amount: 42 + TCPMiddleware02: + ipAllowList: + sourceRange: + - foobar + - foobar udp: routers: UDPRouter0: diff --git a/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml b/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml index 07b7eb3da..960f98fe7 100644 --- a/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml +++ b/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml @@ -1151,7 +1151,7 @@ spec: properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration - used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/#ipstrategy' + used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -1176,14 +1176,43 @@ spec: type: boolean type: object type: object - ipWhiteList: - description: 'IPWhiteList holds the IP whitelist middleware configuration. + ipAllowList: + description: 'IPAllowList holds the IP allowlist middleware configuration. This middleware accepts / refuses requests based on the client IP. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/' + More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/' properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration used - by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/#ipstrategy' + by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' + properties: + depth: + description: Depth tells Traefik to use the X-Forwarded-For + header and take the IP located at the depth position (starting + from the right). + type: integer + excludedIPs: + description: ExcludedIPs configures Traefik to scan the X-Forwarded-For + header and select the first IP not in the list. + items: + type: string + type: array + type: object + sourceRange: + description: SourceRange defines the set of allowed IPs (or ranges + of allowed IPs by using CIDR notation). + items: + type: string + type: array + type: object + ipWhiteList: + description: 'IPWhiteList holds the IP whitelist middleware configuration. + This middleware accepts / refuses requests based on the client IP. + More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/ + Deprecated: please use IPAllowList instead.' + properties: + ipStrategy: + description: 'IPStrategy holds the IP strategy configuration used + by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -1347,7 +1376,7 @@ spec: properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration - used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/#ipstrategy' + used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -1535,8 +1564,22 @@ spec: format: int64 type: integer type: object + ipAllowList: + description: 'IPAllowList defines the IPAllowList middleware configuration. + This middleware accepts/refuses connections based on the client + IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipallowlist/' + properties: + sourceRange: + description: SourceRange defines the allowed IPs (or ranges of + allowed IPs by using CIDR notation). + items: + type: string + type: array + type: object ipWhiteList: - description: IPWhiteList defines the IPWhiteList middleware configuration. + description: 'IPWhiteList defines the IPWhiteList middleware configuration. + This middleware accepts/refuses connections based on the client + IP. Deprecated: please use IPAllowList instead. More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipwhitelist/' properties: sourceRange: description: SourceRange defines the allowed IPs (or ranges of @@ -3415,7 +3458,7 @@ spec: properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration - used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/#ipstrategy' + used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -3440,14 +3483,43 @@ spec: type: boolean type: object type: object - ipWhiteList: - description: 'IPWhiteList holds the IP whitelist middleware configuration. + ipAllowList: + description: 'IPAllowList holds the IP allowlist middleware configuration. This middleware accepts / refuses requests based on the client IP. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/' + More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/' properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration used - by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/#ipstrategy' + by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' + properties: + depth: + description: Depth tells Traefik to use the X-Forwarded-For + header and take the IP located at the depth position (starting + from the right). + type: integer + excludedIPs: + description: ExcludedIPs configures Traefik to scan the X-Forwarded-For + header and select the first IP not in the list. + items: + type: string + type: array + type: object + sourceRange: + description: SourceRange defines the set of allowed IPs (or ranges + of allowed IPs by using CIDR notation). + items: + type: string + type: array + type: object + ipWhiteList: + description: 'IPWhiteList holds the IP whitelist middleware configuration. + This middleware accepts / refuses requests based on the client IP. + More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/ + Deprecated: please use IPAllowList instead.' + properties: + ipStrategy: + description: 'IPStrategy holds the IP strategy configuration used + by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -3611,7 +3683,7 @@ spec: properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration - used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/#ipstrategy' + used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -3799,8 +3871,22 @@ spec: format: int64 type: integer type: object + ipAllowList: + description: 'IPAllowList defines the IPAllowList middleware configuration. + This middleware accepts/refuses connections based on the client + IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipallowlist/' + properties: + sourceRange: + description: SourceRange defines the allowed IPs (or ranges of + allowed IPs by using CIDR notation). + items: + type: string + type: array + type: object ipWhiteList: - description: IPWhiteList defines the IPWhiteList middleware configuration. + description: 'IPWhiteList defines the IPWhiteList middleware configuration. + This middleware accepts/refuses connections based on the client + IP. Deprecated: please use IPAllowList instead. More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipwhitelist/' properties: sourceRange: description: SourceRange defines the allowed IPs (or ranges of diff --git a/docs/content/reference/dynamic-configuration/kubernetes-crd-resource.yml b/docs/content/reference/dynamic-configuration/kubernetes-crd-resource.yml index a7fccce89..b1385cda2 100644 --- a/docs/content/reference/dynamic-configuration/kubernetes-crd-resource.yml +++ b/docs/content/reference/dynamic-configuration/kubernetes-crd-resource.yml @@ -148,7 +148,7 @@ spec: - name: whoamitcp port: 8080 middlewares: - - name: ipwhitelist + - name: ipallowlist tls: secretName: foosecret passthrough: false diff --git a/docs/content/reference/dynamic-configuration/kv-ref.md b/docs/content/reference/dynamic-configuration/kv-ref.md index c12162ccc..13029dd50 100644 --- a/docs/content/reference/dynamic-configuration/kv-ref.md +++ b/docs/content/reference/dynamic-configuration/kv-ref.md @@ -140,6 +140,11 @@ | `traefik/http/middlewares/Middleware21/stripPrefix/prefixes/1` | `foobar` | | `traefik/http/middlewares/Middleware22/stripPrefixRegex/regex/0` | `foobar` | | `traefik/http/middlewares/Middleware22/stripPrefixRegex/regex/1` | `foobar` | +| `traefik/http/middlewares/Middleware23/ipAllowList/ipStrategy/depth` | `42` | +| `traefik/http/middlewares/Middleware23/ipAllowList/ipStrategy/excludedIPs/0` | `foobar` | +| `traefik/http/middlewares/Middleware23/ipAllowList/ipStrategy/excludedIPs/1` | `foobar` | +| `traefik/http/middlewares/Middleware23/ipAllowList/sourceRange/0` | `foobar` | +| `traefik/http/middlewares/Middleware23/ipAllowList/sourceRange/1` | `foobar` | | `traefik/http/routers/Router0/entryPoints/0` | `foobar` | | `traefik/http/routers/Router0/entryPoints/1` | `foobar` | | `traefik/http/routers/Router0/middlewares/0` | `foobar` | diff --git a/docs/content/reference/dynamic-configuration/marathon-labels.json b/docs/content/reference/dynamic-configuration/marathon-labels.json index 5da004819..8d4768f8f 100644 --- a/docs/content/reference/dynamic-configuration/marathon-labels.json +++ b/docs/content/reference/dynamic-configuration/marathon-labels.json @@ -121,6 +121,9 @@ "traefik.http.middlewares.middleware21.stripprefix.forceslash": "true", "traefik.http.middlewares.middleware21.stripprefix.prefixes": "foobar, foobar", "traefik.http.middlewares.middleware22.stripprefixregex.regex": "foobar, foobar", +"traefik.http.middlewares.middleware23.ipallowlist.ipstrategy.depth": "42", +"traefik.http.middlewares.middleware23.ipallowlist.ipstrategy.excludedips": "foobar, foobar", +"traefik.http.middlewares.middleware23.ipallowlist.sourcerange": "foobar, foobar", "traefik.http.routers.router0.entrypoints": "foobar, foobar", "traefik.http.routers.router0.middlewares": "foobar, foobar", "traefik.http.routers.router0.priority": "42", @@ -167,6 +170,7 @@ "traefik.http.services.service01.loadbalancer.server.scheme": "foobar", "traefik.tcp.middlewares.tcpmiddleware00.ipwhitelist.sourcerange": "foobar, foobar", "traefik.tcp.middlewares.tcpmiddleware01.inflightconn.amount": "42", +"traefik.tcp.middlewares.tcpmiddleware02.ipallowlist.sourcerange": "foobar, foobar", "traefik.tcp.routers.tcprouter0.entrypoints": "foobar, foobar", "traefik.tcp.routers.tcprouter0.middlewares": "foobar, foobar", "traefik.tcp.routers.tcprouter0.rule": "foobar", diff --git a/docs/content/reference/dynamic-configuration/traefik.containo.us_middlewares.yaml b/docs/content/reference/dynamic-configuration/traefik.containo.us_middlewares.yaml index f96dafdc9..ad53a5e9a 100644 --- a/docs/content/reference/dynamic-configuration/traefik.containo.us_middlewares.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.containo.us_middlewares.yaml @@ -577,7 +577,7 @@ spec: properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration - used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/#ipstrategy' + used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -602,14 +602,43 @@ spec: type: boolean type: object type: object - ipWhiteList: - description: 'IPWhiteList holds the IP whitelist middleware configuration. + ipAllowList: + description: 'IPAllowList holds the IP allowlist middleware configuration. This middleware accepts / refuses requests based on the client IP. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/' + More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/' properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration used - by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/#ipstrategy' + by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' + properties: + depth: + description: Depth tells Traefik to use the X-Forwarded-For + header and take the IP located at the depth position (starting + from the right). + type: integer + excludedIPs: + description: ExcludedIPs configures Traefik to scan the X-Forwarded-For + header and select the first IP not in the list. + items: + type: string + type: array + type: object + sourceRange: + description: SourceRange defines the set of allowed IPs (or ranges + of allowed IPs by using CIDR notation). + items: + type: string + type: array + type: object + ipWhiteList: + description: 'IPWhiteList holds the IP whitelist middleware configuration. + This middleware accepts / refuses requests based on the client IP. + More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/ + Deprecated: please use IPAllowList instead.' + properties: + ipStrategy: + description: 'IPStrategy holds the IP strategy configuration used + by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -773,7 +802,7 @@ spec: properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration - used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/#ipstrategy' + used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For diff --git a/docs/content/reference/dynamic-configuration/traefik.containo.us_middlewaretcps.yaml b/docs/content/reference/dynamic-configuration/traefik.containo.us_middlewaretcps.yaml index 45ac8aee2..025dd2f7b 100644 --- a/docs/content/reference/dynamic-configuration/traefik.containo.us_middlewaretcps.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.containo.us_middlewaretcps.yaml @@ -45,8 +45,22 @@ spec: format: int64 type: integer type: object + ipAllowList: + description: 'IPAllowList defines the IPAllowList middleware configuration. + This middleware accepts/refuses connections based on the client + IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipallowlist/' + properties: + sourceRange: + description: SourceRange defines the allowed IPs (or ranges of + allowed IPs by using CIDR notation). + items: + type: string + type: array + type: object ipWhiteList: - description: IPWhiteList defines the IPWhiteList middleware configuration. + description: 'IPWhiteList defines the IPWhiteList middleware configuration. + This middleware accepts/refuses connections based on the client + IP. Deprecated: please use IPAllowList instead. More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipwhitelist/' properties: sourceRange: description: SourceRange defines the allowed IPs (or ranges of diff --git a/docs/content/reference/dynamic-configuration/traefik.io_middlewares.yaml b/docs/content/reference/dynamic-configuration/traefik.io_middlewares.yaml index 0ba7bb31b..868a8f3ac 100644 --- a/docs/content/reference/dynamic-configuration/traefik.io_middlewares.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.io_middlewares.yaml @@ -577,7 +577,7 @@ spec: properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration - used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/#ipstrategy' + used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -602,14 +602,43 @@ spec: type: boolean type: object type: object - ipWhiteList: - description: 'IPWhiteList holds the IP whitelist middleware configuration. + ipAllowList: + description: 'IPAllowList holds the IP allowlist middleware configuration. This middleware accepts / refuses requests based on the client IP. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/' + More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/' properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration used - by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/#ipstrategy' + by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' + properties: + depth: + description: Depth tells Traefik to use the X-Forwarded-For + header and take the IP located at the depth position (starting + from the right). + type: integer + excludedIPs: + description: ExcludedIPs configures Traefik to scan the X-Forwarded-For + header and select the first IP not in the list. + items: + type: string + type: array + type: object + sourceRange: + description: SourceRange defines the set of allowed IPs (or ranges + of allowed IPs by using CIDR notation). + items: + type: string + type: array + type: object + ipWhiteList: + description: 'IPWhiteList holds the IP whitelist middleware configuration. + This middleware accepts / refuses requests based on the client IP. + More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/ + Deprecated: please use IPAllowList instead.' + properties: + ipStrategy: + description: 'IPStrategy holds the IP strategy configuration used + by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -773,7 +802,7 @@ spec: properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration - used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/#ipstrategy' + used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For diff --git a/docs/content/reference/dynamic-configuration/traefik.io_middlewaretcps.yaml b/docs/content/reference/dynamic-configuration/traefik.io_middlewaretcps.yaml index cd2988194..3439ea445 100644 --- a/docs/content/reference/dynamic-configuration/traefik.io_middlewaretcps.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.io_middlewaretcps.yaml @@ -45,8 +45,22 @@ spec: format: int64 type: integer type: object + ipAllowList: + description: 'IPAllowList defines the IPAllowList middleware configuration. + This middleware accepts/refuses connections based on the client + IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipallowlist/' + properties: + sourceRange: + description: SourceRange defines the allowed IPs (or ranges of + allowed IPs by using CIDR notation). + items: + type: string + type: array + type: object ipWhiteList: - description: IPWhiteList defines the IPWhiteList middleware configuration. + description: 'IPWhiteList defines the IPWhiteList middleware configuration. + This middleware accepts/refuses connections based on the client + IP. Deprecated: please use IPAllowList instead. More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipwhitelist/' properties: sourceRange: description: SourceRange defines the allowed IPs (or ranges of diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index f588c1d80..05e913a2b 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -124,7 +124,8 @@ nav: - 'Errors': 'middlewares/http/errorpages.md' - 'ForwardAuth': 'middlewares/http/forwardauth.md' - 'Headers': 'middlewares/http/headers.md' - - 'IpWhitelist': 'middlewares/http/ipwhitelist.md' + - 'IPWhiteList': 'middlewares/http/ipwhitelist.md' + - 'IPAllowList': 'middlewares/http/ipallowlist.md' - 'InFlightReq': 'middlewares/http/inflightreq.md' - 'PassTLSClientCert': 'middlewares/http/passtlsclientcert.md' - 'RateLimit': 'middlewares/http/ratelimit.md' @@ -138,7 +139,8 @@ nav: - 'TCP': - 'Overview': 'middlewares/tcp/overview.md' - 'InFlightConn': 'middlewares/tcp/inflightconn.md' - - 'IpWhitelist': 'middlewares/tcp/ipwhitelist.md' + - 'IPWhiteList': 'middlewares/tcp/ipwhitelist.md' + - 'IPAllowList': 'middlewares/tcp/ipallowlist.md' - 'Plugins & Plugin Catalog': 'plugins/index.md' - 'Operations': - 'CLI': 'operations/cli.md' diff --git a/integration/fixtures/k8s/01-traefik-crd.yml b/integration/fixtures/k8s/01-traefik-crd.yml index 07b7eb3da..960f98fe7 100644 --- a/integration/fixtures/k8s/01-traefik-crd.yml +++ b/integration/fixtures/k8s/01-traefik-crd.yml @@ -1151,7 +1151,7 @@ spec: properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration - used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/#ipstrategy' + used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -1176,14 +1176,43 @@ spec: type: boolean type: object type: object - ipWhiteList: - description: 'IPWhiteList holds the IP whitelist middleware configuration. + ipAllowList: + description: 'IPAllowList holds the IP allowlist middleware configuration. This middleware accepts / refuses requests based on the client IP. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/' + More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/' properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration used - by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/#ipstrategy' + by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' + properties: + depth: + description: Depth tells Traefik to use the X-Forwarded-For + header and take the IP located at the depth position (starting + from the right). + type: integer + excludedIPs: + description: ExcludedIPs configures Traefik to scan the X-Forwarded-For + header and select the first IP not in the list. + items: + type: string + type: array + type: object + sourceRange: + description: SourceRange defines the set of allowed IPs (or ranges + of allowed IPs by using CIDR notation). + items: + type: string + type: array + type: object + ipWhiteList: + description: 'IPWhiteList holds the IP whitelist middleware configuration. + This middleware accepts / refuses requests based on the client IP. + More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/ + Deprecated: please use IPAllowList instead.' + properties: + ipStrategy: + description: 'IPStrategy holds the IP strategy configuration used + by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -1347,7 +1376,7 @@ spec: properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration - used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/#ipstrategy' + used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -1535,8 +1564,22 @@ spec: format: int64 type: integer type: object + ipAllowList: + description: 'IPAllowList defines the IPAllowList middleware configuration. + This middleware accepts/refuses connections based on the client + IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipallowlist/' + properties: + sourceRange: + description: SourceRange defines the allowed IPs (or ranges of + allowed IPs by using CIDR notation). + items: + type: string + type: array + type: object ipWhiteList: - description: IPWhiteList defines the IPWhiteList middleware configuration. + description: 'IPWhiteList defines the IPWhiteList middleware configuration. + This middleware accepts/refuses connections based on the client + IP. Deprecated: please use IPAllowList instead. More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipwhitelist/' properties: sourceRange: description: SourceRange defines the allowed IPs (or ranges of @@ -3415,7 +3458,7 @@ spec: properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration - used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/#ipstrategy' + used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -3440,14 +3483,43 @@ spec: type: boolean type: object type: object - ipWhiteList: - description: 'IPWhiteList holds the IP whitelist middleware configuration. + ipAllowList: + description: 'IPAllowList holds the IP allowlist middleware configuration. This middleware accepts / refuses requests based on the client IP. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/' + More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/' properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration used - by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/#ipstrategy' + by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' + properties: + depth: + description: Depth tells Traefik to use the X-Forwarded-For + header and take the IP located at the depth position (starting + from the right). + type: integer + excludedIPs: + description: ExcludedIPs configures Traefik to scan the X-Forwarded-For + header and select the first IP not in the list. + items: + type: string + type: array + type: object + sourceRange: + description: SourceRange defines the set of allowed IPs (or ranges + of allowed IPs by using CIDR notation). + items: + type: string + type: array + type: object + ipWhiteList: + description: 'IPWhiteList holds the IP whitelist middleware configuration. + This middleware accepts / refuses requests based on the client IP. + More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/ + Deprecated: please use IPAllowList instead.' + properties: + ipStrategy: + description: 'IPStrategy holds the IP strategy configuration used + by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -3611,7 +3683,7 @@ spec: properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration - used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/#ipstrategy' + used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -3799,8 +3871,22 @@ spec: format: int64 type: integer type: object + ipAllowList: + description: 'IPAllowList defines the IPAllowList middleware configuration. + This middleware accepts/refuses connections based on the client + IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipallowlist/' + properties: + sourceRange: + description: SourceRange defines the allowed IPs (or ranges of + allowed IPs by using CIDR notation). + items: + type: string + type: array + type: object ipWhiteList: - description: IPWhiteList defines the IPWhiteList middleware configuration. + description: 'IPWhiteList defines the IPWhiteList middleware configuration. + This middleware accepts/refuses connections based on the client + IP. Deprecated: please use IPAllowList instead. More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipwhitelist/' properties: sourceRange: description: SourceRange defines the allowed IPs (or ranges of diff --git a/integration/fixtures/simple_allowlist.toml b/integration/fixtures/simple_allowlist.toml new file mode 100644 index 000000000..03fa451e4 --- /dev/null +++ b/integration/fixtures/simple_allowlist.toml @@ -0,0 +1,18 @@ +[global] + checkNewVersion = false + sendAnonymousUsage = false + +[log] + level = "DEBUG" + +[entryPoints] + [entryPoints.web] + address = ":8000" + [entryPoints.web.ForwardedHeaders] + insecure = true + +[api] + insecure = true + +[providers] + [providers.docker] diff --git a/integration/resources/compose/allowlist.yml b/integration/resources/compose/allowlist.yml new file mode 100644 index 000000000..02e3761ca --- /dev/null +++ b/integration/resources/compose/allowlist.yml @@ -0,0 +1,41 @@ +version: "3.8" +services: + noOverrideAllowlist: + image: traefik/whoami + labels: + traefik.enable: true + traefik.http.routers.rt1.rule: Host(`no.override.allowlist.docker.local`) + traefik.http.routers.rt1.middlewares: wl1 + traefik.http.middlewares.wl1.ipallowlist.sourceRange: 8.8.8.8 + + overrideIPStrategyRemoteAddrAllowlist: + image: traefik/whoami + labels: + traefik.enable: true + traefik.http.routers.rt2.rule: Host(`override.remoteaddr.allowlist.docker.local`) + traefik.http.routers.rt2.middlewares: wl2 + traefik.http.middlewares.wl2.ipallowlist.sourceRange: 8.8.8.8 + traefik.http.middlewares.wl2.ipallowlist.ipStrategy: true + + overrideIPStrategyDepthAllowlist: + image: traefik/whoami + labels: + traefik.enable: true + traefik.http.routers.rt3.rule: Host(`override.depth.allowlist.docker.local`) + traefik.http.routers.rt3.middlewares: wl3 + traefik.http.middlewares.wl3.ipallowlist.sourceRange: 8.8.8.8 + traefik.http.middlewares.wl3.ipallowlist.ipStrategy.depth: 3 + + overrideIPStrategyExcludedIPsAllowlist: + image: traefik/whoami + labels: + traefik.enable: true + traefik.http.routers.rt4.rule: Host(`override.excludedips.allowlist.docker.local`) + traefik.http.routers.rt4.middlewares: wl4 + traefik.http.middlewares.wl4.ipallowlist.sourceRange: 8.8.8.8 + traefik.http.middlewares.wl4.ipallowlist.ipStrategy.excludedIPs: 10.0.0.1,10.0.0.2 + +networks: + default: + name: traefik-test-network + external: true diff --git a/integration/simple_test.go b/integration/simple_test.go index f88afb9e4..3284a5a81 100644 --- a/integration/simple_test.go +++ b/integration/simple_test.go @@ -546,6 +546,76 @@ func (s *SimpleSuite) TestIPStrategyWhitelist(c *check.C) { } } +func (s *SimpleSuite) TestIPStrategyAllowlist(c *check.C) { + s.createComposeProject(c, "allowlist") + + s.composeUp(c) + defer s.composeDown(c) + + cmd, output := s.traefikCmd(withConfigFile("fixtures/simple_allowlist.toml")) + defer output(c) + + err := cmd.Start() + c.Assert(err, checker.IsNil) + defer s.killCmd(cmd) + + err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2*time.Second, try.BodyContains("override")) + c.Assert(err, checker.IsNil) + + err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2*time.Second, try.BodyContains("override.remoteaddr.allowlist.docker.local")) + c.Assert(err, checker.IsNil) + + testCases := []struct { + desc string + xForwardedFor string + host string + expectedStatusCode int + }{ + { + desc: "override remote addr reject", + xForwardedFor: "8.8.8.8,8.8.8.8", + host: "override.remoteaddr.allowlist.docker.local", + expectedStatusCode: 403, + }, + { + desc: "override depth accept", + xForwardedFor: "8.8.8.8,10.0.0.1,127.0.0.1", + host: "override.depth.allowlist.docker.local", + expectedStatusCode: 200, + }, + { + desc: "override depth reject", + xForwardedFor: "10.0.0.1,8.8.8.8,127.0.0.1", + host: "override.depth.allowlist.docker.local", + expectedStatusCode: 403, + }, + { + desc: "override excludedIPs reject", + xForwardedFor: "10.0.0.3,10.0.0.1,10.0.0.2", + host: "override.excludedips.allowlist.docker.local", + expectedStatusCode: 403, + }, + { + desc: "override excludedIPs accept", + xForwardedFor: "8.8.8.8,10.0.0.1,10.0.0.2", + host: "override.excludedips.allowlist.docker.local", + expectedStatusCode: 200, + }, + } + + for _, test := range testCases { + req := httptest.NewRequest(http.MethodGet, "http://127.0.0.1:8000", nil) + req.Header.Set("X-Forwarded-For", test.xForwardedFor) + req.Host = test.host + req.RequestURI = "" + + err = try.Request(req, 1*time.Second, try.StatusCodeIs(test.expectedStatusCode)) + if err != nil { + c.Fatalf("Error while %s: %v", test.desc, err) + } + } +} + func (s *SimpleSuite) TestXForwardedHeaders(c *check.C) { s.createComposeProject(c, "whitelist") diff --git a/pkg/config/dynamic/middlewares.go b/pkg/config/dynamic/middlewares.go index c2ec1ba44..714c459a6 100644 --- a/pkg/config/dynamic/middlewares.go +++ b/pkg/config/dynamic/middlewares.go @@ -19,6 +19,7 @@ type Middleware struct { ReplacePathRegex *ReplacePathRegex `json:"replacePathRegex,omitempty" toml:"replacePathRegex,omitempty" yaml:"replacePathRegex,omitempty" export:"true"` Chain *Chain `json:"chain,omitempty" toml:"chain,omitempty" yaml:"chain,omitempty" export:"true"` IPWhiteList *IPWhiteList `json:"ipWhiteList,omitempty" toml:"ipWhiteList,omitempty" yaml:"ipWhiteList,omitempty" export:"true"` + IPAllowList *IPAllowList `json:"ipAllowList,omitempty" toml:"ipAllowList,omitempty" yaml:"ipAllowList,omitempty" export:"true"` Headers *Headers `json:"headers,omitempty" toml:"headers,omitempty" yaml:"headers,omitempty" export:"true"` Errors *ErrorPage `json:"errors,omitempty" toml:"errors,omitempty" yaml:"errors,omitempty" export:"true"` RateLimit *RateLimit `json:"rateLimit,omitempty" toml:"rateLimit,omitempty" yaml:"rateLimit,omitempty" export:"true"` @@ -346,7 +347,7 @@ func (h *Headers) HasSecureHeadersDefined() bool { // +k8s:deepcopy-gen=true // IPStrategy holds the IP strategy configuration used by Traefik to determine the client IP. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/#ipstrategy +// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy type IPStrategy struct { // Depth tells Traefik to use the X-Forwarded-For header and take the IP located at the depth position (starting from the right). Depth int `json:"depth,omitempty" toml:"depth,omitempty" yaml:"depth,omitempty" export:"true"` @@ -388,6 +389,7 @@ func (s *IPStrategy) Get() (ip.Strategy, error) { // IPWhiteList holds the IP whitelist middleware configuration. // This middleware accepts / refuses requests based on the client IP. // More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/ +// Deprecated: please use IPAllowList instead. type IPWhiteList struct { // SourceRange defines the set of allowed IPs (or ranges of allowed IPs by using CIDR notation). SourceRange []string `json:"sourceRange,omitempty" toml:"sourceRange,omitempty" yaml:"sourceRange,omitempty"` @@ -396,6 +398,17 @@ type IPWhiteList struct { // +k8s:deepcopy-gen=true +// IPAllowList holds the IP allowlist middleware configuration. +// This middleware accepts / refuses requests based on the client IP. +// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/ +type IPAllowList struct { + // SourceRange defines the set of allowed IPs (or ranges of allowed IPs by using CIDR notation). + SourceRange []string `json:"sourceRange,omitempty" toml:"sourceRange,omitempty" yaml:"sourceRange,omitempty"` + IPStrategy *IPStrategy `json:"ipStrategy,omitempty" toml:"ipStrategy,omitempty" yaml:"ipStrategy,omitempty" label:"allowEmpty" file:"allowEmpty" kv:"allowEmpty" export:"true"` +} + +// +k8s:deepcopy-gen=true + // InFlightReq holds the in-flight request middleware configuration. // This middleware limits the number of requests being processed and served concurrently. // More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/inflightreq/ diff --git a/pkg/config/dynamic/tcp_middlewares.go b/pkg/config/dynamic/tcp_middlewares.go index e0cf31919..f4052cd82 100644 --- a/pkg/config/dynamic/tcp_middlewares.go +++ b/pkg/config/dynamic/tcp_middlewares.go @@ -6,6 +6,7 @@ package dynamic type TCPMiddleware struct { InFlightConn *TCPInFlightConn `json:"inFlightConn,omitempty" toml:"inFlightConn,omitempty" yaml:"inFlightConn,omitempty" export:"true"` IPWhiteList *TCPIPWhiteList `json:"ipWhiteList,omitempty" toml:"ipWhiteList,omitempty" yaml:"ipWhiteList,omitempty" export:"true"` + IPAllowList *TCPIPAllowList `json:"ipAllowList,omitempty" toml:"ipAllowList,omitempty" yaml:"ipAllowList,omitempty" export:"true"` } // +k8s:deepcopy-gen=true @@ -23,8 +24,15 @@ type TCPInFlightConn struct { // +k8s:deepcopy-gen=true // TCPIPWhiteList holds the TCP IPWhiteList middleware configuration. -// This middleware accepts/refuses connections based on the client IP. type TCPIPWhiteList struct { // SourceRange defines the allowed IPs (or ranges of allowed IPs by using CIDR notation). SourceRange []string `json:"sourceRange,omitempty" toml:"sourceRange,omitempty" yaml:"sourceRange,omitempty"` } + +// +k8s:deepcopy-gen=true + +// TCPIPAllowList holds the TCP IPAllowList middleware configuration. +type TCPIPAllowList struct { + // SourceRange defines the allowed IPs (or ranges of allowed IPs by using CIDR notation). + SourceRange []string `json:"sourceRange,omitempty" toml:"sourceRange,omitempty" yaml:"sourceRange,omitempty"` +} diff --git a/pkg/config/dynamic/zz_generated.deepcopy.go b/pkg/config/dynamic/zz_generated.deepcopy.go index f897f6f31..fee40799c 100644 --- a/pkg/config/dynamic/zz_generated.deepcopy.go +++ b/pkg/config/dynamic/zz_generated.deepcopy.go @@ -532,6 +532,32 @@ func (in *HealthCheck) DeepCopy() *HealthCheck { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IPAllowList) DeepCopyInto(out *IPAllowList) { + *out = *in + if in.SourceRange != nil { + in, out := &in.SourceRange, &out.SourceRange + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.IPStrategy != nil { + in, out := &in.IPStrategy, &out.IPStrategy + *out = new(IPStrategy) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IPAllowList. +func (in *IPAllowList) DeepCopy() *IPAllowList { + if in == nil { + return nil + } + out := new(IPAllowList) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *IPStrategy) DeepCopyInto(out *IPStrategy) { *out = *in @@ -659,6 +685,11 @@ func (in *Middleware) DeepCopyInto(out *Middleware) { *out = new(IPWhiteList) (*in).DeepCopyInto(*out) } + if in.IPAllowList != nil { + in, out := &in.IPAllowList, &out.IPAllowList + *out = new(IPAllowList) + (*in).DeepCopyInto(*out) + } if in.Headers != nil { in, out := &in.Headers, &out.Headers *out = new(Headers) @@ -1355,6 +1386,27 @@ func (in *TCPConfiguration) DeepCopy() *TCPConfiguration { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TCPIPAllowList) DeepCopyInto(out *TCPIPAllowList) { + *out = *in + if in.SourceRange != nil { + in, out := &in.SourceRange, &out.SourceRange + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TCPIPAllowList. +func (in *TCPIPAllowList) DeepCopy() *TCPIPAllowList { + if in == nil { + return nil + } + out := new(TCPIPAllowList) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TCPIPWhiteList) DeepCopyInto(out *TCPIPWhiteList) { *out = *in @@ -1405,6 +1457,11 @@ func (in *TCPMiddleware) DeepCopyInto(out *TCPMiddleware) { *out = new(TCPIPWhiteList) (*in).DeepCopyInto(*out) } + if in.IPAllowList != nil { + in, out := &in.IPAllowList, &out.IPAllowList + *out = new(TCPIPAllowList) + (*in).DeepCopyInto(*out) + } return } diff --git a/pkg/middlewares/ipallowlist/ip_allowlist.go b/pkg/middlewares/ipallowlist/ip_allowlist.go new file mode 100644 index 000000000..d700a9279 --- /dev/null +++ b/pkg/middlewares/ipallowlist/ip_allowlist.go @@ -0,0 +1,88 @@ +package ipallowlist + +import ( + "context" + "errors" + "fmt" + "net/http" + + "github.com/opentracing/opentracing-go/ext" + "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v2/pkg/ip" + "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/middlewares" + "github.com/traefik/traefik/v2/pkg/tracing" +) + +const ( + typeName = "IPAllowLister" +) + +// ipAllowLister is a middleware that provides Checks of the Requesting IP against a set of Allowlists. +type ipAllowLister struct { + next http.Handler + allowLister *ip.Checker + strategy ip.Strategy + name string +} + +// New builds a new IPAllowLister given a list of CIDR-Strings to allow. +func New(ctx context.Context, next http.Handler, config dynamic.IPAllowList, name string) (http.Handler, error) { + logger := log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)) + logger.Debug("Creating middleware") + + if len(config.SourceRange) == 0 { + return nil, errors.New("sourceRange is empty, IPAllowLister not created") + } + + checker, err := ip.NewChecker(config.SourceRange) + if err != nil { + return nil, fmt.Errorf("cannot parse CIDRs %s: %w", config.SourceRange, err) + } + + strategy, err := config.IPStrategy.Get() + if err != nil { + return nil, err + } + + logger.Debugf("Setting up IPAllowLister with sourceRange: %s", config.SourceRange) + + return &ipAllowLister{ + strategy: strategy, + allowLister: checker, + next: next, + name: name, + }, nil +} + +func (al *ipAllowLister) GetTracingInformation() (string, ext.SpanKindEnum) { + return al.name, tracing.SpanKindNoneEnum +} + +func (al *ipAllowLister) ServeHTTP(rw http.ResponseWriter, req *http.Request) { + ctx := middlewares.GetLoggerCtx(req.Context(), al.name, typeName) + logger := log.FromContext(ctx) + + clientIP := al.strategy.GetIP(req) + err := al.allowLister.IsAuthorized(clientIP) + if err != nil { + msg := fmt.Sprintf("Rejecting IP %s: %v", clientIP, err) + logger.Debug(msg) + tracing.SetErrorWithEvent(req, msg) + reject(ctx, rw) + return + } + logger.Debugf("Accepting IP %s", clientIP) + + al.next.ServeHTTP(rw, req) +} + +func reject(ctx context.Context, rw http.ResponseWriter) { + statusCode := http.StatusForbidden + + rw.WriteHeader(statusCode) + _, err := rw.Write([]byte(http.StatusText(statusCode))) + if err != nil { + log.FromContext(ctx).Error(err) + } +} diff --git a/pkg/middlewares/ipallowlist/ip_allowlist_test.go b/pkg/middlewares/ipallowlist/ip_allowlist_test.go new file mode 100644 index 000000000..df2e49835 --- /dev/null +++ b/pkg/middlewares/ipallowlist/ip_allowlist_test.go @@ -0,0 +1,100 @@ +package ipallowlist + +import ( + "context" + "net/http" + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/traefik/traefik/v2/pkg/config/dynamic" +) + +func TestNewIPAllowLister(t *testing.T) { + testCases := []struct { + desc string + allowList dynamic.IPAllowList + expectedError bool + }{ + { + desc: "invalid IP", + allowList: dynamic.IPAllowList{ + SourceRange: []string{"foo"}, + }, + expectedError: true, + }, + { + desc: "valid IP", + allowList: dynamic.IPAllowList{ + SourceRange: []string{"10.10.10.10"}, + }, + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + next := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}) + allowLister, err := New(context.Background(), next, test.allowList, "traefikTest") + + if test.expectedError { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.NotNil(t, allowLister) + } + }) + } +} + +func TestIPAllowLister_ServeHTTP(t *testing.T) { + testCases := []struct { + desc string + allowList dynamic.IPAllowList + remoteAddr string + expected int + }{ + { + desc: "authorized with remote address", + allowList: dynamic.IPAllowList{ + SourceRange: []string{"20.20.20.20"}, + }, + remoteAddr: "20.20.20.20:1234", + expected: 200, + }, + { + desc: "non authorized with remote address", + allowList: dynamic.IPAllowList{ + SourceRange: []string{"20.20.20.20"}, + }, + remoteAddr: "20.20.20.21:1234", + expected: 403, + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + next := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}) + allowLister, err := New(context.Background(), next, test.allowList, "traefikTest") + require.NoError(t, err) + + recorder := httptest.NewRecorder() + + req := httptest.NewRequest(http.MethodGet, "http://10.10.10.10", nil) + + if len(test.remoteAddr) > 0 { + req.RemoteAddr = test.remoteAddr + } + + allowLister.ServeHTTP(recorder, req) + + assert.Equal(t, test.expected, recorder.Code) + }) + } +} diff --git a/pkg/middlewares/tcp/ipallowlist/ip_allowlist.go b/pkg/middlewares/tcp/ipallowlist/ip_allowlist.go new file mode 100644 index 000000000..dd5d14d43 --- /dev/null +++ b/pkg/middlewares/tcp/ipallowlist/ip_allowlist.go @@ -0,0 +1,65 @@ +package ipallowlist + +import ( + "context" + "errors" + "fmt" + + "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v2/pkg/ip" + "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/middlewares" + "github.com/traefik/traefik/v2/pkg/tcp" +) + +const ( + typeName = "IPAllowListerTCP" +) + +// ipAllowLister is a middleware that provides Checks of the Requesting IP against a set of Allowlists. +type ipAllowLister struct { + next tcp.Handler + allowLister *ip.Checker + name string +} + +// New builds a new TCP IPAllowLister given a list of CIDR-Strings to allow. +func New(ctx context.Context, next tcp.Handler, config dynamic.TCPIPAllowList, name string) (tcp.Handler, error) { + logger := log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)) + logger.Debug("Creating middleware") + + if len(config.SourceRange) == 0 { + return nil, errors.New("sourceRange is empty, IPAllowLister not created") + } + + checker, err := ip.NewChecker(config.SourceRange) + if err != nil { + return nil, fmt.Errorf("cannot parse CIDRs %s: %w", config.SourceRange, err) + } + + logger.Debugf("Setting up IPAllowLister with sourceRange: %s", config.SourceRange) + + return &ipAllowLister{ + allowLister: checker, + next: next, + name: name, + }, nil +} + +func (al *ipAllowLister) ServeTCP(conn tcp.WriteCloser) { + ctx := middlewares.GetLoggerCtx(context.Background(), al.name, typeName) + logger := log.FromContext(ctx) + + addr := conn.RemoteAddr().String() + + err := al.allowLister.IsAuthorized(addr) + if err != nil { + logger.Errorf("Connection from %s rejected: %v", addr, err) + conn.Close() + return + } + + logger.Debugf("Connection from %s accepted", addr) + + al.next.ServeTCP(conn) +} diff --git a/pkg/middlewares/tcp/ipallowlist/ip_allowlist_test.go b/pkg/middlewares/tcp/ipallowlist/ip_allowlist_test.go new file mode 100644 index 000000000..4f3b59e15 --- /dev/null +++ b/pkg/middlewares/tcp/ipallowlist/ip_allowlist_test.go @@ -0,0 +1,139 @@ +package ipallowlist + +import ( + "context" + "io" + "net" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v2/pkg/tcp" +) + +func TestNewIPAllowLister(t *testing.T) { + testCases := []struct { + desc string + allowList dynamic.TCPIPAllowList + expectedError bool + }{ + { + desc: "Empty config", + allowList: dynamic.TCPIPAllowList{}, + expectedError: true, + }, + { + desc: "invalid IP", + allowList: dynamic.TCPIPAllowList{ + SourceRange: []string{"foo"}, + }, + expectedError: true, + }, + { + desc: "valid IP", + allowList: dynamic.TCPIPAllowList{ + SourceRange: []string{"10.10.10.10"}, + }, + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + next := tcp.HandlerFunc(func(conn tcp.WriteCloser) {}) + allowLister, err := New(context.Background(), next, test.allowList, "traefikTest") + + if test.expectedError { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.NotNil(t, allowLister) + } + }) + } +} + +func TestIPAllowLister_ServeHTTP(t *testing.T) { + testCases := []struct { + desc string + allowList dynamic.TCPIPAllowList + remoteAddr string + expected string + }{ + { + desc: "authorized with remote address", + allowList: dynamic.TCPIPAllowList{ + SourceRange: []string{"20.20.20.20"}, + }, + remoteAddr: "20.20.20.20:1234", + expected: "OK", + }, + { + desc: "non authorized with remote address", + allowList: dynamic.TCPIPAllowList{ + SourceRange: []string{"20.20.20.20"}, + }, + remoteAddr: "20.20.20.21:1234", + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + next := tcp.HandlerFunc(func(conn tcp.WriteCloser) { + write, err := conn.Write([]byte("OK")) + require.NoError(t, err) + assert.Equal(t, 2, write) + + err = conn.Close() + require.NoError(t, err) + }) + + allowLister, err := New(context.Background(), next, test.allowList, "traefikTest") + require.NoError(t, err) + + server, client := net.Pipe() + + go func() { + allowLister.ServeTCP(&contextWriteCloser{client, addr{test.remoteAddr}}) + }() + + read, err := io.ReadAll(server) + require.NoError(t, err) + + assert.Equal(t, test.expected, string(read)) + }) + } +} + +type contextWriteCloser struct { + net.Conn + addr +} + +type addr struct { + remoteAddr string +} + +func (a addr) Network() string { + panic("implement me") +} + +func (a addr) String() string { + return a.remoteAddr +} + +func (c contextWriteCloser) CloseWrite() error { + panic("implement me") +} + +func (c contextWriteCloser) RemoteAddr() net.Addr { return c.addr } + +func (c contextWriteCloser) Context() context.Context { + return context.Background() +} diff --git a/pkg/provider/kubernetes/crd/kubernetes.go b/pkg/provider/kubernetes/crd/kubernetes.go index 2759055ef..03807ac9c 100644 --- a/pkg/provider/kubernetes/crd/kubernetes.go +++ b/pkg/provider/kubernetes/crd/kubernetes.go @@ -288,6 +288,7 @@ func (p *Provider) loadConfigurationFromCRD(ctx context.Context, client Client) ReplacePathRegex: middleware.Spec.ReplacePathRegex, Chain: createChainMiddleware(ctxMid, middleware.Namespace, middleware.Spec.Chain), IPWhiteList: middleware.Spec.IPWhiteList, + IPAllowList: middleware.Spec.IPAllowList, Headers: middleware.Spec.Headers, Errors: errorPage, RateLimit: rateLimit, @@ -313,6 +314,7 @@ func (p *Provider) loadConfigurationFromCRD(ctx context.Context, client Client) conf.TCP.Middlewares[id] = &dynamic.TCPMiddleware{ InFlightConn: middlewareTCP.Spec.InFlightConn, IPWhiteList: middlewareTCP.Spec.IPWhiteList, + IPAllowList: middlewareTCP.Spec.IPAllowList, } } diff --git a/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/middleware.go b/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/middleware.go index 54dbe07e6..65b969540 100644 --- a/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/middleware.go +++ b/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/middleware.go @@ -33,6 +33,7 @@ type MiddlewareSpec struct { ReplacePathRegex *dynamic.ReplacePathRegex `json:"replacePathRegex,omitempty"` Chain *Chain `json:"chain,omitempty"` IPWhiteList *dynamic.IPWhiteList `json:"ipWhiteList,omitempty"` + IPAllowList *dynamic.IPAllowList `json:"ipAllowList,omitempty"` Headers *dynamic.Headers `json:"headers,omitempty"` Errors *ErrorPage `json:"errors,omitempty"` RateLimit *RateLimit `json:"rateLimit,omitempty"` diff --git a/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/middlewaretcp.go b/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/middlewaretcp.go index c903a8ca7..923c3d404 100644 --- a/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/middlewaretcp.go +++ b/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/middlewaretcp.go @@ -26,7 +26,14 @@ type MiddlewareTCPSpec struct { // InFlightConn defines the InFlightConn middleware configuration. InFlightConn *dynamic.TCPInFlightConn `json:"inFlightConn,omitempty"` // IPWhiteList defines the IPWhiteList middleware configuration. + // This middleware accepts/refuses connections based on the client IP. + // Deprecated: please use IPAllowList instead. + // More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipwhitelist/ IPWhiteList *dynamic.TCPIPWhiteList `json:"ipWhiteList,omitempty"` + // IPAllowList defines the IPAllowList middleware configuration. + // This middleware accepts/refuses connections based on the client IP. + // More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipallowlist/ + IPAllowList *dynamic.TCPIPAllowList `json:"ipAllowList,omitempty"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/zz_generated.deepcopy.go b/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/zz_generated.deepcopy.go index a91c5cfc1..0b0126432 100644 --- a/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/zz_generated.deepcopy.go @@ -694,6 +694,11 @@ func (in *MiddlewareSpec) DeepCopyInto(out *MiddlewareSpec) { *out = new(dynamic.IPWhiteList) (*in).DeepCopyInto(*out) } + if in.IPAllowList != nil { + in, out := &in.IPAllowList, &out.IPAllowList + *out = new(dynamic.IPAllowList) + (*in).DeepCopyInto(*out) + } if in.Headers != nil { in, out := &in.Headers, &out.Headers *out = new(dynamic.Headers) @@ -862,6 +867,11 @@ func (in *MiddlewareTCPSpec) DeepCopyInto(out *MiddlewareTCPSpec) { *out = new(dynamic.TCPIPWhiteList) (*in).DeepCopyInto(*out) } + if in.IPAllowList != nil { + in, out := &in.IPAllowList, &out.IPAllowList + *out = new(dynamic.TCPIPAllowList) + (*in).DeepCopyInto(*out) + } return } diff --git a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/middleware.go b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/middleware.go index 54dbe07e6..65b969540 100644 --- a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/middleware.go +++ b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/middleware.go @@ -33,6 +33,7 @@ type MiddlewareSpec struct { ReplacePathRegex *dynamic.ReplacePathRegex `json:"replacePathRegex,omitempty"` Chain *Chain `json:"chain,omitempty"` IPWhiteList *dynamic.IPWhiteList `json:"ipWhiteList,omitempty"` + IPAllowList *dynamic.IPAllowList `json:"ipAllowList,omitempty"` Headers *dynamic.Headers `json:"headers,omitempty"` Errors *ErrorPage `json:"errors,omitempty"` RateLimit *RateLimit `json:"rateLimit,omitempty"` diff --git a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/middlewaretcp.go b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/middlewaretcp.go index c903a8ca7..923c3d404 100644 --- a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/middlewaretcp.go +++ b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/middlewaretcp.go @@ -26,7 +26,14 @@ type MiddlewareTCPSpec struct { // InFlightConn defines the InFlightConn middleware configuration. InFlightConn *dynamic.TCPInFlightConn `json:"inFlightConn,omitempty"` // IPWhiteList defines the IPWhiteList middleware configuration. + // This middleware accepts/refuses connections based on the client IP. + // Deprecated: please use IPAllowList instead. + // More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipwhitelist/ IPWhiteList *dynamic.TCPIPWhiteList `json:"ipWhiteList,omitempty"` + // IPAllowList defines the IPAllowList middleware configuration. + // This middleware accepts/refuses connections based on the client IP. + // More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipallowlist/ + IPAllowList *dynamic.TCPIPAllowList `json:"ipAllowList,omitempty"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/zz_generated.deepcopy.go b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/zz_generated.deepcopy.go index a91c5cfc1..0b0126432 100644 --- a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/zz_generated.deepcopy.go @@ -694,6 +694,11 @@ func (in *MiddlewareSpec) DeepCopyInto(out *MiddlewareSpec) { *out = new(dynamic.IPWhiteList) (*in).DeepCopyInto(*out) } + if in.IPAllowList != nil { + in, out := &in.IPAllowList, &out.IPAllowList + *out = new(dynamic.IPAllowList) + (*in).DeepCopyInto(*out) + } if in.Headers != nil { in, out := &in.Headers, &out.Headers *out = new(dynamic.Headers) @@ -862,6 +867,11 @@ func (in *MiddlewareTCPSpec) DeepCopyInto(out *MiddlewareTCPSpec) { *out = new(dynamic.TCPIPWhiteList) (*in).DeepCopyInto(*out) } + if in.IPAllowList != nil { + in, out := &in.IPAllowList, &out.IPAllowList + *out = new(dynamic.TCPIPAllowList) + (*in).DeepCopyInto(*out) + } return } diff --git a/pkg/server/middleware/middlewares.go b/pkg/server/middleware/middlewares.go index 0f666c996..073843472 100644 --- a/pkg/server/middleware/middlewares.go +++ b/pkg/server/middleware/middlewares.go @@ -10,6 +10,7 @@ import ( "github.com/containous/alice" "github.com/traefik/traefik/v2/pkg/config/runtime" + "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/middlewares/addprefix" "github.com/traefik/traefik/v2/pkg/middlewares/auth" "github.com/traefik/traefik/v2/pkg/middlewares/buffering" @@ -19,6 +20,7 @@ import ( "github.com/traefik/traefik/v2/pkg/middlewares/customerrors" "github.com/traefik/traefik/v2/pkg/middlewares/headers" "github.com/traefik/traefik/v2/pkg/middlewares/inflightreq" + "github.com/traefik/traefik/v2/pkg/middlewares/ipallowlist" "github.com/traefik/traefik/v2/pkg/middlewares/ipwhitelist" "github.com/traefik/traefik/v2/pkg/middlewares/passtlsclientcert" "github.com/traefik/traefik/v2/pkg/middlewares/ratelimiter" @@ -231,6 +233,8 @@ func (b *Builder) buildConstructor(ctx context.Context, middlewareName string) ( // IPWhiteList if config.IPWhiteList != nil { + log.FromContext(ctx).Warn("IPWhiteList is deprecated, please use IPAllowList instead.") + if middleware != nil { return nil, badConf } @@ -239,6 +243,16 @@ func (b *Builder) buildConstructor(ctx context.Context, middlewareName string) ( } } + // IPAllowList + if config.IPAllowList != nil { + if middleware != nil { + return nil, badConf + } + middleware = func(next http.Handler) (http.Handler, error) { + return ipallowlist.New(ctx, next, *config.IPAllowList, middlewareName) + } + } + // InFlightReq if config.InFlightReq != nil { if middleware != nil {