Nginx Stream 是 Nginx 提供的一项用于处理 TCP 和 UDP 流量的模块,通常用于反向代理、负载均衡等场景。它特别适用于需要处理非 HTTP 流量的协议,比如数据库、DNS、FTP、SMTP、TLS/SSL 等。
一、Nginx Stream 的基本概念
Nginx 通常用于 HTTP 反向代理和负载均衡,但对于非 HTTP 协议(如 TCP 和 UDP 流量),Nginx 提供了 stream
模块。这个模块使 Nginx 可以作为反向代理或负载均衡器来处理 TCP/UDP 请求。
特性:
- 支持 TCP/UDP 协议
- 负载均衡
- 反向代理
- 基于 IP 地址的会话保持
- 支持 SSL/TLS
- 支持访问控制
二、Nginx Stream 配置基础
1. 安装和启用 Stream 模块
确保 Nginx 编译时启用了 --with-stream
选项。可以通过以下命令确认 Nginx 是否支持 stream
模块:
nginx -V 2>&1 | grep -- '--with-stream'
如果输出中有 --with-stream
,表示 Nginx 支持该模块。
2. 基本配置结构
Stream 配置和 HTTP 配置类似,但 stream
是与 http
独立的块。通常放在 /etc/nginx/nginx.conf
文件的顶级配置中。
示例:简单的 TCP 代理
stream {
server {
listen 3306;
proxy_pass db_backend;
}
upstream db_backend {
server 192.168.1.100:3306;
server 192.168.1.101:3306;
}
}
这个配置将监听本地的 3306 端口,将 MySQL 请求代理到两个后端服务器 192.168.1.100
和 192.168.1.101
。
3. UDP 代理配置
UDP 和 TCP 配置基本相同,唯一不同的是协议。我们只需要在 listen
中指定 udp
。
示例:简单的 UDP 代理
stream {
server {
listen 53 udp;
proxy_pass dns_backend;
}
upstream dns_backend {
server 8.8.8.8:53;
server 8.8.4.4:53;
}
}
这个配置将 DNS 请求代理到 Google 的公共 DNS 服务器。
4. 访问控制
Nginx Stream 模块支持基于 IP 的访问控制(类似于 HTTP 中的 allow
和 deny
指令)。
示例:基于 IP 的访问控制
stream {
server {
listen 3306;
proxy_pass db_backend;
allow 192.168.1.0/24;
deny all;
}
}
此配置允许来自 192.168.1.0/24
网段的客户端访问 MySQL,其它所有访问将被拒绝。
5. 日志配置
默认情况下,stream
不像 http
那样有详细的日志配置。可以启用日志功能以跟踪流量。
示例:启用日志
stream {
log_format main '$remote_addr [$time_local] $protocol $status $bytes_sent $bytes_received $session_time';
access_log /var/log/nginx/stream_access.log main;
server {
listen 3306;
proxy_pass db_backend;
}
}
该配置启用了自定义日志格式,并将日志记录到 /var/log/nginx/stream_access.log
。
三、Nginx Stream 高级配置
1. 基于源 IP 的会话保持
Stream 模块支持会话保持,确保来自同一 IP 的请求被路由到相同的后端服务器。
示例:IP 哈希负载均衡
stream {
upstream db_backend {
hash $remote_addr consistent;
server 192.168.1.100:3306;
server 192.168.1.101:3306;
}
server {
listen 3306;
proxy_pass db_backend;
}
}
这个配置使用 IP 地址哈希来实现会话保持,确保来自同一 IP 的请求总是路由到同一个后端服务器。
2. 基于 SSL 的安全代理
Stream 模块支持为 TCP 流量启用 SSL/TLS 加密。通常用于加密数据库连接或邮件服务器之间的通信。
示例:SSL/TLS 加密代理
stream {
upstream db_backend {
server 192.168.1.100:3306;
server 192.168.1.101:3306;
}
server {
listen 3306 ssl;
proxy_pass db_backend;
ssl_certificate /etc/nginx/ssl/nginx.crt;
ssl_certificate_key /etc/nginx/ssl/nginx.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
}
}
此配置为 3306 端口上的 TCP 连接启用了 SSL 加密,确保客户端和 Nginx 之间的通信是加密的。
3. 基于 SNI 的多服务配置
Nginx Stream 模块也支持 SNI(Server Name Indication)用于基于域名区分 SSL 服务。
示例:基于 SNI 的 SSL 代理
stream {
server {
listen 443 ssl;
ssl_certificate /etc/nginx/ssl/default.crt;
ssl_certificate_key /etc/nginx/ssl/default.key;
ssl_preread on;
# 基于域名路由
set $target_backend "";
if ($ssl_preread_server_name = "mysql.example.com") {
set $target_backend mysql_backend;
}
if ($ssl_preread_server_name = "pgsql.example.com") {
set $target_backend pgsql_backend;
}
proxy_pass $target_backend;
}
upstream mysql_backend {
server 192.168.1.100:3306;
}
upstream pgsql_backend {
server 192.168.1.101:5432;
}
}
在这个配置中,根据 SNI 的值,Nginx 将客户端请求路由到不同的后端服务。
4. 健康检查
Stream 模块也支持主动健康检查,可以定期检查后端服务器是否正常工作。
示例:健康检查配置
stream {
upstream db_backend {
server 192.168.1.100:3306;
server 192.168.1.101:3306;
health_check interval=10s fails=3 passes=2;
}
server {
listen 3306;
proxy_pass db_backend;
}
}
每 10 秒对后端服务器进行一次健康检查,如果某个服务器连续 3 次失败,它将被标记为不可用。
四、Nginx Stream 使用注意事项
- 资源消耗:Nginx 处理 TCP/UDP 流量时会比 HTTP 模式消耗更多资源,特别是在启用了 SSL/TLS 的情况下。
- SSL 性能:启用 SSL/TLS 代理时,请注意选择合适的加密协议和加密套件,以避免性能下降。
- 日志:默认情况下,Nginx Stream 不记录访问日志。如果需要监控 TCP/UDP 流量,需要手动配置日志。
- 健康检查:对于高可用性部署,启用健康检查至关重要。
- 连接数限制:确保在高负载环境中为 Nginx 配置足够的文件描述符和连接数限制,避免超出系统资源。
五、总结
Nginx Stream 模块提供了灵活的方式来处理 TCP 和 UDP 流量,支持反向代理、负载均衡、SSL/TLS 加密等高级特性。它可以很好地集成到非 HTTP 的应用中,比如数据库代理、邮件代理、DNS 代理等。