人间工作P 人间工作P
主站 (opens new window)
首页
  • Bukkit开发教程
投喂
关于
  • 分类
  • 标签
  • 时间线
  • 友情链接

人间工作P

我每天都好困… 最近在学习和进行 VOCALOID 创作
主站 (opens new window)
首页
  • Bukkit开发教程
投喂
关于
  • 分类
  • 标签
  • 时间线
  • 友情链接
  • 使用 HAProxy 转发来自不同域名的地址到不同的 Minecraft 服务器

    • 配置反代
      • 按域名转发
      MrXiaoM
      2026-04-03
      开发
      目录

      使用 HAProxy 转发来自不同域名的地址到不同的 Minecraft 服务器

      节省反向代理节点数量,像 WEB 一样根据域名来转发流量

      书接上回: 我在防 DDoS 网络攻击这块的一些个人见解

      因为 hopper-rs 已经不更新了,所以另寻他路,用久经验证的 HAProxy 做反向代理也许是个好选择。我也已经用了有小半年了,最近才有按域名转发的需求,就把折腾过程给分享一下。

      本文示例配置中,不含优化参数,自己去查资料做针对性优化。

      # 配置反代

      依然是需要在代理端开启 proxy-protocol 选项,配置好防火墙,只允许反向代理服务器访问,然后再在反向代理服务器上安装 HAProxy,编辑配置:

      nano /etc/haproxy/haproxy.cfg
      
      1

      我的配置如下,以供参考

      注意:bind :::25565 是绑定 IPv6 地址,如果不需要可以删掉。

      global
              log stdout format raw local0
              maxconn 4096
      
      defaults
              log     global
              mode    tcp
              option  tcplog
              timeout connect 5s
              timeout client  30s
              timeout server  30s
      
      frontend tcp_proxy_front
              bind *:25565
              bind :::25565
              mode tcp
      
              default_backend tcp_proxy_back
      
      backend tcp_proxy_back
              mode tcp
              server target_server <源站IP>:<源站端口> send-proxy-v2
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22

      改完之后检查一下配置是否正确,然后重启 HAProxy 即可。

      haproxy -c -f /etc/haproxy/haproxy.cfg
      systemctl restart haproxy
      
      1
      2

      # 按域名转发

      你点进这篇文章肯定不是想看上面这个这么简单的配置的,以下方案由 Claude 生成,目前测试可用。

      按 Claude 的说法,需要解析 Minecraft 客户端握手包,获取发送过来的服务器地址,判定客户端要连接到服务器的地址来使用不同的后端。

      HAProxy 并没有 Minecraft 客户端握手包协议支持,所以需要自行实现解析握手包功能,先写一个 lua 脚本用于解析握手包:

      minecraft.lua
      nano /etc/haproxy/minecraft.lua
      
      1
      -- /etc/haproxy/minecraft.lua
      -- 解析 Minecraft Java 版握手包,提取玩家连接时使用的域名
      
      local function read_varint(data, pos)
          local result = 0
          local shift  = 0
          repeat
              if pos > #data then return nil, pos end
              local b = string.byte(data, pos)
              result = result | ((b & 0x7F) << shift)
              shift  = shift + 7
              pos    = pos + 1
              if shift >= 35 then return nil, pos end   -- VarInt 最多 5 字节
          until (b & 0x80) == 0
          return result, pos
      end
      
      core.register_action("mc_handshake", { "tcp-req" }, function(txn)
          local data = txn.req:dup()
      
          if #data < 5 then
              txn:set_var("req.mc_host", "")
              return
          end
      
          local pos = 1
      
          -- 1) Packet Length (VarInt)
          local pkt_len
          pkt_len, pos = read_varint(data, pos)
          if not pkt_len then txn:set_var("req.mc_host", ""); return end
      
          -- 2) Packet ID (VarInt, 握手包 = 0x00)
          local pkt_id
          pkt_id, pos = read_varint(data, pos)
          if not pkt_id or pkt_id ~= 0 then txn:set_var("req.mc_host", ""); return end
      
          -- 3) Protocol Version (VarInt)
          local proto_ver
          proto_ver, pos = read_varint(data, pos)
          if not proto_ver then txn:set_var("req.mc_host", ""); return end
      
          -- 4) Server Address 字符串长度 (VarInt)
          local str_len
          str_len, pos = read_varint(data, pos)
          if not str_len or str_len <= 0 or (pos + str_len - 1) > #data then
              txn:set_var("req.mc_host", "")
              return
          end
      
          -- 5) 提取域名
          local host = string.sub(data, pos, pos + str_len - 1)
      
          -- 去掉 Forge/FML 追加的标记 (例如 "hostname\0FML\0")
          host = (host:match("^([^%z]+)") or host)
      
          -- 转小写,便于后续匹配
          host = host:lower()
      
          txn:set_var("req.mc_host", host)
      end)
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61

      然后编辑 haproxy.cfg 配置,进行如下修改

      global
              log stdout format raw local0
              maxconn 4096
      +       lua-load /etc/haproxy/minecraft.lua
       
      defaults
      
      1
      2
      3
      4
      5
      6
      frontend tcp_proxy_front
              bind *:25565
              mode tcp
      
      +       tcp-request inspect-delay 5s
      +       tcp-request content lua.mc_handshake if { req.len ge 10 }
      +       tcp-request content accept if { req.len gt 10 }
      +
      +       use_backend 后端名 if { var(req.mc_host) -m str -i 你的域名 }
      +
              default_backend tcp_proxy_back
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11

      然后再在配置最后面添加后端就好了,示例如下

      frontend tcp_proxy_front
              # 仅作示例,这里仅编写需要添加的内容
      
              # 添加使用后端的条件为域名匹配
              # 如果需要更多域名转发,复制这一条 use_backend 往下粘贴修改即可
              use_backend my_proxy_1 if { var(req.mc_host) -m str -i mc.example.com }
      
              # 默认后端配置保持不变
              default_backend tcp_proxy_back
              
      # 添加新的后端,代理转发到另一个源站
      backend my_proxy_1
              mode tcp
              server target_server <源站IP>:<源站端口> send-proxy-v2
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14

      省流,完整示例如下

      haproxy.cfg
      global
              log stdout format raw local0
              maxconn 4096
              lua-load /etc/haproxy/minecraft.lua
      
      defaults
              log     global
              mode    tcp
              option  tcplog
              timeout connect 5s
              timeout client  30s
              timeout server  30s
      
      frontend tcp_proxy_front
              bind *:25565
              bind :::25565
              mode tcp
      
              tcp-request inspect-delay 5s
              tcp-request content lua.mc_handshake if { req.len ge 10 }
              tcp-request content accept if { req.len gt 10 }
      
              use_backend my_proxy_1 if { var(req.mc_host) -m str -i mc.example.com }
      
              default_backend tcp_proxy_back
      
      backend tcp_proxy_back
              mode tcp
              server target_server 192.168.0.2:10000 send-proxy-v2
      
      backend my_proxy_1
              mode tcp
              server target_server 192.168.0.3:10000 send-proxy-v2
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      编辑 (opens new window)
      #Minecraft#反向代理#HAProxy
      上次更新: 2026/04/03, 11:37:31
      最近更新
      01
      在构建/运行 Flutter 应用时添加环境变量,作出差异化调整
      03-30
      02
      白嫖老黄的 NVIDIA AI 模型
      03-20
      03
      临时修改 MMOItems 的数值属性,实现不同玩家不同属性功能
      03-13
      更多文章>
      Theme fork from Vdoing | Copyright © 2018-2026 人间工作P | 友情链接
      • 跟随系统
      • 浅色模式
      • 深色模式
      • 阅读模式