首页 > 代码库 > 基于nginx的正向代理实现

基于nginx的正向代理实现

前言:

  一次偶发的运营商故障,导致部分区域访问BGP站点不可达,为了避免问题再次发生,准备了一套正向代理环境, 当出现类似问题时,可以通过修改DNS实现流量转移。

  其核心原理为代理转发,缺点是正向代理后端接收的源IP为正向代理的IP,对WAF、日志统计等产生干扰,所以不建议长时间使用。

  由于是单站点的正向解析,且站点拥有站点的证书文件,可以将HTTP及HTTPS搭建起来。

  刚开始实现正向代理时,没有考虑互联网上大量的爬虫,导致服务器被用作在线代理,为了避免爬虫利用正向代理,在DNS解析中,关闭递归解析,实现指定的域名才能解析的效果。

 allow-recursion { none; };

 

工作原理:

  1. 客户机通过域名解析,访问正向代理

  2. 正向代理接收请求后, 根据请求头部的Host 信息,寻找配置中的DNS私服进行DNS解析IP地址,本文使用IP为 127.0.0.1 的DNS服务器

  3. 正向代理向后端代理请求,并在头部带上客户机的头部信息及定制信息

  4. 正向代理接收数据后,将数据返回给客户端

 

实现方式:

  nginx + bind 实现。

 

使用组件如下:


 

nginx version: nginx/1.8.1
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-11) (GCC)
built with OpenSSL 1.0.2h 3 May 2016
TLS SNI support enabled
configure arguments: --user=nginx --group=nginx --prefix=/usr/local/nginx-1.8.1 --with-http_ssl_module --with-openssl=/usr/local/src/openssl-1.0.2h --with-pcre=/usr/local/src/pcre-8.35 --add-module=/usr/local/src/ngx_devel_kit-master/ --add-module=/usr/local/src/lua-nginx-module-master/ --add-module=/usr/local/src/nginx-http-concat-master/ --add-module=/usr/local/src/nginx_upstream_check_module-master/ --add-module=/usr/local/src/nginx_tcp_proxy_module-master/ --with-http_sub_module
注:为了统一版本,部分插件未在本文使用


 

BIND 9.11.0-P5 <id:ad4fb79>
running on Linux x86_64 2.6.32-431.23.3.el6.x86_64 #1 SMP Thu Jul 31 17:20:51 UTC 2014
built by make with ‘--prefix=/usr/local/bind‘ ‘--enable-threads‘ ‘--enable-largefile‘ ‘--disable-ipv6‘
compiled by GCC 4.4.7 20120313 (Red Hat 4.4.7-17)
compiled with OpenSSL version: OpenSSL 1.0.1e 11 Feb 2013
linked to OpenSSL version: OpenSSL 1.0.1e-fips 11 Feb 2013
compiled with zlib version: 1.2.3
linked to zlib version: 1.2.3
threads support is enabled


 

nginx 的配置信息:

技术分享
user  nobody nobody;
worker_processes  2;

events {
    worker_connections  65535;
}

