Total Pageviews

Monday 14 March 2016

用bind+stunnel+sni proxy翻墙

这里主要介绍电脑无需任何设置,就能够自动加密代理特定网站的HTTP/HTTPS协议。

方案介绍

涉及到的软件
BIND: 一个流行的域名解析服务器,我们可以设置哪些域名需要走加密线路。
Stunnel: 使用TLS对tcp协议进行加密,也就是对tcp建立一条加密线路。
SNI Proxy: 代理软件。对于HTTP协议,它可以根据Host请求头解析得出目标站IP;对于HTTPS协议,它可以根据SNI扩展中的域名解析得出目标站IP。

此方案优缺点
优点:
无需手动设置任何代理,就能够自动加密代理特定网站的HTTP或HTTPS协议
相对于我们常用的ssh隧道,ssh隧道是单路,而此方案是支持多并发连接,可以极大加速网站访问。
缺点:
对于代理HTTPS协议,需要发起HTTPS连接的客户端,比如浏览器支持TLS的SNI扩展。好消息是目前浏览器几乎都支持此扩展,但对于一些非浏览器的客户端,不支持SNI扩展。我们只能设置正向代理来解决此问题。

方案原理
流程图:


原理介绍:
1、首先我们需要准备三台服务器,一台是内网DNS服务器(安装bind),一台是内网代理服务器(安装stunnel),另一台国外服务器(安装stunnel,sniproxy)。
2、我们还需要设置DNS为内网的DNS,并在内网bind dns设置谷歌域名解析的IP为内网代理服务器
3、当我们访问谷歌网站时,首先会向内网DNS服务器发送DNS A记录查询,此时内网DNS服务器会返回内网代理服务器的IP。
4、浏览器得到谷歌域名的解析IP后(即内网代理服务器的IP),会向内网代理服务器发送HTTP或HTTPS请求。
5、此时内网代理服务器(即stunnel),会接收到请求,经过加密,把请求转发到国外服务器(stunnel)的指定端口上。
6、国外服务器(stunnel)接收到来自国内服务器(stunnel)的加密数据后,经过解密,把请求转发到sniproxy。
7、sniproxy再根据HTTP Host请求头或者HTTPS sni扩展的域名解析出谷歌服务器的IP,并把请求转发给谷歌服务器。
8、谷歌服务器收到来自sniproxy发送的请求后,马上返回网页内容给sniproxy,sniproxy再原路返回数据给浏览器。

方案实施
由于时间有限,我们仅在Ubuntu server 12.04演示安装。
环境介绍
系统:Ubuntu server 12.04
内网DNS IP: 10.96.153.201(主),10.96.153.204(从)
内网代理服务器: 10.96.153.204
国外服务器IP: 1.2.3.4

安装BIND9
1、在主DNS和从DNS安装bind,即10.96.153.201(主),10.96.153.204(从)。
wget http://www.isc.org/downloads/file/bind-9-10-0b1-2/?version=tar.gz -O bind-9-10-0b1-2.tar.gz
tar xzf bind-9-10-0b1-2.tar.gz
cd bind-9-10-0b1-2
./configure --prefix=/usr/local/bind
make && make install


2、配置主DNS服务器(10.96.153.201)
2.1、生成/usr/local/bind/etc/rndc.key密钥文件
/usr/local/bind/sbin/rndc-confgen -a -k rndckey -c /usr/local/bind/etc/rndc.key
2.2、编辑/usr/local/bind/etc/named.conf,写入如何内容:
include "/usr/local/bind/etc/rndc.key";
controls { inet 127.0.0.1 port 953 allow { 127.0.0.1; } keys { "rndckey"; }; };
logging {
channel default_syslog { syslog local2; severity notice; };
channel audit_log { file "/var/log/bind.log"; severity notice; print-time yes; };
category default { default_syslog; };
category general { default_syslog; };
category security { audit_log; default_syslog; };
category config { default_syslog; };
category resolver { audit_log; };
category xfer-in { audit_log; };
category xfer-out { audit_log; };
category notify { audit_log; };
category client { audit_log; };
category network { audit_log; };
category update { audit_log; };
category queries { audit_log; };
category lame-servers { audit_log; };
};
options {
    directory "/usr/local/bind/etc";
pid-file "/usr/local/bind/var/run/bind.pid";
transfer-format many-answers;
interface-interval 0;
forward only;
forwarders { 202.96.128.166;202.96.134.133; };
allow-query {any;};
};
zone "google.com" {
type master;
file "google.com.zone";
allow-transfer { 10.96.153.204; };
};
在这个named.conf文件中,我们只需要关心如下内容:
对于options{}区域,202.96.128.166和202.96.134.133这两个是ISP提供的本地DNS,需要修改为自己所在ISP的本地DNS。
对于zone “google.com”{}区域,这里定义了google.com域名的区域文件google.com.zone,还有允许10.96.153.204(即从DNS)同步区域文件。
2.3、建立google.com.zone区域文件
$TTL 3600
@ IN SOA ns1.google.com. hostmaster.google.com. (
2014072015  ; Serial
3600 ; Refresh
900 ; Retry
3600000 ; Expire
3600 ) ; Minimum
@ IN NS ns1.google.com.
@ IN NS ns2.google.com.
ns1 IN A 10.96.153.201
ns2 IN A 10.96.153.204
@ IN A 10.96.153.204
* IN A 10.96.153.204
对于这个区域文件,
ns1 IN A 10.96.153.201 指向第一个dns服务器,即主DNS。
ns2 IN A 10.96.153.204 指向第二个dns服务器,即从DNS。
@ IN A 10.96.153.204和* IN A 10.96.153.204指向内网的代理服务器(stunnel)。我们只需要修改这三个地方就好了。


