在本文开始之前,我们高兴地宣布我们的开源服务网格产品——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
黑白名单访问控制
黑白名单功能是一种有效的网络安全机制,用于控制和管理网络流量。这种功能基于预设的规则列表来确定哪些实体(IP 地址或者 IP 网段)被允许或禁止通过网关。网关使用黑白名单来过滤进入的网络流量。这种方式提供简单直接的访问控制,易于管理,可有效防止已知的安全威胁。
作为集群流量入口的 FSM Gateway,管理着所有进入集群的流量,通过设置黑白名单访问控制策略可以过来进入集群的流量。
FSM Gateway 提供了两种粒度的访问控制,这种粒度都是针对 L7 的 HTTP 协议:
- 域名级访问控制:一种基于域名的网络流量管理策略。它涉及到对符合特定域名条件的流量实施访问规则,如允许或阻止与特定域名的通信。
- 路由维护级访问控制:基于路由(请求头、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 地址。 - 对于拒绝访问的通信,通过
statusCode
和message
来定制相应的内容。
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