5.5.4 HTTPS流量网关

将通过Egress gateway进行HTTPS流量透传(由应用程序发起的TLS)。在相应的ServiceEntry、Egress gateway以及VirtualService中指定端口443,协议TLS。

修改ServiceEntry定义如下:


apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: test
spec:
  hosts:
  - istio.io
  ports:
  - number: 80
    name: http-port
    protocol: HTTP
  - number: 443
    name: tls
    protocol: TLS
  resolution: DNS

验证ServiceEntry是否已正确生效。发送HTTPS请求到https://istio.io


kubectl exec -it $SOURCE_POD -c sleep -- curl -sL -o /dev/null -D - https://istio.io
HTTP/2 200
cache-control: public, max-age=0, must-revalidate
content-type: text/html; charset=UTF-8
date: Mon, 21 Jan 2019 20:22:55 GMT
etag: "660e4bd7ded5a3a85a24118433d3f4b2-ssl"
strict-transport-security: max-age=31536000
x-nf-srv-version: 45aaffea081549dd03a2dfff644cc25cf522edbd
age: 120442
content-length: 25833
server: Netlify
x-nf-request-id: f6a3e5cf-9f20-4983-9a91-d0e319e89bcd-9606565

为istio.io创建端口443、TLS协议的Egress gateway。除此之外还创建了一个DestinationRule和VirtualService来引导流量通过Egress gateway与外部服务通信。

如果在Istio中启用了双向TLS认证,请按照如下定义进行更新:


apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: istio-egressgateway
spec:
  selector:
    istio: egressgateway
  servers:
  - port:
      number: 80
      name: https
      protocol: HTTPS
    hosts:
    - istio.io
    tls:
      mode: MUTUAL
      serverCertificate: /etc/certs/cert-chain.pem
      privateKey: /etc/certs/key.pem
      caCertificates: /etc/certs/root-cert.pem
  - port:
      number: 443
      name: tls
      protocol: TLS
    hosts:
    - istio.io
    tls:
      mode: MUTUAL
      serverCertificate: /etc/certs/cert-chain.pem
      privateKey: /etc/certs/key.pem
      caCertificates: /etc/certs/root-cert.pem    
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: egressgateway-for-test
spec:
  host: istio-egressgateway.istio-system.svc.cluster.local
  subsets:
  - name: test
    trafficPolicy:
      loadBalancer:
        simple: ROUND_ROBIN
      portLevelSettings:
      - port:
          number: 80
        tls:
          mode: ISTIO_MUTUAL
          sni: istio.io
      - port:
          number: 443
        tls:
          mode: ISTIO_MUTUAL
          sni: istio.io

如果没有启用双向TLS认证:


apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: istio-egressgateway
spec:
  selector:
    istio: egressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - istio.io
  - port:
      number: 443
      name: tls
      protocol: TLS
    hosts:
    - istio.io
    tls:
      mode: PASSTHROUGH  
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: egressgateway-for-sample
spec:
  host: istio-egressgateway.istio-system.svc.cluster.local
  subsets:
  - name: test

将HTTP请求重新发送到https://istio.io,输出应与之前相同。此时检查Egress gateway代理的统计信息,并查看与我们对istio.io的请求相对应的计数器。如果Istio部署在istio-system命名空间中,则打印计数器的命令是:


kubectl exec -it $(kubectl get pod -l istio=egressgateway -n istio-system -o jsonpath='
{.items[0].metadata.name}') -c istio-proxy -n istio-system -- curl -s localhost:
15000/stats | grep istio.io.upstream_cx_total

cluster.outbound|443||istio.io.upstream_cx_total: 5
cluster.outbound|80||istio.io.upstream_cx_total: 4

如果再执行几个额外的请求,应该会看到每次请求之后上面的计数器都会加1。

最后,清除上述定义的Egress gateway:


kubectl delete -f egressgateway/serviceentry.yaml
kubectl delete -f egressgateway/gw-dr.yaml
kubectl delete -f egressgateway/vs.yaml
kubectl delete -f egressgateway/sleep.yaml

在Istio中定义的Egress gateway,本身并不会对运行Egress gateway服务的节点进行任何特殊处理。集群管理员或云提供商可以在专用节点上部署Egress gateway,并引入额外的安全措施,使这些节点比网格的其余部分更安全。

另外要注意的是,实际上Istio本身无法安全地强制将所有Egress流量流经Egress gateway,Istio仅通过其Sidecar代理启用此类流量。攻击者只要绕过Sidecar代理,就可以不经Egress gateway直接与网格外面的服务进行通信,从而逃避了Istio的控制和监控。集群管理员或云供应商必须确保所有外发流量都从Egress gateway途径发起。

需要用Istio之外的机制来满足这一需求,例如:

·使用防火墙拒绝所有来自Egress gateway以外的流量。

·通过Kubernetes网络策略也能禁止所有不是从Egress gateway发起的Egress流量。

·管理员或者云供应商还可以对网络进行限制,让运行应用的节点只能通过Gateway来访问外部网络。要完成这一限制,可以只给Gateway pod分配公网IP,或者可以配置NAT设备,丢弃来自Egress gateway以外pod的流量。