3、配置从DNS服务器(10.96.153.204)
编辑named.conf,写入如下内容
logging {
channel default_syslog { syslog local2; severity notice; };
channel audit_log { file "/var/log/bind.log"; severity notice; print-time yes; };
category default { default_syslog; };
category general { default_syslog; };
category security { audit_log; default_syslog; };
category config { default_syslog; };
category resolver { audit_log; };
category xfer-in { audit_log; };
category xfer-out { audit_log; };
category notify { audit_log; };
category client { audit_log; };
category network { audit_log; };
category update { audit_log; };
category queries { audit_log; };
category lame-servers { audit_log; };
};
options {
    directory "/usr/local/bind/etc";
pid-file "/usr/local/bind/var/run/bind.pid";
transfer-format many-answers;
interface-interval 0;
forward only;
forwarders { 202.96.128.166;202.96.134.133; };
allow-query {any;};
};

zone "google.com" {
type slave;
file "google.com.zone";
masters { 10.96.153.201; };
};
配置从DNS就简单得多,只需要写入如上内容到named.conf文件。同样的,
options{}中202.96.128.166和202.96.134.133这两个是当地ISP本地dns。
zone “google.com”{}中10.96.153.201指明主DNS服务器IP。
4、启动bind dns服务器
/usr/local/bind/sbin/named
安装Stunnel
1、在内网代理服务器和国外主机安装stunnel
apt-get install stunnel4
2、内网代理服务器stunnel配置
编辑/etc/default/stunnel4,设置ENABLED=1。
编辑/etc/stunnel/stunnel.conf,内容如下:
client = yes
pid = /etc/stunnel/stunnel.pid
[http]
accept = 80
connect = 1.2.3.4:8082

[https]
accept = 443
connect = 1.2.3.4:4433
此配置文件表示,监听了80端口,并把此端口流量转发到1.2.3.4:8082,监听了443端口,并把此端口流量转发到1.2.3.4:4433
3、国外服务器stunnel配置
3.1、生成ssl证书stunnel.pem文件
openssl genrsa -out key.pem 2048
openssl req -new -x509 -key key.pem -out cert.pem -days 1095
cat key.pem cert.pem >> /etc/stunnel/stunnel.pem
3.2、编辑/etc/stunnel/stunnel.conf文件
client = no
[http]
accept = 1.2.3.4:8082
connect = 127.0.0.1:8082
cert = /etc/stunnel/stunnel.pem

[https]
accept = 1.2.3.4:4433
connect = 127.0.0.1:4433
cert = /etc/stunnel/stunnel.pem
此配置文件表示,监听了1.2.3.4:8082,并转发此地址流量到127.0.0.1:8082,监听了1.2.3.4:4433,并转发给地址流量到127.0.0.1:4433。
3.3、编辑/etc/default/stunnel4,设置ENABLED=1。
4、启动stunnel
service stunnel4 start
安装sniproxy
sniproxy项目地址:https://github.com/dlundquist/sniproxy
1、安装sniproxy
同样只演示在ubuntu server 12.04安装。
1.1、安装UDNS
mkdir udns_packaging
cd udns_packaging
wget http://archive.ubuntu.com/ubuntu/pool/universe/u/udns/udns_0.4-1.dsc
wget http://archive.ubuntu.com/ubuntu/pool/universe/u/udns/udns_0.4.orig.tar.gz
wget http://archive.ubuntu.com/ubuntu/pool/universe/u/udns/udns_0.4-1.debian.tar.gz
tar xfz udns_0.4.orig.tar.gz
cd udns-0.4/
tar xfz ../udns_0.4-1.debian.tar.gz
dpkg-buildpackage
cd ..
dpkg -i *.deb
1.2、安装sniproxy
apt-get install autotools-dev cdbs debhelper dh-autoreconf dpkg-dev gettext libev-dev libpcre3-dev libudns-dev pkg-config
wget https://github.com/dlundquist/sniproxy/archive/master.zip
unzip master.zip
cd sniproxy-master/
dpkg-buildpackage
cd ..
dpkg -i *.deb
2、配置sniproxy
/etc/sniproxy.conf内容如下:
user daemon
pidfile /var/run/sniproxy.pid
error_log {
    syslog deamon
    priority notice
}
listen 127.0.0.1:8082 {
    proto http
    table http_hosts
}
table http_hosts {
        .*      *:80
}

listen 127.0.0.1:4433 {
    proto tls
    table https_hosts
}
table https_hosts {
.* *:443
}
此配置文件表示,监听了127.0.0.1:8082地址,并解析http协议中的Host请求头为IP,然后转发请求到此IP;监听了127.0.0.1:4433地址,并解析TLS中SNI扩展中的域名为IP,并转发请求到此IP。
3、启动sniproxy:
sniproxy

