跳转至

真实 IP 穿透:让 Velocity 看到玩家真实 IP

本文是运维经验笔记,适用于「Windows + Docker Desktop + Velocity」架构的服务器。文中的具体地址、端口、防护阈值均已省略,请以自己的环境为准。

背景

把 Velocity 跑在 Docker Desktop(Windows)里之后,登录插件和日志里玩家的来源 IP 会全部变成网关 IP——容器内看到的是 Docker 网关地址,宿主机上看到的是路由器地址。后果:

  • 按 IP 的防护(限频、封禁、并发限制)全部失效,所有人共享同一个"假 IP";
  • 日志、审计、风控拿不到真实来源。

目标:让 Velocity 拿到玩家的真实公网 IP,并且对外端口保持统一。

定位方法:谁改写了 IP?

排查这类问题用对照实验,不要猜:

  1. 在链路两端(入口机 / 目标机)同时抓 netstat / conntrack,比对同一次连接的「源 IP + 源端口」;
  2. 端口也变了 = 经过了 SNAT 或应用层代理(用户态转发必然改写源地址);
  3. 只有 IP 变、端口没变 = 某种透明改写;
  4. conntrack 里同一次访问出现两段连接(公网IP:端口 → WAN口 + 本机IP:随机端口 → 内网IP:端口)就是"应用层代理在中间起了新连接"的指纹。

三个根因

  1. Docker Desktop(Windows/macOS)必毁源 IP:入站流量经 com.docker.backend.exe 用户态代理转发,bridge 模式下源地址被改写为 Docker 网关,host 模式下变成 127.0.0.1。这是产品机制,没有任何配置可以解决(参见 moby/moby#52945);Linux 原生 Docker 没有这个问题。
  2. 路由器上的"端口转发面板"多是应用层代理:市面上常见的软路由端口转发/内网穿透面板以用户态转发为主,源 IP 会被改写;而内核 DNAT(iptables)保留源 IP。这是分水岭。
  3. Minecraft 握手协议不携带客户端 IP:真实 IP 只能从传输层拿回来。

解法:PROXY protocol v2 全链路

PROXY protocol 的思路:由前置代理在 TCP 流的头部注入"真实四元组"(v1 文本 / v2 二进制,v4 头 28 字节、v6 头 52 字节),后端解析头部还原真实来源。

玩家 → 路由器内核 DNAT(源IP不动)
     → 机器内转发器(在 TCP 流头注入 PROXY protocol v2)
     → Docker 内 Velocity(haproxy-protocol=true,解析真实IP)✅

配置要点:

  • Velocity 原生支持:velocity.toml 的 [advanced] haproxy-protocol = true;
  • 开了这个选项后,无 PROXY 头的直连会被拒绝——这是特性不是 bug,它同时挡住了伪造头的注入攻击(只信任来自自己转发器的连接即可);
  • 内核 DNAT 规则写入路由器的防火墙自定义脚本(如 OpenWrt 的 /etc/firewall.user)持久化;
  • 转发器用任何能注入 PROXY 头的轻量工具都行(几行 Python 或现成的 proxyprotocol 转发器)。

两条关键原则

  1. 注入点必须站在"毁 IP 的那一跳"之前。 Docker Desktop 会毁 IP,所以注入必须发生在进 Docker 之前——这就是机器内那个小转发器存在的意义:它的职责不是转发,是"加头"。
  2. 整条链只允许一层注入。 如果上游已经加了 PROXY 头,下游不要再加一次——第二次注入会把第一次记录的真实 IP 当成来源盖掉。

验证

从外部网络(手机热点 / 云服务器)发一个真实 MC 登录包,在 Velocity 日志里确认登录插件记录的 playerIp 是外部网络的真实地址,而不是网关地址。再用协议工具发一个不带 PROXY 头的直连包,确认被拒(信任保护生效)。

踩坑备忘

  • 部分端口转发面板的"代理协议"开关是入站信任方向(决定信不信别人发来的头),不是向后端发头;TCP 转发规则想"把真实 IP 传给后端",要确认产品真的支持出站 PROXY 头(很多只有 HTTP 反代支持)。
  • 管理面板的 API 有登录失败限速,连续试错会触发锁定——先查官方文档/源码确定接口格式,别穷举。
  • 改路由器只动目标规则(DNAT/端口映射),绝不碰 WAN 口和网络重启;规则写进持久化脚本,并保留可回滚的开关。

收益

真实 IP 还原后,按 IP 的防护语义恢复正常:同 IP 并发在线限制、认证失败冷却、按 IP 限频等都可以正常启用,误伤归零。