nginx ngx_stream_module(2) 指令详解

nginx ngx_stream_module(2) 指令详解

相关链接

  • nginx 嵌入式变量解析目录
  • nginx 嵌入式变量全目录
  • nginx 指令模块目录
  • nginx 指令全目录

一、目录

1.1 模块简介

  • ngx_stream_pass_module:流传递模块,允许将TCP/UDP连接直接传递给指定的后端服务器。类似于HTTP中的 proxy_pass,但用于处理TCP和UDP流量。通过 pass 指令指定后端服务器地址和端口。

  • ngx_stream_proxy_module:流代理模块,提供TCP和UDP流量的反向代理功能。它可以将客户端请求转发到一个或多个后端服务器,并将响应返回给客户端。常用的指令包括 proxy_pass 用于指定后端服务器地址和端口,以及各种超时和缓冲区设置。

  • ngx_stream_proxy_protocol_vendor_module:这是一个商业订阅模块,允许从云平台的应用特定TLV(Type-Length-Value)字段中获取连接的额外信息。它支持通过PROXY协议头获取更多关于连接的详细信息,适用于AWS、Google Cloud Platform 和 Microsoft Azure 等云平台。例如,可以提取AWS VPC端点ID、Azure私有端点LinkID和Google Cloud PSC连接ID。

  • ngx_stream_realip_module:真实IP模块,用于恢复客户端的真实IP地址。当Nginx位于反向代理或负载均衡器之后时,客户端的真实IP地址可能会被代理服务器的IP地址覆盖。通过配置 set_real_ip_fromreal_ip_header 指令,可以将代理服务器传递的真实IP信息提取出来并应用到日志记录和其他逻辑中。

  • ngx_stream_return_module:返回模块,允许在处理过程中立即返回一个预定义的响应。这对于简单的状态码返回或错误处理非常有用。使用 return 指令可以直接返回指定的状态码和消息。

  • ngx_stream_set_module:变量设置模块,允许在处理过程中动态设置变量。这对于实现复杂的条件判断和逻辑控制非常有用。使用 set 指令可以在不同的处理阶段设置或修改变量值。

  • ngx_stream_split_clients_module:客户端拆分模块,用于根据一定的规则(如IP地址范围或哈希值)将客户端分配到不同的组别。这在A/B测试或灰度发布中非常有用,可以按比例分配流量到不同的版本或服务。常用的指令是 split_clients,用于定义拆分规则。

  • ngx_stream_ssl_module:SSL/TLS支持模块,为Nginx的TCP/UDP流处理提供加密连接的能力。它允许配置SSL/TLS服务,确保数据在客户端和服务器之间的传输是安全的。常用的配置指令包括 ssl_certificatessl_certificate_key 来指定证书和私钥文件。

  • ngx_stream_ssl_preread_module:SSL预读模块,允许在不终止连接的情况下读取SSL/TLS握手信息。这对于需要在建立完整SSL连接之前进行某些操作(如基于SNI选择后端服务器)非常有用。使用 ssl_preread on; 指令启用此功能。

1.2 指令目录

1.2.80 ngx_stream_pass_module
  • pass
1.2.81 ngx_stream_proxy_module
  • proxy_bind
  • proxy_buffer_size
  • proxy_connect_timeout
  • proxy_download_rate
  • proxy_half_close
  • proxy_next_upstream
  • proxy_next_upstream_timeout
  • proxy_next_upstream_tries
  • proxy_pass
  • proxy_protocol
  • proxy_requests
  • proxy_responses
  • proxy_session_drop
  • proxy_socket_keepalive
  • proxy_ssl
  • proxy_ssl_certificate
  • proxy_ssl_certificate_cache
  • proxy_ssl_certificate_key
  • proxy_ssl_ciphers
  • proxy_ssl_conf_command
  • proxy_ssl_crl
  • proxy_ssl_key_log
  • proxy_ssl_name
  • proxy_ssl_password_file
  • proxy_ssl_protocols
  • proxy_ssl_server_name
  • proxy_ssl_session_reuse
  • proxy_ssl_trusted_certificate
  • proxy_ssl_verify
  • proxy_ssl_verify_depth
  • proxy_timeout
  • proxy_upload_rate
1.2.82 ngx_stream_proxy_protocol_vendor_module
1.2.83 ngx_stream_realip_module
  • set_real_ip_from
1.2.84 ngx_stream_return_module
  • return
1.2.85 ngx_stream_set_module
  • set
1.2.86 ngx_stream_split_clients_module
  • split_clients
1.2.87 ngx_stream_ssl_module
  • ssl_alpn
  • ssl_certificate
  • ssl_certificate_cache
  • ssl_certificate_key
  • ssl_ciphers
  • ssl_client_certificate
  • ssl_conf_command
  • ssl_crl
  • ssl_dhparam
  • ssl_ecdh_curve
  • ssl_handshake_timeout
  • ssl_key_log
  • ssl_ocsp
  • ssl_ocsp_cache
  • ssl_ocsp_responder
  • ssl_password_file
  • ssl_prefer_server_ciphers
  • ssl_protocols
  • ssl_reject_handshake
  • ssl_session_cache
  • ssl_session_ticket_key
  • ssl_session_tickets
  • ssl_session_timeout
  • ssl_stapling
  • ssl_stapling_file
  • ssl_stapling_responder
  • ssl_stapling_verify
  • ssl_trusted_certificate
  • ssl_verify_client
  • ssl_verify_depth
1.2.88 ngx_stream_ssl_preread_module
  • ssl_preread

二、解释

2.80 ngx_stream_pass_module

ngx_stream_pass_module 模块允许你将 TCP 或 UDP 连接直接传递给指定的后端服务器或 Unix 域套接字。这对于需要在不同的协议层之间进行流量转发的应用场景非常有用。

主要功能

  • 连接传递:将接受的连接直接传递给指定的监听套接字。
  • 支持多种协议:可以与其他模块结合使用,如 HTTP、Stream、Mail 等。
  • SSL/TLS 终止:可以在传递连接之前终止 SSL/TLS 加密。

使用示例

以下是一些具体的配置示例,展示如何利用 ngx_stream_pass_module 来实现连接传递。

将连接传递到 HTTP 服务

假设你想在一个流模块中终止 SSL/TLS 连接,并将解密后的连接传递给一个 HTTP 服务:

http {
    server {
        listen 8000;
        location / {
            root html;
        }
    }
}

stream {
    server {
        listen 12345 ssl;
        ssl_certificate domain.crt;
        ssl_certificate_key domain.key;

        # 将解密后的连接传递给 HTTP 服务
        pass 127.0.0.1:8000;
    }
}

在这个例子中:

  • listen 12345 ssl; 监听在 12345 端口上的 SSL/TLS 流量。
  • ssl_certificatessl_certificate_key 配置了 SSL/TLS 证书和私钥。
  • pass 127.0.0.1:8000; 将解密后的连接传递给本地的 HTTP 服务,监听在 8000 端口。

使用 Unix 域套接字

如果你想将连接传递给一个通过 Unix 域套接字监听的服务:

stream {
    server {
        listen 12345;
        
        # 将连接传递给 Unix 域套接字
        pass unix:/tmp/stream.socket;
    }
}

在这个例子中:

  • listen 12345; 监听在 12345 端口上的流量。
  • pass unix:/tmp/stream.socket; 将连接传递给位于 /tmp/stream.socket 的 Unix 域套接字。

使用变量动态设置目标地址

你可以使用变量动态设置目标地址,这在需要灵活路由时非常有用:

stream {
    server {
        listen 12345;

        # 假设 $upstream 变量已经定义好
        pass $upstream;
    }
}

在这个例子中:

  • pass $upstream; 使用 $upstream 变量动态设置目标地址。你需要确保 $upstream 变量已经在其他地方定义并赋值。

注意事项

  • SSL/TLS 支持

    • 如果你需要终止 SSL/TLS 连接,请确保正确配置 ssl_certificatessl_certificate_key
    • 在传递连接之前终止 SSL/TLS 可以提高安全性,并允许你在应用层进行进一步处理。
  • 性能考虑

    • 根据实际需求选择合适的传递策略,避免不必要的资源浪费。
    • 对于高并发场景,合理设置超时时间和重试机制,减少延迟和资源消耗。
  • 日志记录

    • 合理配置日志级别和格式,便于监控和故障排查。特别是注意记录与连接传递相关的错误信息和性能指标。
2.80.1 指令列表
pass

