我正在尝试让 nginx 工作以平衡 udp 流量。上游服务器配置为 DSR,不会通过 nginx 传回流量。我有一组端口,需要转发到上游服务器,同时保留服务器端口。因此,我需要流量到达 nginx,nginx 查看上游服务器的 ip 列表并使用“hash $remote_addr consistent”选择一个,然后将流量发送到所选上游服务器的 ip,其中包含传入客户端的 ip 和它到达 nginx 的原始目标端口。然后上游服务器将接收流量,就像它没有经过 nginx 一样。有什么想法吗?
我尝试使用范围为 9000-9999 的监听;但是它不起作用,并给出错误“在“监听”指令的“9000-9999”中未找到主机。”因此,我为每个端口都设置了一条监听线,这真的很麻烦。
stream {
upstream stream_backend {
hash $remote_addr consistent;
server 10.10.10.14:8999;
}
server { #use this for upstream lb
listen 8999;
proxy_pass stream_backend;
proxy_bind $remote_addr:$remote_port transparent;
proxy_responses 0;
}
server { #test going directly to ip
listen 9000;
listen 9001;
listen 9002;
listen 9003;
#listen lines continue for whole port range
proxy_pass 10.10.10.30:$server_port; #used this to go directly to a server for testing
proxy_bind $remote_addr:$remote_port transparent;
proxy_responses 0;
}
}
有没有办法设置端口范围?而不是:
upstream stream_backend {
hash $remote_addr consistent;
server 10.10.10.14:8999;
}
像这样吗?
upstream stream_backend {
hash $remote_addr consistent;
server 10.10.10.14; or server 10.10.10.14:8999-9003 or server 10.10.10.14:$server_port
}
答案1
重新阅读您的问题后,我发现有些要求是 nginx 等代理无法满足的。
然后将流量发送到所选上游服务器的 IP,其中包含传入客户端的 IP 和它到达 nginx 的原始目标端口
nginx 使用常规套接字函数来启动 TCP 连接/发送 UDP 数据报。这意味着内核中的网络堆栈会选择传出数据包的 IP 地址。
nginx 无法发送源地址不是服务器现有地址的数据包。
您可以使用 IPTablesDNAT
功能来实现您的目标。DNAT
替换传入数据包中的目标 IP 地址和 UDP/TCP 端口,然后将其转发到目标。此方法保留源 IP 地址。
示例规则集可以是:
iptables -t nat -I PREROUTING -p udp -m multiport --dports 9000:9003 -m statistic --mode nth --every 3 --packet 0 -j DNAT --to-destination 10.0.0.2:8999
iptables -t nat -I PREROUTING -p udp -m multiport --dports 9000:9003 -m statistic --mode nth --every 2 --packet 0 -j DNAT --to-destination 10.0.0.3:8999
iptables -t nat -I PREROUTING -p udp -m multiport --dports 9000:9003 -m statistic --mode nth -j DNAT --to-destination 10.0.0.3:8999
这些规则将传入流量匹配到端口 9000:9003,并匹配目标 NAT,以将其分发到不同的服务器。
match-m statistic
采用循环分发。--every
由于 iptables 处理规则的方式是按顺序进行的,因此参数不断减少。
以下是原始答案
您的帖子标题提到了 UDP,但是您的配置并未包含udp
在listen
指令中。
因此,尝试使用:
server {
listen 8999 udp;
proxy_pass stream_backend;
proxy_bind $remote_addr:$remote_port transparent;
proxy_responses 0;
}