NGINX Stream模块实现子域名端口转发对接多Minecraft服务器问题
问题原因与解决方案
为什么会报错?
NGINX的stream模块是四层(TCP/UDP)代理,仅处理网络层数据包,不解析应用层(如HTTP)内容。而server_name是七层HTTP模块的指令,用于匹配HTTP请求的Host头,因此在stream块下的server中使用server_name必然触发"server_name directive is not allowed here"错误——二者工作层级完全不同。
Minecraft基于TCP协议,且1.7及以上版本客户端支持SNI(Server Name Indication),这是TLS握手阶段传递域名的机制,我们可以借助NGINX的stream_ssl_preread模块读取SNI信息,实现基于子域名的流量转发。
解决步骤
1. 确认NGINX编译了stream_ssl_preread模块
执行命令检查:
nginx -V 2>&1 | grep -- '--with-stream_ssl_preread_module'
若输出包含该参数,说明模块已启用;若没有,需重新编译NGINX并添加该编译选项。
2. 配置示例
以下是适配你需求的完整配置:
在nginx.conf顶层(与http块同级)添加stream配置:
stream { # 定义SNI到目标端口的映射 map $ssl_preread_server_name $mc_backend { server1.example.com 127.0.0.1:25560; server2.example.com 127.0.0.1:25561; # 可继续添加更多子域名映射 } server { listen 25565; # 开启SNI预读取,获取$ssl_preread_server_name变量 ssl_preread on; # 根据映射结果转发流量 proxy_pass $mc_backend; # 可选:添加超时配置 proxy_timeout 10m; } }
3. 验证配置并重启NGINX
nginx -t systemctl restart nginx
你的两次尝试问题所在
- 第一次配置:在
stream的server块中使用server_name,该指令属于HTTP模块,Stream模块无法识别。 - 第二次配置:同样错误地在
stream的server里使用server_name,本质与第一次问题一致。
注意事项
- 确保Minecraft客户端版本为1.7及以上,老版本不支持SNI,无法通过子域名区分转发。
- 通配符子域名的DNS解析需正确配置,所有
*.example.com指向你的NGINX主机IP。
内容的提问来源于stack exchange,提问作者GFoniX
相关产品推荐
相关产品推荐