pass 指令用于指定 Nginx 将请求传递到的目标地址。这个指令通常用于反向代理或负载均衡配置中。

Syntax:	pass address;
Default: —
Context: server
  • address:目标服务器的地址(可以是 IP 地址、域名或 Unix 套接字路径)。

案例

基本用法

最简单的 pass 用法是指定目标地址:

server {
    listen 80;
    server_name example.com;

    # 将请求传递到 backend 服务器
    pass 192.168.1.1:8080;
}

在这个例子中:

  • 当用户访问 example.com 时,Nginx 将请求转发到 IP 地址为 192.168.1.1,端口为 8080 的后端服务器。

复杂用法

使用 upstream 定义多个后端服务器,并通过 pass 进行负载均衡:

stream {
    upstream backend_tcp {
        server 192.168.1.1:12345;
        server 192.168.1.2:12345;
    }

    server {
        listen 12345;
        # 将请求传递到 backend_tcp 组中的服务器
        pass backend_tcp;
    }
}

在这个例子中:

  • 当用户访问监听端口 12345 的服务时,Nginx 将请求分发到 backend_tcp 组中的两个服务器之一。

注意事项

  • 目标地址格式:确保目标地址格式正确,并且 Nginx 能够解析并连接到该地址。
  • 负载均衡策略:结合其他负载均衡策略(如轮询、哈希等),确保流量合理分配到各个后端服务器。

2.81 ngx_stream_proxy_module

ngx_stream_proxy_module 是 Nginx 的一个核心模块,用于在流(stream)上下文中代理 TCP 和 UDP 连接。这个模块允许你将客户端的连接转发到后端服务器,并处理诸如负载均衡、会话持久性、健康检查等功能。

主要功能

  • TCP/UDP 代理:支持代理 TCP 和 UDP 协议。
  • 负载均衡:可以配置多个后端服务器,Nginx 会根据配置的策略选择合适的后端服务器进行请求转发。
  • 健康检查:支持对后端服务器进行健康检查,自动剔除不可用的服务器。
  • 会话持久性:可以通过配置保持客户端与特定后端服务器之间的连接。
  • 日志记录:可以记录代理过程中的连接信息和错误日志。

使用示例

以下是一些简化的配置示例,展示了如何使用 ngx_stream_proxy_module 来实现不同的功能。

基本 TCP 代理

假设你希望将客户端的 TCP 连接代理到后端服务器:

stream {
    upstream backend {
        server backend.example.com:12345;
    }

    server {
        listen 12345;
        proxy_pass backend;
    }
}

在这个例子中:

  • upstream backend 定义了一个名为 backend 的后端服务器组,包含一个后端服务器。
  • server { listen 12345; proxy_pass backend; } 监听端口 12345 上的所有连接,并将其代理到 backend 组中的服务器。

多台后端服务器及负载均衡

假设你有多个后端服务器,并希望通过负载均衡来分发流量:

stream {
    upstream backend {
        server backend1.example.com:12345;
        server backend2.example.com:12345;
        server backend3.example.com:12345;

        # 可选:配置权重
        # server backend1.example.com:12345 weight=3;
        # server backend2.example.com:12345 weight=1;

        # 可选:配置最大失败次数和失败超时
        # server backend1.example.com:12345 max_fails=3 fail_timeout=30s;
    }

    server {
        listen 12345;
        proxy_pass backend;
    }
}

在这个例子中:

  • upstream backend 定义了三个后端服务器,Nginx 会根据默认的轮询算法(round-robin)分发连接。
  • weight 参数可用于调整每个服务器的权重,影响其被选中的概率。
  • max_failsfail_timeout 参数可用于配置健康检查策略,如果某个服务器连续失败超过指定次数,则会在一段时间内被视为不可用。

配置超时和缓冲区大小

假设你需要配置超时时间和缓冲区大小以优化性能:

stream {
    upstream backend {
        server backend.example.com:12345;
    }

    server {
        listen 12345;
        proxy_pass backend;

        # 设置连接超时时间为 5 秒
        proxy_connect_timeout 5s;

        # 设置代理超时时间为 1 分钟
        proxy_timeout 1m;

        # 设置代理缓冲区大小为 16KB
        proxy_buffer_size 16k;
    }
}

在这个例子中:

  • proxy_connect_timeout 5s; 设置了与后端服务器建立连接的超时时间为 5 秒。
  • proxy_timeout 1m; 设置了代理连接的超时时间为 1 分钟。
  • proxy_buffer_size 16k; 设置了代理缓冲区大小为 16KB。

结合 SSL/TLS 加密

假设你希望在代理过程中提供 SSL/TLS 加密:

stream {
    upstream backend {
        server backend.example.com:8883;
    }

    server {
        listen 8883 ssl;
        proxy_pass backend;

        # SSL 证书和私钥
        ssl_certificate /etc/nginx/ssl/example_com.crt;
        ssl_certificate_key /etc/nginx/ssl/example_com.key;

        # 可选:配置其他 SSL 参数
        # ssl_protocols TLSv1.2 TLSv1.3;
        # ssl_ciphers HIGH:!aNULL:!MD5;
    }
}

在这个例子中:

  • listen 8883 ssl; 启用了 SSL/TLS 加密。
  • ssl_certificatessl_certificate_key 分别指定了服务器证书和私钥文件的路径。
  • ssl_protocolsssl_ciphers 参数可用于进一步配置加密协议和密码套件。

注意事项

  • 性能优化:根据实际需求调整超时时间和缓冲区大小,避免过长的等待时间和不必要的内存占用。例如,在高并发环境中,适当减少 proxy_buffer_size 可能有助于提高性能。

  • 安全性:确保 SSL/TLS 配置正确,使用强加密协议和密码套件。定期更新证书并检查其有效性。

  • 健康检查:合理配置健康检查参数,如 max_failsfail_timeout,以确保在后端服务器出现故障时能够及时发现并切换到其他可用服务器。

  • 日志管理:定期轮转日志文件,防止日志文件过大导致磁盘空间不足。可以使用工具如 logrotate 来自动化日志管理。

2.81.1 指令列表
proxy_bind
proxy_buffer_size
proxy_connect_timeout
proxy_download_rate

proxy_download_rate 指令用于设置从上游服务器下载数据的速率限制。这有助于控制带宽使用情况。

Syntax:	proxy_download_rate rate;
Default: proxy_download_rate 0;
Context: stream, server
This directive appeared in version 1.9.3.
  • rate:下载速率限制,单位为字节/秒,默认值为 0 表示不限制。

案例

基本用法

最简单的 proxy_download_rate 用法是指定下载速率限制:

stream {
    upstream backend {
        server 192.168.1.1:12345;
    }

    server {
        listen 12345;
        proxy_pass backend;

        # 设置下载速率为 100 KB/s
        proxy_download_rate 102400;  # 100 * 1024 = 102400 bytes per second
    }
}

在这个例子中:

  • 当 Nginx 从 backend 下载数据时,将限制下载速率为 100 KB/s。

复杂用法

根据不同的客户端 IP 地址设置不同的下载速率限制:

stream {
    upstream backend {
        server 192.168.1.1:12345;
    }

    server {
        listen 12345;

        if ($remote_addr = "192.168.1.10") {
            proxy_download_rate 51200;  # 50 KB/s for specific client
        }

        if ($remote_addr != "192.168.1.10") {
            proxy_download_rate 102400;  # 100 KB/s for other clients
        }

        proxy_pass backend;
    }
}

在这个例子中:

  • 如果客户端 IP 地址是 192.168.1.10,则下载速率为 50 KB/s;否则,下载速率为 100 KB/s。

注意事项

  • 速率单位:注意速率限制的单位是字节/秒,确保计算正确。
  • 用户体验:过低的速率限制可能会影响用户体验,特别是在需要快速传输大量数据的情况下。
proxy_half_close

proxy_half_close 指令用于控制是否启用半关闭模式。半关闭模式允许一端关闭写入操作,而另一端继续读取数据。

Syntax:	proxy_half_close on | off;
Default: proxy_half_close off;
Context: stream, server
This directive appeared in version 1.21.4.
  • on:启用半关闭模式。
  • off:禁用半关闭模式,默认行为。

案例

基本用法

最简单的 proxy_half_close 用法是启用或禁用半关闭模式:

stream {
    upstream backend {
        server 192.168.1.1:12345;
    }

    server {
        listen 12345;
        proxy_pass backend;

        # 启用半关闭模式
        proxy_half_close on;
    }
}

