SNI细节

由于HTTP的HOST字段在HTTP GET中。而TLS的握手以及证书验证都是在HTTP开始之前。

这个时候,TLS协议的HELLO字段中增加了一个server name字段,让HTTP的client的可以提前

设置HOST,从而使server在tls的握手阶段可以选择证书。

然后,这个机制本身可以抛开http不关心,只要TLS client提前设置了server name,便可以实现SNI

nginx的配置

检测nginx是否支持sni, http://nginx.org/en/docs/http/configuring_https_servers.html#Server%20Name%20Indication

$ nginx -V
TLS SNI support enabled

启用了sni的nginx,如下变量会被赋值

$ssl_server_name

证书命令ssl_certificate,也可以通过变量进行设置,形如:

ssl_certificate     $ssl_server_name.crt;
ssl_certificate_key $ssl_server_name.key;

于是我们可以通过 nginx config中的嵌入逻辑,完成sni的完整配置。

stream {
       upstream test {
               server 127.0.0.1:50001;
       map $ssl_server_name $sni_string {
               test1.www.local test1;
               test2.www.local test2;
               test3.www.local test3;
               default test1;
       map $ssl_server_name $sni_string445 {
               test1.www.local test4451;
               test2.www.local test4452;
               test3.www.local test4453;
               default test4451;
       server {
               listen 444 ssl;
               ssl_certificate /data/sni/sni_${sni_string}.cer;
               ssl_certificate_key /data/sni/sni_${sni_string}.key;
               proxy_pass test;
       server {
               listen 445 ssl;
               ssl_certificate /data/sni445/sni_${sni_string445}.cer;
               ssl_certificate_key /data/sni445/sni_${sni_string445}.key;
               proxy_pass test;

注意,如果希望map命令支持host的最长匹配与正则,需要再添加hostnames关键字。

http://nginx.org/en/docs/http/ngx_http_map_module.html#map

map命令的本质,可以理解为通过旧的变量定义出了一个新的变量。

 模拟tcp客户端的方法:

openssl s_client -connect t9:5000 -CAfile ~/Keys/https/root/root.cer -servername test2.www.local

[openssl][nginx] 使用openssl模拟ssl/tls客户端测试nginx stream

模拟http客户端的方法:

curl --cacert ~/Keys/https/root/root.cer -vvvv  https://test1.tls.local/
curl --cacert ~/Keys/https/root/root.cer -vvvv  https://test2.tls.local/
curl --cacert ~/Keys/https/root/root.cer -vvvv  https://test3.tls.local/
curl --cacert ~/Keys/https/root/root.cer -vvvv  https://test3.www.local/