闲来无事给 GCP 上的 Minecraft 配过一个基于 iptables 的端口转发,结果发现效果并没有十分理想,经常会出现断线的情况,而后基于 Nginx 重新配置了一下却很稳定,在此记录
1 、前言
免费的 GCP 谁都想嫖,同学也不例外。嫖了一台组团玩 Minecraft,却发现某些玩家的游戏体验十分的差劲,动不动就完全无法连接。
正巧有一台阿里云服务器可以拿来当中间人,所以就赶紧拿出来配置了一下
Minecraft 服务端主机 45.32.201.1 (已处理) 端口 25565
中转阿里云服务端主机 172.16.10.10 (已处理) 端口 20000 关联公网 IP 101.200.20.20 (已处理)
使用后的总结:还是要用 Nginx 进行管理和配置,比 iptables 稳定多了。
2 、基于 CentOS 的 Firewalld
只需要三条命令,就完成了一个端口转发的配置
firewall-cmd --permanent --zone=public --add-forward-port=port=20000:proto=tcp:toport=25565:toaddr=45.32.201.1 firewall-cmd --permanent --zone=public --add-port=20000/tcp firewall-cmd --permanent --zone=public --add-masquerade firewall-cmd --reload
之后就可以让别的玩家开始使用 101.200.20.20:20000 来代替访问 Minecraft 服务器了
3 、基于 Ubuntu 的 UFW
换汤不换药,一段时间后发现前者在使用时虽然问题比较缓解,但仍然存在不定期掉线(丢包)的情况,于是开始排查到底发生了什么
查了半天也没查出来,只能查到 tcp 会话 reset 了。
那,作为常识,如果搞不懂的话换一个基本环境再试一次
2.1 、开启 Ubuntu 的 ip_forward
sed -i "/net.ipv4.ip_forward/d" /etc/sysctl.conf echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
2.2 、开启 Ubuntu 的 UFW
apt-get install ufw ufw status ufw enable
2.3 、配置 UFW
sed -i 's/#net\/ipv4\/ip_forward=1/net\/ipv4\/ip_forward=1/g' /etc/ufw/sysctl.conf sed -i 's/DEFAULT_FORWARD_POLICY="DROP"/DEFAULT_FORWARD_POLICY="ACCEPT"/g' /etc/default/ufw ufw allow 20000/tcp
2.4 、配置基于 UFW 的端口转发
编辑 /etc/ufw/before.rules
文件,在 *filter 上方新增一段 *nat
的配置,如下
*nat :PREROUTING ACCEPT [0:0] :POSTROUTING ACCEPT [0:0] -A PREROUTING -p tcp --dport 20000 -j DNAT --to-destination 45.32.201.1:25565 -A POSTROUTING -p tcp -d 45.32.201.1 --dport 25565 -j SNAT --to-source 172.16.10.10 COMMIT
注意开头以 *nat
结束以 COMMIT
才算是一个完整的规则
添加好之后我们需要重启 UFW
ufw disable
ufw enable
重启后可以检查防火墙配置的状态
iptables -nvL -t nat
如果有什么配置需要删除或修改,则需要完全重启 iptables 才可以
4 、基于 Nginx 的 upstream
当发现就算更换了系统,也出现同样的问题后,开始怀疑并不是下三层的问题了。
而关于 OSI 上四层的代理方案,其中最熟悉的还当属 Nginx 的 upsteam 模块了。
apt-get install nginx-extras cp -a /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak
安装并备份好配置后,我们就可以直接配置端口转发了,需要在 events{} 下面添加一个 stream{} 里面写配置
stream { include /etc/nginx/tcp.d/*.conf; }
全部样板参考如下
user www-data; worker_processes auto; pid /run/nginx.pid; include /etc/nginx/modules-enabled/*.conf; error_log /var/log/nginx/error.log; events { worker_connections 65535; use epoll; multi_accept on; } stream { include /etc/nginx/tcp.d/*.conf; } http { charset utf-8; tcp_nopush on; tcp_nodelay on; send_timeout 15; keepalive_timeout 60; server_tokens off; autoindex off; }
注意你可以清空 http{} ,但是要保证最外层的 http{} 留下,否则无法启动 Nginx 。
由于可能导致的大量 TIME_OUT 占用了所有端口以至于无法 SSH 所以需要保证 http{} 有一些参数
同时在这里我们可以看到 steam 指向了一个本地的配置文件组,所以我们需要都配置文件组中查找这台设备的配置。
然后我们需要在 /etc/nginx/tcp.d/
目录下做一个实际转发用的配置文件
vim /etc/nginx/tcp.d/minecraft.conf upstream minecraft { server 45.32.201.1:25565; server 45.32.201.2:25565 backup; } server { listen 20000; proxy_pass minecraft; }
此时检查 Nginx 的配置并重启后,端口转发就正常工作了。
如果你希望 Linux Kernel 调度这些转发,则在每个唯一的 listen 端口中增加一个参数 reuseport
如果你希望使用域名的方式让 Nginx 自动寻找服务器,也可以直接添加,添加超时时间进行限制
stream { resolver 114.114.114.114 valid=300s; resolver_timeout 5s; include /etc/nginx/tcp.d/*.conf; } upstream minecraft { server minecraft.example.com:25565 max_fails=3 fail_timeout=300s ; server 45.32.201.1:25565 backup; server 45.32.201.2:25565 backup; } server { listen 20000 reuseport; proxy_pass minecraft; }
5 、相关链接
How to reverse proxy a Minecraft server with Nginx [ Link ]