Nginx代理服务器

 

导航:

  这里将Nginx的一些配置进行整合。根据导航比较容易找到对应的文档。资料来自于weixueyuan

  1.Nginx核心配置详解

  2.Nginx HTTP模块

  3.Nginx搭建 Web服务

  4.Nginx代理服务器

  5.Nginx 缓存

  6.Nginx负载均衡

  7.Nginx日志管理

  8.Nginx在微服务中的应用

  Nginx 不仅可以搭建 Web 服务器对外提供内容服务,还可以实现对客户端访问的代理功能。

  代理是客户端请求数据处理的中间角色,它本身并不产生响应数据,只是将客户端的请求转发给目标应用服务器,然后目标应用服务器再将响应数据通过代理返回客户端。Nginx 不仅可以实现 HTTP 协议的代理,还支持 TCP/UDP 及基于 HTTP/2 的 gRPC 代理。

 

1.Nginx HTTP代理服务器

  代理功能根据应用方式的不同可以分为正向代理和反向代理。正向代理是客户端设置代理地址后,以代理服务器的 IP 作为源 IP 访问互联网应用服务的代理方式;反向代理则是客户端直接访问代理服务器,代理服务器再根据客户端请求的主机名、端口号及 URI 路径等条件判断后,将客户端请求转发到应用服务器获取响应数据的代理方式。

 

1.模块指令

  Nginx 的 HTTP 代理功能是通过 ngx_http_proxy_module 模块实现的,该模块会被默认构建,无须特殊配置编译参数。配置指令如下表所示。

指令名称 指令值格式
默认值 指令说明
 proxy_bind  address[transparent] 或 off  --

 设置从指定的本地 IP 地址及端口与被代理服务器建立连接,指令值可以是变量。指令值参数为 transparent 时,允许将客户端的真实 IP 透传给被代理服务器,

 并将客户端的真实 IP 设置为访问被代理服务器的源 IP;指令值参数为 off 时,取消上一层指令域同名指令的配置

 proxy_buffering  on 或 off  on  设置是否启用响应数据缓冲区
 proxy_buffers  number size   4k 或 8k

 设置每个连接从被代理服务器接收响应数据的缓冲区数量及单个缓冲区的大小。默认单个缓冲区的大小与操作系统的单个内存页(Page Size)的大小相等。

 缓冲区至少有 2 个

 proxy_buffer_size  size   4k 或 8k  设置用于读取被代理服务器响应数据第一部分的缓冲区大小,默认值等于操作系统的单个内存页的大小
 proxy_busy_buffers_size  size  8k 或 16k

 当每个连接从被代理服务器接收响应数据时,限制 proxy_buffers 设置的缓冲区中可用于向客户端发送响应数据的缓冲区大小,以使其余的缓冲区用于从被

 代理服务器接收响应数据。该值必须大于单个缓冲区或 proxy_buffer_size 的大小,小于总缓冲区减掉一个缓冲区的大小。默认值为单个缓冲区大小的 2 倍

 proxy_limit_rate  rate  0   限制从被代理服务器读取响应的每个请求的流量速度,单位是字节/秒,指令值为“0”时表示不限制。该指令只有在 proxy_buffering 启用时才有效
 proxy_max_temp_file_size  size  1024m

 当响应数据超出响应数据缓冲区的大小时,超出部分数据将存储到临时文件中。该指令设置临时文件的最大值,指令值为“0”时,关闭存储临时文件的功能。该值必

 须大于单个缓冲区或 proxy_buffer_size 的大小

 proxy_temp_file_write_size  size  8k 或 16k

 限制一次写入临时文件的数据大小,默认值为 2 个缓冲区的大小。在默认配置下,缓冲区大小由 proxy_buffer_size 和 proxy_buffers 指令配置限制,最大值是

 proxy_max_temp_file_size 指令的值

 proxy_temp_path  path [level1 [level2 [level3]]]  proxy_temp  设置临时文件存储目录
 proxy_request_buffering  on 或 off  on

 设置是否将请求转发给被代理服务器之前,先从客户端读取整个请求体。若禁用该功能,Nginx 接收到请求体时会立即转发给被代理服务器,已经发送请求体的请求,

 将无法使用 proxy_next_upstream 指令功能。对于基于 HTTP/1.1 协议的分块传输请求,会强制读取完整请求体

 proxy_pass  address  --  设置连接被代理服务器的协议、IP 地址或套接字,也可以是域名或 upstream 定义的服务器组
 proxy_method  method  --  将当前客户端的请求方法改为指令值设定的请求方法,并向被代理服务器发送请求
 proxy_pass_request_body  on 或 off  on  设置是否将客户端请求体传递给被代理服务器
 proxy_pass_request_headers  on 或 off  on  设置是否将客户端请求头传递给被代理服务器
 proxy_set_header  field value   --  在转发给被代理服务器前,修改或添加客户端的请求头属性字段
 proxy_set_body  value  --  修改客户端的请求体为指令值指定的内容,指令值可以是文本、变量及其组合
 proxy_redirect  default 或 off 或 redirect   replacement  default  替换被代理服务器返回的响应头中属性字段 location 或 Refresh 的值,并返回给客户端。指令值为 default 时,使用 proxy_pass 指令值的内容进行替换
 proxy_cookie_domain  off 或 domain replacement  off  修改被代理服务器返回的响应头属性字段 Set-Cookie 中 domain 的内容,支持正则及变量
 proxy_cookie_path  off 或 path replacement  off  修改被代理服务器返回的响应头属性字段 Set-Cookie 中 path 的内容,支持正则及变量
 proxy_force_ranges  on 或 off  off   无论被代理服务器的 HTTP 响应头中是否有属性字段 Accept-Ranges,都启用 byte-range 请求支持
 proxy_hide_header  field  --  指定被代理服务器响应数据中不向客户端传递的 HTTP 头字段名称
 proxy_pass_header  field  --  默认配置下 Nginx 不会将头属性字段 Status 和 X-Accel-... 传递给客户端,可通过该指令开放传递
 proxy_headers_hash_bucket_size  size  64  设置指令 proxy_set_header 及 proxy_hide_header 使用哈希表的桶的大小
 proxy_headers_hash_max_size  size  512  设置指令 proxy_set_header 及 proxy_hide_header 使用哈希表的大小
 proxy_ignore_headers  field...  --  设置 Nginx 对被代理服务器响应头包含指定字段时,不执行响应操作。如 Expires 和 Cache-Control
 proxy_send_lowat  size  0  设置 FreeBSD 系统中,使用 kqueue 驱动时 socket 接口 SO_SNDLOWAT 选项的大小。在 Linux、Solaris 及 Windows 平台,该指令无效
 proxy_connect_timeout  time  60s  Nginx 与被代理服务器建立连接的超时时间,通常不应该超过 75s,与请求是否返回响应无关
 proxy_read_timeout  time  60s  在连续两个从被代理服务器接收数据的读操作之间的间隔时间超过设置的时间时,将关闭连接
 proxy_send_timeout  time  60s  在连续两个发送到被代理服务器的操作之间的间隔时间超过设置的时间时,将关闭连接
 proxy_ignore_client_abort  on 或 off  off  设置当客户端未接收响应就关闭连接时,是否关闭 Nginx 与被代理服务器的连接。默认配置下,Nginx 会记录日志响应码 499,并关闭连接
 proxy_http_version  1.0  1.0 或 1.1  设置用于代理的 HTTP 协议版本,若使用 keepalive 或 NTLM 认证,建议指令值设置为 1.1
 proxy_socket_keepalive  on 或 off  off  设置 Nginx 与被代理服务器的 TCP keepalive 行为的心跳检测机制,默认使用操作系统的 socket 配置。若指令值为 on,则开启 SO_KEEPALIVE 选项进行心跳检测
 proxy_intercept_errors  on 或 off  off  当指令值为 on 时,将拦截被代理服务器响应码大于或等于 300 的结果,error_page 指令可对该结果做后续处理;当指令值为 off 时,直接返回给客户端
 proxy_next_upstream error、timeout、
