SNI技术的妙用

SNI即服务器名称指示,是TLS的扩展,通过在client hello消息中加入服务名,来实现同一端口多证书(之前因为无法在连接加密前获取服务名称,导致服务器只能使用一张证书)。

目前SNI主要用于HTTPS协议,实现同一服务器多域名。

但其实SNI还有一种特殊用途:SNI代理。SNI代理类似TCP代理,原理就是client把client hello发给proxy,proxy解析出client实际要访问的target,然后proxy去连接target,连接成功后把client hello原封不动地发往target,随后proxy要做的只是把client发来的数据转向target,把target发来的数据转向client。与tcp代理不同,SNI代理是安全的,因为proxy没有私钥,无法解密client发送的数据,也就没有办法计算随后生成的对称密钥。

以前由于无法获取目标服务器名只能静态代理或者反向代理HTTPS网站,有了SNI,动态代理也得以实现。所以一些运营商会通过架设具有高出口带宽的SNI代理服务器,然后劫持用户请求到代理服务器的方式来实现访问加速。

而这些运营商架设的SNI代理大都没有对client和target进行限制,所以就有了以下两种妙用。

一、绕过墙

因为墙目前没有对SNI进行检测,所以通过把被封网站的IP解析到境外的SNI代理服务器就可以实现对封锁网站的访问。但是这种方法只能访问HTTPS网站,而且需要手动配置hosts或dnsmasq,比较麻烦。而chrome插件SwitchyOmega有一项专门用来配置https代理,如果利用SNI代理搭建一个本地代理,再结合这个插件使用会非常方便。以下是利用SNI代理搭建本地代理的python代码,更改其中的serverip为实际境外SNI代理ip即可,本地http代理端口为4433.

 

二、SSH加速

因为这些SNI代理的出口带宽很高,所以通过境内SNI代理访问境外VPS应该比普通宽带用户快。理论上通过把SSHD监听在vps的443端品,然后把原本解析到VPS IP的域名通过hosts改为SNI代理IP,然后就能实现对SSH访问进行加速了,而且通过ssh的动态转发代理访问网站也变快了。但是有以下问题 :

1.SSH目前不支持SNI

这个可以通过socat程序来解决,socat刚刚添加对SNI的支持。如果没有或者用不了socat也可以用python写一个,很简单,就是把两个socket连接起来。

 服务端: socat  openssl-listen:443,fork,reuseaddr   tcp:localhost:22
客户端: socat tcp-l:22,fork,reuseaddr  openssl:SniProxyIp:443,snihost=test.com

然后客户端 ssh user@localhost 就可以了。

2.SSH与HTTPS共享443端口

HTTP是请求响应式的,所以没有办法把SSH包装到HTTP协议中。只能通过监听在443端口,然后根据client hello中的server name来判断转发到HTTPS还是SSH,这个功能可以通过sniproxy程序来实现。具体流程:让nginx/apache的HTTPS监听在端口A,让上面的socat监听在端口B。然后修改sniproxy.conf:

注意test.com要位于最后,否则子域的配置会失效。

发表评论

电子邮件地址不会被公开。 必填项已用*标注