使用Nginx做正向代理

https://github.com/chobits/ngx_http_proxy_connect_module

HTTP/HTTPS代理服务器

nginx是一个反向代理工具,其实它是不支持正向代理的,如果你真的需要一个正向代理服务器,你应该去用squid。

nginx做正向代理只做简单的转发,也没有设计像squid一样的缓存之类的正向代理的功能。 有L4和L7两种部署方式,L7有些像squid, 但性能可能不大好, 也会有些奇怪的问题,比如网页某一次访问的时候打不开, 刷新一下就又好了。 L4的使用就更奇怪了, nginx会监听某一个端口,比如443或者80, 然后客户机通过DNS解析的方式,把要代理的域名解析到代理服务器,然后由代理服务器转发。

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的源码位置

    #准备CentOS下的编译环境
    yum update
    yum -y install gcc pcre pcre-devel zlib zlib-devel openssl openssl-devel
    
    # ubuntu下的编译环境
    apt update
    apt install build-essential libpcre3 libpcre3-dev libssl-dev zlib1g-dev libgd-dev
    
    #添加用户和组
    
    cd /root/nginx-1.16.1
    ./configure \
    --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            80 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配置成代理,然后打开网页。 此时可以使用tail -f 观察nginx的access.log日志,可以看到访问的日志。

NGINX Stream (L4方案)

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

  1. 编译参数
./configure \
--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. https 代理配置 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. http代理配置 nginx.com
server {
    listen 80;
    location / {
        resolver 8.8.8.8;
        proxy_pass http://$http_host$uri$is_args$args;
    }
}
  1. DNS劫持
    使用这个“代理”需要用DNS解析来配合使用, 把需要走代理的域名解析到nginx代理所在的服务器地址。PS: 这个用法好奇怪 ,不知道在啥环境下能用起来。比如说, 我通过本地的DNS或者host文件,把www.baidu.com 这个域名指向代理服务器的地址, 把我所有想通过代理走的地址都解析到代理服务器的地址去。 当我通过浏览器去打开https://www.baidu.com:443的时候, 请示就会被指向https://代理服务器地址:443去。

配置http和https的代理需要监听80和443两个端口, https的配置会有点不一样,需要ssl_preread_module。 http的代理几乎就是反向代理的配置。

我没有想好具体的应用场景, 我猜想的一个可能的使用场景,比如某个网站如果只允许从一个固定的IP地址A访问, 此时有个在公网IP B的用户也想要访问, 就可以用这个L4的代理转发一下?

  1. 测试
    在局域网的另外一台计算机, 配置一个host文件记录,比如说
    192.168.1.100 baidu.com www.baidu.com
    然后打开浏览器,是否能正常打开百度的首页。 然后再把nginx服务停掉,看看是不是就不能正常打开baidu首页了。

注册nginx到Systemd

vi /etc/systemd/system/nginx.service

[Unit]
Description=The NGINX HTTP and reverse proxy server
After=network.target
 
[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
 
[Install]
WantedBy=multi-user.target

posted @ 2025-02-11 22:23  陈大玉  阅读(257)  评论(0)    收藏  举报