基于客户端证书认证的K8s Ingress配置合理性咨询
场景背景
我有一个需要客户端证书认证的服务,当前使用的Nginx Ingress配置如下:
nginx.ingress.kubernetes.io/auth-tls-secret: "namespace/ca-chain" nginx.ingress.kubernetes.io/auth-tls-verify-client: "on" nginx.ingress.kubernetes.io/auth-tls-pass-certificate-to-upstream: "true"
后端通过接收ssl-client-verify: SUCCESS请求头来判断客户端证书验证通过,但我担心这种配置会让后端和Ingress强耦合——如果Ingress失效,攻击者可以伪造该请求头直接访问后端。
问题1:标准K8s Ingress架构下,所有请求都必须经过Ingress吗?
不是。Ingress只是K8s中对外暴露服务的一种方式,而非唯一方式:
- 如果服务配置了NodePort、LoadBalancer类型的Service,外部流量可以直接通过这些Service访问后端,绕开Ingress
- 集群内部的Pod可以直接访问后端Service的ClusterIP,完全不经过Ingress
- 若集群网络边界被突破,攻击者直接访问后端Pod的IP也能绕开Ingress
只有当你的服务仅通过Ingress对外暴露(未配置其他暴露方式),且集群内部网络做了严格隔离(比如限制Pod间的非授权访问),外部流量才必须经过Ingress。但从安全角度,不能假设所有流量都会经过Ingress。
问题2:是否需要后端自行验证证书链?
必须要。依赖Ingress传入的ssl-client-verify请求头是不安全的:只要攻击者能绕开Ingress直接触达后端,就能轻松伪造这个请求头绕过认证。
既然你已经配置了auth-tls-pass-certificate-to-upstream: true,后端可以拿到完整的客户端证书,建议在后端实现以下验证逻辑:
- 后端本地存储信任的CA证书(和Ingress中
ca-chain的内容一致) - 验证客户端证书的签名链,确认是由信任的CA签发
- 因为仅对接单个客户端,还可以额外校验证书的Subject、序列号等唯一标识,进一步锁死访问权限
这样即使Ingress出现故障或流量绕开Ingress,后端自身也能完成认证,彻底摆脱对Ingress的依赖。
服务移出K8s后的部署要求
是的。如果把服务部署到独立服务器上,要么前置Nginx这类代理来处理客户端证书认证(配置逻辑和K8s中的Ingress一致),要么直接在服务自身实现客户端证书验证逻辑。
如果不做上述处理,攻击者可以直接伪造ssl-client-verify请求头访问服务,完全绕过认证。核心原则是:Ingress/代理只是流量入口的管控手段,后端自身的认证能力才是最可靠的安全屏障,无论部署环境如何变化,这个原则都适用。
内容的提问来源于stack exchange,提问作者mslot

