envoy를 이용한 HTTP2 대응

10977 단어 SSLenvoygRPChttp2
SRE 팀 소속의 오시마입니다. Advent Calendar는 2년째입니다.

이 기사는 ZOZO 테크놀로지스 #2 Advent Calendar 2019 21일째 기사가 됩니다.

우리는 모두 5 개의 Advent Calendar를 공개합니다.

ZOZO 테크놀로지스 #1 Advent Calendar 2019
ZOZO 테크놀로지스 #2 Advent Calendar 2019
ZOZO 테크놀로지스 #3 Advent Calendar 2019
ZOZO 테크놀로지스 #4 Advent Calendar 2019
ZOZO 테크놀로지스 #5 Advent Calendar 2019

개요



ZOZO 테크놀로지스 #5 Advent Calendar 2019 10일째 기사에 NLB 부하에서 gRPC 통신할 때 생각하는 ALPN 대응 상황 라는 내용이 공개되어 있습니다.
위 기사의 되돌아가서 언급된 다음 내용에 우리 팀에서 직면했습니다.

ALPN 대응의 grpc 라이브러리가 준비되어 있는 Java나 Node.js등의 언어로, 또한 외부 통신용으로 gRPC의 API를 공개(NLB 사용)하는 방식이라고 괴롭다고 생각했습니다.
이 경우, Envoy나 Nginx에 TLS 종단시켜 ACM은 포기하는 방향이 될까요? . .

이 내용에 대해 우리 팀이 어떠한 대처를 했는지 적어 드립니다.

도전



NLB에서 ALPN이 지원되지 않아 gRPC에서 연결 오류가 발생했습니다. 그 때문에 일시적으로 SSL 암호화를 하지 않고 검증하고 있었습니다.


상기 상태를 해소하기 위해 이번에는 envoy에서 SSL 종단을 실시했습니다.
평상시라면 ELB에서의 SSL 종단을 실시하고 있었으므로, 최초의 검증이 되었습니다.
이쪽이 구축 이미지가 됩니다.

Client-envoy간은 암호화해, envoy에서 복합하도록(듯이) 설계했습니다.

실시 작업 사항


  • SSL 인증서 준비, 배치
  • envoy에서 TLS 설정 추가
  • envoy 수신 포트를 443으로 변경
  • NLB의 ListenerPort를 443으로 변경
  • 동작 확인

  • SSL 인증서 준비, 배치



    이번은 검증을 위해 자기 서명 증명서를 이용합니다.
    $ openssl req -nodes -x509 -newkey rsa:4096 -keyout example-com.key -out example-com.crt -days 365
    

    그리고/etc/아래에 배치합니다.
    ADD ./example-com.crt /etc/server.crt
    ADD ./example-com.key /etc/server.key
    

    envoy에서 TLS 설정 추가


             tls_context:
                common_tls_context:
                  alpn_protocols: 
                    - "h2,http/1.1"
                  tls_certificates:
                    - certificate_chain:
                        filename: "/tmp/server.crt"
                      private_key:
                        filename: "/tmp/server.key"
    

    들여쓰기에 주의하십시오. 나는 어긋나고 빠졌으므로, 이하를 참고에 부디.
    참고 : Example configuration

    envoy의 Port를 443으로 변경


             ports:
                - name: https
                  containerPort: 443
    

    상기 이외에, 헬스 체크 등의 Port도 443으로 변경해 주세요.

    NLB의 ListenerPort를 443으로 변경


    apiVersion: v1
    kind: Service
    metadata:
      name: envoy
      annotations:
        service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
    spec:
      type: LoadBalancer
      selector:
        app: envoy
      ports:
        - name: https
          protocol: TCP
          port: 443
          targetPort: 443
    

    동작 확인


    $ curl -k -vvv --http2-prior-knowledge https://test.com:443
    * Rebuilt URL to: https://test.com:443/
    *   Trying XX.XX.XX.XX...
    * TCP_NODELAY set
    * Connected to test.com (XX.XX.XX.XX) port 443 (#0)
    * ALPN, offering h2
    * ALPN, offering http/1.1
    * Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
    * successfully set certificate verify locations:
    *   CAfile: /etc/ssl/cert.pem
      CApath: none
    * TLSv1.2 (OUT), TLS handshake, Client hello (1):
    * TLSv1.2 (IN), TLS handshake, Server hello (2):
    * TLSv1.2 (IN), TLS handshake, Certificate (11):
    * TLSv1.2 (IN), TLS handshake, Server key exchange (12):
    * TLSv1.2 (IN), TLS handshake, Server finished (14):
    * TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
    * TLSv1.2 (OUT), TLS change cipher, Client hello (1):
    * TLSv1.2 (OUT), TLS handshake, Finished (20):
    * TLSv1.2 (IN), TLS change cipher, Client hello (1):
    * TLSv1.2 (IN), TLS handshake, Finished (20):
    * SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
    * ALPN, server accepted to use h2
    * Server certificate:
    *  subject: C=AU; ST=Some-State; O=Internet Widgits Pty Ltd; CN=test.com
    *  start date: Dec 20 06:44:26 2019 GMT
    *  expire date: Dec 19 06:44:26 2020 GMT
    *  issuer: C=AU; ST=Some-State; O=Internet Widgits Pty Ltd; CN=test.com
    *  SSL certificate verify result: self signed certificate (18), continuing anyway.
    * Using HTTP2, server supports multi-use
    * Connection state changed (HTTP/2 confirmed)
    * Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
    * Using Stream ID: 1 (easy handle 0x7fc69d004400)
    > GET / HTTP/2
    > Host: test.com
    > User-Agent: curl/7.54.0
    > Accept: */*
    > 
    * Connection state changed (MAX_CONCURRENT_STREAMS updated)!
    < HTTP/2 404 
    < content-length: 0
    < date: Mon, 23 Dec 2019 03:00:57 GMT
    < server: envoy
    < x-envoy-upstream-service-time: 27
    < 
    * Connection #0 to host test.com left intact
    

    안전한 TLS에서 핸드 셰이크를 통과하고 HTTP2로 통신 할 수있었습니다.
    적당한 패스를 curl하고 있으므로, 404가 나와 있습니다만 일단 검증으로서는 완료로 합니다.

    요약



    현재는 검증 단계이므로, 추가로 깨달은 적이 있으면 다른 기사에서 갱신하겠습니다.
    끝까지 교제 해 주셔서 감사합니다!

    참고
    SETTING UP SSL IN ENVOY

    좋은 웹페이지 즐겨찾기