<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Home Network on Code is cheap, let&#39;s talk</title>
    <link>https://blog.ferstar.org/series/home-network/</link>
    <description>Code is cheap, let&#39;s talk</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>zh-CN</language>
    <copyright>© 2026 ferstar · [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh)</copyright>
    <lastBuildDate>Thu, 16 Jul 2026 10:00:00 +0800</lastBuildDate>
    <ttl>60</ttl><atom:link href="https://blog.ferstar.org/series/home-network/index.xml" rel="self" type="application/rss+xml" /><image>
      <url>https://blog.ferstar.org/site-logo.png</url>
      <title>Code is cheap, let&#39;s talk</title>
      <link>https://blog.ferstar.org/</link>
    </image>
    
    <item>
      <title>PS5 Minecraft 卡在“正在加载”：把微软 HTTPS 和游戏 UDP 拆开走</title>
      <link>https://blog.ferstar.org/posts/ps5-minecraft-hybrid-routing/</link>
      <pubDate>Thu, 16 Jul 2026 10:00:00 +0800</pubDate>
      
      <guid isPermaLink="true">https://blog.ferstar.org/posts/ps5-minecraft-hybrid-routing/</guid>
      <description>PS5 上的 Minecraft 长时间卡在“正在加载”；用抓包定位到微软/Azure 的 HTTPS 建连慢，只代理该主机的 TCP 443，保留 DNS 与 UDP 19132 直连后恢复正常。</description><content:encoded><![CDATA[<p>这次问题的表象很像“Minecraft 联机坏了”：PS5 能上网，商店和账号也没报错，但 Minecraft 进到服务器/联机相关页面后，经常长时间停在“正在加载”。</p>
<p>一开始自然会怀疑 DNS、IPv6、BedrockConnect，甚至局域网里的 Geyser。最后都不是根因。</p>
<p>真正有效的改法很小：<strong>只让这台 PS5 的 TCP 443 走 ShellCrash；DNS 和 Minecraft 的 UDP 19132 保持直连。</strong></p>
<pre class="not-prose mermaid">
flowchart LR
  P[PS5] -->|TCP 443: Microsoft / Azure auth and resources| C[ShellCrash proxy]
  P -->|UDP 19132: Minecraft game traffic| I[Direct Internet]
  P -->|DNS| D[Normal DNS]
</pre>


<h2 class="relative group">先别急着改 DNS
    <div id="先别急着改-dns" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%85%88%e5%88%ab%e6%80%a5%e7%9d%80%e6%94%b9-dns" aria-label="锚点">#</a>
    </span>
    
</h2>
<p>BedrockConnect 解决的是“主机版基岩版怎样填自定义服务器”的入口问题，不是 Minecraft 加载慢的通用解法。DNS 被路由器、透明代理或 IPv6 改写时，确实可能让它不生效；但这次即使完全回到默认 DNS，加载问题仍在。</p>
<p>也不要先把整台 PS5 全局代理。Minecraft 的控制面和游戏数据面不是一回事：</p>
<ul>
<li>登录、授权、皮肤与资源下载主要是 TCP 443；</li>
<li>实际联机游戏是 UDP，基岩版默认端口通常为 19132；</li>
<li>DNS 是另一个独立变量。</li>
</ul>
<p>全局代理看起来省事，实际上容易把 UDP、局域网发现和 MTU 问题一起带进来，排查面会迅速变大。</p>

<h2 class="relative group">这次是怎样定位的
    <div id="这次是怎样定位的" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e8%bf%99%e6%ac%a1%e6%98%af%e6%80%8e%e6%a0%b7%e5%ae%9a%e4%bd%8d%e7%9a%84" aria-label="锚点">#</a>
    </span>
    
</h2>
<p>先看了三层事实。</p>
<p>第一层，路由器本身没有压力，PS5 到路由器的 Wi‑Fi 连续 ping 无丢包、延迟在几毫秒内。局域网不是瓶颈。</p>
<p>第二层，路由器直连访问微软授权端点时，IPv4 和 IPv6 的 HTTPS 都能完成；这说明不是“微软服务被完全封死”。</p>
<p>第三层，抓 PS5 的包时，加载阶段出现的是对 Microsoft/Azure 授权与资源域名的 DNS、TCP 443 与 TLS 流量；并没有进入持续的 Minecraft UDP 游戏流。更关键的是，PS5 发出 SYN 后，Azure 的 SYN-ACK 要一秒多才回来。</p>
<p>这把问题从“游戏服务器不可达”缩小成了“这条直连到微软/Azure 的 HTTPS 路径质量差”。路由器正常、游戏 UDP 也还没开始，应该只优化这条控制面路径。</p>

<h2 class="relative group">最终规则：按 MAC 精确分流
    <div id="最终规则按-mac-精确分流" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%9c%80%e7%bb%88%e8%a7%84%e5%88%99%e6%8c%89-mac-%e7%b2%be%e7%a1%ae%e5%88%86%e6%b5%81" aria-label="锚点">#</a>
    </span>
    
</h2>
<p>下面是 OpenWrt + ShellCrash 的最小规则。把 <code>PS5_MAC</code> 换成 PS5 的 MAC，把 <code>REDIR_PORT</code> 换成 ShellCrash 的 redir port（本机实际监听的端口）。规则同时覆盖 IPv4 与 IPv6。</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl"><span class="cp">#!/bin/sh
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">PS5_MAC</span><span class="o">=</span><span class="s1">'AA:BB:CC:DD:EE:FF'</span>
</span></span><span class="line"><span class="cl"><span class="nv">REDIR_PORT</span><span class="o">=</span><span class="s1">'7892'</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">iptables -t nat -D PREROUTING -m mac --mac-source <span class="s2">"</span><span class="nv">$PS5_MAC</span><span class="s2">"</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">  -p tcp --dport <span class="m">443</span> -j REDIRECT --to-ports <span class="s2">"</span><span class="nv">$REDIR_PORT</span><span class="s2">"</span> 2>/dev/null
</span></span><span class="line"><span class="cl">iptables -t nat -I PREROUTING <span class="m">1</span> -m mac --mac-source <span class="s2">"</span><span class="nv">$PS5_MAC</span><span class="s2">"</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">  -p tcp --dport <span class="m">443</span> -j REDIRECT --to-ports <span class="s2">"</span><span class="nv">$REDIR_PORT</span><span class="s2">"</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">ip6tables -t nat -D PREROUTING -m mac --mac-source <span class="s2">"</span><span class="nv">$PS5_MAC</span><span class="s2">"</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">  -p tcp --dport <span class="m">443</span> -j REDIRECT --to-ports <span class="s2">"</span><span class="nv">$REDIR_PORT</span><span class="s2">"</span> 2>/dev/null
</span></span><span class="line"><span class="cl">ip6tables -t nat -I PREROUTING <span class="m">1</span> -m mac --mac-source <span class="s2">"</span><span class="nv">$PS5_MAC</span><span class="s2">"</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">  -p tcp --dport <span class="m">443</span> -j REDIRECT --to-ports <span class="s2">"</span><span class="nv">$REDIR_PORT</span><span class="s2">"</span></span></span></code></pre></div></div>
<p>这段脚本有三个刻意的限制：</p>
<ol>
<li>只匹配一台设备的 MAC，不影响家里其他设备；</li>
<li>只匹配 TCP 443，不碰 UDP 19132；</li>
<li>先删除旧规则再插入，重复执行不会不断叠加相同规则。</li>
</ol>
<p>如果 ShellCrash 给这台 PS5 配过“绕过代理”的 MAC 白名单，也不矛盾：让它继续绕过 ShellCrash 的通用链即可。这条规则插在 <code>PREROUTING</code> 顶部，专门把 TCP 443 送进 redir port；其余流量仍按原来的直连策略走。</p>

<h2 class="relative group">持久化比临时生效更重要
    <div id="持久化比临时生效更重要" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%8c%81%e4%b9%85%e5%8c%96%e6%af%94%e4%b8%b4%e6%97%b6%e7%94%9f%e6%95%88%e6%9b%b4%e9%87%8d%e8%a6%81" aria-label="锚点">#</a>
    </span>
    
</h2>
<p>手工插进去的 <code>iptables</code> 规则会在重启、重载防火墙或 ShellCrash 重新初始化后消失。我的做法是把脚本放在 ShellCrash 的任务目录，并让启动和防火墙钩子都调用它：</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">/userdisk/data/ShellCrash/task/ps5-minecraft-hybrid-proxy.sh
</span></span><span class="line"><span class="cl">/userdisk/data/ShellCrash/task/afstart
</span></span><span class="line"><span class="cl">/userdisk/data/ShellCrash/task/affirewall</span></span></code></pre></div></div>
<p>不同固件的目录或钩子名可能不同，重点不是硬抄路径，而是确认两件事：ShellCrash 启动后会执行一次，防火墙重载后也会执行一次。</p>
<p>每次改完，至少验证下面三项：</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">iptables -t nat -vnL PREROUTING
</span></span><span class="line"><span class="cl">ip6tables -t nat -vnL PREROUTING
</span></span><span class="line"><span class="cl">ss -lntp <span class="p">|</span> grep <span class="m">7892</span></span></span></code></pre></div></div>
<p>应该能看到按 PS5 MAC 命中的 443 重定向规则，以及 redir port 正在监听。然后完全退出并重开 Minecraft；如果仍缓存旧会话，再重启 PS5。</p>

<h2 class="relative group">不要留下已经证伪的规则
    <div id="不要留下已经证伪的规则" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e4%b8%8d%e8%a6%81%e7%95%99%e4%b8%8b%e5%b7%b2%e7%bb%8f%e8%af%81%e4%bc%aa%e7%9a%84%e8%a7%84%e5%88%99" aria-label="锚点">#</a>
    </span>
    
</h2>
<p>排查期间试过 DNS 改写、端口转发和局域网服务器重定向。确认它们不是当前问题后，应当全部删掉，而不是“先留着也许有用”。特别是把 UDP 19132 DNAT 到局域网某台机器的规则：一旦目标服务没有运行，它会制造一个很像网络故障的黑洞。</p>
<p>最后留下的配置只有一句话：<strong>微软控制面走代理，Minecraft UDP、DNS 和局域网流量保持直连。</strong></p>
<p>这种混合路由比“关 IPv6”或“整机代理”更容易解释，也更容易回滚。以后如果症状变化，只要抓包先判断它卡在授权 HTTPS 还是已经进入 UDP 游戏流，再决定该动哪一层。</p>
]]></content:encoded>
      
    </item>
    
  </channel>
</rss>
