feat: re introduce IpWhitelist middleware as deprecated

This commit is contained in:
Michael 2024-01-11 10:40:06 +01:00 committed by GitHub
parent 3bbc560283
commit ff7966f9cd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
38 changed files with 1314 additions and 200 deletions

View file

@ -1192,6 +1192,32 @@ spec:
type: string
type: array
type: object
ipWhiteList:
description: '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/v3.0/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
passTLSClientCert:
description: 'PassTLSClientCert holds the pass TLS client cert middleware
configuration. This middleware adds the selected data from the passed
@ -1528,6 +1554,17 @@ spec:
type: string
type: array
type: object
ipWhiteList:
description: 'IPWhiteList defines the IPWhiteList middleware configuration.
Deprecated: please use IPAllowList instead.'
properties:
sourceRange:
description: SourceRange defines the allowed IPs (or ranges of
allowed IPs by using CIDR notation).
items:
type: string
type: array
type: object
type: object
required:
- metadata

View file

@ -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]

View file

@ -4,6 +4,7 @@
[log]
level = "DEBUG"
noColor = true
[entryPoints]

View file

@ -0,0 +1,52 @@
[global]
checkNewVersion = false
sendAnonymousUsage = false
[log]
level = "DEBUG"
noColor = true
[entryPoints]
[entryPoints.tcp]
address = ":8093"
[api]
insecure = true
[providers.file]
filename = "{{ .SelfFilename }}"
## dynamic configuration ##
[tcp]
[tcp.routers]
[tcp.routers.to-whoami-a]
entryPoints = ["tcp"]
rule = "HostSNI(`whoami-a.test`)"
service = "whoami-a"
middlewares = ["blocking-ipwhitelist"]
[tcp.routers.to-whoami-a.tls]
passthrough = true
[tcp.routers.to-whoami-b]
entryPoints = ["tcp"]
rule = "HostSNI(`whoami-b.test`)"
service = "whoami-b"
middlewares = ["allowing-ipwhitelist"]
[tcp.routers.to-whoami-b.tls]
passthrough = true
[tcp.services]
[tcp.services.whoami-a.loadBalancer]
[[tcp.services.whoami-a.loadBalancer.servers]]
address = "{{ .WhoamiA }}"
[tcp.services.whoami-b.loadBalancer]
[[tcp.services.whoami-b.loadBalancer.servers]]
address = "{{ .WhoamiB }}"
[tcp.middlewares]
[tcp.middlewares.allowing-ipwhitelist.ipWhiteList]
sourceRange = ["127.0.0.1/32"]
[tcp.middlewares.blocking-ipwhitelist.ipWhiteList]
sourceRange = ["127.127.127.127/32"]

View file

@ -0,0 +1,36 @@
version: "3.8"
services:
noOverrideWhitelist:
image: traefik/whoami
labels:
traefik.enable: true
traefik.http.routers.rt1.rule: Host(`no.override.whitelist.docker.local`)
traefik.http.routers.rt1.middlewares: wl1
traefik.http.middlewares.wl1.ipwhitelist.sourceRange: 8.8.8.8
overrideIPStrategyRemoteAddrWhitelist:
image: traefik/whoami
labels:
traefik.enable: true
traefik.http.routers.rt2.rule: Host(`override.remoteaddr.whitelist.docker.local`)
traefik.http.routers.rt2.middlewares: wl2
traefik.http.middlewares.wl2.ipwhitelist.sourceRange: 8.8.8.8
traefik.http.middlewares.wl2.ipwhitelist.ipStrategy: true
overrideIPStrategyDepthWhitelist:
image: traefik/whoami
labels:
traefik.enable: true
traefik.http.routers.rt3.rule: Host(`override.depth.whitelist.docker.local`)
traefik.http.routers.rt3.middlewares: wl3
traefik.http.middlewares.wl3.ipwhitelist.sourceRange: 8.8.8.8
traefik.http.middlewares.wl3.ipwhitelist.ipStrategy.depth: 3
overrideIPStrategyExcludedIPsWhitelist:
image: traefik/whoami
labels:
traefik.enable: true
traefik.http.routers.rt4.rule: Host(`override.excludedips.whitelist.docker.local`)
traefik.http.routers.rt4.middlewares: wl4
traefik.http.middlewares.wl4.ipwhitelist.sourceRange: 8.8.8.8
traefik.http.middlewares.wl4.ipwhitelist.ipStrategy.excludedIPs: 10.0.0.1,10.0.0.2