在这个例子中:

  • 当 Nginx 与 backend 通信时,如果一端关闭了写入操作,另一端仍然可以继续读取数据。

复杂用法

结合不同场景启用或禁用半关闭模式:

stream {
    upstream backend_tcp {
        server 192.168.1.1:12345;
    }

    upstream backend_udp {
        server 192.168.1.1:54321;
    }

    server {
        listen 12345;
        proxy_pass backend_tcp;

        # 对 TCP 流量启用半关闭模式
        proxy_half_close on;
    }

    server {
        listen 54321 udp;
        proxy_pass backend_udp;

        # 对 UDP 流量禁用半关闭模式
        proxy_half_close off;
    }
}

在这个例子中:

  • 对于 TCP 流量,启用了半关闭模式;对于 UDP 流量,禁用了半关闭模式。

注意事项

  • 协议特性:UDP 是无连接协议,通常不需要半关闭模式,因此通常保持禁用状态。
  • 应用场景:根据实际应用需求选择是否启用半关闭模式,以优化性能和资源管理。
proxy_next_upstream
proxy_next_upstream_timeout
proxy_next_upstream_tries
proxy_pass
proxy_protocol
proxy_requests

proxy_requests 指令用于设置每个连接的最大请求数。这有助于控制连接上的请求次数,特别是在长连接场景下。

Syntax:	proxy_requests number;
Default: proxy_requests 0;
Context: stream, server
This directive appeared in version 1.15.7.
  • number:每个连接的最大请求数,默认值为 0 表示不限制。

案例

基本用法

最简单的 proxy_requests 用法是指定最大请求数:

stream {
    upstream backend {
        server 192.168.1.1:12345;
    }

    server {
        listen 12345;
        proxy_pass backend;

        # 设置每个连接的最大请求数为 100
        proxy_requests 100;
    }
}

在这个例子中:

  • 当 Nginx 与 backend 建立连接时,每个连接最多处理 100 个请求。

复杂用法

根据不同的客户端 IP 地址设置不同的最大请求数:

stream {
    upstream backend {
        server 192.168.1.1:12345;
    }

    server {
        listen 12345;

        if ($remote_addr = "192.168.1.10") {
            proxy_requests 50;  # 最大请求数为 50
        }

        if ($remote_addr != "192.168.1.10") {
            proxy_requests 100;  # 最大请求数为 100
        }

        proxy_pass backend;
    }
}

在这个例子中:

  • 如果客户端 IP 地址是 192.168.1.10,则每个连接的最大请求数为 50;否则,最大请求数为 100。

注意事项

  • 连接管理:合理设置最大请求数,避免单个连接占用过多资源。
  • 性能影响:过低的最大请求数可能导致频繁建立新连接,增加开销;过高则可能导致资源浪费。
proxy_responses

proxy_responses 用于在 Nginx 的流(stream)模块中指定代理服务器期望接收的响应数量。这有助于控制代理行为,特别是在处理多个响应时。

Syntax: proxy_responses number;
Default: —
Context: stream, server
This directive appeared in version 1.9.13.
  • number:指定代理服务器期望接收的响应数量。

案例

基本用法

最简单的 proxy_responses 用法是指定代理服务器期望接收的响应数量:

stream {
    server {
        listen 12345;
        proxy_pass backend.example.com:12345;
        proxy_responses 1;  # 期望接收一个响应
    }
}

处理多个响应

根据实际需求处理多个响应:

stream {
    server {
        listen 12345;
        proxy_pass backend.example.com:12345;
        proxy_responses 3;  # 期望接收三个响应
    }
}

注意事项

  • 响应管理:确保设置的响应数量符合实际业务需求,避免不必要的等待或超时。
  • 性能优化:合理设置响应数量,以提高系统性能和响应速度。
proxy_session_drop

proxy_session_drop 用于控制是否在连接关闭时丢弃会话数据。启用该选项可以在某些情况下减少资源占用。

Syntax: proxy_session_drop on | off;
Default: proxy_session_drop off;
Context: stream, server
This directive appeared in version 1.15.8.
  • on:在连接关闭时丢弃会话数据。
  • off:不丢弃会话数据(默认值)。

案例

启用会话数据丢弃

最简单的 proxy_session_drop 用法是启用会话数据丢弃功能:

stream {
    server {
        listen 12345;
        proxy_pass backend.example.com:12345;
        proxy_session_drop on;  # 在连接关闭时丢弃会话数据
    }
}

禁用会话数据丢弃

根据实际需求禁用会话数据丢弃功能:

stream {
    server {
        listen 12345;
        proxy_pass backend.example.com:12345;
        proxy_session_drop off;  # 不丢弃会话数据
    }
}

注意事项

  • 资源管理:启用会话数据丢弃可以减少内存占用,但可能会影响某些需要会话数据的应用。
  • 适用场景:适用于不需要保留会话数据的场景,如短连接服务。
proxy_socket_keepalive
proxy_ssl

proxy_ssl 用于控制是否在代理请求中使用 SSL/TLS 加密。启用该选项可以增强安全性,但在高并发场景下可能会带来额外的性能开销。

Syntax: proxy_ssl on | off;
Default: proxy_ssl off;
Context: stream, server
  • on:启用 SSL/TLS 加密。
  • off:禁用 SSL/TLS 加密(默认值)。

案例

启用 SSL/TLS 加密

最简单的 proxy_ssl 用法是启用 SSL/TLS 加密:

stream {
    server {
        listen 12345 ssl;
        proxy_pass backend.example.com:12345;

        ssl_certificate /etc/nginx/ssl/server.crt;
        ssl_certificate_key /etc/nginx/ssl/server.key;

        proxy_ssl on;  # 启用 SSL/TLS 加密
    }
}

禁用 SSL/TLS 加密

根据实际需求禁用 SSL/TLS 加密:

stream {
    server {
        listen 12345;
        proxy_pass backend.example.com:12345;
        proxy_ssl off;  # 禁用 SSL/TLS 加密
    }
}

注意事项

  • 安全性:启用 SSL/TLS 加密可以增强安全性,防止中间人攻击等安全问题。
  • 性能影响:SSL/TLS 加密会带来一定的性能开销,在高并发场景下需权衡性能与安全性的平衡。
proxy_ssl_certificate
proxy_ssl_certificate_cache
proxy_ssl_certificate_key
proxy_ssl_ciphers
proxy_ssl_conf_command
proxy_ssl_crl
proxy_ssl_key_log
proxy_ssl_name
proxy_ssl_password_file
proxy_ssl_protocols
proxy_ssl_server_name
proxy_ssl_session_reuse
proxy_ssl_trusted_certificate
proxy_ssl_verify
proxy_ssl_verify_depth
proxy_timeout
proxy_upload_rate

proxy_upload_rate 用于限制从客户端到代理服务器的上传速率。这有助于控制带宽使用,特别是在有限带宽的情况下。

Syntax: proxy_upload_rate rate;
Default: proxy_upload_rate 0;
Context: stream, server
This directive appeared in version 1.9.3.
  • rate:指定上传速率,单位为字节每秒(bytes per second)。如果设置为 0,则不限制上传速率。

案例

限制上传速率

最简单的 proxy_upload_rate 用法是指定上传速率:

stream {
    server {
        listen 12345;
        proxy_pass backend.example.com:12345;
        proxy_upload_rate 10240;  # 限制上传速率为 10 KB/s
    }
}

不限制上传速率

根据实际需求不限制上传速率:

stream {
    server {
        listen 12345;
        proxy_pass backend.example.com:12345;
        proxy_upload_rate 0;  # 不限制上传速率
    }
}

结合其他速率限制指令

结合其他速率限制指令进行更复杂的配置:

stream {
    server {
        listen 12345;
        proxy_pass backend.example.com:12345;
        proxy_upload_rate 10240;  # 限制上传速率为 10 KB/s
        proxy_download_rate 20480;  # 限制下载速率为 20 KB/s
    }
}

注意事项

  • 带宽管理:合理设置上传速率,确保在有限带宽的情况下仍能提供稳定的服务。
  • 用户体验:避免过度限制上传速率,以免影响用户体验,特别是在高延迟网络环境中。

2.82 ngx_stream_proxy_protocol_vendor_module

ngx_stream_proxy_protocol_vendor_module 是一个用于流(stream)上下文的模块,它允许从云平台(如 AWS、Google Cloud Platform 和 Microsoft Azure)的应用特定 TLV(Type-Length-Value)字段中获取连接的额外信息。这些信息可以通过 PROXY 协议头进行传递。

