背景信息:
有一台机器,我们称之为“机器 A”,(运行 Xubuntu 18.04),我在防火墙后面托管 Minecraft,从现在开始我将其称为“防火墙”,(运行 Ubuntu Server 16.04)。
以前,Minecraft 服务器在我的文件服务器上运行,称之为“机器 B”,一切运行正常,只是 Java 一直出现分段错误,因此我决定转移到机器 A。
当我使用机器 B 时,我在防火墙上对 iptables 使用了以下规则,将到防火墙 25565 端口的所有连接转发到机器 B 的 25565 端口:
iptables -t nat -A PREROUTING -p tcp -d 128.xxx.xxx.xxx --destination-port 25565 -j DNAT --to 192.xxx.xxx.xxx:25565
iptables -A FORWARD -p tcp -i 'enp2s0' -o 'enp4s0' -d 192.xxx.xxx.xxx --destination-port 25565 -m state --state NEW -j ACCEPT
当时这工作得很好,没有任何问题。但现在我已移至机器 A 并相应地修改了上述规则,转发仍然只发生在机器 B 上,而不发生在机器 A 上。
下面是我用来设置防火墙上的所有规则的 iptables 脚本(省略了不相关的条目):
#!/bin/bash
IPT=/sbin/iptables
INET_IFACE='enp4s0'
INET_SUB=128.xxx.xxx.xxx/28
LOCAL_IFACE='enp2s0'
LOCAL_SUB=192.xxx.xxx.xxx/24
# Flush the tables
$IPT -F INPUT
$IPT -F OUTPUT
$IPT -F FORWARD
# Define default policy to DROP packets
$IPT -P INPUT DROP
$IPT -P OUTPUT ACCEPT
$IPT -P FORWARD ACCEPT
$IPT -t nat -P PREROUTING ACCEPT
$IPT -t nat -P POSTROUTING ACCEPT
$IPT -t nat -P OUTPUT ACCEPT
$IPT -A INPUT -i $INET_IFACE -m state --state INVALID -j DROP
$IPT -A INPUT -s $LOCAL_SUB -i $LOCAL_IFACE -j ACCEPT
$IPT -A FORWARD -o 'enp4s0' -i 'enp2s0' -s 192.xxx.xxx.xxx/24 -m conntrack --ctstate NEW -j ACCEPT
$IPT -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
$IPT -A INPUT -m state -p tcp --dport 1024:65535 --state ESTABLISHED,RELATED -s 0/0 -j ACCEPT
$IPT -t nat -A PREROUTING -p tcp -d 128.xxx.xxx.xxx --destination-port 25565 -j DNAT --to 192.xxx.xxx.xxx:25565
$IPT -A FORWARD -p tcp -i 'enp2s0' -o 'enp4s0' -d 192.xxx.xxx.xxx --destination-port 25565 -m state --state NEW -j ACCEPT
检查iptables -L
并iptables -S
显示转发规则存在于计算机 A 中,但如果我尝试从网络外部访问 Minecraft 服务器,它将无法连接,除非服务器正在运行计算机 B,这使我相信更新的转发规则在某个地方没有生效。输出如下:
user@firewall:~# iptables -L
Chain INPUT (policy DROP)
target prot opt source destination
ACCEPT icmp -- anywhere anywhere icmp echo-reply
ACCEPT icmp -- anywhere anywhere icmp echo-request
ACCEPT icmp -- anywhere anywhere icmp time-exceeded
ACCEPT tcp -- anywhere anywhere tcp dpt:ssh
LOG all -- anywhere anywhere limit: avg 5/min burst 5 LOG level debug prefix "iptables denied: "
ACCEPT tcp -- anywhere anywhere tcp dpt:http
ACCEPT all -- anywhere anywhere
DROP all -- anywhere anywhere state INVALID
ACCEPT udp -- anywhere anywhere udp spt:domain
ACCEPT all -- 192.xxx.xxx.0/24 anywhere
ACCEPT udp -- anywhere anywhere udp dpts:bootps:tftp
ACCEPT tcp -- anywhere anywhere state RELATED,ESTABLISHED tcp dpts:1024:65535
Chain FORWARD (policy ACCEPT)
target prot opt source destination
ACCEPT all -- 192.xxx.xxx.0/24 anywhere ctstate NEW
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
ACCEPT tcp -- anywhere 192.xxx.xxx.xxx tcp dpt:25565 state NEW
ACCEPT tcp -- anywhere 192.xxx.xxx.xxx tcp dpt:http state NEW
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
ACCEPT icmp -- anywhere anywhere icmp echo-reply
ACCEPT icmp -- anywhere anywhere icmp echo-request
ACCEPT icmp -- anywhere anywhere icmp time-exceeded
ACCEPT tcp -- anywhere anywhere tcp spt:ssh
ACCEPT tcp -- anywhere anywhere tcp spt:http
ACCEPT all -- anywhere anywhere
user@firewall:~# iptables -S
-P INPUT DROP
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 0 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 11 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -i enp4s0 -m state --state INVALID -j DROP
-A INPUT -p udp -m udp --sport 53 -j ACCEPT
-A INPUT -s 192.xxx.xxx.0/24 -i enp2s0 -j ACCEPT
-A INPUT -p udp -m udp --dport 67:69 -j ACCEPT
-A INPUT -p tcp -m state --state RELATED,ESTABLISHED -m tcp --dport 1024:65535 -j ACCEPT
-A FORWARD -s 192.xxx.xxx.0/24 -i enp2s0 -o enp4s0 -m conntrack --ctstate NEW -j ACCEPT
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -d 192.xxx.xxx.xxx/32 -i enp2s0 -o enp4s0 -p tcp -m tcp --dport 25565 -m state --state NEW -j ACCEPT
-A FORWARD -d 192.xxx.xxx.xxx/32 -i enp2s0 -o enp4s0 -p tcp -m tcp --dport 80 -m state --state NEW -j ACCEPT
-A OUTPUT -p icmp -m icmp --icmp-type 0 -j ACCEPT
-A OUTPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT
-A OUTPUT -p icmp -m icmp --icmp-type 11 -j ACCEPT
-A OUTPUT -p tcp -m tcp --sport 22 -j ACCEPT
-A OUTPUT -p tcp -m tcp --sport 80 -j ACCEPT
-A OUTPUT -o lo -j ACCEPT
您可能注意到,我还将端口 8080 从防火墙转发到了机器 A 上的端口 80。这只是一个健全性检查,以确保端口转发对该机器有效,并且确实有效。
我的问题正是:什么原因导致 25565 的转发规则仍然对机器 B 起作用,而它应该对机器 A 起作用?
编辑-添加的输出iptables -t nat -S
:
user@firewall:~# iptables -t nat -S
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
-A PREROUTING -i enp4s0 -p tcp -m tcp --dport 25565 -j DNAT --to-destination 192.xxx.xxx.xxx:25565 # (Machine B)
-A PREROUTING -i enp4s0 -p tcp -m tcp --dport 25565 -j DNAT --to-destination 192.xxx.xxx.xxx # (Machine B)
-A PREROUTING -d 128.xxx.xxx.xxx/32 -p tcp -m tcp --dport 25565 -j DNAT --to-destination 192.xxx.xxx.xxx:25565 # (Machine B - Shows up 14 more times)
-A PREROUTING -d 128.xxx.xxx.xxx/32 -p tcp -m tcp --dport 25565 -j DNAT --to-destination 192.xxx.xxx.xxx:25565 # (Machine A - Shows up 2 more times)
-A PREROUTING -d 128.xxx.xxx.xxx/32 -p tcp -m tcp --dport 8080 -j DNAT --to-destination 192.xxx.xxx.xxx:80 # (Machine A)
-A POSTROUTING -j MASQUERADE # (Shows up 35 more times)
答案1
明白了。我包含的脚本在运行时不会清除 nat 表,这导致我的旧规则仍然存在,从而导致我遇到的问题。以下文章帮助我解决了这个问题:清除所有 iptables 规则的最佳方法(在 Server Fault 上清除所有 iptables 规则的最佳方法)。我iptables -t nat -F
在脚本顶部添加了以下内容并重新运行了该脚本,这样就解决了所有问题。在 @Tomek 要求我提供输出后,iptables -t nat -S
我开始怀疑我是否也必须刷新 nat 表。再次感谢!