<?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>Gaming on Code is cheap, let&#39;s talk</title>
    <link>https://blog.ferstar.org/en/tags/gaming/</link>
    <description>Code is cheap, let&#39;s talk</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <copyright>Copyright 2026 ferstar</copyright>
    <lastBuildDate>Thu, 16 Jul 2026 10:00:00 +0800</lastBuildDate>
    <ttl>60</ttl><atom:link href="https://blog.ferstar.org/en/tags/gaming/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 Stuck on Loading: Split Microsoft HTTPS from Game UDP</title>
      <link>https://blog.ferstar.org/en/posts/ps5-minecraft-hybrid-routing/</link>
      <pubDate>Thu, 16 Jul 2026 10:00:00 +0800</pubDate>
      
      <guid isPermaLink="true">https://blog.ferstar.org/en/posts/ps5-minecraft-hybrid-routing/</guid>
      <description>Minecraft on a PS5 stayed on the loading screen; packet capture showed slow Microsoft/Azure HTTPS setup, and proxying only TCP 443 while keeping DNS and UDP 19132 direct fixed it.</description><content:encoded><![CDATA[<blockquote><p>I am not a native English speaker; this article was translated by AI.</p>
</blockquote><p>The symptom looked like “Minecraft multiplayer is broken”: the PS5 had Internet access, the store and account did not show an error, but Minecraft would often sit on the loading screen for a long time when opening server or online-related pages.</p>
<p>The obvious suspects were DNS, IPv6, BedrockConnect, and even a Geyser instance on the LAN. None was the root cause.</p>
<p>The fix was small: <strong>proxy TCP 443 only for this PS5 through ShellCrash; keep DNS and Minecraft UDP 19132 direct.</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">Do not rush to change DNS
    <div id="do-not-rush-to-change-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="#do-not-rush-to-change-dns" aria-label="Anchor">#</a>
    </span>
    
</h2>
<p>BedrockConnect solves an entry-point problem: how to enter a custom server on console Bedrock. It is not a general fix for slow Minecraft loading. DNS rewriting by the router, a transparent proxy, or IPv6 can certainly make it fail; but in this case the loading problem remained even after returning to default DNS.</p>
<p>Do not proxy the entire PS5 first, either. Minecraft’s control plane and game data plane are different:</p>
<ul>
<li>sign-in, authorization, skins, and resource downloads are mostly TCP 443;</li>
<li>actual multiplayer game traffic is UDP; Bedrock commonly uses port 19132;</li>
<li>DNS is another independent variable.</li>
</ul>
<p>Global proxying looks convenient, but it can drag UDP, LAN discovery, and MTU issues into the problem at once. The debugging surface gets much larger.</p>

<h2 class="relative group">How this was narrowed down
    <div id="how-this-was-narrowed-down" 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="#how-this-was-narrowed-down" aria-label="Anchor">#</a>
    </span>
    
</h2>
<p>I checked three layers of evidence.</p>
<p>First, the router was not under load. Continuous Wi-Fi pings from the PS5 to the router had no loss and stayed within a few milliseconds. The LAN was not the bottleneck.</p>
<p>Second, direct HTTPS requests from the router to a Microsoft authorization endpoint completed over both IPv4 and IPv6. Microsoft services were not completely unreachable.</p>
<p>Third, packet capture during the loading stage showed DNS, TCP 443, and TLS traffic for Microsoft/Azure authorization and resource domains. It had not entered sustained Minecraft UDP game traffic. More importantly, after the PS5 sent a SYN, the SYN-ACK from Azure took more than a second to return.</p>
<p>That narrowed the issue from “the game server is unreachable” to “the direct path to Microsoft/Azure HTTPS is poor.” The router was healthy and game UDP had not started, so only that control-plane path needed optimization.</p>

<h2 class="relative group">Final rule: precise routing by MAC address
    <div id="final-rule-precise-routing-by-mac-address" 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="#final-rule-precise-routing-by-mac-address" aria-label="Anchor">#</a>
    </span>
    
</h2>
<p>Here is the smallest rule set for OpenWrt plus ShellCrash. Replace <code>PS5_MAC</code> with the PS5 MAC address and <code>REDIR_PORT</code> with ShellCrash’s redir port, the port actually listening on the router. The rules cover both IPv4 and 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>The script has three deliberate limits:</p>
<ol>
<li>It matches one device MAC address only, so other devices are unaffected.</li>
<li>It matches TCP 443 only and leaves UDP 19132 alone.</li>
<li>It deletes the old rule before inserting the new one, so repeated runs do not accumulate duplicates.</li>
</ol>
<p>It is also compatible with a ShellCrash MAC bypass for the PS5: leave the device bypassed from ShellCrash’s general chain. This rule sits at the top of <code>PREROUTING</code> and sends TCP 443 specifically to the redir port; all other traffic still follows the original direct-routing policy.</p>

<h2 class="relative group">Persistence matters more than a temporary success
    <div id="persistence-matters-more-than-a-temporary-success" 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="#persistence-matters-more-than-a-temporary-success" aria-label="Anchor">#</a>
    </span>
    
</h2>
<p>Manually inserted <code>iptables</code> rules disappear after a reboot, firewall reload, or ShellCrash reinitialization. I put the script in ShellCrash’s task directory and called it from both a startup and firewall hook:</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>Directory and hook names differ by firmware. The important part is not copying these paths literally: run the script once after ShellCrash starts and once after the firewall reloads.</p>
<p>After each change, verify at least these three things:</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>You should see a PS5-MAC-specific 443 redirect rule and a listening redir port. Then fully exit and reopen Minecraft; reboot the PS5 as well if it is still holding an old session.</p>

<h2 class="relative group">Remove rules that the evidence ruled out
    <div id="remove-rules-that-the-evidence-ruled-out" 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="#remove-rules-that-the-evidence-ruled-out" aria-label="Anchor">#</a>
    </span>
    
</h2>
<p>During diagnosis I tried DNS rewriting, port forwarding, and LAN server redirection. Once they were shown not to be the current cause, they should all be removed instead of being kept “just in case.” In particular, a rule that DNATs UDP 19132 to a LAN host becomes a black hole when that target service is not running, and it looks exactly like a network failure.</p>
<p>The final configuration is one sentence: <strong>proxy the Microsoft control plane; keep Minecraft UDP, DNS, and LAN traffic direct.</strong></p>
<p>This hybrid route is easier to explain and roll back than disabling IPv6 or proxying the whole console. If the symptoms change later, capture traffic first to see whether it is stuck on authorization HTTPS or has reached UDP game traffic, then change the matching layer only.</p>
]]></content:encoded>
      
    </item>
    
  </channel>
</rss>