结束
到目前为止,我们已经搭建完成了整套HTTP/HTTPS加密代理方案。方案中的HTTP明文协议,利用stunnel使用了TLS加密,变成了HTTPS协议,使得数据包无法被解析出明文。方案中的HTTPS协议,本身是加密的,但为了防止SNI扩展的中域名被嗅探,还是走了stunnel的加密通道。对于发送HTTPS请求而不支持SNI扩展的客户端,需要手动设置下代理。

相关帖子:
http://briteming.blogspot.com/2015/08/dnsmasq-dnscrypt-sni-proxy.html
http://briteming.blogspot.com/2012/01/vpsstunnel.html
-------------------------------------

SNI Proxy

Proxies incoming HTTP and TLS connections based on the hostname contained in the initial request of the TCP session. This enables HTTPS name-based virtual hosting to separate backend servers without installing the private key on the proxy machine.

News

First user survey, please take a moment to offer your input.

Features

  • Name-based proxying of HTTPS without decrypting traffic. No keys or certificates required.
  • Supports both TLS and HTTP protocols.
  • Supports IPv4, IPv6 and Unix domain sockets for both back end servers and listeners.
  • Supports multiple listening sockets per instance.

Usage

Usage: sniproxy [-c <config>] [-f] [-n <max file descriptor limit>] [-V]
    -c  configuration file, defaults to /etc/sniproxy.conf
    -f  run in foreground, do not drop privileges
    -n  specify file descriptor limit
    -V  print the version of SNIProxy and exit

Installation

For Debian or Fedora based Linux distributions see building packages below.
Prerequisites
  • Autotools (autoconf, automake, gettext and libtool)
  • libev4, libpcre and libudns development headers
  • Perl and cURL for test suite
Install
./autogen.sh && ./configure && make check && sudo make install
Building Debian/Ubuntu package
This is the preferred installation method on recent Debian based distributions:
  1. Install required packages
    sudo apt-get install autotools-dev cdbs debhelper dh-autoreconf dpkg-dev gettext libev-dev libpcre3-dev libudns-dev pkg-config fakeroot devscripts
    
  2. Build a Debian package
    ./autogen.sh && dpkg-buildpackage
    
  3. Install the resulting package
    sudo dpkg -i ../sniproxy_<version>_<arch>.deb
    
Building Fedora/RedHat package
This is the preferred installation method for modern Fedora based distributions.
  1. Install required packages
    sudo yum install autoconf automake curl gettext-devel libev-devel pcre-devel perl pkgconfig rpm-build udns-devel
    
  2. Build a distribution tarball:
    ./autogen.sh && ./configure && make dist
    
  3. Build a RPM package
    rpmbuild --define "_sourcedir `pwd`" -ba redhat/sniproxy.spec
    
  4. Install resulting RPM
    sudo yum install ../sniproxy-<version>.<arch>.rpm
    
I've used Scientific Linux 6 a fair amount, but I prefer Debian based distributions. RPM builds are tested in Travis-CI on Ubuntu, but not natively. This build process may not follow the current Fedora packaging standards, and may not even work.
Building on OS X with Homebrew
  1. install dependencies.
    brew install libev pcre udns autoconf automake gettext libtool
    
  2. Read the warning about gettext and force link it so autogen.sh works. We need the GNU gettext for the macro AC_LIB_HAVE_LINKFLAGS which isn't present in the default OS X package.
    brew link --force gettext
    
  3. Make it so
    ./autogen.sh && ./configure && make
    
OS X support is a best effort, and isn't a primary target platform.

Configuration Syntax

user daemon

pidfile /tmp/sniproxy.pid

error_log {
    syslog daemon
    priority notice
}

listener 127.0.0.1:443 {
    protocol tls
    table TableName

    # Specify a server to use if the initial client request doesn't contain
    # a hostname
    fallback 192.0.2.5:443
}

table TableName {
    # Match exact request hostnames
    example.com 192.0.2.10:4343
    example.net [2001:DB8::1:10]:443
    # Or use regular expression to match
    .*\\.com    [2001:DB8::1:11]:443
    # Combining regular expression and wildcard will resolve the hostname
    # client requested and proxy to it
    .*\\.edu    *:443
}

DNS Resolution

Using hostnames or wildcard entries in the configuration requires sniproxy to be built with UDNS. SNIProxy will still build without UDNS, but these features will be unavailable.
UDNS uses a single UDP socket for all queries, so it is recommended you use a local caching DNS resolver (with a single socket each DNS query is protected by spoofing by a single 16 bit query ID, which makes it relatively easy to spoof).
UDNS is currently not available in Debian stable, but a package can be easily built from the Debian testing or Ubuntu source packages:
mkdir udns_packaging
cd udns_packaging
wget http://archive.ubuntu.com/ubuntu/pool/universe/u/udns/udns_0.4-1.dsc
wget http://archive.ubuntu.com/ubuntu/pool/universe/u/udns/udns_0.4.orig.tar.gz
wget http://archive.ubuntu.com/ubuntu/pool/universe/u/udns/udns_0.4-1.debian.tar.gz
tar xfz udns_0.4.orig.tar.gz
cd udns-0.4/
tar xfz ../udns_0.4-1.debian.tar.gz
dpkg-buildpackage
cd ..
sudo dpkg -i libudns-dev_0.4-1_amd64.deb libudns0_0.4-1_amd64.deb
from https://github.com/dlundquist/sniproxy
-------------

部署 SNI Proxy 加速网页访问 反代 无需证书

我们都知道可以使用 nginx 反代功能来实现跨境访问外网,不过,这种方式有很多的制约,比如说很难实现登录验证,比如说需要针对转发模块单独做编译,比如说需要你有一个有效的 ssl 签名证书等等。
这次,我们来介绍另外一款神器 SNI Proxy,是用 dnsmasq 配合 sniproxy 可以实现无证书任意网站反代。它使用SNI 技术将 TLS 连接通过 TCP 代理到目标网站,这样就避免了对代理服务器的证书需求,而且访问到的网站证书也是原原本本的证书。

编译 SNI Proxy(可以跳过)

示例环境为 Ubuntu 14.04
从git上克隆 sni的源文件: https://github.com/dlundquist/sniproxy.git

准备环境

安装配置 SNI Proxy

编辑 /etc/sniproxy.conf来开启反代:
像上边这样开启针对某个域名的反代,但是这样太麻烦了,每次新增加一个网站,都需要对这个列表增加——为此,我们为了方便稍微牺牲一点安全性——且我不需要对邮件进行反代(容易被滥用,国外对垃圾邮件服务器是深恶痛绝的。),那么我可以直接这样写:
这样就只打开了 https 反代,而且是只要被解析到这个服务器的域名都会被反代,这样一来,我们就可以只通过 dnsmasq 的解析来控制哪个域名反代了。(有那么一点安全隐患就是一旦被别人发现,你可能你服务器的流量会意外流失咯~记得监控你的服务器带宽?)

运行 sniproxy

直接使用命令sniproxy 即可运行,默认配置文件就是“/etc/sniproxy.conf”它会自动加载,如果你使用了其他路径或者配置文件名,那么你需要使用“-c”选项来指定路径:

端口重定向

那么,一般我们访问网站不喜欢输入端口号或者协议名称,那么默认访问的是80端口怎么办?作为辅助,我们安装一个轻量级的 nginx,让它把所有访问80端口的流量转移到443上边去,使用301重定向即可。
我们编辑 nginx 的配置文件“/etc/nginx/sites-available/default
改为如下内容:

域名解析

sniproxy 搭建成功,但是它是不能被直接访问的,你需要将域名解析过去,这样它才能根据域名来代理你的 ssl 链接,那么你可能就需要在自己的 hosts 上修改解析啦。
-----------


SNI proxies

David Fifield, Jiang Jian, Paul Pearce

Code and data download:

An investigation into SNI proxies, special servers that forward TLS streams to the host specified in the Server Name Indication field (SNI) of the TLS handshake. SNI proxies could be useful for Internet censorship circumvention or censorship measurement. We manually investigated and characterized a small number of SNI proxies that had been publicly reported, and did a targeted scan of the IPv4 space to find how many there are. Our scan of port 443 on found 2,500 SNI proxies on the Internet.

Background

An SNI proxy is a TLS server that proxies traffic to any destination given in the Server Name Indication field (SNI). An SNI proxy receives connections on port 443, peeks at the SNI, then forwards the connection to the host given in the SNI. It's not a MITM; the proxy forwards the client's ClientHello and all other traffic unmodified, and the client has a true end-to-end TLS connection to the server, through the SNI proxy. An SNI proxy is like an open proxy, with the restriction that it only works for port 443 and only for TLS.
We first heard of SNI proxies from people in China who were using the proxies to circumvent Internet censorship. (See for example https://github.com/phuslu/goproxy/issues/853.) We speculated that the SNI proxies might be related to ad injection by ISPs on port 80. The ISP falsifies DNS responses to point to its own ad-injection proxy server, which injects ads into HTTP on port 80. But the DNS-based redirection cannot redirect plain HTTP without also redirecting HTTPS. The proxy cannot tamper with the HTTPS, but it also cannot cannot cause HTTPS to break; therefore it just proxies the HTTPS unmodified.
SNI proxying is a standard feature of various firewalls and proxies. HAProxy has it:
http://blog.haproxy.com/2012/04/13/enhanced-ssl-load-balancing-with-server-name-indication-sni-tls-extension/ https://trick77.com/haproxy-and-sni-based-ssl-offloading-with-intermediate-ca/
There are a few projects on GitHub doing it:
https://github.com/dlundquist/sniproxy https://github.com/gpjt/stupid-proxy https://github.com/yrutschle/sslh
We found some servers in the wild that do it, with brand names like Sophos and Blue Coat.

Potential applications and hazards of SNI proxies

The obvious application of SNI proxies is the circumvention of Internet censorship, against a censor that blocks IP addresses and DNS requests but does not examine the SNI field of TLS connections. You can access a blocked HTTPS server by connecting to it indirectly through an SNI proxy located beyond the censor's control. It doesn't even require any special client-side software, just modification of the hosts file. For example, if https://example.com/ is blocked by the censor, and 192.0.2.100 is an SNI proxy, add this line to the hosts file:
192.0.2.100 example.com
You could use SNI proxies to measure censorship. An SNI proxy inside the network controlled by the censor serves as a vantage point to test the reachability of destinations outside the censor's network (port 443 only).
It might be possible to DoS an SNI proxy by asking it to connect to 127.0.0.1, or explore an internal network by giving it a private IP address. Technically, "literal IPv4 and IPv6 addresses are not permitted" in the SNI field (RFC 4366). Even if the SNI proxy does not support an IP address in SNI, it would be easy to set up a DNS server that gives every IP address a domain name (e.g. 127.0.0.1.example.com → 127.0.0.1). There are already some public names that map to internal addresses, like fuf.me → 127.0.0.1.

The GoProxy SNI proxy list

We started by looking at 26 purported SNI proxy IP addresses from a ticket of GoProxy, a circumvention system:
https://github.com/phuslu/goproxy/issues/853
We probed them all on ports 80 and 443 (with and without SNI), with the goal of characterizing in detail some specific SNI proxy implementations. Of the 26 IP addresses, 10 were no longer running, and among the remaining ones we found three distinct fingerprints. On port 80 (HTTP), we saw three distinct responses, described in the next subsection. On port 443 (HTTPS), we saw two distinct behaviors, described in the following subsection.
This table summarizes the results of our manual check of the 26 IP addresses from the GoProxy ticket. "—" means the TCP connection failed.
host HTTP HTTPS HTTPS+SNI reverse DNS
45.127.92.217
103.15.187.54 dns.auth.fail alert proxies 103-15-187-54.op-net.com
110.4.12.173
110.4.12.175
110.4.12.176
110.4.12.178
110.4.24.170 ChinaCache silence proxies
110.4.24.175 ChinaCache silence proxies
110.4.24.176 HAProxy silence proxies
110.4.24.178 HAProxy silence proxies
182.239.95.136 182.239.95.136.hk.chinamobile.com
182.239.95.137 182.239.95.137.hk.chinamobile.com
182.239.127.136 182.239.127.136.hk.chinamobile.com
182.239.127.137 182.239.127.137.hk.chinamobile.com
203.78.36.234 m203-78-36-234.smartone.com
218.254.1.13 ChinaCache silence proxies cm218-254-1-13.hkcable.com.hk
218.254.1.15 ChinaCache silence proxies cm218-254-1-15.hkcable.com.hk
219.76.4.3 HAProxy silence proxies tswc5b003.netvigator.com
219.76.4.4 HAProxy silence proxies tswc5b004.netvigator.com
219.76.4.9 ChinaCache silence proxies tswc5b009.netvigator.com
219.76.4.11 ChinaCache silence proxies tswc5b011.netvigator.com
219.76.4.14 ChinaCache silence proxies tswc5b014.netvigator.com
219.76.4.69 HAProxy silence proxies tswc5b069.netvigator.com
219.76.4.70 HAProxy silence proxies tswc5b070.netvigator.com
219.76.4.75 ChinaCache silence proxies tswc5b075.netvigator.com
219.76.4.76 ChinaCache silence proxies tswc5b076.netvigator.com

HTTP fingerprints

On port 80, we found 3 distinct HTTP fingerprints, not counting no-responses:
9 ChinaCache
6 HAProxy
1 dns.auth.fail
10 no response

The "ChinaCache" HTTP fingerprint

HTTP/1.0 404 Not Found
Server: FC
Date: Fri, 16 Sep 2016 17:53:42 GMT
Content-Type: text/html
Content-Length: 432
Powered-By-ChinaCache: MISS from PCW-HK-3-3X5.8
Connection: close

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML><HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=gb2312">
<TITLE>错误:您所请求的网址(URL)无法获取</TITLE>
<STYLE type="text/css"><!--BODY{background-color:#ffffff;font-family:verdana,sans-serif}PRE{font-family:sans-serif}--></STYLE>
</HEAD><BODY>
<H1>错误</H1>
<H2>您所请求的网址(URL)无法获取</H2>
The Chinese text, originally encoded in gb2312, means "Error: The requested URL (URL) could not be retrieved." The Powered-By-ChinaCache header varies, apparently reflecting the server name.

The "HAProxy" HTTP fingerprint

HTTP/1.0 403 Forbidden
Cache-Control: no-cache
Connection: close
Content-Type: text/html

<html><body><h1>403 Forbidden</h1>
Request forbidden by administrative rules.
</body></html>
Nmap identifies this response as HAProxy.

The "dns.auth.fail" HTTP fingerprint

HTTP/1.0 302 Found
Location: http://dns.auth.fail/
Content-Length: 0
Connection: close
Date: Fri, 16 Sep 2016 17:53:57 GMT
Server: lighttpd/1.4.35
This is a weird one, covered in a separate document.

HTTPS fingerprints

On port 443, we found 2 distinct fingerprints, not counting no-responses. The 10 no-responses are the same 10 as for HTTP.
15 with SNI, proxies; without SNI, sends nothing
1 with SNI, proxies; without SNI, sends TLS "handshake failure" alert
10 no response
When provided with an SNI, all the responsive servers were indistinguishable because they just proxied the connection. Without an SNI, most of the servers simply sent nothing in return; the only exception was the single "dns.auth.fail" server, which sent a TLS alert. It makes sense that an SNI proxy would not be able to do anything useful when not supplied with an SNI.
This is what we did to connect without SNI:
timeout 10 openssl s_client -ign_eof -connect $host:443
And with SNI:
timeout 10 openssl s_client -ign_eof -connect $host:443 -servername www.example.com
To check for proxying, we looked for the proper server certificate:
subject=/C=US/ST=California/L=Los Angeles/O=Internet Corporation for Assigned Names and Numbers/OU=Technology/CN=www.example.org
issuer=/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 High Assurance Server CA

With SNI, proxies; without SNI, sends nothing

Providing SNI causes the server to proxy to the desired destination.
Omitting SNI causes the server to send nothing after receiving the ClientHello, and terminate the connection after a few seconds.

With SNI, proxies; without SNI, sends TLS "handshake failure" alert

This fingerprint was only seen on one host, the dns.auth.fail one.
Providing SNI causes the server to proxy to the desired destination.
Omitting SNI causes the server to send a TLS "handshake failure" alert, viz.:
15 03 01 00 02 02 28
Incidentally, you get the same alert if you send a plaintext HTTP request to port 443.

Scanning for SNI proxies

We did a scan of the IPv4 space on port 443 on and found 2,500 SNI proxies. We used ZMap and a custom program, scan-sniproxy. scan-sniproxy simply connects to an IP address, does a TLS handshake with a given SNI, does certificate validation, and saves a hash of the leaf certificate (as proof that the IP address actually proxied to the destination given in the SNI).
For this experiment, we set up a dedicated HTTPS server at the domain sni-scan-for-research-study.bamsoftware.com. The experiment doesn't require a dedicated server—you could use any HTTPS server—but we wanted to be able to host a web page with contact information in case anyone objected to the scan. (A copy of the web page.) We also wanted to capture and observe the traffic arriving at the server specified in the SNI. If you want to look at the traffic information, see 443.pcap.xz, access.log, error.log, and ssl.log in the scan-sniproxy-20161024.0 subdirectory of the source code.
This is the command line we used:
zmap -p 443 --output-fields=* -r 150000 -u zmap_updates.log -l zmap_log.log -v5 -q | \
  ztee -u ztee_updates.csv zmap_output.csv | \
  scan-sniproxy -input /dev/stdin -maxprocs 4 -maxthreads 10000 -timeout 10s > scan-sniproxy.csv
The scan found 2,500 SNI proxies. You can download a CSV file: scan-sniproxy-20161024.0.proxiesonly.csv. Here they are along with reverse DNS:
There are concentrations of SNI proxies in certain networks:
40.6% are *.rdns.cloudradium.com
6.4% are 101.95.144.68-71, 101.96.9.138-165, 101.96.10.19-74, 101.96.11.19-74, 101.110.119.19-75
5.2% are *.protectedgroup.com (23.19.41.90-94, 23.19.93.2-126)
5.0% are 213.184.119.2-126
Clearly, cloudradium.com is a heavy hitter when it comes to SNI proxies. We did not find out much information about cloudradium.com, whatever it may be. Anthony Joseph found for us a fraud report for "CloudRadium LLC" from 2014 complaining about the accumulation of IP addresses:
Fri Oct 10 01:33:25 EDT 2014
Fraud Report on one of your current member
Some basic info about the company who has deceived its IPv4 application. Name of the Comnapy: CloudRadium LLC. Registry address: 1603 Capitol Ave St3 310, Cheyenne, WY. Owner’s name: Li Xuan (李轩) & Deng Xiu Ping (邓秀平)
As the IPv4 has been depleted in the AP regions, some so-called clever guys from China registered a LLC named CloudRadium LLC in WY in 2012-10-01, meanwhile they registered a domain named http://www.cloudradium.com on 2012-09-26. From then, they’v started their journey of deceiving the Cherish IPv4 resources which should belong to the Arin Internet Community from ARIN. They have carefully studied and researched all Arin’s Policy on IPv4 management and has abused the policy to apply for more IPv4 steps by steps by using the fraud information. See details below.
...
5.In a word, their main purpose is to have as many IPv4 as they can. Their company is not founded for the purpose of doing business in USA, but for accumulating IPv4 addresses

Sidenote: parallel scans

During the scan, we expected to see TLS connections to port 443 on the dedicated web server at sni-scan-for-research-study.bamsoftware.com. Since there were 2,500 SNI proxies, we should have gotten 2,500 connections from them alone, ignoring Internet background traffic. In fact, we received 6,627 connections (6,474 with the correct SNI), and 3,696 cam from a single IP address, 192.107.156.196.
Here are the 10 most common source IP addresses taken from ssl.log during the 8 hours of the scan:
8 211.138.60.14
9 219.76.4.73 tswc5b073.netvigator.com
12 207.249.174.253 na-207-249-174-253.static.avantel.net.mx
12 208.80.194.26 static-208-80-194-26.as13448.com (Websense)
13 110.4.24.175
13 219.76.4.9 tswc5b009.netvigator.com
16 120.198.243.35
16 65.202.124.7
113 66.133.109.36 outbound1.letsencrypt.org
3696 192.107.156.196
66.133.109.36 (outbound1.letsencrypt.org) is easy to explain. sni-scan-for-research-study.bamsoftware.com had a certificate from Let's Encrypt and these were connections related to the ACME protocol. 208.80.194.26 (static-208-80-194-26.as13448.com) is interesting: AS13448 belongs to Websense, a web filtering company. They must do centralized, automatic scans of SNIs seen by their firewall installations.
The clear outlier is 192.107.156.196. During the 8 hours of the scan, this IP address made TLS connections with the correct SNI to our dedicated HTTPS server at a roughly constant rate. It stopped making connections after our scan stopped. Our scan had not touched anything in 192.107.156.0/24 when the first connections from 192.107.156.196 begin to arrive.
To be clear: we measured these connections at the dedicated web server running at sni-scan-for-research-study.bamsoftware.com, the host specified in our SNI, not at the host running ZMap. In other words, it was not a matter of a host back-scanning the source of a detected scan. Instead, while we were scanning random HTTPS servers, an unrelated host—192.107.156.196—was scanning the same host that we specified in our SNI.
One might suppose that 192.107.156.196 is merely a shared exit point for many other SNI proxies. But this can't be the case. For one thing, 192.107.156.196 made more connections to the HTTPS server than we made in total. And for another, the TLS client handshake differed from the ones that our scanner program produced—for example, it used session resumption. If it were merely tunneling our own connections, it would not have been able to modify the TLS handshake and still have validation succeed. Instead, this host was independently sending its own TLS probes while we were doing our scan.
whois says the IP address belongs to Harris Corporation.
NetRange:       192.107.156.0 - 192.107.156.255
CIDR:           192.107.156.0/24
NetName:        HARRISNET5
NetHandle:      NET-192-107-156-0-1
Parent:         NET192 (NET-192-0-0-0-0)
NetType:        Direct Assignment
OriginAS:       
Organization:   Harris Corporation (HARRIS-6)
RegDate:        1991-05-20
Updated:        2015-05-26
Ref:            https://whois.arin.net/rest/net/NET-192-107-156-0-1


OrgName:        Harris Corporation
OrgId:          HARRIS-6
Address:        Mail Stop 57
Address:        1024 West Nasa Blvd
City:           Melbourne
StateProv:      FL
PostalCode:     32919
Country:        US
RegDate:        1989-05-17
Updated:        2011-09-24
Ref:            https://whois.arin.net/rest/org/HARRIS-6

Appendix

The sonar.http proxy list

We looked for the three bootstrap HTTP fingerprints in the Project Sonar HTTP data set dated 20160830. "Project Sonar includes a regular HTTP GET request for all IPv4 hosts with an open 80/TCP." The idea was to use an existing scan of port 80 rather than do our own. The input contains 61,683,005 hosts.
The grepsonar subdirectory in the sniproxy.git repo contains a program that searches the sonar.http file for the 3 HTTP fingerprints found in the GoProxy list. It found:
514 ChinaCache
2511 HAProxy
2460 dns.auth.fail
Of these only a small number are actually SNI proxies, despite having the same fingerprint:
22 of 514 ChinaCache are SNI proxies
37 of 2511 HAProxy are SNI proxies
37 of 2460 dns.auth.fail are SNI proxies (fell to 30 a week later)

ChinaCache SNI proxies

  • scan-sniproxy/scan-sniproxy-chinacache-20160830-http.csv
110.4.24.170
110.4.24.175
111.11.184.10
111.11.184.117
111.11.184.119
111.12.251.162
111.12.251.206
116.246.6.39
116.246.6.46
117.156.13.7
120.198.243.2
183.207.229.136
203.210.6.39
211.138.60.14
218.254.1.13
218.254.1.15
219.76.4.9
219.76.4.11
219.76.4.14
219.76.4.73
219.76.4.75
219.76.4.76

HAProxy SNI proxies

  • scan-sniproxy/scan-sniproxy-haproxy-20160830-http.csv
101.95.144.68
101.95.144.69
101.95.144.70
101.95.144.71
110.4.24.176
110.4.24.178
111.11.153.19
111.11.153.36
111.11.153.37
111.11.153.38
111.11.153.40
111.11.153.42
111.11.153.43
111.11.184.5
111.11.184.7
111.11.184.9
111.11.184.13
111.11.184.116
111.12.251.172
111.12.251.173
111.12.251.175
116.246.6.35
116.246.6.36
116.246.6.38
117.156.13.5
211.138.60.6
211.138.60.7
211.138.60.8
211.138.60.9
211.138.60.10
211.138.60.11
211.138.60.18
211.138.60.19
219.76.4.3
219.76.4.4
219.76.4.69
219.76.4.70

dns.auth.fail SNI proxies

  • tests/dns.auth.fail-sniproxy.csv (scanned 2016-09-20)
  • scan-sniproxy/scan-sniproxy-dns.auth.fail-20160830-http.csv (scanned 2016-09-28)
* denotes hosts that disappeared in the second scan.

5.187.20.130
31.220.5.61
37.235.49.150
46.37.190.246
46.108.39.132
69.12.80.155    *
69.162.73.203
82.103.128.85
83.170.70.124
83.170.70.125
91.210.104.52
95.154.233.196
103.15.187.54
103.19.16.13
104.250.97.19
104.250.98.55
104.250.98.56
104.250.98.67   *
104.250.98.168
104.250.98.169
109.123.113.195
113.20.28.16
158.255.211.127
172.97.82.35
173.44.17.3
185.18.79.87
185.57.116.51
185.70.11.133   *
185.70.11.135   *
185.70.11.137   *
185.70.11.139   *
185.125.168.110
193.182.144.202
194.54.80.146
202.155.223.171
204.152.217.140 *
211.22.145.212

The sonar.https proxy list

We scanned all the hosts in the Project Sonar HTTPS data set dated 20160906. "Project Sonar includes an HTTPS GET request for all IPv4 hosts with an open 443/TCP." The idea was to use an existing scan of port 443 rather than do our own. In retrospect, this was a bad idea, because the Project Sonar scan omits servers that don't return a certificate when contacted without SNI—none of the servers in the GoProxy list returned a certificate in this case. Our scan of these hosts turned up only a few oddball SNI proxies. The input contains 32,327,703 hosts.
First we extracted the IP addresses from the sonar.https-20160906 data set:
cd sonar-ips
./sonar-ips ../20160906-http.gz > ips-20160906-https.txt
Then we scanned all of them for SNI proxy support:
cd scan-sniproxy
./scan-sniproxy -input ../sonar-ips/ips-20160906-https.txt > scan-sniproxy-full-20160906-https.csv
The scan took about 8 hours. The output CSV file is 5.9 GB, but there are only 38 SNI proxies:
grep -a ,T, scan-sniproxy-full-20160906-https.csv > scan-sniproxy-20160906-https.csv
IP address reverse DNS
1.32.63.161
20.138.2.35
40.129.146.22 h22.146.129.40.static.ip.windstream.net
65.202.124.19 intranet.mcwane.com
65.202.124.20 francais.clowcanada.com
65.202.124.23 helpdesk.mcwane.com
65.202.124.28 office.mcwane.com
65.202.124.47 autodiscover.mantank.com
65.202.124.48
65.202.124.55
65.202.124.56 ci.synapse-wireless.com
65.202.124.60
65.202.124.85 aca.mcwane.com
65.202.124.103 apps.mcwane.com
65.202.124.231
68.232.35.34
68.232.44.115
72.22.21.20
72.22.21.30 prostream.net
72.22.21.33
72.22.21.49
72.22.21.58
78.133.124.150
94.124.157.198
119.18.234.60
129.143.4.2 wwwproxy.belwue.de
133.43.191.119
159.12.192.12
159.12.192.13
159.12.192.14
162.243.47.142 proxy2.threatworking.com
183.207.227.132 cache.IDC.js.chinamobile.com
208.250.32.193
209.195.175.8 mail.komenpittsburgh.org
209.195.175.13 hosted.prostream.net
212.200.253.210
212.200.253.211
218.57.200.13
We investigated a few of them manually.

40.129.146.22 — Websense

https://40.129.146.22/ says:
40.129.146.22 uses an invalid security certificate.
The certificate is not trusted because the issuer certificate is unknown.
The server might not be sending the appropriate intermediate certificates. An additional root certificate may need to be imported.
The certificate is only valid for 10.170.10.116
Clicking through gives:
Could not connect to server
Overview: Could not connect to 40.129.146.22 .
Details: Peer suddenly disconnected found
Options: Pressing the button allows you to go to the previous page. You can try to reload the page or check if the URL is correct.
[Websense Logo]

65.202.124.231 — Citrix XenApp

https://65.202.124.231/ says:
65.202.124.231 uses an invalid security certificate.
The certificate is only valid for citrix.mcwane.net
The certificate expired on 01/30/2013 12:00 PM. The current time is 09/24/2016 04:07 PM.
Clicking through times out after redirecting to http://65.202.124.231/Citrix/XenApp/. https://citrix.mcwane.net/, after many redirects, lands at https://citrix.mcwane.net/Citrix/XenApp/clientDetection/downloadNative.aspx.
Citrix XenApp
Your Windows desktops and apps on demand - from any PC, Mac, smartphone or tablet.

72.22.21.30 — Sophos firewall

https://72.22.21.30/ raises the expected certificate error:
The certificate is only valid for the following names: www.prostream.net, prostream.net, hosted.prostream.net, mail.prostream.net, send.prostream.net, spam.prostream.net.
Clicking through gives:
Blocked request
Dear ,
This is a message from the IT Department.
The web site you are trying to access:
https://72.22.21.30/
is listed as a site within the category IPAddress
Current Internet Access Configuration for you does not allow visiting sites within this category at this time.
If the website has been erroneously blocked, please submit it for re-evaluation.
You are currently browsing as an unauthenticated user.
Click here to log in
Sophos Firewall
This server allows the SNI to be an IP address. Here it is proxying to a Tor relay on port 443:
$ torsocks -i openssl s_client -ign_eof -connect 72.22.21.30:443 -servername 82.146.47.17
subject=/CN=www.mn7ntdslcv.net
issuer=/CN=www.x4aigwinbg6m.com
 
from https://www.bamsoftware.com/computers/sniproxy/