You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

跨防火墙Envoy双向TLS代理的SNI适配配置问题求助

跨防火墙Envoy双向TLS代理的SNI适配配置问题求助

大家好,我最近在部署跨防火墙的Envoy代理架构时遇到了SNI相关的流量拦截问题,想请各位帮忙看看怎么解决。先给大家介绍下整体情况:

架构背景

我们的网络分为客户侧和服务商侧,中间隔着客户防火墙,这个防火墙有严格的HTTP和SNI过滤策略,只有envoy-b.example.com这个域名的SNI是被允许的,其他任何域名的流量都会被直接丢弃。

整体架构如下:

┌────────────────────────────────────────┐     ┌────────────────────────────────────────┐
│                  ┌──────────┬────────┘ │     │Provider Network    └──┬──────────────┘ │
│   Customer Network          │          │     │             ┌─────────┴─┐              │
│                             │          │     │       ┌─────┤ Envoy - B ├───────┐      │
│                             │          │     │       │     └─────┬─────┘       │      │
│                      ┌──────┴─────┐    │     │       │           │             │      │
│       ┌─────────┐    │            │    │     │  ┌────┴────┐  ┌───┴─────┐  ┌────┴────┐ │
│       │ Client  ├────┤  Envoy - A │    │     │  │ Service │  │ Service │  │ Service │ │
│       └─────────┘    │            │    │     │  └─────────┘  └─────────┘  └─────────┘ │
│                      └────────────┘    │     │                                        │
│                                        │     │                                        │
└────────────────────────────────────────┘     └────────────────────────────────────────┘
  • 客户侧:Client → Envoy-A → 客户防火墙
  • 服务商侧:服务商防火墙 → Envoy-B → 后端服务(都是HTTP/HTTPS协议)

现有Envoy配置

目前我已经配置了Envoy-A和Envoy-B的基础转发规则:

Envoy-A 配置

Envoy-A监听80和443端口:

  • 80端口:接收HTTP请求,用HTTP2 + TLSv1.3加密转发给Envoy-B的8888端口,这里SNI会被替换成envoy-b.example.com,能正常过防火墙。
  • 443端口:做TCP透传,直接把客户端的HTTPS流量转发给Envoy-B的8889端口,这时候SNI还是原请求的private.service.example.com,直接被防火墙拦了。

完整配置如下:

static_resources:
listeners:
# HTTP
- name: http_forwarder
address:
socket_address:
protocol: TCP
address: 0.0.0.0
port_value: 80
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
route_config:
name: http_route
virtual_hosts:
- name: http_forwarder
domains: [ "*" ]
routes:
- match:
prefix: "/"
route:
cluster: forwarder_to_envoy_b_http
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
# HTTPS/TLS
- name: https_forwarder
address:
socket_address:
protocol: TCP
address: 0.0.0.0
port_value: 443
filter_chains:
- filters:
- name: envoy.filters.network.tcp_proxy
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy
cluster: forwarder_to_envoy_b_tls
stat_prefix: https_passthrough
access_log:
- name: envoy.access_loggers.stdout
typed_config:
"@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog
clusters:
- name: forwarder_to_envoy_b_http
type: STRICT_DNS
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: forwarder_to_envoy_b_http
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: envoy-b.example.com
port_value: 8888
dns_resolution_config:
resolvers:
- socket_address:
address: "1.1.1.1"
port_value: 53
dns_resolver_options:
no_default_search_domain: true
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
common_tls_context:
tls_params:
tls_minimum_protocol_version: TLSv1_3
tls_maximum_protocol_version: TLSv1_3
- name: forwarder_to_envoy_b_tls
type: STRICT_DNS
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: forwarder_to_envoy_b_tls
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: envoy-b.example.com
port_value: 8889
dns_resolution_config:
resolvers:
- socket_address:
address: "1.1.1.1"
port_value: 53
dns_resolver_options:
no_default_search_domain: true

Envoy-B 配置

Envoy-B监听8888和8889端口:

  • 8888端口:接收Envoy-A发来的HTTP2+TLSv1.3流量,解密后转发给后端HTTP服务。
  • 8889端口:做TCP透传,直接把流量转发给后端HTTPS服务。

完整配置如下:

static_resources:
listeners:
- name: http_listener_0
address:
socket_address:
protocol: TCP
address: 0.0.0.0
port_value: 8888
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: [ "*" ]
routes:
- match:
prefix: "/"
route:
cluster: http_cluster
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
common_tls_context:
tls_params:
tls_minimum_protocol_version: TLSv1_3
tls_maximum_protocol_version: TLSv1_3
tls_certificates:
certificate_chain:
filename: /certs/proxy-crt.pem
private_key:
filename: /certs/proxy-key.pem
alpn_protocols: HTTP2
- name: tls_listener_0
address:
socket_address:
protocol: TCP
address: 0.0.0.0
port_value: 8889
filter_chains:
- filters:
- name: envoy.filters.network.tcp_proxy
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy
cluster: tls_cluster
stat_prefix: https_passthrough
access_log:
- name: envoy.access_loggers.stdout
typed_config:
"@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog
clusters:
- name: http_cluster
type: STRICT_DNS
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: http_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: private.service.example.com
port_value: 80
dns_resolution_config:
resolvers:
- socket_address:
address: "1.1.1.1"
port_value: 53
dns_resolver_options:
no_default_search_domain: true
- name: tls_cluster
type: STRICT_DNS
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: tls_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: private.service.example.com
port_value: 443
dns_resolution_config:
resolvers:
- socket_address:
address: "1.1.1.1"
port_value: 53
dns_resolver_options:
no_default_search_domain: true

核心问题

HTTP请求一切正常,但HTTPS请求因为Envoy-A只是透传TCP流,原请求的SNI是private.service.example.com,被防火墙直接丢弃了。我想要实现的是:让Envoy-A把TCP代理的HTTPS流量重新加密,替换SNI为envoy-b.example.com,这样能通过防火墙,同时Envoy-B还能拿到原请求的SNI来转发到对应服务。

已尝试的修改(未生效)

我尝试给两边的相关配置添加了TLS传输套接字,但没起作用:

Envoy-A 修改点

在clusters > forwarder_to_envoy_b_tls下添加了TLS上游配置:

transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
common_tls_context:
tls_params:
tls_minimum_protocol_version: TLSv1_3
tls_maximum_protocol_version: TLSv1_3

Envoy-B 修改点

在listener > tls_listener_0下添加了TLS下游配置:

transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
common_tls_context:
tls_params:
tls_minimum_protocol_version: TLSv1_3
tls_maximum_protocol_version: TLSv1_3
tls_certificates:
certificate_chain:
filename: /certs/proxy-crt.pem
private_key:
filename: /certs/proxy-key.pem
alpn_protocols: HTTP2

额外限制条件

还有几个限制需要注意:

  • 客户端不接受Envoy-B把HTTPS转成HTTP再转发的方式,因为这样证书链会变化,用户体验受影响。
  • 我们没有后端服务的私钥,没法做证书重签或者中间人代理。
  • Envoy-B必须依靠原请求的SNI来判断转发到哪个服务,所以不能丢失这个信息。

有没有大佬知道怎么调整配置才能实现需求?谢谢大家!


备注:内容来源于stack exchange,提问作者M.A. Heshmat Khah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.23 07:39:50