Nginx代理服务应用实战
1、HTTP代理
代理功能根据应用方式的不同可以分为正向代理和反向代理。正向代理是客户端设置代理地址后,以代理服务器的IP作为源IP访问互联网应用服务的代理方式;反向代理则是客户端直接访问代理服务器,代理服务器再根据客户端请求的主机名、端口号及URI路径等条件判断后,将客户端请求转发到应用服务器获取响应数据的代理方式。
1.1、模块指令
Nginx的HTTP代理功能是通过ngx_http_proxy_module模块实现的,该模块会被默认构建,无须特殊配置编译参数。配置指令如表所示。




- ngx_http_proxy_module模块与缓存相关指令请参见第7章。
- 在ngx_http_proxy_module模块指令列表中,除proxy_pass指令以外,其余指令使用的指令域范围都是http、server或location。
- 缓冲区的大小默认为操作系统中单个内存页的大小,在CentOS下可通过如下命令查询:
getconf PAGE_SIZE - proxy_next_upstream指令值中,当non_idempotent参数启用时,请求方法POST、LOCK、PATCH在出现错误时,也可以向下一个服务器重复提交。
1.2、正向代理
正向代理是客户端设置代理地址后,通过将代理服务器的IP作为源IP访问互联网应用服务的代理方式。通过对正向代理访问设置,可以实现限制客户端的访问行为、下载速度、访问记录统计、隐藏客户端信息等目的。实现原理如图所示。

1.2.1、HTTP的正向代理
Nginx的proxy模块可以实现基础的HTTP代理功能。配置样例如下:
map $host $deny {
hostnames;
default 0;
www.google.com 1; # 禁止访问www.google.com
}
server {
listen 8080;
resolver 114.114.114.114;
resolver_timeout 30s;
access_log logs/proxy_access.log; # 记录访问日志
location / {
if ( $deny ) {
return 403; # 被禁止访问的网址返回403错误
}
proxy_limit_rate 102400; # 限制客户端的下载速率是100KB/s
proxy_buffering on ; # 启用代理缓冲
proxy_buffers 8 8k; # 代理缓冲区大小为64KB
proxy_buffer_size 8k; # 响应数据第一部分的缓冲区大小为8KB
proxy_busy_buffers_size 16k; # 向客户端发送响应的缓冲区大小16KB
proxy_temp_file_write_size 16k; # 一次写入临时文件的数据大小为16KB
# 设置所有代理客户端的agent
proxy_set_header User-Agent "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.8.1.14) Gecko/20080404 Firefox/2.0.0.14" ;
proxy_set_header Host $http_host;
proxy_connect_timeout 70s; # 代理连接超时时间
proxy_http_version 1.1; # 代理协议为http/1.1
proxy_pass $scheme://$http_host$request_uri; # 代理到远端服务器
}
}
1.2.2、HTTPS的正向代理
Nginx默认不支持HTTP的CONNECT方法,所以无法实现HTTPS的正向代理的功能,若要实现Nginx的HTTPS的正向代理功能,需要添加一个第三方模块ngx_http_proxy_connect_module,实现HTTPS的正向代理支持。对于该模块,官网提示可支持到Nginx 1.15.8版本,但实测Nginx的1.17.0版本也可以编译通过。模块配置指令如表所示。

proxy_connect模块指令使用的指令域范围为server。模块编译如下:
yum -y install patch
git clone https://github.com/chobits/ngx_http_proxy_connect_module.git
cd nginx
patch -p1 < ../ngx_http_proxy_connect_module/patch/proxy_connect_rewrite_101504.patch
./configure --add-module=../ngx_http_proxy_connect_module
配置样例如下:
server {
listen 8080;
resolver 114.114.114.114;
resolver_timeout 30s;
access_log logs/proxy_access.log # 记录访问日志
proxy_connect; # 启用HTTP的CONNECT方法支持
proxy_connect_allow all; # 允许所有端口
proxy_connect_connect_timeout 60s; # 与互联网网站建立连接的超时时间
location / {
proxy_buffering on ; # 启用代理缓冲
proxy_buffers 8 8k; # 代理缓冲区的大小为64KB
proxy_buffer_size 8k; # 响应数据第一部分的缓冲区的大小为8KB
proxy_busy_buffers_size 16k; # 向客户端发送响应的缓冲区的大小16KB
proxy_limit_rate 102400; # 限制客户端的下载速率是100KB/s
proxy_temp_file_write_size 16k; # 一次写入临时文件的数据大小为16KB
# 设置所有代理客户端的agent
proxy_set_header User-Agent “Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.8.1.14) Gecko/20080404 Firefox/2.0.0.14” ;
proxy_set_header Host $host;
proxy_connect_timeout 70s; # 代理连接
proxy_http_version 1.1; # 代理协议为http/1.1
proxy_pass $scheme://$http_host$request_uri;# 代理到远端服务器
}
}
## 本地测试
curl -x 127.0.0.1:8080 https://www.baidu.com
各浏览器可以通过代理功能配置使用Nginx代理服务器访问互联网服务器。
1.3、HTTP的反向代理
反向代理是用户客户端访问代理服务器后,被反向代理服务器软件按照一定的规则从一个或多个被代理服务器中获取响应资源并返回给客户端的代理模式,客户端只知道代理服务器的IP,并不知道后端服务器的IP,原因是代理服务器隐藏了被代理服务器的信息。因为编写Nginx的反向代理配置时,被代理服务器通常会被编写在upstream指令域中,所以被代理服务器也被称为上游服务器。实现原理如图所示。

为方便反向代理的配置,此处把通用的代理配置写在proxy.conf文件中。在使用时,通过主配置文件nginx.conf用include指令引入。文件proxy.conf的内容如下:
cat >proxy.conf<<EOF
proxy_buffering on; # 启用响应数据缓冲区
proxy_buffers 8 8k; # 设置每个HTTP请求读取上游服务器响应数据缓冲区的大小为64KB
proxy_buffer_size 8k; # 设置每个HTTP请求读取响应数据第一部分缓冲区的大小为8KB
proxy_busy_buffers_size 16k; # 接收上游服务器返回响应数据时,同时用于向客户端发送响应的缓
# 冲区的大小为16KB
proxy_limit_rate 0; # 不限制每个HTTP请求每秒读取上游服务器响应数据的流量
proxy_request_buffering on; # 启用客户端HTTP请求读取缓冲区功能
proxy_http_version 1.1; # 使用HTTP 1.1版本协议与上游服务器建立通信
proxy_connect_timeout 5s; # 设置与上游服务器建立连接的超时时间为5s
proxy_intercept_errors on; # 拦截上游服务器中响应码大于300的响应处理
proxy_read_timeout 60s; # 从上游服务器获取响应数据的间隔超时时间为60s
60sproxy_send_timeout 60s; # 向上游服务器发送请求的间隔超时时间为60s
# 设置发送给上游服务器的头属性字段Host为客户端请求头头字段Host的值
proxy_set_header Host $host:$server_port;
# 设置发送给上游服务器的头属性字段Referer为客户端请求头头字段的值Host
proxy_set_header Referer $http_referer;
# 设置发送给上游服务器的头属性字段Cookie为客户端请求头头字段的值Host
proxy_set_header Cookie $http_cookie;
# 设置发送给上游服务器的头属性字段X-Real-IP为客户端的IP
proxy_set_header X-Real-IP $remote_addr;
# 设置发送给上游服务器的头属性字段X-Forwarded-For为客户端请求头的X-Forwarded-For的
# 值,如果没有该字段,则等于$remote_addr
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 设置发送给上游服务器的头属性字段X-Forwarded-Proto为请求协议的值
proxy_set_header X-Forwarded-Proto $scheme;
EOF
在nginx.conf的http指令域中引入该文件,配置样例如下:
http {
...
include proxy.conf
include conf.d/*.conf
}
Nginx的指令支持在指令域中对上级指令域指令的继承和修改,若对proxy.conf有特殊配置需求的,可在对应的server指令域中添加同名指令。
反向代理的配置样例如下:
server {
listen 8088;
access_log logs/proxy.access.log main;
tcp_nodelay off; # 因启用缓冲区功能,所以关闭立刻发送功能
location ~ ^/ {
proxy_force_ranges on; # 强制启用字节范围请求支持
proxy_pass http://192.168.2.145:8082;
break;
}
}
1.4、HTTPS的反向代理
HTTPS通过加密通道保护客户端与服务端之间的数据传输,已成为当前网站部署的必选配置。在部署有Nginx代理集群的HTTPS站点,通常会把SSL证书部署在Nginx的服务器上,然后把请求代理到后端的上游服务器。这种部署方式由Nginx服务器负责SSL请求的运算,相对减轻了后端上游服务器的CPU运算量,这种方式也被称为SSL终止(SSL Termination)。因Nginx启用了对TSL SNI(ServerName Identification)技术的支持,所以在同一服务器上可以安装多个绑定不同域名的SSL证书,使其可以在Nginx服务器上统一部署,同时也极大地方便了证书的管理和维护。
由Nginx服务器实现SSL终止的HTTPS的反向代理的常见方式有两种,一种是由Nginx通过HTTP方式与被代理服务器建立连接;另一种是由Nginx通过HTTPS方式与被代理服务器建立连接。由Nginx通过HTTP方式与被代理服务器建立连接的部署方式为客户端→Nginx服务器(HTTPS)→上游服务器(HTTP),配置样例如下:
server {
listen 443 ssl;
server_name www.nginxbar.org;
charset utf-8;
access_log logs/sslproxy.access.log main;
tcp_nodelay off; # 因启用缓冲区功能,所以关闭立刻发送功能
ssl_certificate ssl/www_nginxbar_org.pem; # 网站证书文件
ssl_certificate_key ssl/www_nginxbar_org.key; # 网站证书密钥文件
ssl_session_cache shared:SSL:10m; # 会话缓存的存储大小为10MB
ssl_session_timeout 10m; # 会话缓存的超时时间为10分钟
ssl_session_tickets on; # 设置会话凭证为会话缓存机制
ssl_session_ticket_key ssl/session_ticket.key; # 设置会话凭证密钥文件
location ~ ^/ {
proxy_pass http://192.168.2.145:8082;
break;
}
}
按照上面的配置,Nginx服务器与后端的上游服务器之间仍然采用的是HTTP透明传输,虽然可以与上游服务器部署在同一内网,但数据传输仍是不安全的。为了提高传输安全性,建议在上游服务器也开启HTTPS协议,实现全链路的安全数据传输。由Nginx通过HTTPS方式与被代理服务器建立连接的配置样例场景如下。
在配置样例的场景中有两个HTTPS节点,为方便举例说明配置指令的功能及配置指令中所用的SSL证书的区别,共设计了3个SSL证书并通过自签证书的方式进行签发,部署方式如图所示。

- www.nginxbar.org证书为对外网站的域名证书,用于给用户提供身份验证。
- backend.nginxbar.org证书为被代理服务器的域名证书,用于给Nginx服务器提供身份验证。
- proxy.nginxbar.com证书为Nginx服务器的域名证书,用于给被代理服务器提供身份验证。
自签证书命令如下:
# 生成自建根域nginxbar.org证书
openssl req -new -x509 -out /etc/nginx/conf/ssl/root.pem -keyout
/etc/nginx/conf/ssl/root.key -days 3650 -subj
"/C=CN/ST=Shanghai/L=Shanghai/O=nginxbar/OU=admin/CN=nginxbar.org/emailAddress= admin@nginxbar.org"
# 域名www.nginxbar.org生成请求文件,面向用户端的域名请求文件
openssl req -out /etc/nginx/conf/ssl/www_nginxbar_org.csr -new -sha256
-newkey rsa:2048 -nodes -keyout /etc/nginx/conf/ssl/www_nginxbar_org.key
-subj
"/C=CN/ST=Shanghai/L=Shanghai/O=nginxbar/OU=www/CN=www.nginxbar.org/emailAddress= www@nginxbar.org"
# 颁发自签域名www.nginxbar.org证书,面向用户端的域名证书
openssl x509 -req -in /etc/nginx/conf/ssl/www_nginxbar_org.csr -out
/etc/nginx/conf/ssl/www_nginxbar_org.pem -CA /etc/nginx/conf/ssl/root.pem
-CAkey /etc/nginx/conf/ssl/root.key -CAcreateserial -days 3650
# 域名backend.nginxbar.org生成请求文件,后端上游服务器的SSL请求文件
openssl req -out /etc/nginx/conf/ssl/backend_nginxbar_org.csr -new -sha256
-newkey rsa:2048 -nodes -keyout
/etc/nginx/conf/ssl/backend_nginxbar_org.key -subj
"/C=CN/ST=Shanghai/L=Shanghai/O=nginxbar/OU=backend/CN=backend.nginxbar.org/emailAddress=backend@nginxbar.org"
# 颁发自签域名backend.nginxbar.org证书,后端上游服务器的SSL证书
openssl x509 -req -in /etc/nginx/conf/ssl/backend_nginxbar_org.csr -out
/etc/nginx/conf/ssl/backend_nginxbar_org.pem -CA
/etc/nginx/conf/ssl/root.pem -CAkey /etc/nginx/conf/ssl/root.key
-CAcreateserial -days 3650
# 生成自建根域nginxbar.com证书,该域名仅为方便区分代理端和后端证书使用,实际使用时可以使用一个根证书
openssl req -new -x509 -out /etc/nginx/conf/ssl/proxy_root.pem -keyout
/etc/nginx/conf/ssl/proxy_root.key -days 3650 -subj
"/C=CN/ST=Shanghai/L=Shanghai/O=nginxbar/OU=admin/CN=nginxbar.com/emailAddress= admin@nginxbar.com"
# 域名proxy.nginxbar.com生成请求文件,Nginx服务器的SSL代理请求文件
openssl req -out /etc/nginx/conf/ssl/proxy_nginxbar_com.csr -new -sha256
-newkey rsa:2048 -nodes -keyout /etc/nginx/conf/ssl/proxy_nginxbar_com.key
-subj “/C=CN/ST=Shanghai/L=Shanghai/O=nginxbar/OU=proxy/CN=proxy.nginxbar.com
/emailAddress=proxy@nginxbar.com”
# 颁发自签域名proxy.nginxbar.com证书,Nginx服务器的SSL代理证书
openssl x509 -req -in /etc/nginx/conf/ssl/proxy_nginxbar_com.csr -out
/etc/nginx/conf/ssl/proxy_nginxbar_com.pem -CA
/etc/nginx/conf/ssl/proxy_root.pem -CAkey
/etc/nginx/conf/ssl/proxy_root.key -CAcreateserial -days 3650
Nginx代理服务器的配置如下:
resolver 114.114.114.114 valid=300s; # DNS服务器地址
resolver_timeout 5s; # DNS解析的超时时间为5s
server {
listen 443 ssl;
server_name www.nginxbar.org;
access_log logs/sslproxy2_access.log main;
ssl_certificate ssl/www_nginxbar_org.pem; # 网站www.nginxbar.org证书文件
ssl_certificate_key ssl/www_nginxbar_org.key; # 网站www.nginxbar.org证书密钥文件
ssl_session_cache shared:SSL:10m; # 会话缓存的存储大小为10MB
ssl_session_timeout 10m; # 会话缓存的超时时间为10分钟
ssl_session_tickets on; # 设置会话凭证为会话缓存机制
ssl_session_ticket_key ssl/session_ticket.key; # 设置会话凭证密钥文件
location / {
proxy_pass https://backend.nginxbar.org; # 被代理服务器的地址
proxy_ssl_certificate ssl/proxy_nginxbar_com.pem; # 代理服务器的客户端证书
# 文件
proxy_ssl_certificate_key ssl/proxy_nginxbar_com.key; # 代理服务器的客户端证书
# 密钥文件
proxy_ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
proxy_ssl_ciphers HIGH:!aNULL:!MD5;
proxy_ssl_verify on; # 启用验证被代理服务器的证书
proxy_ssl_trusted_certificate ssl/root.pem; # 用于验证被代理服务器的主机名backend.
# nginxbar.org的根证书
proxy_ssl_verify_depth 2; # 证书验证深度为2
proxy_ssl_session_reuse on; # SSL连接启用会话重用
}
}
Nginx Web服务器配置如下:
server {
listen 443 ssl;
server_name backend.nginxbar.org;
access_log logs/sslbackend_access.log main;
ssl_certificate ssl/backend_nginxbar_org.pem;# 网站backend.nginxbar.org证书文件
ssl_certificate_key ssl/backend_nginxbar_org.key;# 网站backend.nginxbar.org证书密钥
# 文件
ssl_verify_client on; # 启用对Nginx服务的证书验证
ssl_client_certificate ssl/proxy_root.pem; # 用以验证Nginx服务器主机名
# proxy.nginxbar.com的根证书
ssl_verify_depth 2; # 证书验证深度为2
ssl_session_cache shared:SSL:10m; # HTTPS会话缓存的存储大小为10MB
ssl_session_tickets off; # 以会话编号机制实现会话缓存
ssl_session_timeout 10m; # 会话缓存的超时时间为10分钟
charset utf-8;
root /opt/nginx-web;
index index.html index.htm;
}
HTTPS相关介绍请参见5.2节。
1.5、反向代理的真实客户端IP
客户端在访问互联网应用服务器时,与真实的应用服务器之间会因为有多层反向代理,而导致真实应用服务器获取的仅是最近一层的反向代理服务器IP。为使Nginx后端的上游服务器可以获得真实客户端IP, Nginx提供了ngx_http_realip_module模块用以实现真实客户端IP的获取及传递的功能。通过该模块提供的配置指令,用户可以手动设置上层反向代理服务器的IP作为授信IP, Nginx服务器根据配置指令的配置排除授信IP,而甄别出真实的客户端IP进行日志记录,并传递给上游服务器。模块配置指令如表所示。

该模块指令使用的指令域范围为http、server、location。配置样例如下:
server {
listen 8088;
access_log logs/proxy.access.log main;
set_real_ip_from 192.168.2.159; # 设置192.168.2.159为授信IP
real_ip_header X-Forwarded-For; # 通过HTTP头字段X-Forwarded-For获取真实客户端IP
real_ip_recursive on; # 以最后一个非授信IP为真实客户端IP
tcp_nodelay off; # 因启用缓冲区功能,所以关闭立刻发送功能
location ~ ^/ {
proxy_force_ranges on; # 强制启用字节范围请求支持
proxy_pass http://192.168.2.145:8082;
break;
}
}
1030



被折叠的 条评论
为什么被折叠?