invalid_header、
http_500、http_502、
http_503、http_504、
http_403、http_404、
http_429、
non_idempotent、
off...
 enror timeout  当出现指令值中指定的条件时,将未返回响应的客户端请求传递给 upstream 中的下一个服务器
 proxy_next_upstream_timeout  time  0  设置将符合条件的客户端请求传递给 upstream 中下一个服务器的超时时间。“0”为不做超时限制,此时须遍历完所有上游服务器组中的服务器
 proxy_next_upstream_tries  number  0  设置将符合条件的客户端请求传递给 upstream 中下一个服务器的尝试次数,包括第一次失败次数。“0”为不做尝试次数限制,此时须遍历完所有上游服务器组中的服务器
 proxy_ssl_protocols [SSLv2][SSLv3]
[TLSv1][TLSv1.1]
[TLSv1.2][TLSv1.3] 
TLSv1 TLSv1.1 TLSv1.2   指定可用于 Nginx 与被代理服务器建立 SSL 连接的 SSL 协议版本
 proxy_ssl_server_name  on 或 off  off  在与被代理服务器建立 HTTPS 连接时,设置是否启用通过 SNI 或 RFC 6066 传递主机名
 proxy_ssl_ciphers  ciphers  DEFAULT  设置与被代理服务器建立 SSL 连接时用于协商使用的加密算法组合,又称密码套件,指令值内容为 openssl 的密码套件名称,多个套件名称由“:”分隔
 proxy_ssl_session_reuse  on 或 off  off  决定是否启用与被代理服务器 HTTPS 连接的 SSL 会话重用功能 
 proxy_ssl_certificate  file  --  指定被代理服务器对 Nginx 服务器身份验证的 PEM 格式 SSL 证书文件
 proxy_ssl_certificate_key  file  --  指定被代理服务器对 Nginx 服务器身份验证的 PEM 格式 SSL 证书私钥文件
 proxy_ssl_password_file  file  --  存放被代理服务器对 Nginx 服务器身份验证的 PEM 格式 SSL 证书私钥文件的密码文件,一个密码一行。有多个密码时,Nginx 会依次尝试
 proxy_ssl_verify  on 或 off  off  设置是否启用对被代理服务器的 SSL 证书验证功能
 proxy_ssl_crl  file  --  证书吊销列表文件,用以验证被代理服务器 SSL 证书有效性的 PEM 格式文件
 proxy_ssl_trusted_certificate  file  --  指定一个 PEM 格式 CA 证书(根或中间证书)文件,该证书用作被代理服务器的证书链验证
 proxy_ssl_name   name   $proxy_host  指定对被代理服务器 SSL 证书验证的主机名
 proxy_ssl_verify_depth  number  1  设置对被代理服务器 SSL 证书链的验证深度

  关于上表,有以下几点需要说明。

    • 在 ngx_http_proxy_module 模块指令列表中,除 proxy_pass 指令以外,其余指令使用的指令域范围都是 http、server 或 location;
    • 缓冲区的大小默认为操作系统中单个内存页的大小,在 CentOS 下可通过如下命令查询:
getconf PAGE_SIZE
    • proxy_next_upstream 指令值中,当 non_idempotent 参数启用时,请求方法 POST、LOCK、PATCH 在出现错误时,也可以向下一个服务器重复提交。

 

2.正向代理

  正向代理是客户端设置代理地址后,通过将代理服务器的 IP 作为源 IP 访问互联网应用服务的代理方式。通过对正向代理访问设置,可以实现限制客户端的访问行为、下载速度、访问记录统计、隐藏客户端信息等目的。实现原理如下图所示。

图:正向代理

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; # 代理到远端服务器
    }
}

 

2) HTTPS 的正向代理

  Nginx 默认不支持 HTTP 的 CONNECT 方法,所以无法实现 HTTPS 的正向代理的功能,若要实现 Nginx 的 HTTPS 的正向代理功能,需要添加一个第三方模块 ngx_http_proxy_connect_module,实现 HTTPS 的正向代理支持。对于该模块,官网提示可支持到 Nginx 1.15.8 版本,但实测 Nginx 的 1.17.0 版本也可以编译通过。模块配置指令如下表所示。

