为 Envoy 启用证书验证
由于微信公众号不能插入外链,请点击 阅读原文 查看原文。
如果你准备将服务暴露在互联网上,最好启用 SSL/TLS
加密协议。当使用 Envoy 作为前端代理或者服务网格代理时,可以通过 SSL/TLS 协议来加密客户端和代理之间的所有通信流量。
Envoy 同时支持监听器中的 TLS 终止 和与上游集群建立连接时的 TLS 发起。不管是为现代 web 服务提供标准的边缘代理功能,还是同具有高级 TLS 要求(TLS1.2, SNI, 等等)的外部服务建立连接,Envoy 都提供了充分的支持。
本文将会演示如何在前端代理中设置 TLS 终止,同时指定访问域名。主要分三个步骤:
创建 Envoy 需要使用的证书
为 Envoy 启用证书验证
配置 Envoy 将 80 端口重定向到 443 端口
1. 创建证书
如果要启用 HTTPS,我们就需要从证书授权机构(以下简称 CA) 处获取一个证书。如果你还没有证书,你可以从 Let’s Encrypt 获得网站域名的免费的证书,因为 Let’s Encrypt 就是一个 CA
。本文为了测试使用 OpenSSL
生成私钥文件 example-com.key
和 自签名证书 example-com.crt
。
需要注意的是 Common Name
字段,本文测试使用的是 example.com
。
2. 为 Envoy 启用证书验证
修改 Dockerfile-frontenvoy
文件:
ADD ./example-com.crt /etc/example-com.crt
ADD ./example-com.key /etc/example-com.key
修改 front-envoy.yaml
配置文件,在 filters
列表后面添加 tls_context
配置项:
tls_context:
common_tls_context:
tls_certificates:
- certificate_chain:
filename: "/etc/example-com.crt"
private_key:
filename: "/etc/example-com.key"
将监听器的监听端口改为标准的 TLS 端口:443。
- address:
socket_address:
address: 0.0.0.0
port_value: 443
还要指定访问的域名,不再使用之前的通配符匹配:
domains:
- "example.com"
Envoy 可以通过在同一个监听器中配置多个监听器过滤器链来支持多个域名的 SNI
(如 example.com 和 www.example.com),你可以在 Envoy 官方文档 中看到一个示例。
最后修改 docker-compose.yaml
文件,将 443 端口暴露出来,同时将 8080 端口替换为 80 端口。
services:
front-envoy:
...
expose:
- "80"
- "443"
ports:
- "80:80"
- "443:443"
重启该示例服务:
$ docker-compose down --remove-orphans
$ docker-compose up --build -d
下面就可以使用 curl 来进行测试了。这里有两个需要注意的地方:
为了确保 curl 能成功验证证书,必须通过
--cacert
参数将证书文件传递给 Envoy。由于 DNS 无法解析 example.com,所以需要通过参数
--connect-to
明确指定连接到 localhost,同时在请求的头文件中申明 localhost 的域名为example.com
。
$ curl --cacert example-com.crt --connect-to localhost -H 'Host: example.com' https://localhost/service/1
Hello from behind Envoy (service 1)! hostname: 56e8a5bff6bd resolvedhostname: 172.18.0.2
如果你的 curl 版本不支持 --connect-to
参数,可以在 /etc/hosts
中添加一个条目:127.0.0.1 example.com
,然后直接通过域名访问:
$ curl --cacert example-com.crt https://example.com/service/1
3. 将 80 端口重定向到 443 端口
为了将所有 80 端口的流量重定向到 443 端口,可以将 443 端口的路由配置复制一份,然后稍作修改:
重启服务:
$ docker-compose down --remove-orphans
$ docker-compose up --build -d
再次通过 HTTP
协议访问 service1,将会返回 301
状态码:
$ curl -I -H 'Host: example.com' http://localhost/service/1
HTTP/1.1 301 Moved Permanently
location: https://example.com/
date: Tue, 03 Jul 2018 06:32:13 GMT
server: envoy
content-length: 0
OK,大功告成!完整的 front-proxy.yaml 配置文件内容如下: