基于http协议的各种反代方法太多太简单了,网上肯定一大把,这里就无需多言了,今天博主来介绍一种更为通用、隐蔽、安全和高效的反代方法,此方法工作在第四层,添加了对第七层ssl/tls协议中域名字段的嗅探,这种代理对https有着更多的支持和配置项,又原生支持TCP、UDP代理,是真的几乎代天代地代空气,反代整个世界。涨姿势的时候到了,请大家撸起。。袖子,准备干他娘的一炮!
由于在国内使用https协议访问谷歌学术时会受到域名字段检测,导致在国内无法正常使用谷歌学术,即使使用SNI代理,依然无法规避这种检测机制导致的连接失败,所以,国内的上网设备,在不使用代理客户端的情况下,使用谷歌学术去检索资料几乎不可能。然而Pure DNS却能支持谷歌学术的访问并且有长期支持的打算,其实现正是得益于Nginx强大到炸裂的代理功能。下面将对四层Nginx反代配置、当前追梦人博客和谷歌学术反代服务器的Nginx配置进行介绍,说到Nginx,真的得夸一夸,在兼顾性能的情况下各种负载均衡、热更新、各种反代、各种骚操作都能搞定,还能有lua加持,点个赞👍。
上面也提到了,通常情况下国内上网设备需要安装代理客户端才能访问谷歌学术,Pure DNS也不能算例外,只不过Pure DNS把客户端也放到了服务器上运行,才实现了用户免装客户端。为了实现谷歌学术的免客户端访问,需要防火墙内、外各一台服务器进行多层代理,防火墙外Nginx服务器反代谷歌学术并同时作为服务端运行,防火墙内服务器Nginx作为客户端与防火墙外服务端加密通信,同时,防火墙内Nginx又作为服务端为用户提供服务,Pure DNS友情劫持谷歌学术的解析结果,使谷歌学术指向防火墙内自建Nginx反代服务器。这时,用户与谷歌学术服务器间的连接路径为:用户→https协议→防火墙内Nginx→tls加密→防火墙外Nginx→sni反代→谷歌学术服务器,用户端效果就像普通https方式一样即可访问谷歌学术。注意,此处单箭头并不合适,但是我懒得画图了。。。
Nginx过早的版本并不支持下面的配置,可以阅读我的另一篇博文Nginx之stream模块初体验,查看对Nginx的要求,下面的配置仅供参考,实际操作前请备份Nginx配置文件。
下面首先是防火墙外Nginx配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | user nginx; #机器几个核就写几,更通用的方法是auto,Nginx会自动应用合适的值 worker_processes auto; error_log /var/log/nginx/error .log error; pid /var/run/nginx .pid; #Nginx允许使用的最大文件描述符数量限制,适当调大可避免"too many open files"错误 worker_rlimit_nofile 1048576; events { #设置轮询方法 use epoll; #单个工作进程可以允许同时建立外部连接的数量,低配机器慎加 worker_connections 262144; #尽可能多地接收连接 multi_accept on; } stream { #这里定义一个后端的map,防止直接通过https方式访问IP造成的循环反代 map $ssl_preread_server_name $backend { #~*[0-9]$ unix:/dev/shm/null.sock; ~*\S$ $ssl_preread_server_name:443; default unix: /dev/shm/null .sock; } #下面这段就是sni代理+tls加密服务端的实现 server { listen 4333 ssl; #与防火墙内Nginx服务器使用tls加密方式进行连接,效果和stunnel等隧道代理类似, #这里主要为了加密流量实现防火墙穿透 ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers AES128-SHA:AES256-SHA:RC4-SHA:DES-CBC3-SHA:RC4-MD5; #服务端加密方式优先 #ssl_prefer_server_ciphers on; #证书文件,可以是自签证书,这里的证书配置主要是服务端验证客户端时要用到, #可以用这两行的命令自签(记得去掉#号): #openssl req -new -x509 -days 3650 -nodes -subj "/C=CA/ST=CA/L=CA/O=CA/OU=CA/CN=CA" \ #-out /etc/nginx/cert.pem -keyout /etc/nginx/key.pem ssl_certificate /etc/nginx/cert .pem; ssl_certificate_key /etc/nginx/key .pem; #下面三条配置是用来验证客户端的,防止非授权客户端连接,没错,这里博主懒得再签一个了 ssl_client_certificate /etc/nginx/cert .pem; ssl_trusted_certificate /etc/nginx/cert .pem; #验证客户端貌有问题 #ssl_verify_client on; ssl_session_cache shared:SSL:20m; ssl_session_timeout 10m; #下面是sni代理转发设置 ssl_preread on; #DNS服务器设置,用来解析$ssl_preread_server_name(也就是https中的域名) #注意,下面一定要替换成可用的dns! #我在此处用来限制被代理域名,不能啥网站都代啊对不,当然你也可以用map去限制域名,一样的效果 #如果允许代理任何https站点,可以设置为resolver 8.8.8.8; resolver 127.0.0.1:5353; #resolver 8.8.8.8; proxy_pass $backend; } } |
下面是防火墙内Nginx配置,因为此服务器上跑着现在这个博客以及Pure DNS官网,需要与谷歌学术共用443端口,而且博客又要能够知道到访客的真实IP,因此配置多了点(好像多了挺多的,我这属于比较硬核的写法,此服务器上若没有网站或网站不需要记录访客IP则写法可以简化很多!),在这里,并没有开放http80端口谷歌学术的访问,因为会被未备案提示拦截…然后刚好省下了80端口的反代,只使用443端口进行反代。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109user nginx;
worker_processes auto;
error_log
/var/log/nginx/error
.log error;
pid
/var/run/nginx
.pid;
worker_rlimit_nofile 1048576;
events {
worker_connections 262144;
multi_accept on;
use epoll;
}
stream {
#代理缓冲区大小
proxy_buffer_size 128k;
#代理超时时间
#proxy_connect_timeout 5s;
#会话状态存储区域,限制单IP最大连接数的时候会用到
#limit_conn_zone $binary_remote_addr zone=addr:10m;
#SNI日志格式,SNI代理并未拆解证书,常规的变量在这里是用不了的
#时间|用户IP|域名|接收字节数|发送字节数|会话用毫秒数
log_format main
'$time_iso8601|$remote_addr|$ssl_preread_server_name'
'|$bytes_received|$bytes_sent|$session_time'
;
#后端转发策略
map $ssl_preread_server_name $backend {
~*[0-9]$ unix:
/dev/shm/localweb
.sock;
~*dream.ren$ unix:
/dev/shm/localweb
.sock;
~*puredns.cn$ unix:
/dev/shm/localweb
.sock;
default unix:
/dev/shm/nginx-sni
.sock;
}
#Nginx加密转发上游配置,也就是防火墙外Nginx,由于经费不足,其中只包含了一台备份机,防止单点故障导致的服务中断
upstream sni_stunnel {
zone upstream_sni_stunnel 64k;
server **.**.**.**:4333 fail_timeout=120s;
server **.**.**.**:4333 backup;
}
#Nginx加密转发
server {
#在内存中监听域套接字(域套接字相比sock套接字具有更好的性能),
#并声明使用proxy_protocol代理协议,这个协议是用来传递客户端真实IP的
listen unix:
/dev/shm/nginx-sni
.sock proxy_protocol;
#并不需要和sni_stunnel配置中的远程服务器使用proxy_protocol协议,要关闭,否则连接会被中断
proxy_protocol off;
#与sni_stunnel服务器使用tls加密方式进行连接
proxy_ssl on;
#证书文件,可以是自签证书,为了能与防火墙外服务器连接时通过验证,
#若防火墙外Nginx未开启客户端验证可以不用配置证书
#proxy_ssl_certificate /etc/nginx/cert.pem;
#证书秘钥文件
#proxy_ssl_certificate_key /etc/nginx/key.pem;
#下面2行是用来验证服务端的,好像还有些问题
#proxy_ssl_trusted_certificate /etc/nginx/cert.pem;
#proxy_ssl_verify on;
#proxy_ssl_ciphers AES128-SHA:AES256-SHA:RC4-SHA:DES-CBC3-SHA:RC4-MD5;
#proxy_connect_timeout 5s;
#转发到sni_stunnel中的服务器
proxy_pass sni_stunnel;
#开启ssl_preread,用来检测域名的
ssl_preread on;
}
#监听服务端口
server {
listen 443;
#声明使用proxy_protocol代理协议,和上面那个server配套使用的
proxy_protocol on;
#限制单IP最大连接数
#limit_conn addr 10;
#单连接限速
#proxy_download_rate 400k;
#proxy_upload_rate 400k;
#配置sni使用日志,并给日志加缓冲,
#if=$ssl_preread_server_name表示只有当sni域名不为空的时候进行记录
access_log
/var/log/nginx/sniproxy
.log main buffer=8k flush=5s
if
=$ssl_preread_server_name;
#使用上面的那个转发策略
proxy_pass $backend;
#开启ssl_preread,用来检测域名的
ssl_preread on;
}
}
#下面是托管在本机上网站的相关配置,网上应该有很多详细介绍,这里就不多做介绍了;
#相信聪明的你配置出一个SSL LAB评分A+的站点应该不是什么难事儿~~
http {
include
/etc/nginx/mime
.types;
default_type application
/octet-stream
;
charset utf-8;
log_format main
'$time_iso8601|$remote_addr|$host|$request|$request_time|$status'
'|$body_bytes_sent|$upstream_addr|$upstream_response_time|$upstream_status'
'|"$http_referer"|"$http_user_agent"|"$http_x_forwarded_for"'
;
access_log
/var/log/nginx/access
.log main;
sendfile on;
#tcp_nopush on;
client_max_body_size 50m;
keepalive_timeout 65;
gzip
on;
gzip_min_length 1k;
gzip_buffers 16 16k;
#gzip_http_version 1.1;
gzip_comp_level 5;
gzip_types text
/plain
application
/javascript
application
/x-javascript
text
/javascript
text
/css
application
/xml
application
/xml
+rss application
/json
application
/vnd
.ms-fontobject font
/ttf
font
/otf
image
/svg
+xml;
#gzip_vary on;
#gzip_proxied expired no-cache no-store private auth;
gzip_proxied any;
gzip_disable
"MSIE [1-6]\."
;
include
/etc/nginx/vhost/
*.conf;
}
配置完后
1nginx -t
检查下配置是否存在错误,没有错误的话
1nginx -s reload
重启nginx服务后一个防火墙内可用的SNI代理就搭建完成了~~~
另外,在写本文的时候,发现了另一个好玩的东西:Go Proxy,看起来可玩性很高,感兴趣的童鞋可以去看看:
https://github.com/snail007/goproxy/blob/master/README_ZH.md
震惊!追梦人终于更新博客了!
@码农BTS诈尸喽
博主加我有事请教。email
域名很个性,头一次见这种后缀的域名
@鸟叔哈哈,比较小众的域名,不然“dream”也不会被我抢到啊
。
有一点想不通的是 用户→https协议→防火墙内Nginx→ssl加密→防火墙外Nginx→sni反代→谷歌学术服务器 中是如何解决ssl证书问题呢?ssl加密 这一步的意思就是对 Google 原本加密过的流量再进行一道加密是吗?
@Mashiro对的
@Dreamer 明白了,谢谢
puredns很好用啊,谢谢大佬
localweb.sock,nginx-sni.sock这两个配置文件可否提供下?
@cdrom这个不是配置文件,这个是域套接字文件,Nginx监听的时候会自动产生的,如果没有本地https网站,配置可以简化很多,localweb.sock那一段对应的配置可以直接删掉。
@Dreamer感谢,已自建。
dns不好用了连接不上怎么回事大佬
不稳呀
@我就是幕后的煮屎人丶如何讲?
刚开始还有反应,还没到一分钟就没网了
@我就是幕后的煮屎人丶机器是什么配置的呢?系统日志有没有报错信息什么的?
手机来的 牌子魅族 报错吗 还没看见
@我就是幕后的煮屎人丶等等。。。。。
你说的是啥?这篇文章是讲nginx的,是在服务器上跑的,你说的是,,,DNS???
博主那里淫?
@我就是幕后的煮屎人丶开封人,目前在南京。
我没说问题是nginx啊
阔以 有机会尬聊一波。
@我就是幕后的煮屎人丶哇靠,你不会是我同学或校友吧。。。
很遗憾 不是
还可以这样吗、
请问,如果想配置 http(80端口)的 sni 反代(也走 sni_stunnel 的 ssl 加密通道),另外还有 http(80端口)的网站的情况下,应该怎么配置?博主能否给个配置示例?
@zxzz墙外服务端:
http{
server{
listen 4433 ssl;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers AES128-SHA:AES256-SHA:RC4-SHA:DES-CBC3-SHA:RC4-MD5;
ssl_certificate
/root/cert
.pem;
ssl_certificate_key
/root/key
.pem;
location / {
proxy_pass http:
//
$host;
proxy_method $request_method;
resolver 8.8.8.8;
}
}
}
墙内客户端:
stream {
server {
listen unix:
/dev/shm/http-stunnel
.sock;
proxy_ssl on;
proxy_pass 173.**.**.4:4433;
}
}
http{
server{
listen 80 default_server;
server_name _;
location / {
proxy_set_header Host $host;
proxy_method $request_method;
proxy_pass http:
//unix
:
/dev/shm/http-stunnel
.sock;
}
}
}
客户端机器上80端口的http网站正常配置即可~~~
有一些网页设置防盗链,那还能代理吗
@zylhttp下的referer防盗链?这个很容易破啊,加个header字段就行了,如果是本文中https下基于tcp的反代,不会出现盗链的问题。