指令名称 指令值格式 默认值 指令说明
proxy_connect -- -- 启用 HTTP 的 CONNECT 方法支持
proxy_connect_allow all 或端口或端口范围 443 563 设置允许 CONNECT 方法的访问端口
proxy_connect_timeout time -- 设置与被代理服务器建立连接的超时时间
proxy_connect_read_timeout time 60s 在连续两个从被代理服务器接收数据的操作之间的间隔时间超过设置的时间时,将关闭连接
proxy_connect_send_timeout time 60s 在连续两个发送到被代理服务器的操作之间的间隔时间超过设置的时间时,将关闭连接
proxy_connect_address address 或 off none 设置代理服务器的 IP 地址,指令值可以是变量。指令值 off 等于 none
proxy_connect_bind address[tran-sparent] 或 off none

设置从指定的本地 IP 地址及端口号与被代理服务器建立连接,指令值不能是变量。transparent 参数启用时,

将会允许以非 Nginx 的客户端 IP 为源 IP 访问被代理服务器。指令值 off 等于 none

  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 代理服务器访问互联网服务器。 

 

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;
    }
}

 

4.HTTPS 的反向代理

  HTTPS 通过加密通道保护客户端与服务端之间的数据传输,已成为当前网站部署的必选配置。在部署有 Nginx 代理集群的 HTTPS 站点,通常会把 SSL 证书部署在 Nginx 的服务器上,然后把请求代理到后端的上游服务器。这种部署方式由 Nginx 服务器负责 SSL 请求的运算,相对减轻了后端上游服务器的 CPU 运算量,这种方式也被称为 SSL 终止(SSL Termination)。

  因 Nginx 启用了对 TSL SNI(Server Name 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 证书并通过自签证书的方式进行签发,部署方式如下图所示。

                         图:HTTPS代理

  www.nginxbar.org (http://www.nginxbar.org) 证书为对外网站的域名证书,用于给用户提供身份验证。

  backend.nginxbar.org (htp://backend.nginxbar.org) 证书为被代理服务器的域名证书,用于给 Nginx 服务器提供身份验证。

  proxy.nginxbar.com (http://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;
}

 

5.反向代理的真实客户端 IP

  客户端在访问互联网应用服务器时,与真实的应用服务器之间会因为有多层反向代理,而导致真实应用服务器获取的仅是最近一层的反向代理服务器 IP。为使 Nginx 后端的上游服务器可以获得真实客户端 IP,Nginx 提供了 ngx_http_realip_module 模块用以实现真实客户端 IP 的获取及传递的功能。

  通过该模块提供的配置指令,用户可以手动设置上层反向代理服务器的 IP 作为授信 IP,Nginx 服务器根据配置指令的配置排除授信 IP,而甄别出真实的客户端 IP 进行日志记录,并传递给上游服务器。模块配置指令如下表所示。

指令名称 指令值格式 默认值 指令说明
set_real_ip_from address 或 CIDR 或 unix -- 设置授信 IP,IP 网段或 UNIX 套接字
real_ip_header field 或 X-Real-IP 或 X-For-warded-For 或 proxy_protocol  X-Real-IP 通过指定的 HTTP 头字段获取真实客户端 IP
real_ip_recursive on 或 off off

当客户端经多层反向代理到达当前服务器时,指定的 HTTP 头字段中会有多个 IP 地址。

默认会以最后一个 IP 为真实客户端 IP,当指令值为 on 时,会以最后一个非信 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;
    }
}

 

2.Nginx stream模块简述

  Nginx 的 TCP/UDP 代理功能的模块分为核心模块和辅助模块、核心模块 stream 需要在编译配置时增加“--with-stream”参数进行编译。核心模块的全局配置指令如下表所示。

参数名称 指令值格式 默认值 参数说明
listen address:port[ssl][udp][proxy protocol]
[backlog=number][rcvbuf=size]
-- stream 监听协议及端口
listen [sndbuf=size][bind][ipv6only=on 或 off]
[reuseport][so_keepalive=on 或 off 或
[keepidle]:[keepintvl]:[keepent]]
-- stream 监听协议及端口
preread_buffer_size size 16k 设置每个会话数据预读缓冲区的大小
preread_timeout timeout 30s 设置每个会话数据预读取的超时时间
proxy_protocol_timeout timeout 30s 读取代理协议头的超时时间
resolver address... [valid=time][ipv6=on 或 off] -- 域名解析服务器地址
resolver_timeout time 30s 域名解析超时时间
tcp_nodelay on 或 off on 启用或关闭立即发送数据(tcp_nodelay)选项
variables_hash_bucket_size size 64 设置变量哈希表中桶的大小
variables_hash_max_size size 1024 设置变量哈希表的最大值

  关于上表有以下几点需要说明。

    • 指令 listen 使用的指令域范围为 server;
    • 指令 variables_hash_bucket_size 和 variables_hash_max_size 使用的指令域范围为 stream;
    • stream 核心模块其余指令使用的指令域范围为 stream、server;
    • resolver 指令值可填写多个域名解析服务器地址,各个地址用空格分隔;
    • listen 指令值参数如下表所示。
参数名称 默认 参数说明
ssl -- 在指定监听端口上启用 SSL 协议支持
udp -- 在指定监听端口上启用 UDP 协议支持
proxy_protocol -- 在指定监听端口上启用 proxy_protocol 协议支持
backlog -1/511 设置挂起连接队列的最大长度,在 FreeBSD、DragonFly BSD 和 macOS 操作系统上,设置默认值为 -1,其他平台为 511
rcvbuf -- 设置套接字(socket)接收缓冲区(SO_RCVBUF 选项)的大小,Linux 操作系统下默认值为内核参数 net.core.rmem_default 的值
sndbuf -- 设置套接字(socket)发送缓冲区(SO_SNDBUF 选项)的大小,Linux 操作系统下默认值为内核参数 net.core.wmem_default 的值
bind -- address:port 指定 IP 及端口
ipv6only on 只接收 IPv6 连接,或接收 IPv6 和 IPv4 连接
reuseport --

在默认情况下,所有的工作进程都会共享一个 socket 去监听同一 IP 和端口的组合。该参数启用后,允许每个工作进程由独立的 socket

去监听同一 IP 和端口的组合,内核会对传入的连接进行负载均衡。目前,它只适用于 Linux 3.9+、DragonFly BSD 和 FreeBSD 12+

so_keepalive off

配置监听的端口启用 TCP keepalive 机制时的心跳检测参数。当指令值为 on 时,默认等同于 so_keepalive=30m::10,表示 30 分钟

无数据传输时发送探测包,总共发送 10 次,发送时间间隔为系统内核参数 tcp_keepalive_intvl 的设定值

  配置样例如下:

stream {
    resolver 114.114.114.114 valid=300s; 
    resolver_timeout 2s;

    upstream backend {
       server 192.168.0.1:333;
       server www.example.com:333;
    }

    server {
        listen 127.0.0.1:333 udp reuseport;
        proxy_timeout 20s;
        proxy_pass backend;
    }

    server {
        listen [::1]:12345;
        proxy_pass unix:/tmp/stream.socket;
    }
}

 

Stream辅助模块

 

1.ngx_stream_map_module

  该模块的功能是在客户端每次连接时,Nginx按照map指令域中源变量的当前值,把设定的对应值赋给新变量。该指令的语法格式如下:

map 源变量 新变量{}

  这个指令使用的指令域只有 stream,指令值参数如下表所示。

参数名称 参数值
default 为新变量指定一个默认值。若不指定这个参数,新变量默认值为空
hostnames 当源变量为主机名时,允许使用主机名前缀或后缀对源变量值进行匹配
include 引入一个外部文件作为 map 的指令域内容
volatile map 默认创建的是可被缓存的变量,启用该参数后,创建的为不可被缓存的变量

  map 指令域中,当源变量值存在相同匹配项时,匹配的顺序如下:

    • 完全匹配的字符串;
    • 有主机前缀的最长字符串;
    • 有主机后缀的最长字符串;
    • 在指令域中按自上而下的顺序最先匹配到的正则表达式;
    • default 参数给定的默认值。

 

  map 哈希表大小指令如下表所示。

名称 map 哈希表大小指令
指令 map_hash_max_size
作用域 stream
默认值 2048
指令说明 map 指令中,存储变量的哈希表的大小

 

  map 哈希桶大小指令如下表所示。

名称 map 哈希桶大小指令
指令 map_hash_bucket_size
作用域 stream
默认值 32、64 或 128
指令说明 map 指令中,存储变量的哈希桶的大小

  配置样例如下:

stream{
   
    map $remote_addr $limit {
        127.0.0.1    “”;
        default      $binary_remote_addr;
    }

    limit_conn_zone $limit zone=addr:10m;
    limit_conn addr 1;
    server {
        listen 33060 reuseport;
        access_log  logs/tcp.log tcp;

        proxy_timeout 20s;
        proxy_pass 127.0.0.1:3306;
    }
}

 

2.ngx_stream_geo_module

  该模块的功能是从源变量获取 IP 地址,并根据设定的 IP 与对应值的列表对新变量进行赋值。该模块只有一个 geo 指令,指令格式如下:

geo [源变量]新变量{}

  geo 指令的默认源变量是 $remote_addr,新变量默认值为空,这个指令使用的指令域只有 stream,指令值参数如下表所示

参数名 参数描述
delete 删除配置中已经存在的相同 IP 地址的设定
default 如果从源变量获取的IP无法匹配任意一个 IP 或 IP 范围时,使用这个参数的值作为新变量赋值
include 引入一个包含 IP 与对应值的外部文件
ranges 以地址段的形式定义 IP 地址,这个参数必须放在最上面

  配置样例如下:

geo $country {
    ranges;
    default                   CN;
    127.0.0.0-127.0.0.0       US;
    10.1.0.0-10.1.255.255     RU;
    192.168.1.0-192.168.1.255 UK;
}

geo $country {
    default        ZZ;
    include        conf/geo.conf;
    delete         127.0.0.0/16;

    127.0.0.0/24   US;
    10.1.0.0/16    RU;
    192.168.1.0/24 UK;
}

 

3.ngx_stream_geoip_module

  该模块的功能首先是根据客户端的 IP 地址与 MaxMind 数据库中的城市地址信息做比对,然后再将对应的城市地址信息赋值给内置变量。

  国家信息数据库指令如下表所示。

名称 国家信息数据库指令
指令 geoip_country
作用域 stream
默认值 1
指令说明 指定国家信息的 MaxMind 数据库文件路径

 

  城市信息数据库指令如下表所示。

名称 城市信息数据库指令
指令 geoip_city
作用域 stream
默认值 1
指令说明 指定城市信息的 MaxMind 数据库文件路径

 

  机构信息数据库指令如下表所示。

名称 机构信息数据库指令
指令 geoip_org
作用域 stream
默认值 1
指令说明 指定机构信息的 MaxMind 数据库文件路径

  配置样例如下:

stream {
    geoip_country         /usr/share/GeoIP/GeoIP.dat;
    geoip_city            /usr/share/GeoIP/GeoLiteCity.dat;

    map $geoip_city_continent_code $nearest_server {
        default        example.com;
        EU          eu.example.com;
        NA          na.example.com;
        AS          as.example.com;
    }
    ...
}

 

4.ngx_stream_split_clients_module

  该模块会按照配置指令将一个 0~232 之间的数值根据设定的比例分割为多个数值范围,每个数值范围会被设定一个对应的给定值。用户每次请求时,指定的字符串会被计算出一个数值,该模块会将该数值所在范围对应的给定值赋值给配置中定义的变量。该功能常用来按照用户的来源IP进行访问流量分流。该指令的语法格式如下:

split_clients 字符串 新变量 {}

  配置样例如下:

stream {
    split_clients "${remote_addr}AAA" $upstream {  # ${remote_addr}AAA会被计算出一个数值
        0.5%     backend1;  # 数值在0 ~ 21474835之间,$upstream被赋值backend1
        80.0%    backend2;  # 数值在21474836 ~ 3435973836之间,$upstream被赋值backend2
        *        backend;   # 数值在3435973837 ~ 4294967295,$upstream被赋值backend
    }
    server {
        listen 389;
        proxy_pass $upstream;
    }
}

  这个指令使用的指令域只有 stream;客户端每次请求时,指定字符串会被使用 MurmurHash2 算法计算出一个 0~232(0~4294967295)之间的数值,该模块会将该数值所在范围对应的给定值赋值给配置中定义的变量。

 

5.ngx_stream_ssl_preread_module

  该模块可以在预读取阶段从 ClientHello 消息中提取信息,赋值给内置变量后供用户调用。

  SSL 信息预读如下表所示。

名称 SSL 信息预读
指令 ssl_preread
作用域 stream、server
可选项 on 或 off
默认值 off
指令说明 设置是否启用 SSL 信息预读功能

  内置变量如下表所示

变量名 变量说明
$ssl_preread_protocol 客户端支持的最高 SSL 协议版本
$ssl_preread_server_name 通过 SNI 请求的服务器名称
$ssl_preread_alpn_protocols 客户通过 ALPN 公布的协议列表

  配置样例如下:

stream {
    map $ssl_preread_protocol $upstream {
        ""        ssh.example.com:22;
        "TLSv1.2" new.example.com:443;
        default   tls.example.com:443;
    }

    server {
        listen      192.168.0.1:443;
        proxy_pass  $upstream;
        ssl_preread on;
    }
}

 

6.ngx_stream_limit_conn_module

  该模块对访问连接中含有指定变量且变量值相同的连接数进行计数,当计数值达到 limit_conn 指令设定的值时,Nginx 服务器将关闭此类连接。由于 Nginx 采用的是多进程的架构,因此该模块通过共享内存存储计数状态并实现了多个进程间的计数状态共享。

  计数存储区指令如下表所示。

名称 计数存储区指令
指令 limit_conn_zone
作用域 stream
默认值 --
指令说明 设定用以存储指定变量计数的共享内存区域

 

  连接数设置指令如下表所示。

名称 连接数设置指令
指令 limit_conn
作用域 stream、server
默认值 --
指令说明 设置指定变量并发连接的最大数

 

  连接数日志级别指令如下表所示。

名称 连接数日志级别指令
指令 limit_conn_log_level
作用域 stream、server
默认值 error
可选项 info、notice、warn、error
指令说明 当指定变量的并发连接数达最大值时,输出日志的级别

  配置样例如下:

stream {
    limit_conn_zone $binary_remote_addr zone=addr:10m; # 对客户端IP进行并发计数,计数内存区
                                                       # 命名为addr,计数内存区的大小为10MB
    server {
        limit_conn addr 1;                             # 限制客户端的并发连接数为1
        ...
    }
}

  配置说明如下所示:

    • limit_conn_zone 的格式如下:
limit_conn_zone key zone=name:size;
    • limit_conn_zone 的 key 可以是文本、变量或文本与变量的组合;
    • $binary_remote_addr 为 IPv4 时,占用 4B;为 IPv6 时,占用 16B;
    • limit_conn_zone 中,1MB 的内存空间可以存储 32000 个 32B 或 16000 个 64B 的变量计数状态;
    • 变量计数状态在 32 位系统平台占用 32B 或 64B,在 64 位系统平台占用 64B。

 

7.ngx_stream_access_module

  这个模块可以允许或拒绝客户端的源 IP 地址进行连接。

  允许连接指令如下表所示。

名称 允许连接指令
指令 allow
作用域 stream、server
可选项 address 或 CIDR 或 unix: 或 all
默认值 --
指令说明 允许指定源 IP 的客户端连接

 

  拒绝连续指令如下表所示。

名称 拒绝连接指令
指令 deny
作用域 stream、server
可选项 address 或 CIDR 或 unix: 或 all
默认值 --
指令说明 拒绝指定源 IP 的客户端连接

  配置样例如下:

stream {
    server {
        deny  192.168.1.1;          # 禁止192.168.1.1
        allow 192.168.0.0/24;       # 允许192.168.0.0/24的IP访问
        allow 10.1.1.0/16;          # 允许10.1.1.0/16的IP访问
        allow 2001:0db8::/32;
        deny  all;
    }
}

  Nginx 按照自上而下的顺序进行匹配。

 

8.ngx_stream_return_module

  该模块向客户端返回指定值并关闭连接。

  返回值指令如下表所示。

名称 返回值指令
指令 return
作用域 server
指令说明 向客户端返回指定值并关闭连接

  配置样例如下:

stream {
    server {
        listen 12345;
        return $time_iso8601; # 返回当前连接的时间
    }
}

 

3.Nginx TCP/UDP代理简述

  Nginx 并不直接提供 TCP/UDP 的应用响应,Nginx Stream 模块的核心功能是将客户端的 TCP/UDP 连接反向代理给后端的被代理服务器。

1.核心配置指令

  TCP/UDP 代理功能的核心配置指令如下表所示。

指令名称 指令值格式 默认值 指令说明
proxy_bind address[transparent] 或 off --

设置从指定的本地 IP 地址及端口与被代理服务器建立连接,指令值可以是变量。指令值参数为 transparent 时,允许将客户端的真实 IP 透传给被代理服务器,

并以客户端真实 IP 为访问被代理服务器的源 IP;指令值参数为 off 时,则取消上一层指令域同名指令的配置

proxy_buffer_size size 16k 设置用于从被代理服务器读取数据的缓冲区的大小,也用于设置从客户端读取会话数据的缓冲区的大小
proxy_connect_timeout time 60s 与被代理服务器建立连接的超时时间
proxy_timeout time 10m Nginx 服务器与客户端或被代理服务器的两个连续成功的读或写操作的最大间隔时间,如果在间隔时间内没有数据传输,则关闭连接
proxy_download_rate rate 0 限制每个连接每秒从被代理服务器中读取数据的字节数,默认不限制
proxy_upload_rate rate 0 限制每个连接每秒发送到被代理服务器的数据的字节数,默认不限制
proxy_next_upstream on 或 off on 当被代理的服务返回错误或超时时,将未返回响应的客户端连接请求传递给 upstream 中的下一个服务器
proxy_next_upstream_timeout time 0 设置将符合条件的客户端连接请求传递给 upstream 中下一个服务器的超时时间。“0”为不做超时限制,即直到遍历完所有上游服务器组中的服务器为止
proxy_next_upstream_tries number 0

设置将符合条件的客户端连接请求传递给 upstream 中下一个服务器的尝试次数,包括第一次的失败次数。“0”为不做尝试次数限制,即直到遍历完所有上游服务器

组中的服务器为止

proxy_pass address -- 被代理服务器的地址,支持 IP 或域名加端口、UNIX 域套接字、upstream 名
proxy_protocol on 或 off off 设置是否对被代理服务器的连接启用代理协议(proxy_protocol)支持
proxy_socket_keepalive on 或 off off 设置 Nginx 与被代理服务器的 TCP keepalive 行为的心跳检测机制,默认使用操作系统的 socket 配置,若指令值为 on,则开启 SO_KEEPALIVE 选项进行心跳检测
proxy_ssl on 或 off off 设置是否启用 SSL/TLS 协议与被代理服务器建立连接
proxy_ssl_protocols [SSLv2][SSLv3]
[TLSv1][TLSv1.1]
[TLSv1.2][TLSv1.3]
TLSv1
TLSv1.1
TLSv1.2
指定可用于 Nginx 与被代理服务器建立 SSL 连接的 SSL 协议版本
proxy_ssl_session_reuse on 或 off on 是否启用与被代理服务器 SSL TCP 连接的 SSL 会话重用功能
proxy_ssl_ciphers ciphers DEFAULT 设置与被代理服务器建立 SSL 连接时,用于协商使用的加密算法组合,也称为密码套件,指令值内容为 openssl 的密码套件名称,多个套件名称由“:”分隔
proxy_ssl_server_name on 或 off off 在与被代理服务器建立 SSL 连接时,设置是否启用通过 SNI 或 RFC 6066 传递主机名
proxy_ssl_certificate file -- 指定被代理服务器对 Nginx 服务器身份验证的 PEM 格式 SSL 证书文件
proxy_ssl_certificate_key file -- 指定被代理服务器对 Nginx 服务器身份验证的 PEM 格式 SSL 证书私钥文件
proxy_ssl_password_file file -- 存放被代理服务器对 Nginx 服务器身份验证的 PEM 格式 SSL 证书私钥文件的密码文件,一个密码一行。有多个密码时,Nginx 会依次尝试
proxy_ssl_verify on 或 off off 设置是否启用对被代理服务器的 SSL 证书的验证功能
proxy_ssl_name name proxy_pass
指令指定的主机名
指定对被代理服务器 SSL 证书验证的主机名
proxy_ssl_crl file -- 证书品销列表文件,用于验证被代理服务器 SSL 证书有效性的 PEM 格式文件
proxy_ssl_trusted_certificate file -- 指定一个 PEM 格式的 CA 证书(根或中间证书)文件,该证书用作被代理服务器的证书链验证
proxy_ssl_verify_depth number 1 设置被代理服务器的证书链的验证深度
proxy_requests number 0

UDP 代理时,设置同一客户端被 Nginx 在每次 UDP 会话中,转发给被代理服务器的数据报的数量。当达到这个数量时,将启用一个新的 UDP 会话继续转发。

可用于 Nginx 对 UDP 虚拟连接会话的控制

proxy_responses number -- UDP 代理时,设置允许被代理服务器返回 UDP 数据报的数量,超过指令值时将中止会话。默认无限制,0 为不返回响应数据

  该模块的指令使用的指令域范围为 stream、server。


2.TCP 反向代理配置样例

  配置样例如下:

stream {
    server {
        listen 389 ;                          # 设置监听端口为389
        proxy_pass 192.168.2.100:389;         # 将连接代理到后端192.168.2.100:389
        proxy_timeout 5s;                     # 与被代理服务器的连续通信间隔大于5s,
                                              # 则认为通信超时,将关闭连接
        proxy_connect_timeout 5s;             # 与被代理服务器建立连接的超时时间为5s
        access_log logs/ldap_access.log tcp;  # 记录日志文件为logs/ldap_access.log,
                                              # 日志模板为tcp
    }
}

 

3.代理 SSL TCP

  代理模块 stream 可以实现基于 SSL/TLS 协议的被代理服务器的反向代理,部署方式为客户端 → Nginx 服务器(TCP)→ 被代理服务器(SSL TCP)。配置样例如下:

stream {
    server{
        listen 636;                            # 设置监听端口为636
        access_log  logs/ldap_access.log tcp;
        proxy_pass  192.168.2.100:636;
        proxy_ssl   on;                        # 启用SSL/TLS协议,与被代理服务器建立连接
        proxy_ssl_session_reuse on;            # 与被代理服务器SSL TCP连接的SSL会话重用功能
    }
}

 

4.UDP 反向代理配置

  UDP 协议是一种无连接的协议,发送端与接收端传输数据之前不需要建立连接,发送端会尽最大努力把数据发送出去,不能保证安全地传输到接收端。由于传输数据不建立连接,也不需要维持复杂的链路关系(包括连接状态、收发状态等),因此发送端可同时向多个接收端传输相同的消息。

  虽然 UDP 的数据传输是不可靠的,但如果有一个数据报丢失,另一个新的数据报会在几秒内替换它发送到接收端。UDP 协议通常被用在单向传输无须返回响应及信息分发的场景,如日志收集或在屏幕上的航班信息、股票行情等多媒体场景。

stream {
    server {
        listen 1514 udp;               # 设置监听端口为1514并启用UDP协议
        proxy_pass 192.168.2.123:1514;
        proxy_responses 0;             # 会话接收数据报后无须等待返回响应,立即关闭会话
    }
}

 

4.Nginx基于SSL的TCP代理服务器

  Nginx 可以通过代理模块实现上游服务器 SSL/TLS 协议的连接,同时 Nginx 还通过模块 ngx_stream_ssl_module 提供了基于 SSL/TLS 协议的 TCP 连接监听。Nginx 还可以把 SSL 证书部署在 Nginx 服务器上,这就减轻了后端上游服务器的 CPU 运算量并实现 SSL 证书的统一管理和维护。

  ngx_stream_ssl_module 模块默认不会被构建,这就需要在编译的时候通过--with-stream_ssl_module参数进行启用。相关配置指令如下表所示。

指令名称 指令值格式 默认值 指令说明
ssl_protocols [SSLv2][SSLv3]
[TLSv1][TLSv1.1]
[TLSv1.2][TLSv1.3]
TLSv1 TLSv1.1 TLSv1.2 设置使用的 SSL 协议版本
ssl_certificate file -- PEM 格式的 SSL 证书文件,可自建或由 CA 机构颁发
ssl_certificate_key file -- PEM 格式的 SSL 证书私钥文件,可自建或由 CA 机构颁发
ssl_password_file file -- 存放 SSL 证书私钥文件的密码文件,一个密码一行。有多个密码时,Nginx 会依次尝试
ssl_ciphers ciphers HIGH:!aNULL:!MD5 设置 SSL TCP 建立连接时用于协商使用的加密算法组合,也称为密码套件。指令值内容为 openssl 的密码套件名称,多个套件名称由“:”分隔
ssl_prefer_server_ciphers on 或 off off 是否启用 SSLv3 和 TLSv1 协议在 SSL TCP 连接时优先使用服务端设置的密码套件
ssl_dhparam file -- DH 密钥交换的 Diffie-Hellman 参数文件
ssl_ecdh_curve curve auto

配置 SSL 加密时使用椭圆曲线 DH 密钥交换的曲线参数,多个参数使用“:”分隔。ecdh 是 Elliptic-Curve 和 Diffie-Hellman 的缩写,指令值

为 auto 时,配置的曲线参数是 prime256v1

ssl_session_cache off 或 none 或
[builtin[:size]]
[shared:name:size]
none SSL TCP 会话缓存设置
ssl_session_tickets on 或 off on 是否启用 SSL TCP 会话缓存 session ticket 机制,指令值为 off 时,使用 session ID 会话缓存机制
ssl_session_ticket_key file -- 指定会话凭证密钥文件,用以多台 Nginx 间实现 session ticket 共享,否则 Nginx 会随机生成一个会话凭证密钥
ssl_session_timeout time 5m 设置客户端可用会话缓存的超时时间
ssl_verify_client on 或 off 或
optional 或
optional_no_ca
off

设置是否启用对客户端证书验证功能,指令值为 on 时,启用验证;指令值为 optional 时,如果接收到客户端证书则启用验证;指令值为 optional_no_ca 时,

若接收到客户端证书,则启用客户端证书验证,但不进行证书链校验。验证结果将存储在 $ssl_client_verity 变量中

ssl_crl file -- 证书吊销列表文件,用以验证客户端 SSL 证书有效性的 PEM 格式文件
ssl_client_certificate file -- 指定一个 PEM 格式的 CA 证书(根或中间证书)文件,该证书用作客户端的证书验证。该证书列表会被发送给客户端
ssl_trusted_certificate file -- 指定一个 PEM 格式的 CA 证书(根或中间证书)文件,该证书用作客户端的证书验证。该证书列表不会被发送给客户端
ssl_verify _depth number 1 设置客户端证书链验证深度

  关于上表有以下几点需要说明。

    • 该模块指令值使用的指令域范围为 stream、server。
    • Nginx 建立 SSL TCP 监听,用户发送 SSL TCP 连接时,由 Nginx 实现 SSL 终止并把 TCP 会话代理到上游服务器,部署方式为客户端 → Nginx 服务器(SSL TCP)→ 上游服务器(TCP)。配置样例如下:
stream {
    server {
        listen              636 ssl;                    # 设置监听端口为636
        access_log logs/ldap_access.log tcp;

        ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;      # 设置使用的SSL协议版本
        ssl_ciphers         AES128-SHA:AES256-SHA:RC4-SHA:DES-CBC3-SHA:RC4-MD5;
            # 设置服务端使用的密码套件
        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;             # SSL TCP会话缓存设置共享内存区域名为
                                                        # SSL,区域大小为10MB
        ssl_session_timeout 10m;                        # SSL TCP会话缓存超时时间为10分钟
        proxy_pass                    192.168.2.100:389;
    }
}
    • 也可以通过代理模块的 proxy_ssl 指令配置与上游服务器实现全链路的安全数据通信。部署方式为客户端 → Nginx 服务器(SSL TCP)→ 被代理服务器(SSL TCP)。配置样例如下:
stream {
    server {
        listen              636 ssl;                   # 设置监听端口为636
        access_log logs/ldap_access.log tcp;

        ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;     # 设置使用的SSL协议版本
        ssl_ciphers         AES128-SHA:AES256-SHA:RC4-SHA:DES-CBC3-SHA:RC4-MD5;
            # 设置服务端使用的密码套件
        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;  # SSL TCP会话缓存设置共享内存区域名为SSL,区域大小为10MB
        ssl_session_timeout 10m;             # SSL TCP会话缓存超时时间为10分钟

        proxy_ssl   on;                      # 启用SSL/TLS协议,与被代理服务器建立连接
        proxy_ssl_session_reuse on;          # 与被代理服务器SSL TCP连接的SSL会话重用功能
    }
}

 

5.Nginx gRPC代理服务器

  Nginx 从 1.13.10 版本开始就提供了对 gRPC 代理的支持,其可以通过 gRPC 模块的反向代理功能对外发布包括基于 SSL 的 gRPC 服务,且其应用 Nginx 提供的 HTTPv2 模块可实现速率限定、基于 IP 的访问控制以及日志等功能。

  通过 Nginx 的 location 指令可检查方法调用,可将不同的调用方法路由到后端的多个不同 gRPC 服务器,以实现单点部署多个 gRPC 服务器的应用场景。并且通过 Nginx 实现 gRPC 服务器负载均衡,还可以使用轮询、最少连接数等算法实现流量分发。

1.gRPC 介绍

  gRPC 是一个开源的基于 HTTP/2 协议的高性能、跨语言的远程过程调用(RPC)框架。它提供了双向流、流控、头部压缩、单 TCP 连接上的多复用请求等功能,这些功能使其在移动设备上可更节省空间和降低电量消耗。而且 gRPC 相对于 REST 的数据调用方式,提供了一个更加适合服务间调用数据的通信方案。

  基于 gRPC 的客户端应用可以像调用本地对象方法一样直接调用 gRPC 服务端提供的方法,使其更适合分布式应用和服务场景。

2.gRPC 模块指令

  Nginx 默认会构建 gRPC 代理的支持,但 gRPC 是基于 HTTP/2 协议的,而 ngx_http_v2_module 模块默认不会被构建,这就需要在编译时通过–with-http_v2_module参数来启用对 HTTP/2 协议的支持。

  gRPC 代理模块配置指令下表所示。

指令名称 指令值格式 默认值 指令说明
grpc_bind address[transparent]或 off --

设置从指定的本地 IP 地址及端口与被代理服务器建立连接,指令值可以是变量。指令值参数为 transparent 时,

允许将客户端的真实 IP 透传给被代理服务器,并以客户端真实 IP 为访问被代理服务器的源 IP

grpc_buffer_size size 4k 或 8k 设置用于从 gRPC 服务器读取响应数据缓冲区的大小,当 Nginx 收到响应数据后将同步传递给客户端
grpc_pass address -- 设置 gRPC 服务器的地址及端口,地址可以是 IP、域名或 UNIX 套接字
grpc_hide_header field -- 指定 gRPC 服务器响应数据中,不向客户端传递的 HTTP 头字段名称
grpc_pass_header field -- 默认配置下 Nginx 不会将头字段属性 Status 和 X-Accel-... 传递给客户端,可通过该指令开放传递
grpc_ignore_headers field... -- 设置禁止 Nginx 处理从 gRPC 服务器获取响应的头字段
grpc_set_header field value Content-Length
$content_length
在转发给 gRPC 服务器前,修改或添加客户端的请求头属性字段
grpc_connect_timeout time 60s Nginx 与 gRPC 服务器建立连接的超时时间,通常不应该超过 75s
grpc_read_timeout time 60s 在连续两个从 gRPC 服务器接收数据的“读”操作之间的间隔时间超过设置的时间时,将关闭连接
grpc_send_timeout time 60s 在连续两个发送到 gRPC 服务器的“写”操作之间的间隔时间超过设置的时间时,将关闭连接
grpc_socket_keepalive on 或 off off

设置 Nginx 与被代理服务器的 TCP keepalive 行为的心跳检测机制,默认使用操作系统的 socket 配置,若指令值为 on 时,

则开启 SO_KEEPALIVE 选项进行心跳检测

grpc_intercept_errors on 或 off off

指令值为 on 时,将拦截 gRPC 服务器啊应码大于或等于 300 的结果,error page 指令可对该结果做后续处理;指令值为 off 时,

则直接返回给客户端

grpc_next_upstream error、timeout、
invalid_header、
http_500、http_503、
http_403、http_404、
http_429、
non_idempotent、
off...
error timeout 当出现指令值中指定的条件时,将未返回响应的客户请求传递给 upstream 中的下一个服务器
grpc_next_upstream_timeout time 0

设置将符合条件的客户端请求传递给 upstream 的过程中,下一个服务器的超时时间。指令值为 0 不做超时限制,

直到遍历完所有上游服务器组中的服务器为止

grpc_next_upstream_tries number 0

设置符合条件的客户端请求传递给 upstream 的过程中,下一个服务器的尝试次数,包括第一次的失败次数。指令值为 0 不做尝试次数限制,

直到遍历完所有上游服务器组中的服务器为止

grpe_ssl_protocols [SSLv2][SSLv3]
[TLSv1][TLSv1.1]
[TLSv1.2][TLSv1.3]
TLSv1
TLSv1.1
TLSv1.2
指定可用于 Nginx 与 gRPC 服务器建立 SSL 连接的 SSL 协议的版本
grpe_ssl_session_reuse on 或 off on 是否启用与 gRPC 服务器 HTTPS 连接的 SSL 会话重用功能
grpc_ssl_ciphers ciphers DEFAULT 设置 HTTPS 建立连接时用于协商使用的加密算法组合,也称为密码套件,指令值内容为 openssl 的密码套件名称,多个套件名称由“:”分隔
grpc_ssl_server_name on 或 off off 在与 gRPC 服务器建立 SSL 连接时,设置是否启用通过 SNI 或 RFC 6066 传递主机名
grpc_ssl_certificate file -- 指定 gRPC 服务器对 Nginx 服务器身份验证的 PEM 格式 SSL 证书文件
grpc_ssl_certificate_key file -- 指定 gRPC 服务器对 Nginx 服务器身份验证的 PEM 格式 SSL 证书私钥文件
grpc_ssl_password_file file -- 存放 gRPC 服务器对 Nginx 服务器身份验证的 PEM 格式 SSL 证书私钥文件的密码文件,一个密码一行。有多个密码时,Nginx 会依次尝试
grpe_ssl_verify on 或 off off 设置是否启用对 gRPC 服务器的 SSL 证书验证机制
grpc_ssl_name name proxy_pass
指令指定的主机名
指定对 gRPC 服务器 SSL 证书验证的主机名
grpc_ssl_crl file -- 证书吊销列表文件,用以验证被代理服务器 SSL 证书有效性的 PEM 格式文件
grpc_ssl_trusted_certificate file -- 指定一个 PEM 格式的 CA 证书(根或中间证书)文件,该证书用作 gRPC 服务器的证书链验证
grpc_ssl_verify_depth number 1 设置 gRPC 服务器的证书链的验证深度

 

3.gRPC反向代理

  gRPC 是基于 HTTP/2 协议的,所以 Nginx 的 gRPC 代理需要启用 HTTP/2,然后 gRPC 客户端将请求发送到 Nginx。Nginx 为 gRPC 服务提供了一个稳定的网关。其部署方式如下图所示。

图:gRPC 代理

  配置样例如下:

server {
    listen  8080 http2;                               # 设置监听端口为8080并启用http/2协议支持
    access_log /var/log/nginx/grpc_access.log main;
    location / {
        grpc_pass grpc://192.168.2.145:50051;         # 设置gRPC服务器
    }
}

  gRPC 模块同样提供对后端 SSL gRPC 服务器的反向代理,配置样例如下:

server {
    listen  80 http2;                                 # 设置监听端口为80并启用http/2协议支持
    access_log /var/log/nginx/grpcs_access.log main;
    grpc_ssl_verify off;                              # 关闭对gRPC服务器的SSL证书验证
    grpc_ssl_session_reuse on;                        # 设置gRPC服务器
    location / {
        grpc_pass grpcs://192.168.2.145:50051;        # 设置SSL gRPC服务器
    }
}

  Nginx 可以通过 HTTP 协议的 SSL 证书,对外提供安全的 gRPC 代理转发,部署方式为客户端 → Nginx 服务器(HTTPS)→ 被代理服务器(SSL gRPC)。配置样例如下:

server {
    listen 443 ssl http2 default_server;         # 设置监听端口为443并启用SSL及HTTP/2协议支持
    access_log /var/log/nginx/grpcs_access.log main;

    ssl_certificate ssl/www_nginxbar_org.pem;    # 网站证书文件
    ssl_certificate_key ssl/www_nginxbar_org.key;# 网站证书密钥文件

    grpc_ssl_verify off;
    grpc_ssl_session_reuse on;
    location / {
        grpc_pass grpcs://192.168.2.145:50051;
    }
}
posted @ 2021-07-22 17:19  小家电维修  阅读(798)  评论(0编辑  收藏  举报