关于端口转发的配置记录

2020-08-18 1277点热度 2人点赞

闲来无事给 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 ]

StarryVoid

Have a good time