支持的云平台

  • Amazon Web Services (AWS)
  • Google Cloud Platform (GCP)
  • Microsoft Azure

常用指令和变量

启用 PROXY 协议

在使用此模块之前,必须通过设置 proxy_protocol 参数启用 PROXY 协议。这通常在 listen 指令中完成:

server {
    listen 12345 proxy_protocol;
    # 其他配置...
}

内置变量

该模块提供了多个内置变量,用于提取 PROXY 协议头中的特定信息:

  • $proxy_protocol_tlv_aws_vpce_id: 表示 AWS VPC 终端节点 ID。
  • $proxy_protocol_tlv_azure_pel_id: 表示 Azure 私有终端链接 ID。
  • $proxy_protocol_tlv_gcp_conn_id: 表示 Google Cloud PSC 连接 ID。

使用示例

以下是一些具体的配置示例,展示了如何使用 ngx_stream_proxy_protocol_vendor_module 来获取并利用连接的额外信息。

基本配置

假设你想根据客户端连接中的信息设置 HTTP 头部,并将其转发到后端服务器:

stream {
    server {
        listen 12345 proxy_protocol;

        # 设置 HTTP 头部以包含 GCP 连接 ID
        proxy_set_header X-Conn-ID $proxy_protocol_tlv_gcp_conn_id;

        # 将请求代理到后端服务器
        proxy_pass backend_server;
    }
}

在这个例子中:

  • listen 12345 proxy_protocol; 启用了 PROXY 协议。
  • proxy_set_header X-Conn-ID $proxy_protocol_tlv_gcp_conn_id; 设置了一个自定义的 HTTP 头部 X-Conn-ID,其值为从 PROXY 协议头中提取的 GCP 连接 ID。
  • proxy_pass backend_server; 将请求代理到后端服务器。

结合负载均衡

假设你的应用部署在多个后端服务器上,并希望通过提取的连接信息选择合适的后端服务器:

stream {
    upstream backend_usa {
        server backend_usa_1.example.com;
        server backend_usa_2.example.com;
    }

    upstream backend_eu {
        server backend_eu_1.example.com;
        server backend_eu_2.example.com;
    }

    server {
        listen 12345 proxy_protocol;

        # 根据提取的信息选择不同的上游服务器组
        if ($proxy_protocol_tlv_aws_vpce_id ~* "us-") {
            proxy_pass backend_usa;
        }
        if ($proxy_protocol_tlv_aws_vpce_id ~* "eu-") {
            proxy_pass backend_eu;
        }
    }
}

在这个例子中:

  • upstream backend_usa { ... }upstream backend_eu { ... } 定义了两个不同的上游服务器组。
  • listen 12345 proxy_protocol; 启用了 PROXY 协议。
  • server 块中,根据 $proxy_protocol_tlv_aws_vpce_id 的值选择不同的上游服务器组进行代理。

注意事项

  • PROXY 协议支持:确保前端代理或负载均衡器正确地发送 PROXY 协议头,以便 Nginx 能够解析并提取相关信息。
  • 性能优化:尽量减少不必要的条件判断和变量设置,以提高性能。
  • 安全性:确保传输过程中的数据安全,防止中间人攻击。可以考虑使用 TLS 加密连接。
  • 测试验证:在部署之前进行全面测试,确保所有配置按预期工作,并检查是否有任何潜在的问题(如 PROXY 协议头未正确解析、变量值错误等)。
2.82.1 指令列表

2.83 ngx_stream_realip_module

ngx_stream_realip_module 是 Nginx 的一个模块,用于在处理 TCP 和 UDP 流量时修改客户端的真实 IP 地址。通常情况下,当使用代理或负载均衡器时,Nginx 会看到代理服务器的 IP 地址而不是客户端的真实 IP 地址。ngx_stream_realip_module 模块通过解析来自代理服务器的特定头部信息(如 X-Real-IPX-Forwarded-For),来恢复客户端的真实 IP 地址。

主要功能

  • 恢复真实 IP:从代理服务器传递的头部信息中提取并设置客户端的真实 IP 地址。
  • 支持多种协议:可以应用于 TCP 和 UDP 流量。
  • 日志记录和访问控制:允许基于真实的客户端 IP 地址进行日志记录和访问控制。

常用指令

以下是与 ngx_stream_realip_module 模块相关的常用配置指令及其简要说明:

  • set_real_ip_from:指定信任的代理服务器的 IP 地址或地址范围。只有来自这些地址的请求才会被信任,并从中提取真实的客户端 IP 地址。

  • real_ip_header:指定用于提取客户端真实 IP 地址的头部字段。常见的头部字段包括 X-Real-IPX-Forwarded-For

  • real_ip_recursive:启用递归查找真实 IP 地址。如果设置了这个指令,Nginx 将遍历 X-Forwarded-For 头部中的所有 IP 地址,直到找到一个未被信任的 IP 地址为止。

使用示例

以下是一些具体的配置示例,展示如何利用 ngx_stream_realip_module 来恢复客户端的真实 IP 地址。

设置信任的代理服务器和头部字段

假设你的应用部署在一个反向代理后面,并且你希望从 X-Forwarded-For 头部中提取客户端的真实 IP 地址:

stream {
    upstream backend_servers {
        server backend1.example.com:12345;
        server backend2.example.com:12345;
    }

    server {
        listen 12345;

        # 设置信任的代理服务器
        set_real_ip_from 192.168.1.0/24;  # 信任的代理服务器网段
        set_real_ip_from 203.0.113.5;     # 另一个信任的代理服务器

        # 指定用于提取真实 IP 地址的头部字段
        real_ip_header X-Forwarded-For;

        proxy_pass backend_servers;
    }
}

在这个例子中:

  • set_real_ip_from 192.168.1.0/24;set_real_ip_from 203.0.113.5; 定义了信任的代理服务器网段和单个 IP 地址。
  • real_ip_header X-Forwarded-For; 指定了用于提取客户端真实 IP 地址的头部字段为 X-Forwarded-For

启用递归查找

如果你的应用有多层代理,你可以启用递归查找来确保找到最终的客户端 IP 地址:

stream {
    upstream backend_servers {
        server backend1.example.com:12345;
        server backend2.example.com:12345;
    }

    server {
        listen 12345;

        # 设置信任的代理服务器
        set_real_ip_from 192.168.1.0/24;  # 信任的代理服务器网段
        set_real_ip_from 203.0.113.5;     # 另一个信任的代理服务器

        # 指定用于提取真实 IP 地址的头部字段
        real_ip_header X-Forwarded-For;

        # 启用递归查找
        real_ip_recursive on;

        proxy_pass backend_servers;
    }
}

在这个例子中:

  • real_ip_recursive on; 启用了递归查找,Nginx 将遍历 X-Forwarded-For 头部中的所有 IP 地址,直到找到一个未被信任的 IP 地址为止。

使用 X-Real-IP 头部

除了 X-Forwarded-For,你还可以使用 X-Real-IP 头部来传递客户端的真实 IP 地址:

stream {
    upstream backend_servers {
        server backend1.example.com:12345;
        server backend2.example.com:12345;
    }

    server {
        listen 12345;

        # 设置信任的代理服务器
        set_real_ip_from 192.168.1.0/24;  # 信任的代理服务器网段
        set_real_ip_from 203.0.113.5;     # 另一个信任的代理服务器

        # 指定用于提取真实 IP 地址的头部字段
        real_ip_header X-Real-IP;

        proxy_pass backend_servers;
    }
}

在这个例子中:

  • real_ip_header X-Real-IP; 指定了用于提取客户端真实 IP 地址的头部字段为 X-Real-IP

记录真实 IP 地址到日志

你可以将恢复后的客户端真实 IP 地址记录到日志中,便于后续分析和监控:

stream {
    upstream backend_servers {
        server backend1.example.com:12345;
        server backend2.example.com:12345;
    }

    log_format stream_log '$remote_addr [$time_local] '
                          '"$protocol" $status $bytes_sent $bytes_received '
                          '$session_time "$upstream_addr" '
                          '"$realip_remote_addr"';  # 记录真实 IP 地址

    server {
        listen 12345;

        # 设置信任的代理服务器
        set_real_ip_from 192.168.1.0/24;  # 信任的代理服务器网段
        set_real_ip_from 203.0.113.5;     # 另一个信任的代理服务器

        # 指定用于提取真实 IP 地址的头部字段
        real_ip_header X-Forwarded-For;

        access_log /var/log/nginx/stream_access.log stream_log;

        proxy_pass backend_servers;
    }
}

