追梦人博客Dream.ren

追梦人 Dream.ren

如何用Nginx搬运整个世界


基于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配置:

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端口进行反代。

user  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;
}

配置完后

nginx -t

检查下配置是否存在错误,没有错误的话

nginx -s reload

重启nginx服务后一个防火墙内可用的SNI代理就搭建完成了~~~
另外,在写本文的时候,发现了另一个好玩的东西:Go Proxy,看起来可玩性很高,感兴趣的童鞋可以去看看:
https://github.com/snail007/goproxy/blob/master/README_ZH.md

2018年3月10日 48 / /
标签:  暂无标签

评论回复

  1. 回复 码农BTS

    震惊!追梦人终于更新博客了!

  2. 回复 +wo

    博主加我有事请教。email

  3. 回复 鸟叔

    域名很个性,头一次见这种后缀的域名

    • 回复 Dreamer

      @鸟叔哈哈,比较小众的域名,不然“dream”也不会被我抢到啊 :smile:

  4. 回复 Mashiro

    有一点想不通的是 用户→https协议→防火墙内Nginx→ssl加密→防火墙外Nginx→sni反代→谷歌学术服务器 中是如何解决ssl证书问题呢?ssl加密 这一步的意思就是对 Google 原本加密过的流量再进行一道加密是吗?

  5. 回复 woshiluo

    :eek: 诈尸???

  6. 回复 1092916593

    puredns很好用啊,谢谢大佬 :roll:

  7. 回复 cdrom

    localweb.sock,nginx-sni.sock这两个配置文件可否提供下?

    • viagra cialis Dreamer

      @cdrom这个不是配置文件,这个是域套接字文件,Nginx监听的时候会自动产生的,如果没有本地https网站,配置可以简化很多,localweb.sock那一段对应的配置可以直接删掉。

  8. 回复 哈哈

    dns不好用了连接不上怎么回事大佬 :cry:

  9. 回复 buy cheap cialis

    不稳呀

  10. 回复 我就是幕后的煮屎人丶

    刚开始还有反应,还没到一分钟就没网了

  11. 回复 我就是幕后的煮屎人丶

    手机来的 牌子魅族 报错吗 还没看见

  12. 回复 我就是幕后的煮屎人丶

    博主那里淫?

  13. 回复 我就是幕后的煮屎人丶

    我没说问题是nginx啊

  14. generic viagra online fast delivery 我就是幕后的煮屎人丶

    阔以 有机会尬聊一波。

  15. 回复 我就是幕后的煮屎人丶

    很遗憾 不是 :cool:

  16. 回复 夏目贵志

    还可以这样吗、

  17. 回复 zxzz

    请问,如果想配置 http(80端口)的 sni 反代(也走 sni_stunnel 的 ssl 加密通道),另外还有 http(80端口)的网站的情况下,应该怎么配置?博主能否给个配置示例?

    • 回复 Dreamer

      @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网站正常配置即可~~~

  18. how to purchase viagra zyl

    有一些网页设置防盗链,那还能代理吗

    • 回复 Dreamer

      @zylhttp下的referer防盗链?这个很容易破啊,加个header字段就行了,如果是本文中https下基于tcp的反代,不会出现盗链的问题。

most effective ed pill

8 + 9 =

回到顶部