Gateway API 实践之(二)FSM Gateway 的黑白名单访问控制

在本文开始之前,我们高兴地宣布我们的开源服务网格产品——FSM,已成功推出最新版本 1.2.0。

此次版本 1.2.0 的更新重点在于对 Gateway API 策略的支持、支持复杂的混合架构环境,并对已知问题进行了修复。我们致力于不断优化 FSM 的功能、稳定性和用户体验,以适应不断变化的技术需求和挑战。

为了帮助用户更好地理解和利用这些新特性,FSM 文档 正在加紧更新中。在未来的系列文章中,我们将详细介绍这些新功能的操作指南及其在实际场景中的应用,以助力用户最大限度地发挥 FSM 在网络管理中的潜力。

更新内容:

  • 支持 Gateway API 的 Policy Attachment
    • Rate Limit
    • Fault Injection
    • Access Control
    • Gateway TLS Configuration
    • Circuit Breaking
    • Session Sticky
    • Load Balancer
    • Health Check
    • Upstream TLS Configuration
  • 统一服务目录,支持以下注册中心
    • Eureka
    • Consul

敬请关注我们的后续更新,了解 FSM 如何助您在服务网格领域取得新的突破。


黑白名单访问控制

黑白名单功能是一种有效的网络安全机制,用于控制和管理网络流量。这种功能基于预设的规则列表来确定哪些实体(IP 地址或者 IP 网段)被允许或禁止通过网关。网关使用黑白名单来过滤进入的网络流量。这种方式提供简单直接的访问控制,易于管理,可有效防止已知的安全威胁。

作为集群流量入口的 FSM Gateway,管理着所有进入集群的流量,通过设置黑白名单访问控制策略可以过来进入集群的流量。

FSM Gateway 提供了两种粒度的访问控制,这种粒度都是针对 L7 的 HTTP 协议:

  1. 域名级访问控制:一种基于域名的网络流量管理策略。它涉及到对符合特定域名条件的流量实施访问规则,如允许或阻止与特定域名的通信。
  2. 路由维护级访问控制:基于路由(请求头、method、路径、参数)的管理策略,通过将访问控制策略施加在路由上,对访问特定路由的流量进行管理。

接下来就通过演示,为大家介绍黑白名单访问控制的使用。

演示

前置条件

  • Kubernetes 集群
  • kubectl 工具

环境准备

安装 FSM Gateway

FSM Gateway 的安装,可以参考 安装文档。这里选择 CLI 的方式安装。

下载 FSM CLI,当前为 *v1.2.0 版本。

system=$(uname -s | tr '[:upper:]' '[:lower:]')
arch=$(uname -m | sed -E 's/x86_/amd/' | sed -E 's/aarch/arm/')
release=v1.2.0
curl -L https://github.com/flomesh-io/fsm/releases/download/$release/fsm-$release-$system-$arch.tar.gz | tar -vxzf -
./$system-$arch/fsm version
sudo cp ./$system-$arch/fsm /usr/local/bin/fsm

在安装 FSM 时启用 FSM Gateway,默认情况是不启用的。

fsm install \
    --set=fsm.fsmGateway.enabled=true

确认已经安装 GatewayClass 控制器:flomesh.io/gateway-controller

kubectl get gatewayclass 
NAME              CONTROLLER                      ACCEPTED   AGE
fsm-gateway-cls   flomesh.io/gateway-controller   True       12h

部署示例应用

接下来部署示例应用,使用常用的 httpbin 服务,并创建 网关(Gateway) 和 HTTP 路由(HttpRoute)。

kubectl create namespace httpbin
kubectl apply -n httpbin -f https://raw.githubusercontent.com/flomesh-io/fsm-docs/main/manifests/gateway/http-routing.yaml

检查网关和 HTTP 路由,可以看到创建了两个不同域名的路由。

kubectl get gateway,httproute -n httpbin
NAME                                                   CLASS             ADDRESS   PROGRAMMED   AGE
gateway.gateway.networking.k8s.io/simple-fsm-gateway   fsm-gateway-cls             Unknown      3s

NAME                                                 HOSTNAMES             AGE
httproute.gateway.networking.k8s.io/http-route-foo   ["foo.example.com"]   2s
httproute.gateway.networking.k8s.io/http-route-bar   ["bar.example.com"]   2s

访问应用验证 HTTP 路由是否生效。

export GATEWAY_IP=$(kubectl get svc -n httpbin -l app=fsm-gateway -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}')

curl http://$GATEWAY_IP:8000/headers -H 'host:foo.example.com'
{
  "headers": {
    "Accept": "*/*",
    "Connection": "keep-alive",
    "Host": "10.42.0.15:80",
    "User-Agent": "curl/7.81.0"
  }
}

访问控制测试

基于域名的访问控制