View file

@ -483,6 +483,69 @@ func (s *SimpleSuite) TestIPStrategyAllowlist() {
}
}
func (s *SimpleSuite) TestIPStrategyWhitelist() {
s.createComposeProject("whitelist")
s.composeUp()
defer s.composeDown()
s.traefikCmd(withConfigFile("fixtures/simple_whitelist.toml"))
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2*time.Second, try.BodyContains("override"))
require.NoError(s.T(), err)
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2*time.Second, try.BodyContains("override.remoteaddr.whitelist.docker.local"))
require.NoError(s.T(), err)
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.whitelist.docker.local",
expectedStatusCode: 403,
},
{
desc: "override depth accept",
xForwardedFor: "8.8.8.8,10.0.0.1,127.0.0.1",
host: "override.depth.whitelist.docker.local",
expectedStatusCode: 200,
},
{
desc: "override depth reject",
xForwardedFor: "10.0.0.1,8.8.8.8,127.0.0.1",
host: "override.depth.whitelist.docker.local",
expectedStatusCode: 403,
},
{
desc: "override excludedIPs reject",
xForwardedFor: "10.0.0.3,10.0.0.1,10.0.0.2",
host: "override.excludedips.whitelist.docker.local",
expectedStatusCode: 403,
},
{
desc: "override excludedIPs accept",
xForwardedFor: "8.8.8.8,10.0.0.1,10.0.0.2",
host: "override.excludedips.whitelist.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))
require.NoErrorf(s.T(), err, "Error during %s: %v", test.desc, err)
}
}
func (s *SimpleSuite) TestXForwardedHeaders() {
s.createComposeProject("allowlist")

View file

@ -248,6 +248,30 @@ func (s *TCPSuite) TestMiddlewareAllowList() {
assert.Contains(s.T(), out, "whoami-b")
}
func (s *TCPSuite) TestMiddlewareWhiteList() {
file := s.adaptFile("fixtures/tcp/ip-whitelist.toml", struct {
WhoamiA string
WhoamiB string
}{
WhoamiA: s.getComposeServiceIP("whoami-a") + ":8080",
WhoamiB: s.getComposeServiceIP("whoami-b") + ":8080",
})
s.traefikCmd(withConfigFile(file))
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI(`whoami-a.test`)"))
require.NoError(s.T(), err)
// Traefik not passes through, ipWhiteList closes connection
_, err = guessWhoTLSPassthrough("127.0.0.1:8093", "whoami-a.test")
assert.ErrorIs(s.T(), err, io.EOF)
// Traefik passes through, termination handled by whoami-b
out, err := guessWhoTLSPassthrough("127.0.0.1:8093", "whoami-b.test")
require.NoError(s.T(), err)
assert.Contains(s.T(), out, "whoami-b")
}
func (s *TCPSuite) TestWRR() {
file := s.adaptFile("fixtures/tcp/wrr.toml", struct {
WhoamiB string

View file

@ -45,7 +45,7 @@
"url": "http://10.42.0.3:80"
},
{
"url": "http://10.42.0.6:80"
"url": "http://10.42.0.5:80"
}
],
"passHostHeader": true,
@ -59,7 +59,7 @@
],
"serverStatus": {
"http://10.42.0.3:80": "UP",
"http://10.42.0.6:80": "UP"
"http://10.42.0.5:80": "UP"
}
},
"noop@internal": {

View file

@ -139,7 +139,7 @@
"url": "http://10.42.0.3:80"
},
{
"url": "http://10.42.0.7:80"
"url": "http://10.42.0.5:80"
}
],
"passHostHeader": true,
@ -153,7 +153,7 @@
],
"serverStatus": {
"http://10.42.0.3:80": "UP",
"http://10.42.0.7:80": "UP"
"http://10.42.0.5:80": "UP"
}
},
"default-test2-route-23c7f4c450289ee29016@kubernetescrd": {
@ -163,7 +163,7 @@
"url": "http://10.42.0.3:80"
},
{
"url": "http://10.42.0.7:80"
"url": "http://10.42.0.5:80"
}
],
"passHostHeader": true,
@ -177,7 +177,7 @@
],
"serverStatus": {
"http://10.42.0.3:80": "UP",
"http://10.42.0.7:80": "UP"
"http://10.42.0.5:80": "UP"
}
},
"default-testst-route-60ad45fcb5fc1f5f3629@kubernetescrd": {
@ -187,7 +187,7 @@
"url": "http://10.42.0.3:80"
},
{
"url": "http://10.42.0.7:80"
"url": "http://10.42.0.5:80"
}
],
"passHostHeader": true,
@ -202,7 +202,7 @@
],
"serverStatus": {
"http://10.42.0.3:80": "UP",
"http://10.42.0.7:80": "UP"
"http://10.42.0.5:80": "UP"
}
},
"default-whoami-80@kubernetescrd": {
@ -212,7 +212,7 @@
"url": "http://10.42.0.3:80"
},
{
"url": "http://10.42.0.7:80"
"url": "http://10.42.0.5:80"
}
],
"passHostHeader": true,
@ -223,7 +223,7 @@
"status": "enabled",
"serverStatus": {
"http://10.42.0.3:80": "UP",
"http://10.42.0.7:80": "UP"
"http://10.42.0.5:80": "UP"
}
},
"default-wrr1@kubernetescrd": {
@ -295,7 +295,7 @@
"address": "10.42.0.2:8080"
},
{
"address": "10.42.0.4:8080"
"address": "10.42.0.6:8080"
}
]
},
@ -347,10 +347,10 @@
"loadBalancer": {
"servers": [
{
"address": "10.42.0.5:8090"
"address": "10.42.0.4:8090"
},
{
"address": "10.42.0.6:8090"
"address": "10.42.0.7:8090"
}
]
},

