假设这个架构
................................................
. .
. .
. .
. .
┌───────────────────┐ ┌─────────────────┐
┌──────────────────┤ Customer Firewall ├─┐ ┌────────────────────┤Provider Firewall├─┐
│ └──────────┬────────┘ │ │Provider Network └──┬──────────────┘ │
│ Customer Network │ │ │ ┌─────────┴─┐ │
│ │ │ │ ┌─────┤ Envoy - B ├───────┐ │
│ │ │ │ │ └─────┬─────┘ │ │
│ ┌──────┴─────┐ │ │ │ │ │ │
│ ┌─────────┐ │ │ │ │ │ │ │ │
│ │ Client ├────┤ Envoy - A │ │ │ ┌────┴────┐ ┌───┴─────┐ ┌────┴────┐ │
│ └─────────┘ │ │ │ │ │ Service │ │ Service │ │ Service │ │
│ └────────────┘ │ │ └─────────┘ └─────────┘ └─────────┘ │
│ │ │ │
└────────────────────────────────────────┘ └────────────────────────────────────────┘
客户端想要连接到提供商网络上的服务,但客户防火墙有严格的政策HTTP 过滤和SNI 过滤。
它将丢弃任何未经授权的流量,因此任何不允许的域/SNI 都将被丢弃。
SNI/域名特使B(envoy-b.example.com
) 是允许在防火墙中,但他们不允许任何其他域名。
所有服务均采用 HTTP/HTTPS
以下是 Envoy 服务器的配置:
特使-A:
- 它监听端口
80
,对于每个 HTTP 流量,它将使用以下方式将流量转发到 Envoy - B:HTTP2 + TLSv1.3 - 它监听端口
443
,以及每个传输控制协议流量,它将转发流量到 Envoy - B无需任何进一步加密
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
特使-B:
- 它监听端口
8888
,并且每当有HTTP2 + TLSv1.3
流量时,它都会解密流量并转发普通 HTTP 请求前往服务 - 它监听端口
8889
,以及每个传输控制协议流量,它将转发流量到 Envoy - B无需进一步加密/解密
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 请求时,特使-A将对其进行加密,并且 SNI 将是envoy-b.example.com
客户端防火墙允许的(而不是原始请求的 HOST 标头private.service.example.com
)
但当客户端发送 HTTPS/TLS 流量时,特使-A只是转发TCP 流,因此 SNI 不会改变并保持不变private.service.example.com
-> 因为防火墙不允许此主机名它将被丢弃!
我希望 TCP 代理的流量再次加密,以便 SNI 发生变化envoy-b.example.com
并且防火墙不会丢弃请求。
我尝试transport_socket
在两个 Envoy 主机上添加 TLS 流量,但没有成功:
Envoy A > clusters > forwarder_to_envoy_b_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
:
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,然后传输(使用 HTTPS),然后在 Envoy A 再次进行 HTTPS 加密
- 我们无权访问服务私钥,因此如果我们按照注释 1 中的说明进行操作,证书将会更改
- 特使B需要 SNI确定流量应该转发到哪些服务