<?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>Networking on Frank&#39;s Blog</title>
    <link>https://frankblogs.com/tags/networking/</link>
    <description>Recent content in Networking on Frank&#39;s Blog</description>
    <generator>Hugo -- 0.150.0</generator>
    <language>en-us</language>
    <lastBuildDate>Fri, 10 Oct 2025 21:39:48 +0800</lastBuildDate>
    <atom:link href="https://frankblogs.com/tags/networking/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Service Deployment &amp; Advanced Troubleshooting on iStoreOS</title>
      <link>https://frankblogs.com/posts/article-6/</link>
      <pubDate>Fri, 10 Oct 2025 21:39:48 +0800</pubDate>
      <guid>https://frankblogs.com/posts/article-6/</guid>
      <description>With iStoreOS running stably on my N100 Proxmox setup, it was time to deploy AdGuard Home, Tailscale, and troubleshoot lingering issues like speed bottlenecks and remote access failures. This is where the real power of the platform shone.</description>
      <content:encoded><![CDATA[<p>My N100 soft router was finally running a stable router OS – iStoreOS – within a Proxmox VE virtual machine. The core networking was solid. Now came the rewarding part: deploying the services I actually wanted and tackling the inevitable advanced troubleshooting challenges.</p>
<h2 id="adguard-home-taming-the-dns-loop">AdGuard Home: Taming the DNS Loop</h2>
<p>Installing AdGuard Home (AGH) via the iStoreOS app store was straightforward. The initial setup wizard (<code>:3000</code>) guided me through setting ports. I changed AGH&rsquo;s DNS port to <code>:5353</code> to avoid conflict with iStoreOS&rsquo;s built-in <code>dnsmasq</code> (running on <code>:53</code>).</p>
<p>The goal: <code>Clients -&gt; iStoreOS (dnsmasq :53) -&gt; AdGuard Home (:5353) -&gt; Public DNS (e.g., 1.1.1.1)</code>.</p>
<p>Configuration involved:</p>
<ol>
<li><strong>dnsmasq:</strong> Set it to <em>not</em> forward upstream queries found in <code>/etc/resolv.conf</code>, and explicitly forward <em>all</em> queries to AGH listening on the loopback address: <code>server=127.0.0.1#5353</code>.</li>
<li><strong>AdGuard Home:</strong> Set its upstream DNS servers to Cloudflare/Google.</li>
<li><strong>DHCP:</strong> Configure iStoreOS&rsquo;s DHCP server (Option 6) to advertise the router&rsquo;s IP (<code>10.0.0.1</code>) as the DNS server for all clients.</li>
</ol>
<p>Initially, this resulted in DNS resolution failures and <code>context deadline exceeded</code> errors in the AGH logs. Diagnosis: a <strong>DNS loop</strong>. Dnsmasq was forwarding to AGH, but AGH, possibly due to a misconfiguration or startup order issue, was somehow trying to query dnsmasq back.</p>
<p>Adding to the confusion was a &ldquo;ghost configuration.&rdquo; I had initially tried installing AGH via a <code>curl</code> script before using the app store version. This seemed to leave conflicting settings. The breakthrough came almost accidentally: running the AdGuard Home binary directly from the command line with the <code>-s run</code> flag (<code>./AdGuardHome -s run</code>) triggered some kind of self-reset or reinitialization. After this, restarting the service properly allowed the correct DNS chain (<code>dnsmasq -&gt; AGH -&gt; Public</code>) to establish, and DNS resolution started working beautifully across my network.</p>
<h2 id="the-network-speed-crisis-a-virtualization-bottleneck">The Network Speed Crisis: A Virtualization Bottleneck</h2>
<p>With DNS filtering active, I ran a speed test. Disaster! My gigabit fiber connection, which previously delivered ~950 Mbps, was now capped at a measly <strong>400 Mbps</strong>.</p>
<p>The troubleshooting began:</p>
<ul>
<li><strong>Disable AdGuard Home:</strong> No change. DNS filtering wasn&rsquo;t the bottleneck.</li>
<li><strong>Check Physical Links:</strong> Used <code>ethtool eth0</code> and <code>ethtool eth1</code> within the iStoreOS VM to confirm the virtual NICs were negotiating at 2500 Mbps with the PVE bridges. Links were fine.</li>
<li><strong>Enable Software Flow Offloading:</strong> Toggled this common OpenWrt optimization. No significant change.</li>
</ul>
<p>The problem had to lie deeper, likely within the virtualization layer itself. Research pointed towards a common issue with high-speed networking in VMs: the CPU struggling to handle the sheer volume of network packets being processed by a single core for the virtual NIC.</p>
<h3 id="the-solution-multiqueue">The Solution: Multiqueue</h3>
<p>Proxmox VE (and the underlying KVM/QEMU) supports a feature called <strong>Multiqueue VirtIO-Net</strong>. This allows the network packet processing load for a virtual NIC to be spread across multiple vCPU cores assigned to the VM.</p>
<ol>
<li>Shut down the iStoreOS VM.</li>
<li>In the PVE web UI, go to the VM&rsquo;s &ldquo;Hardware&rdquo; tab.</li>
<li>Select the VirtIO network device corresponding to the <strong>LAN</strong> interface (<code>net0</code> in my case, connected to <code>vmbr1</code>).</li>
<li>Click &ldquo;Edit&rdquo;.</li>
<li>Check the <strong>&ldquo;Multiqueue&rdquo;</strong> box.</li>
<li>Set the &ldquo;Queues&rdquo; number equal to the number of vCPU cores assigned to the VM (e.g., if you gave it 4 cores, set Queues to 4).</li>
<li>Repeat steps 3-6 for the <strong>WAN</strong> network device (<code>net1</code>, connected to <code>vmbr0</code>).</li>
<li>Start the iStoreOS VM.</li>
</ol>
<p>Ran the speed test again. Success! Speeds jumped right back up to the ~950 Mbps range. The virtualization bottleneck was eliminated.</p>
<h2 id="tailscale-triumph-conquering-remote-access">Tailscale Triumph: Conquering Remote Access</h2>
<p>My final major goal was setting up remote access, primarily to manage services like my NAS (planned OMV VM) and potentially the router itself when away from home. I opted for <strong>Tailscale</strong> due to its ease of use and availability in the iStoreOS app store.</p>
<p>Installation was simple. Following the command-line instructions (<code>tailscale up --advertise-routes=10.0.0.0/24</code>) connected the router to my Tailnet and advertised my home LAN subnet. However, while the router appeared online in the Tailscale admin console, I couldn&rsquo;t access <em>any</em> devices on my home LAN (like <code>10.0.0.1</code>) from my phone connected via Tailscale.</p>
<h3 id="troubleshooting-round-1-firewall">Troubleshooting Round 1: Firewall</h3>
<p>Pinging <code>10.0.0.1</code> from my phone resulted in &ldquo;Destination Port Unreachable.&rdquo; This screamed <strong>firewall</strong>. iStoreOS hadn&rsquo;t automatically created a firewall zone or rules for the new <code>tailscale0</code> interface.</p>
<h3 id="troubleshooting-round-2-interface--zone">Troubleshooting Round 2: Interface &amp; Zone</h3>
<p>Following guidance from GitHub issues, I manually edited <code>/etc/config/network</code> to define the <code>tailscale0</code> interface:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">config interface <span class="s1">&#39;tailscale&#39;</span>
</span></span><span class="line"><span class="cl">        option proto <span class="s1">&#39;none&#39;</span>
</span></span><span class="line"><span class="cl">        option device <span class="s1">&#39;tailscale0&#39;</span>
</span></span></code></pre></div><p>Then, in the LuCI Firewall settings (<code>Network -&gt; Firewall</code>), I:</p>
<ol>
<li>Created a new firewall zone named <code>tailscale</code>.</li>
<li>Set its Input/Output/Forward policies to <code>ACCEPT</code>.</li>
<li>Assigned the <code>tailscale0</code> network interface to this zone.</li>
<li>Crucially, created a <strong>Forwarding rule</strong> allowing traffic from the <code>tailscale</code> zone to the <code>lan</code> zone.</li>
</ol>
<p>Saved and applied. Tried connecting again. The &ldquo;Port Unreachable&rdquo; error was gone, but now attempts to access <code>10.0.0.1</code>just&hellip; hung. Loading indefinitely.</p>
<h3 id="troubleshooting-round-3-mtumss">Troubleshooting Round 3: MTU/MSS</h3>
<p>This new symptom – indefinite loading – strongly suggested an <strong>MTU (Maximum Transmission Unit)</strong> mismatch problem, common with VPNs and tunnels like Tailscale. Packets were likely getting fragmented or dropped because their size exceeded what the tunnel could handle. The standard fix is <strong>MSS Clamping (Maximum Segment Size)</strong>, where the router rewrites TCP packet headers to request smaller segment sizes.</p>
<h3 id="the-final-fix-iptables-mss-clamping">The Final Fix: iptables MSS Clamping</h3>
<p>Added the following rules via <code>Network -&gt; Firewall -&gt; Custom Rules</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Tailscale MSS Clamping for IPv4</span>
</span></span><span class="line"><span class="cl">iptables -t mangle -A FORWARD -o tailscale0 -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Tailscale MSS Clamping for IPv6 (if using IPv6 with Tailscale)</span>
</span></span><span class="line"><span class="cl">ip6tables -t mangle -A FORWARD -o tailscale0 -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
</span></span></code></pre></div><p>Restarted the firewall. Tried accessing <code>10.0.0.1</code> from my phone via Tailscale one last time.</p>
<p><strong>Victory!</strong> The iStoreOS login page loaded instantly. Remote access was finally conquered.</p>
<h2 id="conclusion-a-system-forged-in-debugging">Conclusion: A System Forged in Debugging</h2>
<p>This journey, from a simple IPv6 issue to a fully virtualized N100 soft router with custom services and robust remote access, was far more challenging than I initially anticipated. Every step seemed to uncover a new problem, requiring deep dives into networking concepts, Linux internals, and virtualization quirks.</p>
<p>However, each problem solved solidified my understanding and resulted in a final system that is incredibly powerful, stable, and perfectly tailored to my needs. The N100 platform with Proxmox and iStoreOS has proven to be an outstanding foundation. The debugging war is over, and the era of enjoying a truly capable home lab has begun.</p>
]]></content:encoded>
    </item>
    <item>
      <title>The Router VM Saga: OpenWrt vs. iStoreOS &amp; The Great Migration</title>
      <link>https://frankblogs.com/posts/article-5/</link>
      <pubDate>Mon, 06 Oct 2025 21:32:45 +0800</pubDate>
      <guid>https://frankblogs.com/posts/article-5/</guid>
      <description>With PVE running, it was time to create the router VM. This post details my struggles with vanilla OpenWrt, the dependency hell, and the eventual, crucial decision to migrate to the pre-integrated iStoreOS.</description>
      <content:encoded><![CDATA[<p>My Proxmox VE (PVE) hypervisor was installed and the host networking configured on my N100 box. Now it was time to create the core component: the virtual machine that would act as my main home router. My initial plan was to use vanilla <strong>OpenWrt</strong>, the classic, highly customizable Linux distribution for routers.</p>
<h2 id="act-i-the-struggles-with-vanilla-openwrt">Act I: The Struggles with Vanilla OpenWrt</h2>
<p>Creating the VM in PVE (giving it VM ID 100) involved several steps:</p>
<ol>
<li><strong>Download Firmware:</strong> Get the official OpenWrt x86-64 combined-ext4 image (<code>.img.gz</code>).</li>
<li><strong>Upload &amp; Import:</strong> Upload the <code>.img.gz</code> file to PVE (e.g., via SCP or the web UI&rsquo;s storage browser – note: uploading directly as an ISO image type fails). Import the disk image into the VM using <code>qm importdisk 100 openwrt.img.gz local-lvm</code>.</li>
<li><strong>VM Hardware Config:</strong> Assign CPU cores, RAM. Remove the default SCSI disk. Attach the imported OpenWrt disk as a VirtIO block device. Add two VirtIO network cards – one connected to PVE&rsquo;s <code>vmbr0</code> (WAN) and one to <code>vmbr1</code> (LAN). Set the boot order to use the OpenWrt disk.</li>
<li><strong>Disk Resizing:</strong> The default image is tiny. Resize the virtual disk in PVE&rsquo;s hardware tab. Boot the VM with a GParted Live ISO attached, use GParted to expand the OpenWrt partition to fill the larger virtual disk.</li>
<li><strong>Initial Network Config:</strong> Boot OpenWrt. Access the console (via PVE&rsquo;s web UI or <code>qm terminal 100</code> - not <code>qm console</code>). Use the <code>vi</code> editor to modify <code>/etc/config/network</code>, changing the LAN interface&rsquo;s IP address to <code>10.0.0.1</code>.</li>
</ol>
<p>So far, so good. I could access the OpenWrt LuCI web interface at <code>10.0.0.1</code>. I configured PPPoE on <code>eth1</code> (WAN, connected to <code>vmbr0</code>) and set up the LAN interface (<code>eth0</code>, connected to <code>vmbr1</code>) with DHCP and IPv6 server settings. Basic routing worked!</p>
<h3 id="the-dependency-hell">The Dependency Hell</h3>
<p>The problems began when I tried to customize OpenWrt by installing packages. My goal was simple: install <code>luci-app-adguardhome</code>. But <code>opkg update</code> often failed to connect to the repositories. When it did connect, attempting to install AdGuard Home resulted in a cascade of errors about <strong>incompatible architectures</strong> or missing dependencies (<code>luci-lua-runtime</code> was a frequent culprit). Even manually downloading <code>.ipk</code> packages failed with similar architecture errors.</p>
<p>I spent hours trying different package versions, compiling dependencies, and scouring forums. I even managed to &ldquo;force install&rdquo; some packages, but this led to a broken LuCI interface – the &ldquo;Services&rdquo; menu simply wouldn&rsquo;t appear, despite the package seemingly being installed.</p>
<p>[<strong>Placeholder: Add a screenshot of the terminal showing the <code>opkg</code> errors or the LuCI interface missing the Services menu.</strong>]</p>
<p>Clearing LuCI caches (<code>rm /tmp/luci-indexcache</code>) did nothing. Log files (<code>logread</code>) showed no obvious errors. File permissions seemed correct. The final nail in the coffin was a detailed error log clearly stating that key LuCI components and their dependencies were fundamentally incompatible with the base system. Trying to manually build a complex setup on vanilla OpenWrt felt like assembling a car from mismatched parts found in a junkyard.</p>
<h2 id="act-ii-the-turn-towards-istoreos">Act II: The Turn Towards iStoreOS</h2>
<p>Frustrated and realizing the &ldquo;DIY package management&rdquo; route was unsustainable, I revisited earlier advice: use a <strong>pre-integrated firmware</strong> like <strong>iStoreOS</strong>. Based on OpenWrt but comes with a user-friendly interface and, crucially, a curated app store where dependencies <em>should</em> just work.</p>
<h3 id="the-migration-plan">The Migration Plan</h3>
<p>The challenge: perform this migration without disrupting my family&rsquo;s internet access for too long.</p>
<ol>
<li><strong>Preparation:</strong> In PVE, create a <em>new</em> VM (e.g., VM ID 101) for iStoreOS. Download the iStoreOS x86 <code>.img.gz</code> firmware.</li>
<li><strong>Import &amp; Basic Config:</strong> Upload and import the iStoreOS disk into VM 101. Configure its hardware similarly to the OpenWrt VM (CPU, RAM, 2x VirtIO NICs connected to <code>vmbr0</code> and <code>vmbr1</code>).</li>
<li><strong>Offline Config Attempt (Failed):</strong> Boot VM 101 with GParted. Try to mount the iStoreOS partition to change the default IP (<code>192.168.100.1</code>) to <code>10.0.0.1</code> offline. <strong>Failure!</strong> GParted couldn&rsquo;t identify the filesystem. Manual <code>mount</code> commands failed, complaining about unknown filesystem types or missing superblocks. Offline config was impossible.</li>
<li><strong>The Switch:</strong> Plan B - configure online. Physically disconnect the WAN cable from the N100. Shut down the old OpenWrt VM (100). Start the new iStoreOS VM (101). Set my Mac&rsquo;s IP statically to <code>192.168.100.5</code>. Connect my Mac to one of the N100&rsquo;s LAN ports (connected to <code>vmbr1</code>). Try accessing <code>192.168.100.1</code>.</li>
</ol>
<h3 id="the-wanlan-inversion-twist">The WAN/LAN Inversion Twist</h3>
<p>Failure again! <code>192.168.100.1</code> was unreachable. In a moment of desperation (or maybe just random plugging), I moved my Mac&rsquo;s cable to the N100 port I had designated for <strong>WAN</strong> (connected to <code>vmbr0</code>). And&hellip; success! I reached the iStoreOS login page.</p>
<p><strong>Diagnosis:</strong> iStoreOS had, for some reason, <strong>reversed</strong> the network interface identification compared to OpenWrt. It saw <code>eth0</code> (connected to PVE&rsquo;s <code>vmbr1</code>, my LAN bridge) as its <em>WAN</em> interface, and <code>eth1</code> (connected to PVE&rsquo;s <code>vmbr0</code>, my WAN bridge) as its <em>LAN</em> interface, assigning the <code>192.168.100.1</code> address there.</p>
<p><strong>Resolution:</strong> Logged into iStoreOS via the &ldquo;wrong&rdquo; port. Navigated to <code>Network -&gt; Interfaces</code>. Edited the LAN and WAN interfaces, <strong>swapping</strong> their assigned physical devices (<code>eth0</code> &lt;-&gt; <code>eth1</code>). Saved and applied. Moved my Mac&rsquo;s cable back to a correct LAN port. Set my Mac back to DHCP. Accessed <code>192.168.100.1</code> (the default iStore IP). Success! Changed the iStoreOS LAN IP to <code>10.0.0.1</code>. Plugged the WAN cable back into the N100&rsquo;s WAN port.</p>
<p>The network migration was complete in under 15 minutes. The foundation was finally stable. iStoreOS provided the pre-packaged environment I needed. Now, it was time to deploy the services that started this whole journey.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Proxmox VE Initiation: Taming the Virtualization Hypervisor</title>
      <link>https://frankblogs.com/posts/article-4/</link>
      <pubDate>Wed, 01 Oct 2025 21:30:18 +0800</pubDate>
      <guid>https://frankblogs.com/posts/article-4/</guid>
      <description>With my N100 soft router hardware assembled, the next step was installing Proxmox VE (PVE). This post covers the installation process and my first major challenge: configuring PVE networking without losing access.</description>
      <content:encoded><![CDATA[<p>The N100 hardware for my new soft router/home server was assembled and ready. The grand vision involved virtualization, allowing this single machine to run my router, NAS, and potentially other services simultaneously. The chosen foundation for this was <strong>Proxmox Virtual Environment (PVE)</strong>, a powerful, open-source hypervisor based on Debian Linux.</p>
<h2 id="installing-pve-the-first-hurdle">Installing PVE: The First Hurdle</h2>
<p>Installing PVE itself is relatively straightforward, similar to installing any Linux distribution:</p>
<ol>
<li><strong>Create Installation Media:</strong> Download the PVE ISO image. On my Mac, I used <strong>Balena Etcher</strong> to write the ISO to a USB drive. My first attempt failed – turns out the old USB drive I grabbed was faulty. A newer drive worked perfectly.</li>
<li><strong>Boot from USB:</strong> Connect a monitor and keyboard to the N100 box, plug in the USB drive, and boot into the BIOS/UEFI settings (usually by pressing DEL or F2 during startup). Set the USB drive as the primary boot device.</li>
<li><strong>PVE Installer:</strong> Follow the graphical installer prompts. Key settings during installation:
<ul>
<li>Target Hard Disk: Select the Fanxiang NVMe SSD.</li>
<li>Location/Timezone: Set appropriately.</li>
<li>Hostname: Set to something memorable, like <code>pve.local</code>.</li>
<li>Network Configuration: <strong>Crucially</strong>, assign a <strong>static IP address</strong> for PVE&rsquo;s management interface (e.g., <code>10.0.0.2</code>), along with the gateway (<code>10.0.0.1</code> - my eventual router VM&rsquo;s address) and DNS servers. I chose one of the four physical ports (e.g., <code>enp1s0</code>) for this initial management access.</li>
</ul>
</li>
</ol>
<p>The installation completed smoothly, and PVE rebooted. I could access the command line directly on the N100, and more importantly, access the web UI from my Mac at <code>https://10.0.0.2:8006</code>. Stage one complete!</p>
<h2 id="the-networking-nightmare-reconfiguring-for-vms">The Networking Nightmare: Reconfiguring for VMs</h2>
<p>PVE&rsquo;s default network setup uses one physical port (<code>enp1s0</code> in my case) solely for its own management. However, to allow my <em>virtual machines</em> (like the router VM) to connect to both the internet (WAN) and my home network (LAN), I needed to create <strong>Linux Bridges</strong>.</p>
<p>My plan:</p>
<ul>
<li><code>vmbr0</code>: Use a different physical port (e.g., <code>enp2s0</code>) for the <strong>WAN</strong> connection (connecting to my ISP modem).</li>
<li><code>vmbr1</code>: Use the remaining two physical ports (e.g., <code>enp3s0</code>, <code>enp4s0</code>) bridged together for the <strong>LAN</strong> connection (connecting to my home switch).</li>
<li><strong>Crucially:</strong> Move PVE&rsquo;s <em>own</em> management interface from the physical port <code>enp1s0</code> onto the newly created <strong>LAN bridge (<code>vmbr1</code>)</strong>. This way, I could manage PVE from any computer on my home network using the <code>10.0.0.2</code> address, freeing up <code>enp1s0</code> perhaps for other uses.</li>
</ul>
<p>This reconfiguration is done by editing the <code>/etc/network/interfaces</code> file directly via the PVE console (or SSH). I carefully modified the file, creating the bridge definitions and changing the management interface settings.</p>
<p>I applied the changes (<code>systemctl restart networking</code> or a reboot). And then&hellip; disaster.</p>
<p>I could no longer access the PVE web UI at <code>10.0.0.2</code>. Pings failed. It seemed I had completely locked myself out.</p>
<h2 id="troubleshooting-in-the-dark">Troubleshooting in the Dark</h2>
<p>Panic set in. Had I made a typo in the config file? Did the bridge fail to come up? I had to go back to the &ldquo;direct connection&rdquo; method: plug a monitor and keyboard directly into the N100 box.</p>
<p>Logging into the PVE console, I ran <code>ip a</code> to check the network interface status. The output revealed the problem: <code>vmbr1</code> (my intended LAN bridge and new management interface) <strong>had no IP address</strong>. My configuration changes hadn&rsquo;t been applied correctly, or something had gone wrong during the network restart.</p>
<p>Carefully re-examining <code>/etc/network/interfaces</code> line by line, I eventually spotted the error – perhaps a typo, a missing <code>auto vmbr1</code>, or incorrect bridge port settings. I corrected the file using the <code>nano</code> editor (a bit friendlier than <code>vi</code> for quick edits).</p>
<p>After saving the corrected file and restarting the networking service again (<code>systemctl restart networking</code>), I ran <code>ip a</code> one more time. Success! <code>vmbr1</code> now showed the correct <code>10.0.0.2</code> address.</p>
<p>Back on my Mac, I refreshed <code>https://10.0.0.2:8006</code>, and the Proxmox login screen reappeared. Access restored!</p>
<p>This harrowing experience was my first real taste of configuring Linux networking and the importance of meticulousness when editing critical system files. With the PVE host networking finally stable, I was ready for the main event: creating the virtual machine that would become my new home router.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Entering the World of x86 Soft Routers: Choosing the N100 Beast</title>
      <link>https://frankblogs.com/posts/article-3/</link>
      <pubDate>Thu, 25 Sep 2025 21:21:37 +0800</pubDate>
      <guid>https://frankblogs.com/posts/article-3/</guid>
      <description>After failed attempts with consumer routers, I decided to take the plunge into the world of x86 soft routers. This post covers the decision process, comparing platforms like N5105 and N100, and my final hardware selection.</description>
      <content:encoded><![CDATA[<p>My journey to achieve reliable home networking, particularly stable IPv6, had hit roadblocks with both my ISP&rsquo;s modem and a powerful-but-faulty Netgear R8000 running OpenWrt. It became clear that consumer-grade hardware, even with custom firmware, might not offer the raw power, flexibility, and reliability I craved. It was time to explore the next level: <strong>x86 Soft Routers</strong>.</p>
<h2 id="what-is-a-soft-router">What is a Soft Router?</h2>
<p>Unlike traditional &ldquo;hard&rdquo; routers with proprietary hardware and software, a soft router is essentially a small, dedicated PC running a specialized router operating system (like OpenWrt, pfSense, OPNsense, or RouterOS). The &ldquo;x86&rdquo; refers to the standard PC processor architecture (Intel/AMD), offering significantly more power and flexibility than the ARM or MIPS chips found in most consumer routers.</p>
<h2 id="the-allure-of-x86">The Allure of x86</h2>
<p>The potential benefits were immense:</p>
<ul>
<li><strong>Raw Performance:</strong> Capable of handling gigabit+ speeds with complex firewall rules, VPNs, and traffic shaping without breaking a sweat.</li>
<li><strong>Flexibility:</strong> Run virtually any router OS or even standard Linux distributions.</li>
<li><strong>Expandability:</strong> Add more RAM, faster storage, or even specialized network cards.</li>
<li><strong>Virtualization:</strong> This was the game-changer. An x86 platform could potentially run <em>multiple</em> operating systems simultaneously using a hypervisor like Proxmox VE (PVE). I could have my router, a NAS, a media server, and more, all running on one efficient box.</li>
</ul>
<h2 id="choosing-the-platform-n5105j4125-vs-n100">Choosing the Platform: N5105/J4125 vs. N100</h2>
<p>My research focused on popular low-power x86 chips commonly used in mini PCs and soft routers:</p>
<ul>
<li><strong>Older Generation (Jasper Lake N5105, Celeron J4125):</strong> Widely available, often cheaper, proven platforms. Decent performance for routing and light server tasks.</li>
<li><strong>New Generation (Alder Lake-N N100):</strong> Significant performance uplift (especially single-core, crucial for routing), much better integrated graphics (useful for PVE console/light desktop tasks), generally more power-efficient, supports faster DDR5 RAM. Often comes paired with newer <strong>Intel i226-V 2.5GbE</strong> network controllers, known for better driver support and stability compared to the sometimes-problematic Realtek chips found in cheaper units.</li>
</ul>
<p>Given the relatively small price difference for new units and the significant performance and efficiency gains, the <strong>Intel N100</strong> quickly became the clear winner for future-proofing.</p>
<h2 id="navigating-the-hardware-maze">Navigating the Hardware Maze</h2>
<p>Choosing the N100 platform opened up a dizzying array of options, mostly from Chinese manufacturers like Beikong (Topton/Kingnovy), CWWK, etc., often sold as barebones systems (no RAM/SSD). Key considerations:</p>
<ul>
<li><strong>Ports:</strong> How many? What speed? The standard was 4x 2.5GbE Intel i226-V ports, perfect for high-speed LAN and future ISP upgrades. Some offered 2x 2.5GbE + 2x 10GbE SFP+ (fiber) – tempting, but overkill and more expensive for my current needs.</li>
<li><strong>Cooling:</strong> Passive (fanless) is preferred for silent operation, requiring a well-designed chassis.</li>
<li><strong>RAM/SSD:</strong> DDR5 SO-DIMM and NVMe M.2 slots were standard.</li>
<li><strong>Price:</strong> Barebones N100 boxes with 4x 2.5GbE ports were readily available.</li>
<li><strong>Used Market:</strong> While tempting for cost savings, diagnosing potential issues on used hardware felt risky after my R8000 experience.</li>
</ul>
<h2 id="my-final-choice-beikong-h30w-n100">My Final Choice: Beikong H30W (N100)</h2>
<p>After much comparison, I settled on a brand new <strong>Beikong H30W N100 barebones</strong> unit featuring:</p>
<ul>
<li>Intel N100 Processor</li>
<li>4x Intel i226-V 2.5GbE ports</li>
<li>Passive cooling chassis</li>
<li>DDR5 SO-DIMM slot</li>
<li>NVMe M.2 slot</li>
</ul>
<p>To complete the build with maximum cost-effectiveness:</p>
<ul>
<li><strong>RAM:</strong> I salvaged a compatible 16GB DDR5 stick from an old laptop – a huge saving!</li>
<li><strong>SSD:</strong> I purchased a new, budget-friendly but well-regarded <strong>Fanxiang S500 Pro 256GB NVMe SSD</strong>. Plenty of space for PVE and multiple VMs.</li>
</ul>
<h2 id="the-grand-vision-virtualization">The Grand Vision: Virtualization</h2>
<p>With the hardware assembled, the real excitement began. This N100 wasn&rsquo;t just going to be a router. It was going to be the heart of my home lab. The plan: install <strong>Proxmox VE (PVE)</strong> as the bare-metal hypervisor, then create virtual machines for:</p>
<ol>
<li><strong>OpenWrt/iStoreOS:</strong> My primary router, firewall, and network manager.</li>
<li><strong>OpenMediaVault (OMV):</strong> A NAS for file storage and backups.</li>
<li><strong>Future Possibilities:</strong> Home Assistant, AdGuard Home, a web server, maybe even AI experiments?</li>
</ol>
<p>This N100 box represented a convergence of all my needs and aspirations. The hardware was ready. Now came the software challenge: installing and taming the Proxmox hypervisor.</p>
]]></content:encoded>
    </item>
    <item>
      <title>The IPv6 Nightmare and the Double NAT Trap: My Quest for True Connectivity</title>
      <link>https://frankblogs.com/posts/article-1/</link>
      <pubDate>Thu, 18 Sep 2025 19:57:57 +0800</pubDate>
      <guid>https://frankblogs.com/posts/article-1/</guid>
      <description>My journey began with a simple problem: my ISP router wouldn&amp;#39;t give my devices public IPv6 addresses. Little did I know it would lead me down a rabbit hole of Prefix Delegation failures, Double NAT, and CGNAT.</description>
      <content:encoded><![CDATA[<p>It all started with a seemingly simple problem. My home network, centered around a Xiaomi AX6000 router running its stock firmware, was supposed to support IPv6. I had enabled it, and indeed, the router&rsquo;s WAN port proudly displayed a public IPv6 address. Yet, none of my devices – my computers, my phone, my game consoles – could get one. Accessing IPv6-only websites was impossible.</p>
<h2 id="diving-deep-into-ipv6-and-network-structure">Diving Deep into IPv6 and Network Structure</h2>
<p>After some initial head-scratching, research pointed towards a concept called <strong>Prefix Delegation (PD)</strong>. In simple terms, my ISP assigns a block (prefix) of IPv6 addresses to my router, and the router is then responsible for distributing individual addresses from that block to my devices. The symptom – WAN gets an address, LAN doesn&rsquo;t – strongly suggested PD was failing.</p>
<p>Why? The prime suspect became my <strong>ISP&rsquo;s modem (Optical Network Terminal or ONT)</strong>. Was it running in router mode instead of bridge mode? If the modem itself was acting as a router and didn&rsquo;t properly support delegating the prefix downstream, my AX6000 would never receive the necessary block.</p>
<p>I confirmed my network topology: ONT (in router mode) -&gt; Switch -&gt; Multiple Routers (including the AX6000). Unfortunately, due to other devices directly connected to the ONT via the switch, simply switching the ONT to bridge mode wasn&rsquo;t feasible without restructuring everything.</p>
<p>As a temporary workaround, I enabled <strong>NAT6</strong> on the AX6000. Success! My devices could now access IPv6 websites. However, I knew this wasn&rsquo;t <em>true</em> end-to-end IPv6. NAT6 essentially translates internal IPv6 addresses, similar to how traditional NAT works for IPv4. It solved the immediate browsing issue but didn&rsquo;t address the underlying PD failure and wouldn&rsquo;t help with services requiring direct public IPv6 reachability.</p>
<h2 id="enter-the-double-nat-monster">Enter the Double NAT Monster</h2>
<p>Around the same time, my Xbox started complaining: &ldquo;Double NAT detected.&rdquo; This made perfect sense. My network traffic was going through two layers of Network Address Translation: first at the AX6000, and then again at the ISP&rsquo;s ONT (which was also acting as a router). This configuration is notorious for causing issues with online gaming, peer-to-peer connections, and services requiring open ports.</p>
<p>We discussed potential mitigations like UPnP, manual port forwarding, and placing the AX6000 in the ONT&rsquo;s DMZ, but none felt like a clean solution.</p>
<h2 id="the-cgnat-revelation">The CGNAT Revelation</h2>
<p>The real blow came when investigating the Double NAT further. By comparing the WAN IP address shown on my ONT&rsquo;s status page with the public IP address reported by websites like &ldquo;whatismyip.com&rdquo;, I confirmed a dreaded reality: I was behind <strong>Carrier-Grade NAT (CGNAT)</strong>. My ISP wasn&rsquo;t assigning my ONT a unique, public IPv4 address. Instead, I was sharing one with potentially hundreds of other customers.</p>
<p>[<strong>Placeholder: Add a screenshot here showing the discrepancy between your ONT&rsquo;s WAN IP (likely a private 10.x or 100.x address) and your public IP, confirming CGNAT.</strong>]</p>
<p>This revelation made two things crystal clear:</p>
<ol>
<li>Solving the Xbox NAT issue reliably via IPv4 was going to be nearly impossible without resorting to complex (and often unreliable) tunneling solutions.</li>
<li>Getting <strong>native, public IPv6</strong> working correctly was no longer just desirable; it was <strong>essential</strong> for any kind of future-proof home networking or self-hosting.</li>
</ol>
<h2 id="back-to-the-ipv6-root-the-faulty-ont">Back to the IPv6 Root: The Faulty ONT</h2>
<p>With renewed focus, the investigation circled back to the ONT. I confirmed the ONT itself <em>was</em> receiving a <code>/64</code> or similar public IPv6 prefix starting with <code>240e:</code>. The problem was solely its inability to delegate this prefix downstream.</p>
<p>Analyzing the ONT&rsquo;s configuration page revealed a peculiar &ldquo;Port Binding&rdquo; setting. Initially, only LAN1 was bound for internet services.</p>
<p>I modified the settings to bind <em>all</em> LAN ports. Hope surged&hellip; but was quickly dashed. Even after ensuring all ports were bound, testing with the AX6000 and other routers on different ports yielded the same result: no PD, no LAN-side public IPv6.</p>
<p>The conclusion was unavoidable: the ONT&rsquo;s Prefix Delegation functionality was faulty, likely due to a hardware limitation or firmware bug. Relying on it was a dead end.</p>
<p>I needed a router powerful and flexible enough to potentially work around the ONT&rsquo;s limitations, or perhaps even replace its routing functions altogether. This led me to revisit an old piece of hardware sitting in my closet&hellip; a supposedly bricked Netgear R8000 running OpenWrt. Could it be resurrected?</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