View file

@ -127,7 +127,7 @@
"url": "http://10.42.0.3:80"
},
{
"url": "http://10.42.0.4:80"
"url": "http://10.42.0.5:80"
}
],
"passHostHeader": true,
@ -138,7 +138,7 @@
"status": "enabled",
"serverStatus": {
"http://10.42.0.3:80": "UP",
"http://10.42.0.4:80": "UP"
"http://10.42.0.5:80": "UP"
}
},
"noop@internal": {

View file

@ -83,10 +83,10 @@
"loadBalancer": {
"servers": [
{
"url": "http://10.42.0.2:80"
"url": "http://10.42.0.3:80"
},
{
"url": "http://10.42.0.7:80"
"url": "http://10.42.0.5:80"
}
],
"passHostHeader": true,
@ -99,8 +99,8 @@
"default-test-ingress-whoami-test-whoami@kubernetes"
],
"serverStatus": {
"http://10.42.0.2:80": "UP",
"http://10.42.0.7:80": "UP"
"http://10.42.0.3:80": "UP",
"http://10.42.0.5:80": "UP"
}
},
"noop@internal": {

View file

@ -119,10 +119,10 @@
"loadBalancer": {
"servers": [
{
"url": "XXXX"
"url": "http://10.42.0.3:80"
},
{
"url": "XXXX"
"url": "http://10.42.0.5:80"
}
],
"passHostHeader": true,
@ -136,18 +136,18 @@
"default-whoami-keep-route-whoami-test-keep-keep@kubernetes"
],
"serverStatus": {
"http://XXXX": "UP",
"http://XXXX": "UP"
"http://10.42.0.3:80": "UP",
"http://10.42.0.5:80": "UP"
}
},
"default-whoami-http@kubernetes": {
"loadBalancer": {
"servers": [
{
"url": "http://10.42.0.10:80"
"url": "http://10.42.0.3:80"
},
{
"url": "http://10.42.0.8:80"
"url": "http://10.42.0.5:80"
}
],
"passHostHeader": true,
@ -161,8 +161,8 @@
"default-test-ingress-whoami-test-whoami@kubernetes"
],
"serverStatus": {
"http://10.42.0.10:80": "UP",
"http://10.42.0.8:80": "UP"
"http://10.42.0.3:80": "UP",
"http://10.42.0.5:80": "UP"
}
},
"noop@internal": {

View file

@ -83,7 +83,7 @@
"loadBalancer": {
"servers": [
{
"url": "http://10.42.0.4:80"
"url": "http://10.42.0.3:80"
},
{
"url": "http://10.42.0.5:80"
@ -99,7 +99,7 @@
"default-whoami-keep-route-whoami-test-keep-keep@kubernetes"
],
"serverStatus": {
"http://10.42.0.4:80": "UP",
"http://10.42.0.3:80": "UP",
"http://10.42.0.5:80": "UP"
}
},