最近搭建MC服务器,虽然有公网IP但是不想使用frp,最后采用了通过了Wireguard组网,nftables进行转口转发的方式,这里记录一下端口转发的配置以及相关介绍
先上一些基础名词配置
# 标准 NAT 钩子点有约定名称:
# - prerouting (入站数据包处理)
# - input (目标为本机的数据包)
# - output (本机产生的数据包)
# - postrouting (出站数据包处理)
# - forward (转发的数据包)
# nftables iptables
# ---------------------------------
# prerouting ↔ PREROUTING
# input ↔ INPUT
# output ↔ OUTPUT
# postrouting ↔ POSTROUTING
# forward ↔ FORWARD
# 如果你改名,熟悉 iptables 的人会困惑直接上配置,咱们逐行解析
table ip nat {
chain prerouting {
type nat hook prerouting priority -100; policy accept;
# 外部访问转发
tcp dport 80 redirect to :8080
}
chain output {
type nat hook output priority -100; policy accept;
# 本地访问转发
ip daddr 127.0.0.1 tcp dport 80 redirect to :8080
# 或者更通用(包括本机IP)
# tcp dport 80 redirect to :8080
}
chain postrouting {
type nat hook postrouting priority 100; policy accept;
}
}表定义
table ip nat
- table:定义一个 nftables 表
- ip:仅处理 IPv4 数据包(IPv6 需要 ip6 或 inet)
- nat:表名称,专门用于网络地址转换(NAT)
PREROUTING 链定义
chain prerouting {
type nat hook prerouting priority -100; policy accept;- chain prerouting:创建名为 "prerouting" 的链
- type nat:这是一个 NAT 类型的链
- hook prerouting:挂接到内核的 PREROUTING 钩子点
- priority -100:优先级,数字越小优先级越高
- policy accept:默认策略是接受(如果规则不匹配)
工作流程:
外部访问: 客户端 → 服务器IP:80 → PREROUTING → 目标端口改为8080 → 本地进程
PREROUTING 规则
# 外部访问转发
tcp dport 80 redirect to :8080
}- tcp dport 80:匹配 TCP 协议且目标端口为 80 的数据包
- redirect to :8080:将目标端口重定向到 8080
工作流程:
外部访问: 客户端 → 服务器IP:80 → PREROUTING → 目标端口改为8080 → 本地进程
OUTPUT 链定义
chain output {
type nat hook output priority -100; policy accept;- chain output:创建名为 "output" 的链
- hook output:挂接到 OUTPUT 钩子点
- 优先级相同:-100,与 PREROUTING 并行处理
OUTPUT 钩子位置:
本地进程发送数据 → OUTPUT → POSTROUTING → 发送到网络
OUTPUT 链规则
# 本地访问转发
ip daddr 127.0.0.1 tcp dport 80 redirect to :8080- ip daddr 127.0.0.1:匹配目标 IP 地址为 127.0.0.1(localhost)
- tcp dport 80:匹配目标端口 80
- redirect to :8080:重定向到 8080 端口
为什么需要这个规则
本地访问: curl 127.0.0.1:80 → OUTPUT链 → 端口改为8080 → 回环接口 → 本地进程
POSTROUTING 链定义
chain postrouting {
type nat hook postrouting priority 100; policy accept;
}
}- hook postrouting:挂接到 POSTROUTING 钩子点
- priority 100:较低优先级,在路由决策后执行
POSTROUTING 钩子位置:
数据包发送前 → POSTROUTING → 网络接口发送
完整数据包流向
场景1:外部客户端访问

场景2:本地 curl 访问

场景3:本地 curl 访问服务器公网IP

问题
当咱们有这个配置
chain output {
type nat hook output priority -100; policy accept;
# 本地访问转发
ip daddr 127.0.0.1 tcp dport 80 redirect to :8080
# 或者更通用(包括本机IP)
# tcp dport 80 redirect to :8080
}咱们访问curl 127.0.0.1的时候会转发到80,但是curl 192.x.x.x则不会,因为咱们只配置了127.0.0.1
解决方案1:更通用的 OUTPUT 规则
chain output {
type nat hook output priority -100; policy accept;
# 匹配所有目标端口80的TCP流量
tcp dport 80 redirect to :8080
}但是这样有大问题,本机所有目标端口的80都会到8080,甚至是curl http://www.baidu.com
所以慎用
解决方案2:指定所有本地IP
chain output {
type nat hook output priority -100; policy accept;
# 匹配多个本地地址
ip daddr { 127.0.0.1, 192.168.1.100, 10.0.0.1 } tcp dport 80 redirect to :8080
}进阶
代理到其他内网机器
大部分时候MC服务器不一定是在本机,所以有时候我们需要转发到别的内网机或者外网机
先上配置:
table ip nat {
chain prerouting {
type nat hook prerouting priority 0; policy accept;
#ip daddr 公网ip tcp dport 80 dnat to 172.32.100.11:25565
iifname "eth0" tcp dport 80 dnat to 172.32.100.11:25565
}
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
#ip daddr 172.32.100.11 masquerade
oifname "test" masquerade
}
}prerouting部分
咱们先看第一部分
ip daddr 公网ip tcp dport 80 dnat to 172.32.100.11:25565
iifname "eth0" tcp dport 80 dnat to 172.32.100.11:25565
为什么我把第一段注释了呢,这段意思是把ip端口为公网:80的流量转发给172xxxx:25565,那么正常应该是没问题,但是咱们一般都是公网云服务器,一般也都是弹性IP,也就是说,如果正常网络下访问公网:80, 服务器的确能收到流量,但是目标ip可能被云服务器厂商转换了,而转换的ip大概率就是本机eth0(本机网卡)的IP

如图这个10.0.16.2,当然我没试过,所以咱们直接最暴力的就是本机eth所有的80端口流量都到172.32.100.11:25565就行
postrouting部分
咱们再看第二部分,首先我们回顾一下场景
① 客户端访问公网服务器
客户端 → 82.x.x.x:80
② PREROUTING
iifname "eth0" tcp dport 80 dnat to 172.32.100.11:25565
数据包变为了
源 IP: 客户端公网 IP
目标 IP: 172.32.100.11
目标端口: 25565③ 路由判断
系统发现:172.32.100.11 在 wg/本机局域网 网段 → 走 test/eth0 网卡
④ 到达 POSTROUTING(当前部分)
oifname "test" masquerade
那这里发生了什么呢?
内核准备把包从 test 网卡发出去,于是 nftables 检查这个包是不是要从 test 网卡出去
✔ 是 → 命中规则
⑤ masquerade 做了什么(核心)
原始包(DNAT 后):
源 IP: 客户端公网 IP
目标 IP: 172.32.100.11经过 masquerade 后:
源 IP: 172.32.100.1 ←(本机 test 网卡 IP)
目标 IP: 172.32.100.11源地址被“伪装”成 WG 网卡自己
为什么必须 masquerade?
如果不 masquerade(常见错误)
MC 服务器收到的是:
源 IP: 客户端公网 IP
目标 IP: 172.32.100.11然后 MC 服务器回包时会:
目的 IP = 客户端公网 IPBut 这就是问题:
- MC 服务器根本不知道怎么去公网
- 默认路由可能不在 WG
- 回包直接丢失
有 masquerade 的情况
MC 服务器看到的是:
源 IP: 172.32.100.1(你的公网服务器)
回包:
172.32.100.11 → 172.32.100.1
- 走 WG 回到公网服务器
- 内核根据 NAT 表反查
- 自动还原成:82.x.x.x → 客户端
连接成功
评论 (0)