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
模拟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/