<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Wan on Dexome</title>
        <link>https://blog.dexome.com/tags/wan/</link>
        <description>Recent content in Wan on Dexome</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>en</language>
        <lastBuildDate>Thu, 30 Jul 2026 00:00:00 +0530</lastBuildDate><atom:link href="https://blog.dexome.com/tags/wan/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>Moving My PPPoE WAN to VLAN 999</title>
        <link>https://blog.dexome.com/post/migrate-live-isp-wan-without-lockout/</link>
        <pubDate>Thu, 30 Jul 2026 00:00:00 +0530</pubDate>
        
        <guid>https://blog.dexome.com/post/migrate-live-isp-wan-without-lockout/</guid>
        <description>&lt;p&gt;I wanted to move the WAN connection from a dedicated port on OPNsense to VLAN
999 through my Omada switch. This would allow both OPNsense nodes to reach the
same ONT connection and was needed for the HA setup.&lt;/p&gt;
&lt;p&gt;The PPPoE username, password and ONT were not changing. I had already configured
the VLAN and expected the Internet to be down only for the time needed to move
the cable and connect again.&lt;/p&gt;
&lt;p&gt;It did not work that way. The first connection failed because I had left the old
PPPoE session active at the ISP. Once I fixed that, the connection dropped again
because the Omada switch was sending loop-detection packets towards the ONT.&lt;/p&gt;
&lt;p&gt;This post covers both issues and the order I now use for a PPPoE cutover.&lt;/p&gt;
&lt;h2 id=&#34;the-setup&#34;&gt;The setup
&lt;/h2&gt;&lt;p&gt;The old topology was direct. The Syrotech GPON ONT connected to the bare-metal
OPNsense firewall&amp;rsquo;s &lt;code&gt;igc0&lt;/code&gt; interface. The new design moved that Ethernet segment
onto VLAN 999 through a TP-Link Omada TL-SG2008P, then carried the tag over a
trunk to OPNsense as &lt;code&gt;igc2_vlan999&lt;/code&gt;.&lt;/p&gt;
&lt;figure class=&#34;article-diagram&#34;&gt;
    &lt;pre class=&#34;mermaid&#34;&gt;