http {
    server_tokens off ;
    include       mime.types;
    include ./blockip.conf;
    default_type  application/octet-stream;

    client_body_temp_path           /usr/local/nginx/tmpdir/client_body_temp 1 2;
    proxy_temp_path                 /usr/local/nginx/tmpdir/proxy_temp 1 2;
    fastcgi_temp_path               /usr/local/nginx/tmpdir/fastcgi_temp 1 2;
    uwsgi_temp_path                 /usr/local/nginx/tmpdir/uwsgi_temp 1 2;
    scgi_temp_path                  /usr/local/nginx/tmpdir/scgi_temp 1 2;

    # gzip
    gzip                            on;
    gzip_http_version               1.1;
    gzip_vary                       on;
    gzip_proxied                    any;
    gzip_min_length                 1024;
    gzip_comp_level                 6;
    gzip_buffers                    16 8k;
    gzip_proxied                    expired no-cache no-store private auth no_last_modified no_etag;
    gzip_types                      text/plain application/x-javascript text/css application/xml application/json;
    gzip_disable                    "MSIE [1-6]\.(?!.*SV1)";
    
    reset_timedout_connection       on;
    keepalive_timeout               10 5;
    keepalive_requests              100;

    ignore_invalid_headers          off;
    server_names_hash_max_size      256;
    server_names_hash_bucket_size   6400;
    client_header_buffer_size       8k;
    #large_client_header_buffers     4 32k;
    connection_pool_size            256;
    request_pool_size               64k;

    output_buffers                  2 128k;
    postpone_output                 1460;

    client_header_timeout           1m;
    client_body_timeout             3m;
    send_timeout                    3m;
    proxy_intercept_errors  on;
    fastcgi_intercept_errors    on;

    # log 
    log_format  main  ‘$remote_addr - $remote_user [$time_iso8601] "$host" "$upstream_addr" "$request" ‘
                      ‘$status $request_time $body_bytes_sent "$http_referer" ‘
                      ‘"$http_user_agent" "$http_x_forwarded_for" "$http_cookie"‘;
    access_log  /home/logs/nginx/access.log  main;
    
    #log_format  compression  ‘$remote_addr - $remote_user [$time_local] "$request" ‘
    #                  ‘$status $body_bytes_sent "$http_referer" ‘
    #                  ‘"$http_user_agent" "$http_x_forwarded_for"‘;
    #access_log  /home/logs/nginx/awstate.log  compression;
    
    error_log /home/logs/nginx/error.log  notice; 
    log_not_found                   on;

    sendfile                        on;
    tcp_nodelay                     on;
    tcp_nopush                      off;

    error_page   500 502 503 504  /errorPage/50x.html;
    error_page   404  /errorPage/404.html;
        
    # proxy configuration
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_next_upstream   error timeout invalid_header http_500 http_502 http_503 http_504 http_404;
    #proxy_redirect                off;
    client_max_body_size          20m;
    client_body_buffer_size       1024k;
    proxy_connect_timeout         360;
    proxy_send_timeout            360;
    proxy_read_timeout            260;
    proxy_buffer_size             128k;
    proxy_buffers                 4 64k;
    proxy_busy_buffers_size       128k;
    proxy_temp_file_write_size    128k;
    proxy_headers_hash_max_size   51200;

server {
 listen 80;
 location / {
 resolver 127.0.0.1;
 resolver_timeout 30s;
 proxy_pass http://$host$request_uri;
 }

}

server {
 listen 443;
 ssl on ;
            ssl_session_cache shared:SSL:50m;
            ssl_session_timeout 5m;
            ssl_dhparam /usr/local/nginx/conf/ssl/dhparam.pem;
            ssl_prefer_server_ciphers on;

            ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
            ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
            ssl_certificate                /usr/local/nginx/conf/ssl/123321.crt;
            ssl_certificate_key            /usr/local/nginx/conf/ssl/123321.com.key;
            ssl_trusted_certificate        /usr/local/nginx/conf/ssl/gd_bundle-g2-g1.crt;

            ssl_stapling on;
            ssl_stapling_verify on;
 location / {
 resolver 127.0.0.1;
 resolver_timeout 30s;
 proxy_pass https://$host$request_uri;
 }

}


}
Nginx 配置信息

 

Bind的配置信息: 

技术分享
key "rndc-key" {
        algorithm hmac-md5;
        secret "**********";
};

controls {
        inet 127.0.0.1 port 953
                allow { 127.0.0.1; } keys { "rndc-key"; };
};

options {
        listen-on port 53 { any; };
//      listen-on-v6 port 53 { ::1; };
        directory       "/var/named";
        dump-file       "/var/named/data/cache_dump.db";
        statistics-file "/var/named/data/named_stats.txt";
        memstatistics-file "/var/named/data/named_mem_stats.txt";
        allow-query     { any; };
        recursion yes;

        dnssec-enable no;
        dnssec-validation no;
        dnssec-lookaside auto;

        #forward only;
        #forwarders { 114.114.114.114; };
        forwarders { 0.0.0.0; };
        allow-recursion { none; };
        /* Path to ISC DLV key */
        //bindkeys-file "/etc/named.iscdlv.key";

        //managed-keys-directory "/var/named/dynamic";
};

acl general { 0.0.0.0/0; };
acl localNetWork { 127.0.0.1;47.89.48.10/32; };

view qipeipu.com {
     #match-clients { localNetWork; };
     #allow-query { localNetWork; };

     zone "qipeipu.com" IN {
        type master;
        file "qipeipu.com.zone.local";
        #notify yes;
        #also-notify { 192.168.0.254; };
        #allow-transfer { 192.168.0.254; };
        forwarders {};
     };
    #include "/etc/named.rfc1912.zones";
    # include "/etc/named.root.key";

};
Bind 配置信息
技术分享
$TTL 86400
@       IN SOA localhost.  @  (
                                        1    ;serial
                                        1D      ; refresh
                                        1H      ; retry
                                        1W      ; expire
                                        3H )    ; minimum
@                         IN      NS      localhost.
www                     IN      A       121.201.16.120
Bind 域名配置信息

 

基于nginx的正向代理实现