使用基于域名的访问控制,我们可以在策略中设置一个或者多个域名,为设定的域名添加黑白名单。

比如下面的策略中:

  • targetRef 是对应用策略的目标资源的引用,对于 HTTP 请求引用的是 HTTPRoute 资源。
  • 通过字段 hostname,我们为两个域名中的 foo.example.com` 添加黑白名单策略。
  • 随着云服务和分布式网络架构的普及,直接连接到网关不再是客户端,而是中间代理。这种情况下我们通常会使用 HTTP 请求头 X-Forwarded-For 来标识客户端的 IP 地址。在 FSM Gatewat 的策略中,提供了 enableXFF 字段控制是否从 X-Forwarded-For 标头中获取客户端 IP 地址。
  • 对于拒绝访问的通信,通过 statusCodemessage 来定制相应的内容。
kubectl apply -n httpbin -f - <<EOF
apiVersion: gateway.flomesh.io/v1alpha1
kind: AccessControlPolicy
metadata:
  name: access-control-sample
spec:
  targetRef:
    group: gateway.networking.k8s.io
    kind: HTTPRoute
    name: http-route-foo
    namespace: httpbin
  hostnames:
    - hostname: foo.example.com
      config: 
        blacklist:
          - 192.168.0.0/24
        whitelist:
          - 112.94.5.242
        enableXFF: true
        statusCode: 403
        message: "Forbidden"
EOF

策略生效后,我们发送请求进行测试,记住请求时添加 X-Forwarded-For 来指定客户端 IP。

curl -I http://$GATEWAY_IP:8000/headers -H 'host:foo.example.com'  -H 'x-forwarded-for:112.94.5.242'
HTTP/1.1 200 OK
server: gunicorn/19.9.0
date: Fri, 29 Dec 2023 02:29:08 GMT
content-type: application/json
content-length: 139
access-control-allow-origin: *
access-control-allow-credentials: true
connection: keep-alive

curl -I http://$GATEWAY_IP:8000/headers -H 'host:foo.example.com'  -H 'x-forwarded-for: 10.42.0.1'
HTTP/1.1 403 Forbidden
content-length: 9
connection: keep-alive

从结果来看,当白名单和黑名单同时存在时,黑名单的配置会被忽略

基于路由的访问控制

基于路由的访问控制允许我们对特定的路由(路径、请求头、method、参数)设置访问控制策略,一次来限制对特定路由的访问。

在配置访问策略之前,在 HTTP 路由 foo.example.com 下我们添加一条路径前缀为 /headers 的路由,方便为其设置访问控制策略。

kubectl apply -n httpbin -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
  name: http-route-foo
spec:
  parentRefs:
  - name: simple-fsm-gateway
    port: 8000
  hostnames:
  - foo.example.com
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /headers
    backendRefs:
    - name: httpbin
      port: 8080  
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - name: httpbin
      port: 8080
EOF

下面的策略中:

  • 通过 match 来配置要匹配的路由,这里我们使用路径匹配。
  • 其他配置依然沿用上面使用的配置。
 kubectl apply -n httpbin -f - <<EOF
apiVersion: gateway.flomesh.io/v1alpha1
kind: AccessControlPolicy
metadata:
  name: access-control-sample
spec:
  targetRef:
    group: gateway.networking.k8s.io
    kind: HTTPRoute
    name: http-route-foo
    namespace: httpbin
  http:
    - match:
        path:
          type: PathPrefix
          value: /headers
      config: 
        blacklist:
          - 192.168.0.0/24
        whitelist:
          - 112.94.5.242
        enableXFF: true
        statusCode: 403
        message: "Forbidden"
EOF

更新策略后,发送请求来进行测试,对于路径 /headers 的访问同前面的结果一样。

curl -I http://$GATEWAY_IP:8000/headers -H 'host:foo.example.com'  -H 'x-forwarded-for:112.94.5.242'
HTTP/1.1 200 OK
server: gunicorn/19.9.0
date: Fri, 29 Dec 2023 02:39:02 GMT
content-type: application/json
content-length: 139
access-control-allow-origin: *
access-control-allow-credentials: true
connection: keep-alive

curl -I http://$GATEWAY_IP:8000/headers -H 'host:foo.example.com'  -H 'x-forwarded-for: 10.42.0.1'
HTTP/1.1 403 Forbidden
content-length: 9
connection: keep-alive

但如果访问的是路径 /get,则没有任何限制。

curl -I http://$GATEWAY_IP:8000/get -H 'host:foo.example.com'  -H 'x-forwarded-for: 10.42.0.1'
HTTP/1.1 200 OK
server: gunicorn/19.9.0
date: Fri, 29 Dec 2023 02:40:18 GMT
content-type: application/json
content-length: 230
access-control-allow-origin: *
access-control-allow-credentials: true
connection: keep-alive

你可能感兴趣的:(gateway)