Посланник для посланника TLS для прокси-сервера TLS
Предположим, что эта архитектура
................................................
. .
. .
. .
. .
┌───────────────────┐ ┌─────────────────┐
┌──────────────────┤ Customer Firewall ├─┐ ┌────────────────────┤Provider Firewall├─┐
│ └──────────┬────────┘ │ │Provider Network └──┬──────────────┘ │
│ Customer Network │ │ │ ┌─────────┴─┐ │
│ │ │ │ ┌─────┤ Envoy - B ├───────┐ │
│ │ │ │ │ └─────┬─────┘ │ │
│ ┌──────┴─────┐ │ │ │ │ │ │
│ ┌─────────┐ │ │ │ │ │ │ │ │
│ │ Client ├────┤ Envoy - A │ │ │ ┌────┴────┐ ┌───┴─────┐ ┌────┴────┐ │
│ └─────────┘ │ │ │ │ │ Service │ │ Service │ │ Service │ │
│ └────────────┘ │ │ └─────────┘ └─────────┘ └─────────┘ │
│ │ │ │
└────────────────────────────────────────┘ └────────────────────────────────────────┘
Клиент хочет подключиться к службам в сети провайдера, но межсетевой экран клиента имеет строгую политику фильтрации HTTP и фильтрации SNI .
Он отбросит любой несанкционированный трафик, поэтому любой неразрешенный домен/SNI будет удален.
SNI/домен Envoy B () разрешен в брандмауэре, но они не разрешают использование других доменов .
Все сервисы HTTP/HTTPS.
Вот конфигурация серверов посланников:
Посланник - А:
- Он слушает порт
80
, и при каждом HTTP-трафике он перенаправляет трафик на Envoy-B, используя HTTP2 + TLSv1.3. - Он слушает порт
443
, и каждый трафик TPC перенаправляется на 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
Посланник - Б:
- Он слушает порт
8888
, и на каждомHTTP2 + TLSv1.3
трафик, он расшифровывает трафик и пересылает простой HTTP-запрос службам - Он слушает порт
8889
, и каждый трафик TPC перенаправляется на 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-запрос, Envoy-A зашифрует его, и будет использован SNI, разрешенный в клиентском брандмауэре (вместо заголовка HOST исходного запроса).
Но когда клиент отправляет трафик HTTPS/TLS, Envoy-A просто пересылает поток TCP , поэтому SNI не меняется и остаетсяprivate.service.example.com
-> Поскольку это имя хоста не разрешено в брандмауэре, оно будет удалено !
Я хочу, чтобы трафик TCP-прокси снова зашифровался, чтобы SNI изменился наenvoy-b.example.com
и брандмауэр не отбрасывает запрос.
Я попытался добавитьtransport_socket
для трафика 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
Примечания
- Клиент не принимает, что посланник Б преобразует трафик HTTPS в HTTP, затем передает его (используя HTTPS), а затем снова шифрование HTTPS происходит в посланнике А.
- У нас нет доступа к закрытым ключам службы, поэтому, если мы сделаем то, что описано в примечании 1, сертификаты изменятся.
- Посланник B ТРЕБУЕТ SNI , чтобы определить, к каким сервисам следует перенаправить трафик.