Skip to content

Instantly share code, notes, and snippets.

@libesz
Created November 29, 2024 09:21
Show Gist options
  • Save libesz/bd7b5f5ddc0c675d459f84c263a3695a to your computer and use it in GitHub Desktop.
Save libesz/bd7b5f5ddc0c675d459f84c263a3695a to your computer and use it in GitHub Desktop.
Single listener based egress routing config for istio, supporting wildcard hostnames
# This is an improved version of egress routing config for istio.
# I published the original here: https://istio.io/latest/blog/2023/egress-sni/
# This config is a drop-in replacement for the the blog's second code block.
# Since ser filter state is GA in envoy, we can use it on the sidecar side to
# properly set up the original requested server name from the application in the
# mesh mTLS SNI.
# Define a new listener that enforces Istio mTLS on inbound connections.
# This is where sidecar will route the application traffic, wrapped into
# Istio mTLS.
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: egressgateway
namespace: istio-system
spec:
selector:
istio: egressgateway
servers:
- port:
number: 8443
name: tls-egress
protocol: TLS
hosts:
# As the GW pod is now filtering traffic at this point, we shall set up the hostname
# list properly here as well
- "*.wikipedia.org"
tls:
mode: ISTIO_MUTUAL
---
# VirtualService that will instruct sidecars in the mesh to route the outgoing
# traffic to the egress gateway Service if the SNI target hostname matches
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: direct-wildcard-through-egress-gateway
namespace: istio-system
spec:
hosts:
- "*.wikipedia.org"
gateways:
- mesh
- egressgateway
tls:
- match:
- gateways:
- mesh
port: 443
sniHosts:
- "*.wikipedia.org"
route:
- destination:
host: egressgateway.istio-egress.svc.cluster.local
subset: wildcard
# Dummy routing instruction. If omitted, no reference will point to the Gateway
# definition, and istiod will optimise the whole new listener out.
tcp:
- match:
- gateways:
- egressgateway
port: 8443
route:
- destination:
host: "dummy.local"
weight: 100
---
# Instruct sidecars to use Istio mTLS when sending traffic to the egress gateway
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: egressgateway
namespace: istio-system
spec:
host: egressgateway.istio-egress.svc.cluster.local
subsets:
- name: wildcard
trafficPolicy:
tls:
mode: ISTIO_MUTUAL
---
# Put the remote targets into the Service Registry
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: wildcard
namespace: istio-system
spec:
hosts:
- "*.wikipedia.org"
ports:
- number: 443
name: tls
protocol: TLS
---
# Access logging for the gateway
apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
name: mesh-default
namespace: istio-system
spec:
accessLogging:
- providers:
- name: envoy
---
# And finally, the configuration of the SNI forwarder, it has two parts.
# First is to instruct sidecars, when forwarding traffic towards the egress GW,
# push the original SNI into the mesh mTLS session. That is, GW will be able to
# inspect it directly when terminating mesh mTLS.
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: forward-downstream-sni
namespace: istio-system
spec:
configPatches:
- applyTo: NETWORK_FILTER
match:
context: SIDECAR_OUTBOUND
listener:
name: 0.0.0.0_443
patch:
operation: INSERT_FIRST
value:
name: envoy.filters.network.set_filter_state
typed_config:
'@type': type.googleapis.com/envoy.extensions.filters.network.set_filter_state.v3.Config
on_new_connection:
- format_string:
text_format_source:
inline_string: '%REQUESTED_SERVER_NAME%'
object_key: envoy.network.upstream_server_name
---
# Second, set up the gateway config:
# - create a dynamic dynamic_forward_proxy instance
# - patch the listener on 8443 (created with the Gateway definition above) to
# - map the outbound port back to 443 (from 8443)
# - forward everything to the dynamic_forward_proxy
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: sni-magic
namespace: istio-system
spec:
configPatches:
- applyTo: CLUSTER
match:
context: GATEWAY
patch:
operation: ADD
value:
cluster_type:
name: envoy.clusters.dynamic_forward_proxy
typed_config:
'@type': type.googleapis.com/envoy.extensions.clusters.dynamic_forward_proxy.v3.ClusterConfig
dns_cache_config:
name: dynamic_forward_proxy_cache_config
dns_lookup_family: V4_ONLY
lb_policy: CLUSTER_PROVIDED
name: dynamic_forward_proxy_cluster
- applyTo: NETWORK_FILTER
match:
context: GATEWAY
listener:
filterChain:
filter:
name: "envoy.filters.network.tcp_proxy"
patch:
operation: MERGE
value:
name: envoy.tcp_proxy
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy
cluster: dynamic_forward_proxy_cluster
stat_prefix: tcp
- applyTo: NETWORK_FILTER
match:
context: GATEWAY
listener:
filterChain:
filter:
name: envoy.filters.network.tcp_proxy
patch:
operation: INSERT_BEFORE
value:
name: envoy.filters.network.sni_dynamic_forward_proxy
typed_config:
'@type': type.googleapis.com/envoy.extensions.filters.network.sni_dynamic_forward_proxy.v3.FilterConfig
dns_cache_config:
dns_lookup_family: V4_ONLY
name: dynamic_forward_proxy_cache_config
port_value: 443
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment