用Nginx+Tinyproxy搭建HTTPS Proxy,进行翻墙(亲测有效)

by FISHERMAN

/ 2018-11-12 08:59

这里使用Nginx 和Tinyproxy 的组合进行配置。系统使用debian/ubuntu或centos最新版,安装系统默认的软件包。

先编译nginx:
wget http://nginx.org/download/nginx-1.15.6.tar.gz
tar zxvf nginx-1.15.6.tar.gz
cd nginx-1.15.6
./configure –prefix=/usr/local/nginx –with-http_ssl_module –with-http_dav_module –with-http_flv_module –with-http_realip_module –with-http_gzip_static_module –with-http_stub_status_module –with-mail –with-mail_ssl_module –with-http_mp4_module –with-stream –with-stream_ssl_module
make && make install
其中 --with-stream --with-stream_ssl_module 是必须的.

root@whme:~# cd /usr/local/nginx
root@whme:/usr/local/nginx# ls
conf  logs            
html  sbin                     

root@whme:/usr/local/nginx# 
root@whme:/usr/local/nginx# cd sbin
root@whme:/usr/local/nginx/sbin# ls
nginx
root@whme:/usr/local/nginx/sbin# echo ‘export PATH=$PATH:/usr/local/nginx/sbin’ >> /etc/profile && source /etc/profile
root@whme:/usr/local/nginx/sbin#

nginx编译完成。
root@whme:/usr/local/nginx/sbin# mkdir -p /etc/nginx/
root@whme:/usr/local/nginx/sbin# nano /etc/nginx/options-ssl-proxy.conf
root@whme:/usr/local/nginx/sbin# cat /etc/nginx/options-ssl-proxy.conf
ssl_session_cache shared:proxy_nginx_SSL:1m;
ssl_session_timeout 1440m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers “ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS”;
root@whme:/usr/local/nginx/sbin#

(当然你把options-ssl-proxy.conf放在/usr/local/nginx/conf/里面也行。
然后在/usr/local/nginx/conf/nginx.conf文件的http段的上方加入如下的配置片段:
stream {
        upstream http_proxy {
                server 127.0.0.1:8888;
        }
server {
listen 8443 ssl;
ssl_certificate /root/.acme.sh/yourdomain.com/fullchain.cer;
ssl_certificate_key /root/.acme.sh/yourdomain.com/yourdomain.com.key;
include /etc/nginx/options-ssl-proxy.conf;
proxy_pass http_proxy;
}
}

如果你把options-ssl-proxy.conf放在/usr/local/nginx/conf/里面,则上面的include那行相应的改为:
include /usr/local/nginx/conf/options-ssl-proxy.conf;

其中,证书使用Let’t Encrypt的免费证书,在此感谢Let’t Encrypt的卓越服务。安装letsencrypt的免费SSL证书,见此文https://briteming.blogspot.com/2018/10/acmeshletsencryptssl.html

接下来安装Tinyproxy,并启动服务:
apt-get install -y tinyproxy
(centos系统下,则yum install -y tinyproxy)
systemctl start tinyproxy
systemctl enable tinyproxy

systemctl start nginx
systemctl enable nginx

tinyproxy的配置文件在/etc/tinyproxy/tinyproxy.conf,使用默认配置就可以了,默认监听127.0.0.1:8888。

然后在本地机器的chrome里设置https proxy为yourdomain.com,端口:8443,用
chrome就能翻墙了。


HTTPS Proxy基本上可用了,你可以到此为止。

但是Tinyproxy不支持用户认证,也就是说proxy authorization 不能使用。那么可以使用SSL的双向认证,在Nginx上设置ssl_verify_client on。在 server 段中加入以下配置:
ssl_client_certificate /etc/nginx/certs/client.crt;
ssl_verify_client on
12

客户端证书与网站证书不同,可以使用Easy-RSA 自己申请和管理,不需要第三方认证,client.crt 就是自己生成的Root CA。
客户端使用CA签发的证书与服务器连接,没有证书无法连接,Chrome 支持使用 AutoSelectCertificateForUrls 策略自动选证书。
 ./easyrsa init-pki
./easyrsa build-ca
./easyrsa gen-req proxy.example.name
./easyrsa sign-req client proxy.example.name
1234

以上命令会询问CN,即你的域名。基本上Root CA即执行init-pki 时填写example.com,gen-req 时填写一个子域名,proxy.example.comexample.com 根据需要替换。
这时生成了pki 文件夹,里面要用的文件是pki/ca.crt,把内容写入/etc/nginx/certs/client.crt:
cat pki/ca.crt > /etc/nginx/certs/client.crt
接下来要把proxy.example.com 的证书转换为Chrome 可识别的p12 格式:
openssl pkcs12 -export -clcerts -in pki/issued/proxy.example.com.crt -inkey pki/privae/proxy.example.com.key -out proxy.example.com.p12
执行完会生成proxy.example.com.p12 文件,可以导入Chrome 使用,Linux 下进入 chrome://settings/certificates 执行导入,Windows 下双击打开,导入系统,Chrome 使用系统的证书管理程序。
客户端证书认证必须配合AutoSelectCertificateForUrls, Chrome 不会主动提示代理需要选择证书。
Linux 下创建/etc/opt/chrome/policies/managed/policies.json 文件,写入以下内容:
{
"AutoSelectCertificateForUrls": ["{"pattern":"https://proxy.example.com","filter":{"ISSUER":{"CN":"example.com"}}}"]
}
123

Windows 下导入以下注册表:
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINESOFTWAREPoliciesGoogleChromeAutoSelectCertificateForUrls]
"1"="{"pattern":"https://proxy.example.com","filter":{"ISSUER":{"CN":"example.com"}}}"
1234

chrome://policy/ 应该会出现对应的值。
如果以上步骤完成,那么使用SwitchyOmega 配置一个 HTTPS 代理, 服务器填写 proxy.example.com, 端口 8443,访问 https://httpbin.org/ip 应该能得到服务器IP。
以上就是所有步骤,增加客户端可以使用相同的证书进行导入,也可以使用Easy-RSA申请新的证书,只需执行gen-req和sign-req即可。不要忘记导入AutoSelectCertificateForUrls 的配置,查看chrome://policy/ 检查配置是否生效。
以上完成了HTTP1.1 over TLS 代理,这在大部分情况下工作良好,只是在高延迟的网络条件下有点慢.

参考文档:
Easy-RSA – Github
Easy-RSA – ArchWiki
带你使用Nginx实现HTTPS双向验证
AutoSelectCertificateForUrls

Shared via Inoreader