使用Nginx做正向代理

使用nginx做正向代理

https://github.com/chobits/ngx_http_proxy_connect_module

HTTP/HTTPS代理服务器

nginx作为一个反向代理工具,刚开始的时候是不支持正向代理的, 后来支持了。代理本身不复杂 ,有一个难点在于如何加密https的流量。解决这个问题有两种方法。

  1. 代理服务器不处理加密

    它在客户机和服务器之间建立一个TUNNEL, 客户机然后直接与服务器通信。本文件讨论的nginx正向代理都用的是这种不解密的方式。

  2. “中间人”代理服务器,Man-in-the-Middle (MITM):

    代理服务器用一个自签名的证书完成与客户机的TLS handshake,然后转头再去和服务器完成TLS 握手。 在这种配置中, 代理服务器上用的那个自签名证书的CA得被客户机信任。 这种代理通常以Web Gateway的方式存在企业环境中,对用户来说是透明的,用户也不需要配置客户机的代理服务器环境变量或者相关配置。

Nginx提供了两种方案来解决这个问题, 即L7和L4方案。

HTTP CONNECT (L7 方案)

Nginx设计出来是做反向代理的,所以它天生不支持HTTP CONNECT这个Method, github上有个大哥写了这么个插件 https://github.com/chobits/ngx_http_proxy_connect_module,需要通过编译的方式来安装nginx.

  1. 下载nginx源码

  2. 下载ngx_http_proxy_connect_module源码

  3. 根据nginx的版本patch connect module中带的指定patch文件,这在github的Readme中有说明,比如本文举例子用的nginx-1.16.1对应的是 proxy_connect_rewrite_101504.patch

    $ cd /root
    $ git clone https://github.com/chobits/ngx_http_proxy_connect_module
    $ wget http://nginx.org/download/nginx-1.16.1.tar.gz
    $ tar zxvf nginx-1.16.1.tar.gz
    $ cd nginx-1.16.1
    $ patch -p1 < ../ngx_http_proxy_connect_module/patch/proxy_connect_rewrite_101504.patch
    
  4. 编译时指定connect module的源码位置

    $ yum update
    $ yum -y install gcc pcre pcre-devel zlib zlib-devel openssl openssl-devel
    
    #添加用户和组
    $ groupadd www
    $ useradd -g www www
    $ cd /root/nginx-1.16.1
    $ ./configure \
    --user=www \
    --group=www \
    --prefix=/usr/local/nginx \
    --with-http_ssl_module \
    --with-http_stub_status_module \
    --with-http_realip_module \
    --with-threads \
    --add-module=/root/ngx_http_proxy_connect_module
    
    ## 如果已经有nginx环境了,可以不执行make install, make之后把./objs/nginx二进行文件拷贝出来就能用, 执行nginx -V可以显示编译的参数
    $ make && make install
    
    
  5. nginx.conf 的配置样例

    server {
         listen  8001;
      
         # dns resolver used by forward proxying
         resolver  114.114.114.114;
         # forward proxy for CONNECT request
         proxy_connect;
         proxy_connect_allow            443;
         proxy_connect_connect_timeout  10s;
         proxy_connect_read_timeout     10s;
         proxy_connect_send_timeout     10s;
         # forward proxy for non-CONNECT request
         location / {
             proxy_pass http://$host;
             proxy_set_header Host $host;
         }
     }
    
    1. 测试
    ## 在局域网中找另外一台机器,执行下面的命令, 把http://192.168.1.100:8001配置到环境变量里面就可以正常工作了
    curl https://www.baidu.com -svo /dev/null -x 192.168.1.100:8001
    
     About to connect() to proxy 192.168.1.100 port 8001 (#0)
    *   Trying 192.168.1.100...
    * Connected to 192.168.1.100 (192.168.1.100) port 8001 (#0)
    * Establish HTTP proxy tunnel to www.baidu.com:443
    > CONNECT www.baidu.com:443 HTTP/1.1
    > Host: www.baidu.com:443
    > User-Agent: curl/7.29.0
    > Proxy-Connection: Keep-Alive
    >
    < HTTP/1.1 200 Connection Established
    < Proxy-agent: nginx
    <
    * Proxy replied OK to CONNECT request
    * Initializing NSS with certpath: sql:/etc/pki/nssdb
    *   CAfile: /etc/pki/tls/certs/ca-bundle.crt
      CApath: none
    * SSL connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
    * Server certificate:
    *     subject: CN=baidu.com,O="Beijing Baidu Netcom Science Technology Co., Ltd",OU=service operation department,L=beijing,ST=beijing,C=CN
    ...
    > GET / HTTP/1.1
    > User-Agent: curl/7.29.0
    > Host: www.baidu.com
    > Accept: */*
    >
    < HTTP/1.1 200 OK
    ...
    
    

NGINX Stream (L4方案)

在L4方案中, nginx可以做透明代理, nginx需要的编译模块和L7的不一样, 不需要下载connect module,只需要下载nginx的源码,并使用以下

  1. 编译参数
$ ./configure \
--user=www \
--group=www \
--prefix=/usr/local/nginx \
--with-http_ssl_module \
--with-http_stub_status_module \
--with-http_realip_module \
--with-threads \
--with-stream \
--with-stream_ssl_preread_module \
--with-stream_ssl_module
  1. nginx.conf 配置例
stream {
    resolver 114.114.114.114;
    server {
        listen 443;
        ssl_preread on;
        proxy_connect_timeout 5s;
        proxy_pass $ssl_preread_server_name:$server_port;
    }
}
  1. DNS劫持

使用这个“代理”需要使用DNS的力量, 把需要走代理的域名解析到nginx代理所在的服务器地址。PS: 这个用法好奇怪 ,不知道在啥环境下能用起来。

注册nginx到Systemd

vi /etc/systemd/system/nginx.service

[Unit]
Description=The NGINX HTTP and reverse proxy server
After=network.target
 
[Service]
Type=forking
ExecStart=/usr/local/nginx/sbin/nginx      # Nginx 可执行文件的路径
ExecReload=/usr/local/nginx/sbin/nginx  -s reload
ExecStop=/usr/local/nginx/sbin/nginx  -s stop
PIDFile=/var/run/nginx.pid          # Nginx 的 PID 文件路径
PrivateTmp=true
 
[Install]
WantedBy=multi-user.target

posted @   陈大玉  阅读(31)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示