T91 — mTLS passthrough (HTTPS over mTLS) + connectionPool on both DRs Istio 1.30.0 / k8s 1.30.6 / registry domain homelab.local (istiod --domain homelab.local) Date: 2026-07-05 External target: mock.istio-verify-ext (mendhak/http-https-echo:37, NO sidecar, self-signed HTTPS :443) Dedicated gateway: t91-egress (inject.istio.io/templates: gateway) — shared istio-egressgateway untouched Client: curl pod (sidecar injected), ns istio-vt-t91 ============================================================ [N1] NEGATIVE — tls.mode: tcp is not a valid enum ============================================================ $ kubectl apply -f dr-mode-tcp-invalid.yaml The DestinationRule "t91-invalid-mode" is invalid: * spec.trafficPolicy.tls.mode: Unsupported value: "tcp": supported values: "DISABLE", "SIMPLE", "MUTUAL", "ISTIO_MUTUAL" exit=1 ============================================================ [E1] E2E — client curl https:// via 2-hop path ============================================================ $ kubectl -n istio-vt-t91 exec client -c curl -- curl -sk \ --resolve api.partner.example:443:240.240.34.91 https://api.partner.example/ \ -o /dev/null -w 'http=%{http_code} ssl_verify=%{ssl_verify_result} remote=%{remote_ip}:%{remote_port}\n' http=200 ssl_verify=18 remote=240.240.34.91:443 # ssl_verify=18 = self-signed cert (mock's own) seen by the CLIENT — inner TLS untouched in transit server cert seen by client (curl -v): * SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 / x25519 / RSASSA-PSS * subject: C=GB; ST=London; L=London; O=Mendhak; CN=my.example.com * issuer: C=GB; ST=London; L=London; O=Mendhak; CN=my.example.com # = mock's self-signed cert, NOT any istio/gateway cert -> no re-termination in path echo response (what the SERVER saw): "ip": "::ffff:10.255.126.27", <- t91-egress GATEWAY pod IP (path proof) "protocol": "https", "connection": { "servername": "api.partner.example" }, <- app's INNER SNI arrived intact (blind relay) "clientCertificate": {} <- no client cert on inner TLS (app-side one-way TLS) ============================================================ [P1] PATH — gateway access log + L4 telemetry ============================================================ $ kubectl -n istio-vt-t91 logs deploy/t91-egress --tail=5 | grep -o 'outbound|443||api.partner.example.*' outbound|443||api.partner.example 10.255.126.27:41436 10.255.126.27:8443 10.255.194.79:50570 api.partner.example - outbound|443||api.partner.example 10.255.126.27:41448 10.255.126.27:8443 10.255.194.79:50580 api.partner.example - # downstream 10.255.194.79 = client pod; response flag "-" (success) $ pilot-agent request GET 'stats?filter=api.partner.example' (on gateway) istio_tcp_connections_opened_total{...destination_service=api.partner.example, request_protocol=tcp...}: 3 istio_tcp_connections_closed_total{...}: 3 # L4(istio_tcp_*)로만 잡힘 — 이중 TLS라 L7 지표 없음 (문서 C12와 일치) ============================================================ [C1] DR1 connectionPool -> compiles into CLIENT sidecar cluster (hop1) ============================================================ $ istioctl proxy-config cluster client.istio-vt-t91 \ --fqdn t91-egress.istio-vt-t91.svc.homelab.local -o json | jq '...|partner|...' { "name": "outbound|8443|partner|t91-egress.istio-vt-t91.svc.homelab.local", "max": 111, <- DR1 marker value "connectTimeout": "3s", "ka": { "keepaliveProbes": 3, "keepaliveTime": 300, "keepaliveInterval": 30 }, "tls_sni": "api.partner.example", "tls_sds": ["default"] <- mesh cert via SDS = ISTIO_MUTUAL } ============================================================ [C2] DR2 connectionPool -> compiles into GATEWAY cluster (hop2), NO TLS ============================================================ $ istioctl proxy-config cluster deploy/t91-egress -n istio-vt-t91 \ --fqdn api.partner.example -o json | jq '...outbound|443||api.partner.example...' { "name": "outbound|443||api.partner.example", "max": 222, <- DR2 marker value "connectTimeout": "3s", "ka": { "keepaliveProbes": 3, "keepaliveTime": 300, "keepaliveInterval": 30 }, "transportSocket": "ABSENT (raw TCP)" <- no tls block = no TLS origination } ============================================================ [S1] SPIFFE enforcement on hop1 (gateway 8443 listener) ============================================================ $ istioctl proxy-config listener deploy/t91-egress -n istio-vt-t91 --port 8443 -o json "filterChainMatch": { "serverNames": [...] } "requireClientCertificate": true <- client cert 강제 + mesh CA 검증 ============================================================ [B1] BONUS — exportTo ["."] does not hide DR2 from same-ns sidecars ============================================================ $ istioctl proxy-config cluster client.istio-vt-t91 --fqdn api.partner.example -o json { "name": "outbound|443||api.partner.example", "max": 222, "transportSocket": "ABSENT" } # 같은 ns라 client sidecar에도 DR2가 컴파일됨(무해 — 트래픽은 VS tls 라우트가 gateway로 우회). # 프로덕션 배치(gateway ns=istio-system, client는 타 ns)에선 exportTo ["."]가 의도대로 가림. ============================================================ VERDICT ============================================================ - tls.mode "tcp" : 존재하지 않음 — CRD가 거부 (DISABLE/SIMPLE/MUTUAL/ISTIO_MUTUAL만) - hop2 "일반 TCP"의 정답 : DR2에서 tls 블록 생략(또는 DR 자체 생략/DISABLE) — 실측 raw TCP forward 확인 - connectionPool 배치 : DR1 값은 client sidecar cluster에, DR2 값은 gateway cluster에 각각 컴파일 (발효 위치 원칙 그대로) - E2E : 200 + inner TLS end-to-end 보존 + gateway 경유 + SPIFFE 강제 모두 성립