写在前面
这两天领导让搭建VPC内的测试环境,给了一个外网地址,映射到了一个VPC内的私网的虚IP:192.168.30.100(虚IP用的是keepalived,见下节内容),内网内部署了两个app,都是https的服务,现在需要实现外网访问内网的这些服务,本来是打算用LVS实现的(出现了一些问题,收不到回包,见下下节内容),现在用nginx勉强跑起来了,需要后续优化,本篇作为开篇,简单记录所做的工作,其实主要是记录ssl-passthrough的方案。
| IP | 业务 | 域名 |
|---|---|---|
| 192.168.30.1 | app1 | app1.ctyun.cn |
| 192.168.30.2 | app1 | app1.ctyun.cn |
| 192.168.30.3 | app1 | app1.ctyun.cn |
| 192.168.30.4 | app2 | app2.ctyun.cn |
因为我们backend服务都是自带证书的,所以要越过nginx的证书。
我们之前写过→ingress-controller←的帖子,帖子中介绍了几种ingress的https服务的访问方式,双向认证、termination、pass-through,因为ingress是把nginx包装了一层
,以为nginx配置起来会很容易的,但是还是。。着实的费了一把力气。
利用stream做ssl passthrough
过程不说了,直接上结果,利用了nginx的stream配置,stream其实就是做tcp的转发
stream {
server {
listen 5000;
proxy_pass 192.168.30.54:443;
}
}
ssl passthrough识别SNI(service name indication)
上面的配置还有个缺陷,我只想绑定一个443端口,通过用户访问的域名来区分不同的服务,类似ingress的功能。由于上面的配置只是tcp层面的,他不进行https报文的拆包,所以拿不到任何https相关的字段,怎么能区分用户访问的不同域名呢?
原来nginx可以打开一个预读开关,可以(在握手阶段?)把域名读出来,如下面的preread on。
stream {
map $ssl_preread_server_name $name {
app1.ctyun.cn app1_backend;
app2.ctyun.cn app2_backend;
}
upstream app1_backend {
server 192.168.30.1:8443 weight=5 max_fails=1 fail_timeout=10s;
server 192.168.30.2:8443 weight=5 max_fails=1 fail_timeout=10s;
server 192.168.30.3:8443 weight=5 max_fails=1 fail_timeout=10s;
}
upstream app2_backend {
server 192.168.30.4:443 weight=5 max_fails=1 fail_timeout=10s;
}
server {
listen 443;
proxy_pass $name;
ssl_preread on;
}
}
是不是感觉原来https的也不是绝对安全的?
附录
nginx是一个很不错的项目,值的专门拿出来时间好好研究一下。
在此记下一些nginx的学习计划:
《HTTP 权威指南》
《TCP/IP 详解卷一:协议》
《Lniux 内核设计与实现》/《深入理解 Linux 内核》
《深入理解 Nginx;模块开发与架构解析》
与君共勉,以上↑