本文介绍如何限制特定IP访问网格内应用。
前提条件
已添加集群到ASM实例,且ASM实例版本为1.15.3.25及以上。
已部署httpbin应用,且可以正常访问。
使用说明
本文网关的externalTrafficPolicy
均设置为Local
。externalTrafficPolicy
设置为Cluster
无法保留源IP。
场景一:ASM网关之前不存在7层代理
执行以下命令,直接访问httpbin。
curl 47.111.XXX.XX:80/ -I
客户端实际IP为106.11.XX.X
。从网关日志可以看到downstream_remote_address
和x_forwarded_for
中的值都正确。此时,在网关上配置ipBlocks
和remoteIpBlocks
都可以生效。
从Sidecar侧的访问日志可以看到x_forwarded_for
中的值依然为客户端真实IP。downstream_remote_address
也是客户端真实IP,但是丢失了端口信息,显示为0
。
示例一:网关侧配置黑白名单
测试ipBlocks
使用以下内容,创建授权策略gateway-test.yaml。
您可以使用ASM安全策略或网关的黑白名单简化配置。
apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: gateway-test namespace: istio-system spec: action: DENY rules: - from: - source: ipBlocks: - 106.11.XX.X selector: matchLabels: istio: ingressgateway
执行以下命令,部署授权策略。
kubectl apply -f gateway-test.yaml
执行以下命令,访问httpbin。
curl 47.111.175.XX:XX/ -I
预期输出:
HTTP/1.1 403 Forbidden content-length: 19 content-type: text/plain date: Thu, 31 Aug 2023 06:56:00 GMT server: istio-envoy
测试remoteIpBlocks
使用以下内容,创建授权策略gateway-test.yaml。
您可以使用ASM安全策略或网关的黑白名单简化配置。
apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: gateway-test namespace: istio-system spec: action: DENY rules: - from: - source: remoteIpBlocks: - 106.11.XX.X selector: matchLabels: istio: ingressgateway
执行以下命令,部署授权策略。
kubectl apply -f gateway-test.yaml
执行以下命令,访问httpbin。
curl 47.111.175.XX:XX/ -I
预期输出:
HTTP/1.1 403 Forbidden content-length: 19 content-type: text/plain date: Thu, 31 Aug 2023 09:59:02 GMT server: istio-envoy
示例二:Sidecar侧配置黑白名单
测试ipBlocks
使用以下内容,创建授权策略gateway-test.yaml。
apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: gateway-test namespace: default spec: action: DENY rules: - from: - source: ipBlocks: - 106.11.XX.X selector: matchLabels: app: httpbin
执行以下命令,部署授权策略。
kubectl apply -f gateway-test.yaml
执行以下命令,访问httpbin。
curl 47.111.175.XX:XX/ -I
预期输出:
HTTP/1.1 200 OK server: istio-envoy date: Thu, 31 Aug 2023 10:14:01 GMT content-type: text/html; charset=utf-8 content-length: 9593 access-control-allow-origin: * access-control-allow-credentials: true x-envoy-upstream-service-time: 2
从Sidecar侧的访问日志可以看到,
downstream_remote_address
是客户端IP,但是没有被拦截。downstream_remote_address
并不完全等于ipBlocks
中限制的字段。ipBlocks
限制“和当前代理直接建立TCP连接的客户端IP”,所以真实发送过来的源IP是网关的Pod IP。downstream_remote_address
是一个较为灵活的字段,并不总是下游的物理IP。downstream_remote_address
表示下游连接的远端地址。如果该地址是一个IP地址,则它包含IP和端口。它不是远端的真实物理地址,该地址可能来自于ProxyProtocol过滤器或x_forwarded_for
请求头。您可以测试将
ipBlocks
中的地址换成网关的Pod IP,配置后将无法访问httpbin。
测试remoteIpBlocks
使用以下内容,创建授权策略gateway-test.yaml。
apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: gateway-test namespace: default spec: action: DENY rules: - from: - source: remoteIpBlocks: - 106.11.XX.X selector: matchLabels: app: httpbin
执行以下命令,部署授权策略。
kubectl apply -f gateway-test.yaml
执行以下命令,访问httpbin。
curl 47.111.XXX.XX:80/ -I
预期输出:
HTTP/1.1 403 Forbidden content-length: 19 content-type: text/plain date: Thu, 31 Aug 2023 11:06:42 GMT server: istio-envoy x-envoy-upstream-service-time: 0
remoteIpBlocks
配置生效,因为x_forwarded_for
中的值正常。
场景二:ASM网关之前存在7层代理
此场景下,ASM网关收到的请求中,x_forwarded_for
请求头中应有默认值(由网关之前的7层代理提添加)。
到达网关之前的x_forwarded_for
请求头应为56.5.X.X, 72.9.X.X, 98.1.X.X
,最后的一个IP(106.11.XX.X
)由ASM网关添加。downstream_remote_address
表示与网关直接相连的对端IP(此时是真实的物理IP,所以是一个有效的端口)。
从Sidecar的日志可以看到,x_forwarded_for
请求头和网关侧相同。downstream_remote_address
此时并不是真实的物理地址,而是来自于x_forwarded_for
请求头的最后一个值(由于x_forwarded_for
中只有IP,所以此处端口为0
)。
下文不再测试ipBlocks
字段(该字段表示对端真实物理IP),仅测试remoteIpBlocks
字段。这种情况下,需要将x_forwarded_for
看作一个数组,此时限制“谁可以访问ASM网关”,即限制上述日志中x_forwarded_for
的最后一个元素。
示例一:配置remoteIpBlocks为x_forwarded_for中的最后一个地址
使用以下内容,创建授权策略gateway-test.yaml。
apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: gateway-test-ap-wg-gateway-test-istio-system-gateway-ingressgateway namespace: istio-system spec: action: DENY rules: - from: - source: remoteIpBlocks: - 106.11.XX.X selector: matchLabels: istio: ingressgateway
执行以下命令,部署授权策略。
kubectl apply -f gateway-test.yaml
执行以下命令,访问httpbin。
curl 47.111.175.XX:XX/ -H 'X-Forwarded-For: 56.5.X.X, 72.9.X.X, 98.1.X.X' -I
预期输出:
HTTP/1.1 403 Forbidden content-length: 19 content-type: text/plain date: Thu, 31 Aug 2023 11:50:36 GMT server: istio-envoy
预期输出表明成功限制
x_forwarded_for
中的最后一个地址。
示例二:设置网关的numTrustedProxies为2
在入口网关YAML的
spec
字段中添加如下配置。关于如何编辑入口网关,请参见登录ASM控制台管理入口网关。podAnnotations: proxy.istio.io/config: '{"gatewayTopology" : { "numTrustedProxies": 2 } }'
说明该配置会导致网关重启。
网关重启后,执行以下命令,访问httpbin。
curl 47.111.XXX.XX:80/ -H 'X-Forwarded-For: 56.5.X.X, 72.9.X.X, 98.1.X.X' -I
预期输出:
HTTP/1.1 200 OK server: istio-envoy date: Thu, 31 Aug 2023 12:10:15 GMT content-type: text/html; charset=utf-8 content-length: 9593 access-control-allow-origin: * access-control-allow-credentials: true x-envoy-upstream-service-time: 2
预期输出表明访问成功,
numTrustedProxies
影响了remoteIpBlocks
中的判断结果。numTrustedProxies
设置为2
,表示网关会认为最靠近ASM网关的2个代理是可信的,第三近的代理不可信。因此,remoteIpBlocks
限制第三近的代理IP。numTrustedProxies
在不配置的情况下,默认值为0。
示例三:授权策略中限制网关日志x_forwarded_for的倒数第三个地址
使用以下内容,创建授权策略gateway-test.yaml。
apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: gateway-test-ap-wg-gateway-test-istio-system-gateway-ingressgateway namespace: istio-system spec: action: DENY rules: - from: - source: remoteIpBlocks: - 72.9.X.X selector: matchLabels: istio: ingressgateway
执行以下命令,部署授权策略。
kubectl apply -f gateway-test.yaml
执行以下命令,访问httpbin。
curl 47.111.XXX.XX:80/ -H 'X-Forwarded-For: 56.5.X.X, 72.9.X.X, 98.1.X.X' -I
预期输出:
HTTP/1.1 403 Forbidden content-length: 19 content-type: text/plain date: Thu, 31 Aug 2023 12:38:09 GMT server: istio-envoy
预期输出表明成功限制
x_forwarded_for
的倒数第三个地址。
示例四:变更上述授权策略的生效范围为httpbin应用
使用以下内容,创建授权策略gateway-test.yaml。
apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: gateway-test namespace: default spec: action: DENY rules: - from: - source: remoteIpBlocks: - 72.9.X.X selector: matchLabels: app: httpbin
执行以下命令,部署授权策略。
kubectl apply -f gateway-test.yaml
执行以下命令,访问httpbin。
curl 47.111.XXX.XX:80/ -H 'X-Forwarded-For: 56.5.X.X, 72.9.X.X, 98.1.X.X' -I
预期输出:
HTTP/1.1 200 OK server: istio-envoy date: Thu, 31 Aug 2023 12:39:36 GMT content-type: text/html; charset=utf-8 content-length: 9593 access-control-allow-origin: * access-control-allow-credentials: true x-envoy-upstream-service-time: 6
预期输出表明访问成功,授权策略规则失效。因为上述
numTrustedProxies
是为网关配置的,Sidecar的numTrustedProxies
默认值还是0,它会校验自己收到的x_forwarded_for
请求头的最后一个值,因此没有成功拒绝当前请求。您可以修改该授权策略中的
remoteIpBlocks
为Sidecar日志中x_forwarded_for
的最后一个IP,即可看到访问被拒绝。