)
Nginx代理服务应用实战1、HTTP代理1.1、模块指令1.2、正向代理1.2.1、HTTP的正向代理1.2.2、HTTPS的正向代理1.3、HTTP的反向代理1.4、HTTPS的反向代理1.5、反向代理的真实客户端IP1、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_SIZEproxy_next_upstream指令值中当non_idempotent参数启用时请求方法POST、LOCK、PATCH在出现错误时也可以向下一个服务器重复提交。1.2、正向代理正向代理是客户端设置代理地址后通过将代理服务器的IP作为源IP访问互联网应用服务的代理方式。通过对正向代理访问设置可以实现限制客户端的访问行为、下载速度、访问记录统计、隐藏客户端信息等目的。实现原理如图所示。1.2.1、HTTP的正向代理Nginx的proxy模块可以实现基础的HTTP代理功能。配置样例如下map$host$deny{hostnames;default0;www.google.com1;# 禁止访问www.google.com}server{listen8080;resolver114.114.114.114;resolver_timeout 30s;access_log logs/proxy_access.log;# 记录访问日志location /{if($deny){return403;# 被禁止访问的网址返回403错误}proxy_limit_rate102400;# 限制客户端的下载速率是100KB/sproxy_buffering on;# 启用代理缓冲proxy_buffers88k;# 代理缓冲区大小为64KBproxy_buffer_size 8k;# 响应数据第一部分的缓冲区大小为8KBproxy_busy_buffers_size 16k;# 向客户端发送响应的缓冲区大小16KBproxy_temp_file_write_size 16k;# 一次写入临时文件的数据大小为16KB# 设置所有代理客户端的agentproxy_set_header User-AgentMozilla/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_version1.1;# 代理协议为http/1.1proxy_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-yinstallpatchgitclone https://github.com/chobits/ngx_http_proxy_connect_module.gitcdnginx patch-p1../ngx_http_proxy_connect_module/patch/proxy_connect_rewrite_101504.patch ./configure --add-module../ngx_http_proxy_connect_module配置样例如下server{listen8080;resolver114.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_buffers88k;# 代理缓冲区的大小为64KBproxy_buffer_size 8k;# 响应数据第一部分的缓冲区的大小为8KBproxy_busy_buffers_size 16k;# 向客户端发送响应的缓冲区的大小16KBproxy_limit_rate102400;# 限制客户端的下载速率是100KB/sproxy_temp_file_write_size 16k;# 一次写入临时文件的数据大小为16KB# 设置所有代理客户端的agentproxy_set_header User-Agent “Mozilla/5.0(Windows;U;Windows NT5.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_version1.1;# 代理协议为http/1.1proxy_pass$scheme://$http_host$request_uri;# 代理到远端服务器}}## 本地测试curl-x127.0.0.1:8080 https://www.baidu.com各浏览器可以通过代理功能配置使用Nginx代理服务器访问互联网服务器。1.3、HTTP的反向代理反向代理是用户客户端访问代理服务器后被反向代理服务器软件按照一定的规则从一个或多个被代理服务器中获取响应资源并返回给客户端的代理模式客户端只知道代理服务器的IP并不知道后端服务器的IP原因是代理服务器隐藏了被代理服务器的信息。因为编写Nginx的反向代理配置时被代理服务器通常会被编写在upstream指令域中所以被代理服务器也被称为上游服务器。实现原理如图所示。为方便反向代理的配置此处把通用的代理配置写在proxy.conf文件中。在使用时通过主配置文件nginx.conf用include指令引入。文件proxy.conf的内容如下catproxy.confEOF 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_addrproxy_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{listen8088;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{listen443ssl;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;# 会话缓存的存储大小为10MBssl_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-days3650-subj/CCN/STShanghai/LShanghai/Onginxbar/OUadmin/CNnginxbar.org/emailAddress adminnginxbar.org# 域名www.nginxbar.org生成请求文件面向用户端的域名请求文件openssl req-out/etc/nginx/conf/ssl/www_nginxbar_org.csr-new-sha256-newkeyrsa:2048-nodes-keyout/etc/nginx/conf/ssl/www_nginxbar_org.key-subj/CCN/STShanghai/LShanghai/Onginxbar/OUwww/CNwww.nginxbar.org/emailAddress wwwnginxbar.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-days3650# 域名backend.nginxbar.org生成请求文件后端上游服务器的SSL请求文件openssl req-out/etc/nginx/conf/ssl/backend_nginxbar_org.csr-new-sha256-newkeyrsa:2048-nodes-keyout/etc/nginx/conf/ssl/backend_nginxbar_org.key-subj/CCN/STShanghai/LShanghai/Onginxbar/OUbackend/CNbackend.nginxbar.org/emailAddressbackendnginxbar.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-days3650# 生成自建根域nginxbar.com证书该域名仅为方便区分代理端和后端证书使用实际使用时可以使用一个根证书openssl req-new-x509-out/etc/nginx/conf/ssl/proxy_root.pem-keyout/etc/nginx/conf/ssl/proxy_root.key-days3650-subj/CCN/STShanghai/LShanghai/Onginxbar/OUadmin/CNnginxbar.com/emailAddress adminnginxbar.com# 域名proxy.nginxbar.com生成请求文件Nginx服务器的SSL代理请求文件openssl req-out/etc/nginx/conf/ssl/proxy_nginxbar_com.csr-new-sha256-newkeyrsa:2048-nodes-keyout/etc/nginx/conf/ssl/proxy_nginxbar_com.key-subj“/CCN/STShanghai/LShanghai/Onginxbar/OUproxy/CNproxy.nginxbar.com /emailAddressproxynginxbar.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-days3650Nginx代理服务器的配置如下resolver114.114.114.114valid300s;# DNS服务器地址resolver_timeout 5s;# DNS解析的超时时间为5sserver{listen443ssl;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;# 会话缓存的存储大小为10MBssl_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_depth2;# 证书验证深度为2proxy_ssl_session_reuse on;# SSL连接启用会话重用}}Nginx Web服务器配置如下server{listen443ssl;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_depth2;# 证书验证深度为2ssl_session_cache shared:SSL:10m;# HTTPS会话缓存的存储大小为10MBssl_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{listen8088;access_log logs/proxy.access.log main;set_real_ip_from192.168.2.159;# 设置192.168.2.159为授信IPreal_ip_header X-Forwarded-For;# 通过HTTP头字段X-Forwarded-For获取真实客户端IPreal_ip_recursive on;# 以最后一个非授信IP为真实客户端IPtcp_nodelay off;# 因启用缓冲区功能所以关闭立刻发送功能location ^/{proxy_force_ranges on;# 强制启用字节范围请求支持proxy_pass http://192.168.2.145:8082;break;}}