flowchart TB
	BEFORE[&#34;Before&lt;br/&gt;Syrotech ONT to OPNsense igc0 to PPPoE&#34;]
	AFTER[&#34;After&lt;br/&gt;Syrotech ONT to Omada TL-SG2008P to VLAN 999 to OPNsense igc2_vlan999 to PPPoE&#34;]
	BEFORE --&gt;|Move WAN onto the managed-switch trunk| AFTER
&lt;/pre&gt;
    &lt;figcaption&gt;The WAN migration inserted an Omada switch and VLAN 999 between the Syrotech ONT and OPNsense.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The VLAN setup looked correct. A test device on the same path could reach the
management IP of the ONT and packet captures showed the expected VLAN traffic.
So I pulled the cable from the old port, moved it and enabled the new interface.&lt;/p&gt;
&lt;p&gt;The connection never completed.&lt;/p&gt;
&lt;p&gt;Packet captures showed PADI discovery frames leaving the firewall, but the
expected PADO response did not come back. At other points the logs showed LCP
negotiation repeating with new magic numbers, never reaching a usable session.
It looked close enough to working to keep sending me down the wrong paths.&lt;/p&gt;
&lt;h2 id=&#34;checking-the-vlan-first&#34;&gt;Checking the VLAN first
&lt;/h2&gt;&lt;p&gt;VLANs are an obvious suspect because they can fail silently. An access port can
be untagged in the wrong VLAN, a trunk can omit the tag, or a native VLAN can
consume traffic that was supposed to remain tagged.&lt;/p&gt;
&lt;p&gt;I tested the transport independently of PPPoE. A client attached to the same
logical path could reach the optical terminal&amp;rsquo;s management network. Captures on
the firewall showed the expected Ethernet discovery frames on the expected VLAN.
That did not prove every switch behavior was correct, but it proved that this was
not simply a missing tag.&lt;/p&gt;
&lt;h2 id=&#34;checking-the-wan-mac&#34;&gt;Checking the WAN MAC
&lt;/h2&gt;&lt;p&gt;Many providers bind service to a router or ONT MAC address, so MAC locking was
the next theory. I tried preserving the previous WAN MAC and inspected the
provider-facing frames. It was a reasonable theory, but it did not explain the
behavior.&lt;/p&gt;
&lt;p&gt;Some ISPs lock the connection to a MAC address, so this was still worth checking.
There are three separate things which can cause a new router or port to fail:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Does the provider authenticate only with a username and password?&lt;/li&gt;
&lt;li&gt;Does it also remember the client MAC?&lt;/li&gt;
&lt;li&gt;Does it permit more than one simultaneous PPPoE session on the line?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;All three look similar from OPNsense. In my case, the third one was the problem.&lt;/p&gt;
&lt;h2 id=&#34;closing-the-old-pppoe-session&#34;&gt;Closing the old PPPoE session
&lt;/h2&gt;&lt;p&gt;I had moved the cable while PPPoE was still active. That is not a clean session
shutdown.&lt;/p&gt;
&lt;p&gt;A graceful PPPoE disconnect sends a PADT (PPPoE Active Discovery Terminate), or
terminates the link through PPP before removing the carrier. A cable pull sends
neither. From the ISP access concentrator&amp;rsquo;s point of view, the old session can
remain alive until its own timeout expires.&lt;/p&gt;
&lt;p&gt;The provider allowed one session on the line. My new firewall interface was not
replacing the old session; it was asking for a second one while the first still
existed upstream.&lt;/p&gt;
&lt;p&gt;That explained why waiting sometimes appeared to fix the problem. A long
power-off interval gave the stale session time to age out. It also explained why
rechecking credentials and VLAN tags accomplished nothing. The obstacle was not
in my current configuration at all.&lt;/p&gt;
&lt;p&gt;The reliable cutover was:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Leave the old WAN connected.&lt;/li&gt;
&lt;li&gt;Disconnect or disable PPPoE on the old interface.&lt;/li&gt;
&lt;li&gt;Verify that a PADT leaves the old interface.&lt;/li&gt;
&lt;li&gt;Move the cable or change the VLAN assignment.&lt;/li&gt;
&lt;li&gt;Enable PPPoE on the new interface.&lt;/li&gt;
&lt;/ol&gt;
&lt;figure class=&#34;article-diagram&#34;&gt;
    &lt;pre class=&#34;mermaid&#34;&gt;
sequenceDiagram
	participant Old as OPNsense igc0
	participant BRAS as ISP access concentrator
	participant New as OPNsense igc2_vlan999

	Old-&gt;&gt;BRAS: PPPoE session established
	Note over Old,BRAS: Cable pulled without LCP Terminate or PADT
	New-&gt;&gt;BRAS: PADI from VLAN 999
	BRAS--xNew: One-session policy blocks new session
	Note over BRAS: Old session remains until timeout
	Old-&gt;&gt;BRAS: PADT during controlled retry
	BRAS--&gt;&gt;Old: Old session removed
	New-&gt;&gt;BRAS: PADI then PADR
	BRAS--&gt;&gt;New: PADO then PADS
	Note over New,BRAS: New PPPoE session succeeds
&lt;/pre&gt;
    &lt;figcaption&gt;The cable pull left the old session alive at the ISP; a PADT-first cutover explicitly closed it before the new interface dialled.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;On a BSD-based firewall, a capture like this is enough to observe the discovery
traffic:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;tcpdump -ni &amp;lt;wan-interface&amp;gt; -e ether proto 0x8863
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The exact command used to disconnect varies by platform. I prefer the firewall&amp;rsquo;s
normal interface disconnect action because it follows the same control path the
system uses in production. The capture is there to prove the shutdown emitted a
termination frame before any cable moved.&lt;/p&gt;
&lt;p&gt;With the old session closed first, the new interface authenticated normally.&lt;/p&gt;
&lt;p&gt;The connection came up on VLAN 999 after this. But it did not stay up.&lt;/p&gt;
&lt;h2 id=&#34;omada-loop-detection-on-the-ont-port&#34;&gt;Omada loop detection on the ONT port
&lt;/h2&gt;&lt;p&gt;The PPPoE session later failed again, this time after it had already been stable.
The pattern was different: discovery could be blocked outright, or an established
session would disappear several minutes later.&lt;/p&gt;
&lt;p&gt;The managed switch between the firewall and optical terminal had loop-detection
features enabled. It injected control traffic into the provider-facing bridged
segment: first spanning-tree-style frames, then vendor loopback-detection probes.
On an ordinary LAN those features can be useful. On a transparent WAN transport,
the ISP side is not an ordinary LAN and did not appreciate the extra frames.&lt;/p&gt;
&lt;p&gt;The fix was not to disable protection across the whole switch. I disabled
loopback control only on the port connected to the optical terminal. The WAN
VLAN remained isolated and tagged exactly as before; only the switch&amp;rsquo;s active
probing stopped.&lt;/p&gt;
&lt;figure class=&#34;article-diagram&#34;&gt;
    &lt;pre class=&#34;mermaid&#34;&gt;
flowchart TD
	MOVE[Move ONT cable from igc0 to VLAN 999] --&gt; IMMEDIATE{When does it fail?}
	IMMEDIATE --&gt;|Immediately| STALE[Old PPPoE session still held by ISP]
	STALE --&gt; PADT[Disconnect old WAN and verify PADT]
	PADT --&gt; UP[PPPoE connects on igc2_vlan999]
	IMMEDIATE --&gt;|Minutes after connecting| PROBES[Omada loopback-control probes enter WAN segment]
	PROBES --&gt; DROP[Established PPPoE session drops]
	DROP --&gt; PORT[Disable Loopback Control on ONT-facing port]
	PORT --&gt; STABLE[Session remains stable through soak and reboot]
&lt;/pre&gt;
    &lt;figcaption&gt;Two independent faults occupied the same WAN path and failed on different timelines.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;After that per-port change, the PPPoE session stayed up through the observation
window and survived reboots of the relevant equipment.&lt;/p&gt;
&lt;p&gt;Initially I thought the earlier fix was incomplete, but this was a separate
problem on the same path:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the cutover failed immediately because the old PPPoE session was never closed;&lt;/li&gt;
&lt;li&gt;the repaired connection later failed because the switch injected control
traffic into the WAN bridge.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;the-migration-steps-i-use-now&#34;&gt;The migration steps I use now
&lt;/h2&gt;&lt;p&gt;Below is the order I now use when moving a live PPPoE WAN between ports, VLANs or
firewall nodes.&lt;/p&gt;
&lt;h3 id=&#34;before-the-maintenance-window&#34;&gt;Before the maintenance window
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;Record the working parent interface, VLAN ID, MTU, credentials source, and WAN
MAC.&lt;/li&gt;
&lt;li&gt;Confirm whether the provider documents MAC binding or single-session limits.&lt;/li&gt;
&lt;li&gt;Preconfigure the destination interface without enabling it.&lt;/li&gt;
&lt;li&gt;Verify the VLAN at layer 2 independently of PPPoE when possible.&lt;/li&gt;
&lt;li&gt;Review the ISP-facing switch port for spanning tree, loop detection, LLDP,
discovery, or other active control protocols.&lt;/li&gt;
&lt;li&gt;Keep a management path that does not depend on the WAN being migrated.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;during-the-cutover&#34;&gt;During the cutover
&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;old PPPoE connected
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	│
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	▼
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;disconnect old PPPoE cleanly
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	│
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	▼
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;observe PADT / termination
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	│
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	▼
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;move cable or VLAN ownership
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	│
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	▼
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;enable new PPPoE interface
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	│
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	▼
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;verify discovery, LCP, IPCP, route and DNS
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Do not clone the MAC reflexively. Preserve it only when you know the provider
requires it or when a controlled test demonstrates that it matters. Unnecessary
MAC duplication is especially hazardous if old and new devices can be online at
the same time.&lt;/p&gt;
&lt;h3 id=&#34;after-the-session-comes-up&#34;&gt;After the session comes up
&lt;/h3&gt;&lt;p&gt;Do more than check that a public IP appeared:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;inspect the PPP logs for successful LCP and IPCP negotiation;&lt;/li&gt;
&lt;li&gt;confirm the default route uses the new interface;&lt;/li&gt;
&lt;li&gt;test DNS through the normal client path;&lt;/li&gt;
&lt;li&gt;verify the negotiated MTU with don&amp;rsquo;t-fragment pings;&lt;/li&gt;
&lt;li&gt;keep the session under observation long enough to catch periodic switch probes;&lt;/li&gt;
&lt;li&gt;reboot the switch or firewall if reboot survival is part of the acceptance
criteria.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The distinction between &amp;ldquo;connected once&amp;rdquo; and &amp;ldquo;operationally complete&amp;rdquo; saved me
from calling the migration finished before the loop-detection failure surfaced.&lt;/p&gt;
&lt;h2 id=&#34;key-things-to-check&#34;&gt;Key things to check
&lt;/h2&gt;&lt;p&gt;The immediate failure and the delayed failure had different causes. If PPPoE
does not connect after moving a cable, first check whether the old session was
closed properly. If it connects and drops later, check what the switch is sending
on the WAN VLAN.&lt;/p&gt;
&lt;p&gt;Also, a managed switch is not always transparent. Disable STP, loop detection or
similar active features on the ONT-facing port unless you know the ISP path can
handle them.&lt;/p&gt;
&lt;p&gt;Most importantly, disconnect PPPoE before moving the cable and verify the PADT in
a packet capture. Waiting for the ISP timeout also worked, but it made a simple
cutover take much longer than needed.&lt;/p&gt;
</description>
        </item>
        
    </channel>
</rss>