在这个例子中:

  • log_format stream_log ... 定义了一个新的日志格式 stream_log,其中包括 $realip_remote_addr 变量,用于记录恢复后的客户端真实 IP 地址。
  • access_log /var/log/nginx/stream_access.log stream_log; 使用自定义的日志格式记录日志。

注意事项

  • 安全性

    • 确保只信任可信的代理服务器,避免恶意用户伪造头部信息欺骗 Nginx。
    • 对敏感数据进行加密传输,防止中间人攻击。
  • 性能考虑

    • 在高并发场景下,尽量简化头部解析逻辑,避免复杂的嵌套和多次查询。
    • 如果启用递归查找,请注意性能影响,特别是在有多层代理的情况下。
  • 日志记录

    • 合理配置日志级别和格式,便于监控和故障排查。特别是注意记录与真实 IP 提取相关的错误信息和访问情况。
2.83.1 指令列表
set_real_ip_from

2.84 ngx_stream_return_module

ngx_stream_return_module 是 Nginx 的一个模块,用于在流(stream)上下文中快速返回预定义的响应。这个模块特别适用于需要简单处理 TCP 或 UDP 连接而不进行实际代理的情况。它可以帮助你实现诸如拒绝连接、返回特定数据或执行其他简单的操作。

主要功能

  • 快速返回:可以配置 Nginx 在收到连接请求时立即返回预定义的数据或状态。
  • 简化配置:相比复杂的代理设置,使用 return 指令可以大大简化配置文件。
  • 灵活性:可以根据不同的条件返回不同的响应。

使用示例

以下是一些简化的配置示例,展示了如何使用 ngx_stream_return_module 来实现不同的功能。

拒绝所有连接

假设你希望拒绝所有到达特定端口的连接:

stream {
    server {
        listen 12345;
        return 503;  # 返回 503 Service Unavailable 状态
    }
}

在这个例子中:

  • listen 12345; 监听端口 12345 上的所有连接。
  • return 503; 配置了当有连接请求到达时,Nginx 将返回 503 状态码并关闭连接。

返回自定义消息

假设你希望在收到连接请求时返回一个自定义的消息:

stream {
    server {
        listen 12345;

        # 返回自定义消息
        return "Connection refused by policy.\n";
    }
}

在这个例子中:

  • return "Connection refused by policy.\n"; 配置了当有连接请求到达时,Nginx 将返回一条自定义的消息并关闭连接。

注意:在 stream 上下文中,直接返回文本消息并不常见,因为 TCP 和 UDP 协议本身不支持像 HTTP 那样的消息体。你可以通过其他方式如关闭连接或发送特定字节序列来实现类似的效果。

基于条件返回不同响应

假设你希望根据客户端 IP 地址返回不同的响应:

stream {
    map $remote_addr $response {
        default "Access denied\n";
        "~^192\.168\." "Welcome to internal network\n";
    }

    server {
        listen 12345;

        # 根据映射表返回不同的响应
        return $response;
    }
}

在这个例子中:

  • map $remote_addr $response 定义了一个映射表 $response,根据客户端 IP 地址返回不同的响应。
  • server { listen 12345; return $response; } 根据映射表中的值返回不同的响应。

结合 SSL/TLS 加密

假设你希望在返回自定义消息的同时提供 SSL/TLS 加密:

stream {
    server {
        listen 12345 ssl;
        return "Connection refused by policy.\n";

        # SSL 证书和私钥
        ssl_certificate /etc/nginx/ssl/example_com.crt;
        ssl_certificate_key /etc/nginx/ssl/example_com.key;

        # 可选:配置其他 SSL 参数
        # ssl_protocols TLSv1.2 TLSv1.3;
        # ssl_ciphers HIGH:!aNULL:!MD5;
    }
}

在这个例子中:

  • listen 12345 ssl; 启用了 SSL/TLS 加密。
  • ssl_certificatessl_certificate_key 分别指定了服务器证书和私钥文件的路径。
  • return "Connection refused by policy.\n"; 配置了当有连接请求到达时,Nginx 将返回一条自定义的消息并关闭连接。

注意事项

  • TCP/UDP 特性:由于 TCP 和 UDP 协议本身的特性,直接返回文本消息并不总是可行。通常情况下,return 指令主要用于关闭连接或发送特定字节序列。如果你需要更复杂的交互,可能需要考虑使用其他模块或自定义脚本。

  • 安全性:确保 SSL/TLS 配置正确,使用强加密协议和密码套件。定期更新证书并检查其有效性。

  • 日志记录:虽然 ngx_stream_return_module 主要用于简单的响应,但你仍然可以通过访问日志记录连接信息,以便于后续分析和调试。

2.84.1 指令列表
return

2.85 ngx_stream_set_module

ngx_stream_set_module 是 Nginx 的一个模块,用于在流(stream)上下文中动态设置变量。这个模块允许你根据连接的某些属性或条件来设置变量,并在后续处理中使用这些变量,例如路由、访问控制和日志记录等。

主要功能

  • 动态变量设置:根据连接中的某些属性(如 IP 地址、端口等)动态设置变量。
  • 灵活配置:支持多种条件判断和复杂的表达式,以实现更复杂的逻辑。
  • 变量传递:将设置的变量传递给其他模块或配置指令,以便进一步处理。

使用示例

以下是一些具体的配置示例,展示了如何使用 ngx_stream_set_module 来动态设置变量。

基本配置

假设你想根据客户端的 IP 地址设置一个变量 $client_type,并将其用于后续处理:

stream {
    # 根据客户端 IP 地址设置变量
    set $client_type "untrusted";
    if ($remote_addr = "192.168.1.10") {
        set $client_type "trusted";
    }
    if ($remote_addr = "203.0.113.5") {
        set $client_type "special";
    }

    server {
        listen 12345;
        proxy_pass backend_server;

        # 根据变量设置不同的代理服务器
        if ($client_type = "trusted") {
            proxy_pass trusted_backend;
        }
        if ($client_type = "special") {
            proxy_pass special_backend;
        }
        if ($client_type = "untrusted") {
            proxy_pass untrusted_backend;
        }
    }
}

在这个例子中:

  • set $client_type "untrusted"; 初始化变量 $client_type
  • 使用 if 指令根据客户端 IP 地址更新 $client_type 的值。
  • server 块中,根据 $client_type 的值选择不同的后端服务器进行代理。

结合 map 指令

你可以使用 map 指令来简化上述配置:

stream {
    # 使用 map 指令定义键值映射
    map $remote_addr $client_type {
        default          "untrusted";
        192.168.1.10     "trusted";
        203.0.113.5      "special";
    }

    server {
        listen 12345;
        proxy_pass backend_server;

        # 根据变量设置不同的代理服务器
        if ($client_type = "trusted") {
            proxy_pass trusted_backend;
        }
        if ($client_type = "special") {
            proxy_pass special_backend;
        }
        if ($client_type = "untrusted") {
            proxy_pass untrusted_backend;
        }
    }
}

其中 map 指令定义了一个键值映射表,根据 $remote_addr 的值设置 $client_type

结合负载均衡

假设你的应用部署在多个后端服务器上,并希望通过提取的连接信息选择合适的后端服务器:

stream {
    upstream trusted_backend {
        server backend_trusted_1.example.com;
        server backend_trusted_2.example.com;
    }

    upstream special_backend {
        server backend_special_1.example.com;
        server backend_special_2.example.com;
    }

    upstream untrusted_backend {
        server backend_untrusted_1.example.com;
        server backend_untrusted_2.example.com;
    }

    # 使用 map 指令定义键值映射
    map $remote_addr $client_type {
        default          "untrusted";
        include          /etc/nginx/client_types.conf;
    }

    server {
        listen 12345;

        # 根据变量选择不同的上游服务器组
        if ($client_type = "trusted") {
            proxy_pass trusted_backend;
        }
        if ($client_type = "special") {
            proxy_pass special_backend;
        }
        if ($client_type = "untrusted") {
            proxy_pass untrusted_backend;
        }
    }
}

其中 /etc/nginx/client_types.conf 文件的内容可能如下:

192.168.1.10 "trusted";
203.0.113.5 "special";

