Nginx之正向代理与反向代理进阶(支持https)
作者:mmseoamin日期:2023-12-14

在【Nginx之正向代理与反向代理】一文中我们实现了将Nginx服务器作为正向代理服务器和反向代理服务器,但美中不足的是仅支持http协议,不支持https协议。

我们先看看看http和https的区别:

  • http协议:协议以明文方式发送数据,不提供任何方式的数据加密。不适合传输一些敏感信息,例如密码。其使用的端口是80。
  • https协议:在http协议的基础上,加入了SSL(Secure Sockets Layer),用于对数据进行加密。其使用的端口为443。

    Nginx之正向代理与反向代理进阶(支持https),第1张

    现在,我们要完成Nginx对https协议的支持。

    1.Nginx正向代理(http)

    我们来回顾一下Nginx作为正向代理服务器支持http协议的配置。

    代理服务器:192.168.110.101

    代理服务器配置:

    server {
    	listen 8080;
    	server_name localhost;
    	# 解析域名时需要配置
    	resolver 8.8.8.8;
    	location / {
    		proxy_pass http://$host$request_uri;
    	}
    }
    

    客户端配置:

    我们使用Windows系统作为客户端环境。

    Nginx之正向代理与反向代理进阶(支持https),第2张

    访问http://nginx.org/en/index.html,可以正常访问。

    Nginx之正向代理与反向代理进阶(支持https),第3张

    访问https://www.baidu.com,则无法正常访问了。

    Nginx之正向代理与反向代理进阶(支持https),第4张

    查看代理服务器的error.log,发现其报400错误码。

    Nginx之正向代理与反向代理进阶(支持https),第5张

    这是因为,Nginx作为正向代理服务器时,默认仅支持http协议,是不支持https协议的。

    2.Nginx正向代理(https)

    那么怎么让Nginx作为正向代理服务器的时候支持https协议呢?

    我们可以使用第三方模块ngx_http_proxy_connect_module。

    下载地址:https://github.com/chobits/ngx_http_proxy_connect_module

    我们知道如果要为Nginx添加第三方模块,需要在配置configure时添加--add-module。从Nginx1.9.11版本开始,支持load_module指令来动态加载模块。

    我们这里使用--add-module进行模块的添加。

    1)查看Nginx版本以及configure信息

    nginx -V
    nginx version: nginx/1.22.1
    built by gcc 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.1) 
    configure arguments: --sbin-path=/usr/local/nginx/nginx --conf-path=/usr/local/nginx/nginx.conf --pid-path=/usr/local/nginx/nginx.pid --with-http_gzip_static_module
    

    2)下载模块

    下载地址:https://codeload.github.com/chobits/ngx_http_proxy_connect_module/zip/refs/heads/master

    3)重新编译

    这里我们两种添加第三方模块的方式都尝试一下。

    使用--add-module

    cd /home/stone/nginx-1.22.1
    # 1、添加patch
    patch -p1 < /home/stone/nginx-1.22.1/module/ngx_http_proxy_connect_module/patch/proxy_connect_rewrite_102101.patch
    # 2、configure
    ./configure --sbin-path=/usr/local/nginx/nginx --conf-path=/usr/local/nginx/nginx.conf --pid-path=/usr/local/nginx/nginx.pid --with-http_gzip_static_module --add-module=/home/stone/nginx-1.22.1/module/ngx_http_proxy_connect_module
    # 3、make
    make
    # 4、备份旧的nginx可执行文件,复制编译之后的可执行文件
    mv /usr/local/nginx/nginx /usr/local/nginx/nginx.old
    cp objs/nginx /usr/local/nginx/nginx
    # 5、升级
    make upgrade
    

    使用load_module,需要将--add-module替换为--add-dynamic-module

    cd /home/stone/nginx-1.22.1
    # 1、添加patch
    patch -p1 < /home/stone/nginx-1.22.1/module/ngx_http_proxy_connect_module/patch/proxy_connect_rewrite_102101.patch
    # 2、configure
    ./configure --sbin-path=/usr/local/nginx/nginx --conf-path=/usr/local/nginx/nginx.conf --pid-path=/usr/local/nginx/nginx.pid --with-http_gzip_static_module --add-dynamic-module=/home/stone/nginx-1.22.1/module/ngx_http_proxy_connect_module
    # 3、make
    make
    # 4 创建module文件夹,并将编译生成的ngx_http_proxy_connect_module.so拷贝过去
    mkdir /usr/local/nginx/module
    cp /home/stone/nginx-1.22.1/objs/ngx_http_proxy_connect_module.so /usr/local/nginx/module
    # 5、备份旧的nginx可执行文件,复制编译之后的可执行文件
    mv /usr/local/nginx/nginx /usr/local/nginx/nginx.old
    cp objs/nginx /usr/local/nginx/nginx
    # 6、升级
    make upgrade
    

    4)修改配置文件

    # --add-dynamic-module动态添加第三方模块时使用
    # load_module module/ngx_http_proxy_connect_module.so;
    http {
    	server {
    		listen 8080;
    		server_name localhost;
    		resolver 114.114.114.114 ipv6=off;
    		proxy_connect;
    		proxy_connect_allow 443 80;
    		proxy_connect_connect_timeout  10s;
    		proxy_connect_data_timeout     10s;
    		# 指定代理日志
    		access_log logs/access_proxy.log main;
    		location / {
    			proxy_pass $scheme://$host$request_uri;
    		}
    	}
    }
    

    此时访问https://www.baidu.com,在access_proxy.log产生如下日志,说明https代理成功。

    Nginx之正向代理与反向代理进阶(支持https),第6张

    3.Nginx反向代理(http)

    同样的,Nginx作为反向代理服务器,默认也是只支持http协议,我们来回顾一下Nginx作为反向代理服务器支持http协议的配置。

    server {
    	listen       80;
    	server_name  localhost;
        location /proxy {
        	proxy_set_header X-Real-IP $remote_addr;
        	proxy_pass http://192.168.110.98;
        }
    }
    

    可以看到,我们配置的server_name为localhost,但在实际项目中,我们是使用域名绑定Nginx服务器的IP,并且使用https协议进行访问,配置的server_name就是指定的域名,例如www.aaa.com。

    Nginx为我们提供了ngx_http_ssl_module来支持https协议,并且在提供的默认配置文件里已经给出了示例。

    4.Nginx反向代理(https)

    添加ngx_http_ssl_module的步骤和添加ngx_http_proxy_connect_module的步骤一致,只是这是Nginx提供的模块,因此在configure时使用--with-http_ssl_module 即可。

    我们再来看看采用https协议时的配置:

    server {
    	listen       443 ssl;
    	server_name  www.aaa.com;
    	
    	# 申请ssl证书后,会提供cert.pem和cert.key
    	ssl_certificate      cert.pem;
    	ssl_certificate_key  cert.key;
    	ssl_session_cache    shared:SSL:1m;
    	ssl_session_timeout  5m;
    	ssl_ciphers  HIGH:!aNULL:!MD5;
    	ssl_prefer_server_ciphers  on;
    	location /proxy {
    		proxy_pass http://192.168.110.98;
    	}
    }
    

    我们需要去为指定的域名申请ssl证书,然后将证书中的cert.pem和cert.key放到指定文件,并在配置文件中指定。例如我们这里指定的server_name为www.aaa.com,所以我们就需要为www.aaa.com申请ssl证书。

    后续我们访问https://www.aaa.com/proxy就可以被代理到指定服务端了。

    以上就是Nginx实现正向代理和反向代理支持https协议的全部内容,Nginx是多模块化的,还有很多高级功能,我们后面继续探索。