在 Nginx 中,四层的数据被称为 stream,和四层代理有关的模块主要有: ngx_stream_core_module:四层代理的基本功能模块 使用的注意事项 Nginx 的四层反代功能较为简单,其访问控制模块因为源站 IP 可以进行伪造,基本不可用于 UDP Flood 的防护。 使用健康检测功能的前提是他们在一个共享内存的 zone 里,注意各个区块的层次关系即可,zone 是配置上游服务器组共享内存的功能,因此 zone 要放在 upstream 区块。status 命令即监控dashboard 是 ngx_http_status_module 的内容,严格来说不是四层代理的部分。 我使用的 UDP 反代配置: stream { 健康检测页面配置:
ngx_stream_core_module 模块从1.9.0版本开始提供,默认编译不包含此模块,需要在编译参数中加上--with-stream。 语法:listen address:port [ssl] [udp] [backlog=number] [bind] [ipv6only=on|off] [reuseport] [so_keepalive=on|off|[keepidle]:[keepintvl]:[keepcnt]]; 设置接受连接的端口和地址,可以只有端口号,也可以包含IP或主机名。 listen 127.0.0.1:12345; Shell listen [::1]:12345; listen unix:/var/run/nginx.sock; ssl 参数所有连接都需要使用 SSL 加密; udp 参数指定监听 UDP 端口(从1.9.13版本开始支持); 其他相关参数: backlog=number 参数设置 listen() 调用的最大等待连接队列数,默认情况下,backlog 在 BSD 上被设置为-1,在其他平台被设置为511; bind 参数使用所给的 address:port 产生一个独立的 bind() 调用,用于使用多个 listen 命令监听不同地址上的相同端口号; ipv6only=on|off 参数,配置 [::] 监听地址是否接受 IPV4 请求,此选项默认为 on; reuseport 参数(从1.9.1开始支持)为每个 worker 进程独立地创建一个监听的 socket(使用 SO_REUSEPORT),允许内核将入站连接分发到不同 worker 进程,仅支持 Linux3.9+ 和 DragonFly BSD; so_keepalive=on|off|[keepidle]:[keepintvl]:[keepcnt] 参数配置 TCP keepalive 特性; 不同的 Server 区块必须 listen 不同的地址+端口组合。 语法:resolver address … [valid=time] [ipv6=on|off]; 配置解析 upstream 域名所使用的 DNS 服务器: resolver 127.0.0.1 [::1]:5353; 地址可以以 IP 或者域名的形式给出,也可以附带端口号。默认情况下,nginx 会解析 V4 和 V6 地址,并会在 TTL 时间内缓存解析结果。 语法:resolver_timeout time; 设置 DNS 解析超时时间。 语法:server {…} 设置一个独立的 Server。 语法:stream {…} 提供四层代理的 Server 的配置环境,和 http {…} 类似。 语法:tcp_nodelay on | off; 开启或关闭 TCP_NODELAY 选项,这个选项将会同时应用于到客户端和到上游服务器的连接。 语法:variables_hash_bucket_size size; 设置变量 hash 表的桶大小,详细设置参见独立文档 语法:variables_hash_max_size size; 设置 hash 表的最大大小,详细设置参见独立文档 内置变量,(ngx_stream_core_module 模块从1.11.2开始支持变量): $binary_remote_addr:二进制形式的客户端地址 ngx_stream_proxy_module允许被代理的数据流通过 TCP、UDP、Unix socket,从1.9.0版本开始提供。 语法:proxy_bind address [transparent] | off; 指定向外的连接通过指定的 IP,参数的值可以包含变量(1.11.2)。参数 off 可以取消从上一级继承的 proxy_bind 命令的效果,让系统自动选择出口 IP。 transparent(透明代理)参数可以发往源站(proxied server)的连接的源 IP 为非本地的 IP,如:客户端的真实 IP。proxy_bind $remote_addr transparent; 为达到这个目的,nginx worker 进程需要以超级用户权限运行并配置内核路由表以拦截被源站发回的网络流量。 语法:proxy_buffer_size size; 设置从源站读取数据时候缓冲区的大小,也将同时设置从客户端读取数据的缓冲区大小。 语法:proxy_connect_timeout time; 定义和源站已经建立的连接超时时间。 语法:proxy_download_rate rate; 从源站接受数据的速率限制,rate 的单位是 byte,默认数值为0即没有限制。这个限制是针对每个连接的,因此在打开两个到源站的连接时,总速率将会是 rate 值的两倍。 语法:proxy_next_upstream on | off; 当往源站的连接无法建立时,是否尝试将客户端的连接传往下一个源站。 尝试连接下一个源站的次数和时间都可被限制。 语法:proxy_next_upstream_timeout time; 限制连接到下一个源站时最大的尝试时间,默认数值为0 ,即没有限制。 语法:proxy_next_upstream_tires number; 限制连接到下一个源站时最大的尝试次数,默认数值为0 ,即没有限制。 语法:proxy_pass address; 设置源站地址,地址可以以域名或 IP 和端口的形式出现,如proxy_pass localhost:12345; 当域名被解析为多个 IP 时,将使用 round-robin 方式进行轮询,也可以使用服务器组(ngx_stream_upstream_module 提供),如proxy_pass $upstream; 在使用服务器组的情况下,server name 将首先在服务器组中搜索,如无结果则使用 resolver 进行查询。 语法:proxy_protocol; 启用PROXY proxy_protocol 语法:proxy_response number; 在 UDP 代理启用的情况下,设置从源站期望接收的数据报数量,默认情况下接收报文的数量没有限制,将持续接收响应直到 proxy_timeout 超时。 语法:proxu_ssl on | off; 对和源站之间的连接启用 SSL。 语法:proxy_ssl_certificate file; 指定一个 PEM 格式的证书用于进行和源站的 SSL 连接认证。 语法:proxy_ssl_certificate_key file; 指定一个 PEM 格式的私钥用于进行和源站的 SSL 连接认证。 语法:proxy_ssl_ciphers ciphers; 指定和源站进行握手所使用的加密套件,以 OpenSSL 库可读的格式书写,使用命令openssl ciphers可以查看完整的列表。 语法:proxy_ssl_crl file; 指定吊销证书列表。 语法:proxy_ssl_name name; 用于覆盖发往源站的 SNI 请求中的 server name,该 server name 可以包含变量(自1.11.3版本开始),默认情况下,proxy_pass 参数中的主机名将被使用。 语法:proxy_ssl_password_file file; 指定私钥的加密口令,每行一个,口令将在加载私钥文件的时候被依次尝试。 语法:proxy_ssl_session_reuse on | off; 指定和源站连接时,SSL session 是否被复用,如果出现“SSL3_GET_FINISHED”错误,请尝试关闭 SSL 会话复用。 语法:proxy_ssl_protocols [SSLv2] [SSLv3] [TLSv1] [TLSv1.1] [TLSv1.2]; 和源站连接时使用指定的 SSL 协议版本。 语法:proxy_ssl_trusted_certificate file; 指定 PEM 格式的可信的 CA 列表用于验证源站的认证有效性。 语法:proxy_ssl_verify on | off; 是否启用和源站之间的认证。 语法:proxy_ssl_verify_depth number; 指定验证源站认证的证书链层数。 语法:proxy_timeout time; 指定两次读和写操作的超时间隔,此设置将同时应用在与客户端的连接和与源站的连接。若在这个时间内没有数据传输,连接将被关闭。 语法:proxy_upload_rate rate; 限制从客户端读取数据的速率,数字单位是 byte/s,默认值0表示没有限制。这个数值是针对每个连接的,因此打开两个连接时,数据传输速率将是这个值的两倍。 ngx_stream_upstream_module ngx_stream_upstream_module模块出现于1.9.0版本,用于定义可以被proxy_pass所调用的源站服务器组和相关的配置,收费订阅版本还支持动态配置组和主动健康检测。 语法:upstream name { … } 定义一组服务器,服务器可以监听不同的端口,也可以监听 TCP 端口和 Unix Socket 的混合搭配: upstream backend { 语法:server address [parameters]; 定义 server 的地址和参数,地址可以以 IP 或者域名的形式给出,此时端口号必须指明;也可以使用unix:前缀指明地址是个 Unix socket,如果域名被解析为多个 IP,则被认为是定义了多个服务器。 参数表: weight=number 参数指定了加权 round-robin 算法的权重值。 stream { upstream u {
语法:zone name [size]; 一个 zone 使用 name 和 size 定义了一个共享的内存区域,workers 之间可以共享配置文件和实时状态,多个服务器组可以共享一个 zone,因此只需要声明一个 zone。 另外,作为收费订阅的一部分,动态配置组允许组内服务器在不完整重读配置文件的前提下更换或者修改组内成员,相关配置方式参见upstream_conf in ngx_http_stream_module。 语法:state file; 指定一个文件路径,保存动态配置组当前配置状态,当前版本中这个状态包括配置组中的服务器列表和各个服务器的参数。这个文件在每次配置文件解析时被载入、upstream 配置变动的时候被更新,注意不应直接对这个文件进行编辑。 语法:hash key [consistent]; 负载均衡所使用的客户端-服务端映射的哈希算法是基于 key 的,hash key 可以包含文字和变量,如hash $remote_addr。 语法:least_conn; 使用“最少连接”负载均衡算法,nginx 将自动选择连接最少的后端,如果存在多个后端连接数相等,将使用加权的 round-robin 进行选择。 语法:least_time connect | first_byte | last_byte; 使用“最快连接”负载均衡算法,nginx 将选择速度最快的后端,可以通过参数选择“最快”的定义是首包时间、传输完成时间还是连接建立时间。 语法:health_check [parameters]; 开启服务器组的周期性主动健康检测功能。 参数表: interval=time 参数设置了两次健康检查的间隔,单位是秒,默认值为5。 server {
健康检测也可以指定发送的数据内容和期待接收的内容,这部分配置独立地在 match 命令中设置,并在 health_check 命令的 match 参数中进行引用。 服务器组必须在同一个共享内存区域里。 如果一个服务器组设置了多项健康检查,一项未能通过的检查就会将整个服务器组标记为不健康的。 语法:health_check_timeout timeout; 对健康检测操作,以 health_check_timeout 的值覆盖 proxy_timeout 的值。 语法:match name { … } 以名称定义一组验证健康检测返回值的测试集。 参数表: send string 参数定义发送给 server 的字符串。 Shell upstream backend { match http { server {
|