注意事项

  • 数据更新:确保定期更新映射数据文件,以保持最新的信息。可以通过脚本自动化更新过程。
  • 性能优化
    • 尽量减少不必要的条件判断和变量设置,以提高性能。
    • 使用 map 指令代替多个 if 指令,可以提高配置的可读性和执行效率。
  • 安全性:确保映射数据文件的安全性,防止未经授权的访问。可以设置适当的文件权限,并考虑加密敏感数据。
  • 测试验证:在部署之前进行全面测试,确保所有配置按预期工作,并检查是否有任何潜在的问题(如键未正确匹配、变量值错误等)。
2.85.1 指令列表
set

2.86 ngx_stream_split_clients_module

ngx_stream_split_clients_module 是 Nginx 的一个模块,用于在处理 TCP 和 UDP 流量时根据指定的条件将客户端请求分发到不同的后端服务器组。这个模块允许你通过定义不同的分割规则来实现流量分配和 A/B 测试等功能。

主要功能

  • 流量分割:根据指定的条件(如客户端 IP 地址、随机数等)将流量分配到不同的后端服务器或上游组。
  • A/B 测试:可以用来进行不同版本的服务测试,例如将一部分流量定向到新版本的服务,另一部分流量保持在旧版本。
  • 灵活配置:支持多种变量和条件组合,提供了高度灵活性。

常用指令

以下是与 ngx_stream_split_clients_module 模块相关的常用配置指令及其简要说明:

  • split_clients:定义分割规则,指定如何根据条件将流量分配到不同的后端服务器或上游组。

  • $variable:用于生成键的变量,例如 $remote_addr(客户端 IP 地址)、$binary_remote_addr(二进制格式的客户端 IP 地址)、$random(随机数)等。

使用示例

以下是一些具体的配置示例,展示如何利用 ngx_stream_split_clients_module 来实现流量分割和 A/B 测试。

根据客户端 IP 地址分割流量

假设你想根据客户端 IP 地址将流量分配到两个不同的后端服务器组:

stream {
    upstream backend_a {
        server backend1.example.com:12345;
        server backend2.example.com:12345;
    }

    upstream backend_b {
        server backend3.example.com:12345;
        server backend4.example.com:12345;
    }

    # 定义分割规则
    split_clients $binary_remote_addr $backend {
        50% backend_a;
        *   backend_b;
    }

    server {
        listen 12345;

        # 根据分割结果选择后端服务器
        proxy_pass $backend;
    }
}

在这个例子中:

  • split_clients $binary_remote_addr $backend { ... } 定义了一个分割规则,基于二进制格式的客户端 IP 地址 $binary_remote_addr 进行分割。
    • 50% backend_a; 表示 50% 的客户端会被分配到 backend_a
    • * backend_b; 表示剩余的客户端(即另外 50%)会被分配到 backend_b
  • proxy_pass $backend; 根据分割结果选择后端服务器。

使用随机数进行流量分割

如果你想使用随机数而不是客户端 IP 地址来进行流量分割,可以这样做:

stream {
    upstream backend_a {
        server backend1.example.com:12345;
        server backend2.example.com:12345;
    }

    upstream backend_b {
        server backend3.example.com:12345;
        server backend4.example.com:12345;
    }

    # 定义分割规则
    split_clients $remote_addr $backend {
        10% backend_a;
        90% backend_b;
    }

    server {
        listen 12345;

        # 根据分割结果选择后端服务器
        proxy_pass $backend;
    }
}

在这个例子中:

  • split_clients $remote_addr $backend { ... } 定义了一个分割规则,基于客户端 IP 地址 $remote_addr 进行分割。
    • 10% backend_a; 表示 10% 的客户端会被分配到 backend_a
    • 90% backend_b; 表示剩余的客户端(即 90%)会被分配到 backend_b

为了更灵活地使用随机数,可以使用 $random 变量:

stream {
    upstream backend_a {
        server backend1.example.com:12345;
        server backend2.example.com:12345;
    }

    upstream backend_b {
        server backend3.example.com:12345;
        server backend4.example.com:12345;
    }

    # 定义分割规则
    split_clients $random $backend {
        10% backend_a;
        *   backend_b;
    }

    server {
        listen 12345;

        # 根据分割结果选择后端服务器
        proxy_pass $backend;
    }
}

在这个例子中:

  • split_clients $random $backend { ... } 定义了一个分割规则,基于随机数 $random 进行分割。
    • 10% backend_a; 表示 10% 的连接会被分配到 backend_a
    • * backend_b; 表示剩余的连接(即 90%)会被分配到 backend_b

组合多个条件进行流量分割

你可以组合多个条件来进一步细化流量分割策略。例如,根据不同的条件执行不同的操作:

stream {
    upstream backend_a {
        server backend1.example.com:12345;
    }

    upstream backend_b {
        server backend2.example.com:12345;
    }

    upstream backend_c {
        server backend3.example.com:12345;
    }

    # 定义分割规则
    split_clients $remote_addr $backend {
        10% backend_a;
        20% backend_b;
        *   backend_c;
    }

    server {
        listen 12345;

        # 根据分割结果选择后端服务器
        proxy_pass $backend;
    }
}

在这个例子中:

  • split_clients $remote_addr $backend { ... } 定义了一个分割规则,基于客户端 IP 地址 $remote_addr 进行分割。
    • 10% backend_a; 表示 10% 的连接会被分配到 backend_a
    • 20% backend_b; 表示 20% 的连接会被分配到 backend_b
    • * backend_c; 表示剩余的连接(即 70%)会被分配到 backend_c

记录分割结果到日志

你可以将分割结果记录到日志中,便于后续分析和监控:

stream {
    upstream backend_a {
        server backend1.example.com:12345;
        server backend2.example.com:12345;
    }

    upstream backend_b {
        server backend3.example.com:12345;
        server backend4.example.com:12345;
    }

    log_format stream_log '$remote_addr [$time_local] '
                          '"$protocol" $status $bytes_sent $bytes_received '
                          '$session_time "$upstream_addr" '
                          '"$backend"';  # 记录分割结果

    # 定义分割规则
    split_clients $binary_remote_addr $backend {
        50% backend_a;
        *   backend_b;
    }

    server {
        listen 12345;

        access_log /var/log/nginx/stream_access.log stream_log;

        # 根据分割结果选择后端服务器
        proxy_pass $backend;
    }
}

在这个例子中:

  • log_format stream_log ... 定义了一个新的日志格式 stream_log,其中包括 $backend 变量,用于记录分割结果。
  • access_log /var/log/nginx/stream_access.log stream_log; 使用自定义的日志格式记录日志。

注意事项

  • 性能考虑

    • 在高并发场景下,尽量简化分割逻辑,避免复杂的嵌套和多次查询。
    • 确保共享内存区大小足够大以容纳所有可能的键值。
  • 安全性

    • 确保对敏感数据进行加密传输,防止中间人攻击。
    • 对分割规则进行适当的验证和过滤,避免恶意输入。
  • 日志记录

    • 合理配置日志级别和格式,便于监控和故障排查。特别是注意记录与流量分割相关的错误信息和访问情况。
2.86.1 指令列表
split_clients

2.87 ngx_stream_ssl_module

ngx_stream_ssl_module 是 Nginx 的一个模块,用于在流(stream)上下文中启用 SSL/TLS 加密。这个模块允许你在代理 TCP 连接时提供安全的通信通道,适用于需要加密传输的应用场景,如数据库连接、邮件服务器等。

主要功能

  • SSL/TLS 加密:支持在 TCP 代理中启用 SSL/TLS 加密,保护数据传输的安全性。
  • 证书管理:可以配置服务器证书和私钥,确保客户端与服务器之间的安全通信。
  • 协议支持:支持多种 SSL/TLS 协议版本,如 TLSv1.2 和 TLSv1.3。
  • 密码套件配置:可以根据需求选择合适的加密算法,提高安全性。
  • 会话缓存:通过启用会话缓存和会话票证(session tickets),可以加快后续连接的建立速度。

使用示例

以下是一些简化的配置示例,展示了如何使用 ngx_stream_ssl_module 来实现不同的功能。

基本 SSL/TLS 配置

假设你希望为 TCP 代理启用 SSL/TLS 加密:

stream {
    upstream backend {
        server backend.example.com:12345;
    }

    server {
        listen 12345 ssl;
        proxy_pass backend;

        # SSL 证书和私钥
        ssl_certificate /etc/nginx/ssl/example_com.crt;
        ssl_certificate_key /etc/nginx/ssl/example_com.key;

        # 支持的 SSL/TLS 协议版本
        ssl_protocols TLSv1.2 TLSv1.3;

        # 支持的加密套件
        ssl_ciphers HIGH:!aNULL:!MD5;
    }
}

在这个例子中:

  • listen 12345 ssl; 启用了 SSL/TLS 加密。
  • ssl_certificatessl_certificate_key 分别指定了服务器证书和私钥文件的路径。
  • ssl_protocols TLSv1.2 TLSv1.3; 指定了支持的 SSL/TLS 协议版本。
  • ssl_ciphers HIGH:!aNULL:!MD5; 指定了支持的加密套件。

配置会话缓存和超时

假设你希望通过会话缓存来加快后续连接的建立速度,并设置会话缓存的有效期:

stream {
    upstream backend {
        server backend.example.com:12345;
    }

    server {
        listen 12345 ssl;
        proxy_pass backend;

        # SSL 证书和私钥
        ssl_certificate /etc/nginx/ssl/example_com.crt;
        ssl_certificate_key /etc/nginx/ssl/example_com.key;

        # 支持的 SSL/TLS 协议版本
        ssl_protocols TLSv1.2 TLSv1.3;

        # 支持的加密套件
        ssl_ciphers HIGH:!aNULL:!MD5;

        # 启用会话缓存
        ssl_session_cache shared:SSL:10m;

        # 设置会话缓存的有效期
        ssl_session_timeout 10m;
    }
}

在这个例子中:

  • ssl_session_cache shared:SSL:10m; 启用了共享会话缓存,大小为 10MB。
  • ssl_session_timeout 10m; 设置了会话缓存的有效期为 10 分钟。

结合健康检查

假设你希望在启用 SSL/TLS 加密的同时进行后端服务器的健康检查:

stream {
    upstream backend {
        server backend1.example.com:12345 max_fails=3 fail_timeout=30s;
        server backend2.example.com:12345 max_fails=3 fail_timeout=30s;
    }

    server {
        listen 12345 ssl;
        proxy_pass backend;

        # SSL 证书和私钥
        ssl_certificate /etc/nginx/ssl/example_com.crt;
        ssl_certificate_key /etc/nginx/ssl/example_com.key;

        # 支持的 SSL/TLS 协议版本
        ssl_protocols TLSv1.2 TLSv1.3;

        # 支持的加密套件
        ssl_ciphers HIGH:!aNULL:!MD5;

        # 启用会话缓存
        ssl_session_cache shared:SSL:10m;

        # 设置会话缓存的有效期
        ssl_session_timeout 10m;
    }
}

在这个例子中:

  • upstream backend 定义了两个后端服务器,并启用了健康检查。
  • max_fails=3 fail_timeout=30s; 配置了健康检查参数,如果某个服务器连续失败超过 3 次,则会在 30 秒内被视为不可用。

启用会话票证

假设你希望通过启用会话票证来进一步优化连接性能:

stream {
    upstream backend {
        server backend.example.com:12345;
    }

    server {
        listen 12345 ssl;
        proxy_pass backend;

        # SSL 证书和私钥
        ssl_certificate /etc/nginx/ssl/example_com.crt;
        ssl_certificate_key /etc/nginx/ssl/example_com.key;

        # 支持的 SSL/TLS 协议版本
        ssl_protocols TLSv1.2 TLSv1.3;

        # 支持的加密套件
        ssl_ciphers HIGH:!aNULL:!MD5;

        # 启用会话缓存
        ssl_session_cache shared:SSL:10m;

        # 设置会话缓存的有效期
        ssl_session_timeout 10m;

        # 启用会话票证
        ssl_session_tickets on;
    }
}

在这个例子中:

  • ssl_session_tickets on; 启用了会话票证,这可以帮助加速后续连接的建立。

注意事项

  • 证书管理:确保使用的证书和私钥是有效的,并定期更新证书。过期或无效的证书会导致连接失败。

  • 协议版本:尽量使用最新的 SSL/TLS 协议版本,如 TLSv1.2TLSv1.3,并禁用不安全的旧版本,如 SSLv3TLSv1.0

  • 加密套件:选择强加密套件,避免使用已知存在漏洞的加密算法,如 MD5 和 RC4。

  • 性能优化:启用会话缓存和会话票证可以显著提高性能,尤其是在高并发环境中。

  • 日志记录:通过访问日志记录连接信息,以便于后续分析和调试。

2.87.1 指令列表
ssl_alpn

ssl_alpn 指令用于指定支持的应用层协议(Application-Layer Protocol Negotiation, ALPN)。这个指令帮助在TLS握手过程中协商应用层协议。

Syntax:	ssl_alpn protocol ...;
Default:	—
Context:	stream, server
This directive appeared in version 1.21.4.
  • protocol:指定一个或多个支持的应用层协议。常见的协议包括 http/1.1, h2 (HTTP/2), mqtt, 等。

案例

基本用法

最简单的 ssl_alpn 用法是指定具体的协议列表:

stream {
    server {
        listen 443 ssl;
        ssl_certificate /etc/nginx/ssl/example.com.crt;
        ssl_certificate_key /etc/nginx/ssl/example.com.key;

        ssl_alpn http/1.1 h2;

        proxy_pass backend_server;
    }
}

在这个例子中:

  • 设置了 ssl_alpn http/1.1 h2,这意味着Nginx将支持HTTP/1.1和HTTP/2协议。

动态设置不同配置

你可以根据不同的服务器块动态设置不同的协议列表:

stream {
    server {
        listen 443 ssl;
        ssl_certificate /etc/nginx/ssl/example1.com.crt;
        ssl_certificate_key /etc/nginx/ssl/example1.com.key;

        ssl_alpn http/1.1;

        proxy_pass backend_example1;
    }

    server {
        listen 444 ssl;
        ssl_certificate /etc/nginx/ssl/example2.com.crt;
        ssl_certificate_key /etc/nginx/ssl/example2.com.key;

        ssl_alpn h2 mqtt;

        proxy_pass backend_example2;
    }
}

在这个例子中:

  • 对于监听端口443的服务器块,设置了 ssl_alpn http/1.1
  • 对于监听端口444的服务器块,设置了 ssl_alpn h2 mqtt

注意事项

  • 协议选择:合理选择需要支持的应用层协议,避免不必要的协议增加复杂性和潜在的安全风险。
  • 适用场景:适用于需要在TLS握手时协商应用层协议的应用场景。例如,在需要同时支持HTTP/1.1和HTTP/2的网站、物联网(IoT)应用等环境中使用。
  • 调试和监控:如果你遇到ALPN问题,可以检查以下几点:
    • 确保协议设置合理,并符合你的需求。
    • 查看Nginx的日志文件,确认是否有与此相关的警告或错误信息。
    • 使用工具模拟不同负载条件下的请求进行测试,确保在各种情况下都能正常工作。
ssl_certificate
ssl_certificate_cache
ssl_certificate_key
ssl_ciphers
ssl_client_certificate
ssl_conf_command
ssl_crl
ssl_dhparam
ssl_ecdh_curve
ssl_handshake_timeout

ssl_handshake_timeout 指令用于设置SSL/TLS握手的最大超时时间。这个指令帮助控制连接建立过程中的等待时间。

Syntax:	ssl_handshake_timeout time;
Default:	ssl_handshake_timeout 60s;
Context:	stream, server
  • time:指定最大等待时间,默认值为 60s(60秒)。

案例

基本用法

最简单的 ssl_handshake_timeout 用法是指定具体的时间值:

stream {
    server {
        listen 443 ssl;
        ssl_certificate /etc/nginx/ssl/example.com.crt;
        ssl_certificate_key /etc/nginx/ssl/example.com.key;

        ssl_handshake_timeout 30s;

        proxy_pass backend_server;
    }
}

在这个例子中:

  • 设置了 ssl_handshake_timeout 30s,这意味着Nginx将在SSL/TLS握手过程中等待最多30秒。

动态设置不同配置

你可以根据不同的服务器块动态设置不同的超时时间:

stream {
    server {
        listen 443 ssl;
        ssl_certificate /etc/nginx/ssl/example1.com.crt;
        ssl_certificate_key /etc/nginx/ssl/example1.com.key;

        ssl_handshake_timeout 45s;

        proxy_pass backend_example1;
    }

    server {
        listen 444 ssl;
        ssl_certificate /etc/nginx/ssl/example2.com.crt;
        ssl_certificate_key /etc/nginx/ssl/example2.com.key;

        ssl_handshake_timeout 90s;

        proxy_pass backend_example2;
    }
}

在这个例子中:

  • 对于监听端口443的服务器块,设置了 ssl_handshake_timeout 45s
  • 对于监听端口444的服务器块,设置了 ssl_handshake_timeout 90s

注意事项

  • 超时管理:合理设置最大等待时间,避免过长导致的资源占用或过短影响连接成功率。
  • 适用场景:适用于需要精确控制SSL/TLS握手超时时间的应用场景。例如,在高并发网站、API网关等环境中使用。
  • 调试和监控:如果你遇到握手超时问题,可以检查以下几点:
    • 确保超时时间设置合理,并符合你的需求。
    • 查看Nginx的日志文件,确认是否有与此相关的警告或错误信息。
    • 使用工具模拟不同负载条件下的请求进行测试,确保在各种情况下都能正常工作。
ssl_key_log
ssl_ocsp
ssl_ocsp_cache
ssl_ocsp_responder
ssl_password_file
ssl_prefer_server_ciphers
ssl_protocols
ssl_reject_handshake
ssl_session_cache
ssl_session_ticket_key
ssl_session_tickets
ssl_session_timeout
ssl_stapling
ssl_stapling_file
ssl_stapling_responder
ssl_stapling_verify
ssl_trusted_certificate
ssl_verify_client
ssl_verify_depth

2.88 ngx_stream_ssl_preread_module

ngx_stream_ssl_preread_module 是 Nginx 的一个模块,用于在流(stream)上下文中通过 SSL/TLS 握手数据预读取来识别客户端连接的协议类型。这个模块允许你根据客户端连接使用的协议(如 TLS 版本、SNI 主机名等)进行路由或访问控制,而无需完全解密流量。

主要功能

  • SSL/TLS 预读取:通过分析 SSL/TLS 握手数据,识别客户端连接的协议信息。
  • 动态路由:根据识别出的协议信息,将连接路由到不同的后端服务器。
  • 变量支持:提供内置变量,用于提取握手数据中的特定信息(如 SNI 主机名、TLS 版本等)。

使用示例

以下是一些具体的配置示例,展示了如何使用 ngx_stream_ssl_preread_module 来识别并处理 SSL/TLS 连接。

基本配置

假设你想根据客户端连接的 SNI 主机名将连接路由到不同的后端服务器:

stream {
    upstream backend_example_com {
        server backend1.example.com:443;
        server backend2.example.com:443;
    }

    upstream backend_example_org {
        server backend1.example.org:443;
        server backend2.example.org:443;
    }

    map $ssl_preread_server_name $backend {
        default          backend_example_com;
        example.org      backend_example_org;
    }

    server {
        listen 12345;
        ssl_preread on;

        # 根据 SNI 主机名选择不同的上游服务器组
        proxy_pass $backend;
    }
}

在这个例子中:

  • map $ssl_preread_server_name $backend { ... } 定义了一个映射表,根据 $ssl_preread_server_name 的值设置 $backend 变量。
  • server 块中,启用 SSL/TLS 握手数据的预读取,并根据 $backend 变量选择不同的上游服务器组进行代理。

基于协议版本的路由

假设你想根据客户端使用的 SSL/TLS 协议版本将连接路由到不同的后端服务器:

stream {
    upstream tls12_backend {
        server backend_tls12_1.example.com:443;
        server backend_tls12_2.example.com:443;
    }

    upstream tls13_backend {
        server backend_tls13_1.example.com:443;
        server backend_tls13_2.example.com:443;
    }

    map $ssl_preread_protocol $backend {
        default          tls12_backend;
        "TLSv1.3"        tls13_backend;
    }

    server {
        listen 12345;
        ssl_preread on;

        # 根据 SSL/TLS 协议版本选择不同的上游服务器组
        proxy_pass $backend;
    }
}

在这个例子中:

  • map $ssl_preread_protocol $backend { ... } 定义了一个映射表,根据 $ssl_preread_protocol 的值设置 $backend 变量。
  • server 块中,启用 SSL/TLS 握手数据的预读取,并根据 $backend 变量选择不同的上游服务器组进行代理。

结合负载均衡和 ALPN

假设你想根据客户端支持的应用层协议(ALPN)列表将连接路由到不同的后端服务器:

stream {
    upstream http2_backend {
        server backend_http2_1.example.com:443;
        server backend_http2_2.example.com:443;
    }

    upstream http1_backend {
        server backend_http1_1.example.com:443;
        server backend_http1_2.example.com:443;
    }

    map $ssl_preread_alpn_protocols $backend {
        default          http1_backend;
        "~*http/2"       http2_backend;
    }

    server {
        listen 12345;
        ssl_preread on;

        # 根据 ALPN 协议选择不同的上游服务器组
        proxy_pass $backend;
    }
}

在这个例子中:

  • map $ssl_preread_alpn_protocols $backend { ... } 定义了一个映射表,根据 $ssl_preread_alpn_protocols 的值设置 $backend 变量。
  • server 块中,启用 SSL/TLS 握手数据的预读取,并根据 $backend 变量选择不同的上游服务器组进行代理。

注意事项

  • 性能优化
    • 尽量减少不必要的条件判断和变量设置,以提高性能。
    • 使用 map 指令代替多个 if 指令,可以提高配置的可读性和执行效率。
  • 安全性
    • 确保传输过程中的数据安全,防止中间人攻击。可以考虑使用 TLS 加密连接。
    • 确保映射数据文件的安全性,防止未经授权的访问。可以设置适当的文件权限,并考虑加密敏感数据。
  • 测试验证:在部署之前进行全面测试,确保所有配置按预期工作,并检查是否有任何潜在的问题(如握手数据未正确解析、变量值错误等)。
2.88.1 指令列表
ssl_preread

ssl_preread 指令用于启用或禁用SSL预读功能。这个指令帮助在TLS握手之前读取客户端数据以决定如何处理连接。

Syntax:	ssl_preread on | off;
Default:	ssl_preread off;
Context:	stream, server
  • on:启用SSL预读功能。
  • off:禁用SSL预读功能(默认值)。

案例

基本用法

最简单的 ssl_preread 用法是指定是否启用SSL预读功能:

stream {
    upstream backend_http {
        server 192.168.1.1:80;
    }

    upstream backend_mqtt {
        server 192.168.1.2:1883;
    }

    map $ssl_preread_protocol $upstream {
        default backend_http;
        mqtt backend_mqtt;
    }

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

在这个例子中:

  • 设置了 ssl_preread on,这意味着Nginx将在TLS握手之前读取客户端数据,并根据协议类型将请求转发到相应的上游服务器。

动态设置不同配置

你可以根据不同的服务器块动态设置是否启用SSL预读功能:

stream {
    upstream backend_http_1 {
        server 192.168.1.1:80;
    }

    upstream backend_mqtt_1 {
        server 192.168.1.2:1883;
    }

    map $ssl_preread_protocol $upstream_1 {
        default backend_http_1;
        mqtt backend_mqtt_1;
    }

    server {
        listen 443;
        proxy_pass $upstream_1;
        ssl_preread on;
    }

    upstream backend_http_2 {
        server 192.168.1.3:80;
    }

    upstream backend_mqtt_2 {
        server 192.168.1.4:1883;
    }

    map $ssl_preread_protocol $upstream_2 {
        default backend_http_2;
        mqtt backend_mqtt_2;
    }

    server {
        listen 444;
        proxy_pass $upstream_2;
        ssl_preread off;
    }
}

在这个例子中:

  • 对于监听端口443的服务器块,设置了 ssl_preread on
  • 对于监听端口444的服务器块,设置了 ssl_preread off

注意事项

  • 预读功能:合理启用SSL预读功能,避免不必要的开销或复杂性增加。
  • 适用场景:适用于需要在TLS握手之前读取客户端数据以决定如何处理连接的应用场景。例如,在需要区分不同协议类型的流量并路由到相应服务的环境中使用。
  • 调试和监控:如果你遇到预读功能问题,可以检查以下几点:
    • 确保预读功能设置合理,并符合你的需求。
    • 查看Nginx的日志文件,确认是否有与此相关的警告或错误信息。
    • 使用工具模拟不同负载条件下的请求进行测试,确保在各种情况下都能正常工作。

你可能感兴趣的:(nginx,nginx,网络,java)