<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Padavan on 猫猫鱼的小窝</title>
    <link>https://cat.fjh1997.top/tags/padavan/</link>
    <description>Recent content from 猫猫鱼的小窝</description>
    <generator>Hugo</generator>
    <language>zh-CN</language>
    
    <managingEditor>xxx@example.com (catcatyu)</managingEditor>
    <webMaster>xxx@example.com (catcatyu)</webMaster>
    
    <copyright>本博客所有文章除特别声明外，均采用 BY-NC-SA 许可协议。转载请注明出处！</copyright>
    
    <lastBuildDate>Mon, 05 Oct 2026 08:20:00 +0800</lastBuildDate>
    
    
    <atom:link href="https://cat.fjh1997.top/tags/padavan/atom.xml" rel="self" type="application/rss&#43;xml" />
    

    
    

    <item>
      <title>Padavan 在光猫路由模式下只桥接 IPv6，让内网拿到原生地址</title>
      <link>https://cat.fjh1997.top/posts/202610051.html</link>
      <pubDate>Mon, 05 Oct 2026 08:20:00 &#43;0800</pubDate>
      <author>xxx@example.com (catcatyu)</author>
      <guid>https://cat.fjh1997.top/posts/202610051.html</guid>
      <description>
        <![CDATA[<h1>Padavan 在光猫路由模式下只桥接 IPv6，让内网拿到原生地址</h1><p>作者：catcatyu（xxx@example.com）</p>
        
          <p>背景：斐讯 K2 刷的是 RT-AC54U 的 Padavan。光猫工作在路由模式，K2 的 WAN（<code>eth2.2</code>）向上用 DHCP，地址落在光猫 LAN 的 <code>192.168.1.0/24</code>。K2 自己的 LAN 是 <code>br0</code>，<code>192.168.123.0/24</code>，下面接着 <code>eth2.1</code> 和 2.4G/5G 无线。</p>
<p>目标很明确：内网要原生公网 IPv6，不要 NAT66。路由器 WAN 口自己已经能用，内网不行。</p>
<h2 id="正常的光猫是怎么分-ipv6-的">
<a class="header-anchor" href="#%e6%ad%a3%e5%b8%b8%e7%9a%84%e5%85%89%e7%8c%ab%e6%98%af%e6%80%8e%e4%b9%88%e5%88%86-ipv6-%e7%9a%84"></a>
正常的光猫是怎么分 IPv6 的
</h2><p>家庭宽带上，IPv6 不该靠下游路由器去蹭光猫 LAN 的那一个网段。规范做法是前缀委托：光猫和家用路由器各管各的 <code>/64</code>，中间是路由，不是同一个广播域。</p>
<p>运营商先把一段前缀交给光猫，常见是 <code>/56</code>（能切出 256 个 <code>/64</code>）或 <code>/60</code>（16 个 <code>/64</code>）。光猫自己的 LAN 只用其中第一段 <code>/64</code>：发 Router Advertisement，前缀标志是 <code>onlink</code> + <code>auto</code>，直连设备 SLAAC。剩下的前缀留给下游。</p>
<p>接在光猫 LAN 上的家用路由器做两件不同的事：</p>
<ul>
<li>要一个地址，用来和光猫通信。SLAAC 或 DHCPv6 IA-NA 都可以。这个地址落在光猫自己的那个 <code>/64</code> 里，只是上联链路。</li>
<li>再发 IA-PD，向光猫要一段可以继续往下发的前缀。光猫从剩下的前缀里切一个 <code>/64</code>（或更大一块）回去，并在自己的路由表里加一条：这段前缀的下一跳是下游路由器的链路本地地址。</li>
</ul>
<p>下游路由器拿到自己的前缀之后，在自己的 LAN 上另发一条 RA。电脑和手机 SLAAC 出来的地址属于路由器的 <code>/64</code>，默认网关是路由器，不是光猫。光猫只把这一段路由给下游，看不见内网设备的 MAC，也不参与它们的邻居发现。</p>
<p>示意用的是文档前缀，不是这条线路上的真实地址：</p>
<pre tabindex="0"><code>运营商 ──PD /60──► 光猫
                    ├─ 自己的 LAN：2001:db8:abcd:0::/64   （RA，给直连设备）
                    └─ 委托出去：  2001:db8:abcd:1::/64   （IA-PD，下一跳是下级路由器）
                                      │
                                   家用路由器
                                      └─ 自己的 LAN：2001:db8:abcd:1::/64 （另一条 RA）
</code></pre><p>IPv4 可以继续 NAT。IPv6 是纯三层转发，WAN 和 LAN 仍然是两个广播域。访客、IoT 还能再各切一个 <code>/64</code>。路由器的 <code>ip6tables</code> 看得到转发的 IPv6。</p>
<p>如果运营商只委托了一个 <code>/64</code>，光猫又把整段用在自己的 LAN 上，就没有剩余前缀可以再委托。这时正规做法是让运营商改发 <code>/56</code> 或 <code>/60</code>，或者把光猫改成桥接，由下游路由器自己拨号去拿 PD。这次两条都没走：光猫保持路由模式，内网也不做 NAT66。</p>
<h2 id="这次实际差在哪">
<a class="header-anchor" href="#%e8%bf%99%e6%ac%a1%e5%ae%9e%e9%99%85%e5%b7%ae%e5%9c%a8%e5%93%aa"></a>
这次实际差在哪
</h2><table>
  <thead>
      <tr>
          <th></th>
          <th>正常委托</th>
          <th>这次</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>光猫向下</td>
          <td>另给一段前缀</td>
          <td>下游要 PD，没有可用前缀</td>
      </tr>
      <tr>
          <td>内网前缀</td>
          <td>和光猫 LAN 不是同一个 <code>/64</code></td>
          <td>和光猫 LAN 共用一个 <code>/64</code></td>
      </tr>
      <tr>
          <td>内网的默认网关</td>
          <td>家用路由器</td>
          <td>光猫。RA 是光猫发的，经桥原样过来</td>
      </tr>
      <tr>
          <td>邻居发现</td>
          <td>各子网自己做</td>
          <td>内网和光猫在同一个 IPv6 广播域</td>
      </tr>
      <tr>
          <td>IPv4</td>
          <td>和 IPv6 互不干扰</td>
          <td>仍然 NAT，靠 broute 把 IPv4 留在路由栈</td>
      </tr>
      <tr>
          <td>路由器防火墙</td>
          <td>能过滤转发的 IPv6</td>
          <td>桥上的 IPv6 不进 <code>ip6tables</code></td>
      </tr>
  </tbody>
</table>
<p>路由器 WAN 口自己是通的。它 SLAAC 拿到光猫通告的 <code>/64</code>，默认路由指向光猫的 <code>fe80::1</code>，从路由器 <code>ping6 2400:3200::1</code> 没问题。<code>br0</code> 上没有全局前缀，插在 K2 下面的设备就没有地址。通告是存在的，缺的是另一段可以再通告的前缀。</p>
<h2 id="排查里的判断">
<a class="header-anchor" href="#%e6%8e%92%e6%9f%a5%e9%87%8c%e7%9a%84%e5%88%a4%e6%96%ad"></a>
排查里的判断
</h2><p>光猫路由表里一度叠着三样东西：一条更短的前缀挂在 <code>lo</code> 上，自己的 LAN 用掉其中一个 <code>/64</code>，另外一个 <code>/64</code> 经由某台设备的链路本地地址指向别处。这看起来像光猫已经在做前缀委托，而且委托对象不是这台 K2。</p>
<p>同一时间，K2 上的 dhcp6c 停在 Solicit，往 <code>ff02::1:2</code> 重发，syslog 里没有 Advertise。所以不是「前缀已经分下来，只是没写进 <code>br0</code>」，而是协商没完成。后来能确认光猫的 dhcp6s 对这类请求会回 Advertise，状态是 <code>NoPrefixAvail</code>。服务器在听，只是不给前缀。</p>
<p>中间有几个判断后来站不住：</p>
<ol>
<li>dhcp6c 里的 <code>sla-len 0</code>。它的意思是拿到的前缀不再切短，只在已经拿到一段比 <code>/64</code> 更短的前缀时才有意义。客户端根本没收到前缀，改 <code>sla-len</code> 改变不了 <code>NoPrefixAvail</code>。</li>
<li>光猫保存的 WAN 前缀长度写成 <code>/64</code>，和路由表里那条更短的聚合前缀对不上。不能据此说「运营商只给了 <code>/64</code>，物理上不可能再委托」。<code>/64</code> 不能再切给另一个 SLAAC 子网，这是对的；但两种长度记录互相矛盾，说明当时看到的并不是单一事实。能确定的只有：这版固件没有把一段新前缀交给这台新的下游路由器。</li>
<li>dhcp6s 的配置里有 IA-NA 的单地址池，也有一条写死的 host 静态前缀，没有给新客户端用的 PD 池。二进制里能找到 IA-NA 的分配函数，没找到名字里带 <code>iapd</code> 的分配函数，同时又还留着前缀绑定过期、释放的字符串。少一个符号不能证明分配代码被删了。改 DUID、改那条静态 host，新请求仍然是 <code>NoPrefixAvail</code>。这次够用的结论是：当前固件不会给新设备下发 PD，不是 Padavan 少写了一行配置。</li>
<li>路由表里「另一个 <code>/64</code> 指向另一台设备」，后来也对不上一次新的 PD。那台设备更像是接在光猫 LAN 上，用同一条 RA 做了 SLAAC。K2 的 WAN 口已经是这种状态。内网缺的不是再要一次 DHCPv6，而是让光猫的 RA 到达 K2 下面的设备。</li>
</ol>
<p>因此剩下的选择是：</p>
<ul>
<li>思路 1：K2 改成 AP，WAN 和 LAN 纯二层。IPv6 能通，IPv4 的 NAT 和自己的网段也没了。</li>
<li>思路 2：IPv4 继续路由，IPv6 用 NDP 代理加 RA 中继。逻辑上还是隔着路由器，靠代理回答邻居发现。这台 Padavan 没有 ndppd、odhcpd。</li>
<li>思路 3：只把 IPv6 帧桥过去，IPv4 和 ARP 继续走原来的 NAT。RA、SLAAC、DAD 都是光猫那个 <code>/64</code> 上的原生行为。选了这条。</li>
</ul>
<p>还有一条当时想过、标准上走不通的路：路由器从自己收到的 RA 里再切一段，比如 <code>/80</code>，发给内网。SLAAC 规定前缀必须是 64 位，后面 64 位才是接口标识。切短之后 Android 不会自动配置，它也不做 DHCPv6。所以不能自己根据 RA 分一小段，只能让内网和光猫共用这一个 <code>/64</code>。</p>
<p>硬件 VLAN 那次改法也是错的。WAN 口和 LAN 口的 VLAN 都包含 CPU，RA 已经能进 <code>eth2.2</code>。要送到 <code>eth2.1</code>，在软件桥上转发就行。当时以为硬件 VLAN 在帧进 CPU 之前就把它挡住了，于是把 WAN 口并进 LAN 的 VLAN。这样帧在交换芯片上直接过去，不进 CPU，<code>ebtables</code> 拦不住，光猫的 IPv4 DHCP 会泄到内网。VLAN 保持原样。</p>
<h2 id="硬件-vlan-不用动">
<a class="header-anchor" href="#%e7%a1%ac%e4%bb%b6-vlan-%e4%b8%8d%e7%94%a8%e5%8a%a8"></a>
硬件 VLAN 不用动
</h2><p>MT7620 的交换芯片把口隔开了：</p>
<table>
  <thead>
      <tr>
          <th>VLAN</th>
          <th>成员</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>1</td>
          <td>LAN 口（0–3）+ CPU，对应 <code>eth2.1</code></td>
      </tr>
      <tr>
          <td>2</td>
          <td>WAN 口（4）+ CPU，对应 <code>eth2.2</code></td>
      </tr>
  </tbody>
</table>
<p>WAN 上的 RA 会进 CPU，出现在 <code>eth2.2</code> 上。软件桥可以把这个帧再从 <code>eth2.1</code>、<code>ra0</code> 送出去。硬件 VLAN 并没有挡住「经 CPU 转发」这条路。</p>
<p>反过来，如果把 WAN 口的 PVID 改成 1、并进 VLAN 1，WAN 和 LAN 就在交换芯片上直接二层互通。这种帧不经过 CPU，<code>ebtables</code> 看不见，IPv4 的 DHCP 也会泄到内网。这个改法要避开。VLAN 保持出厂划分。</p>
<h2 id="可用的做法ipv6-过桥ipv4-继续路由">
<a class="header-anchor" href="#%e5%8f%af%e7%94%a8%e7%9a%84%e5%81%9a%e6%b3%95ipv6-%e8%bf%87%e6%a1%a5ipv4-%e7%bb%a7%e7%bb%ad%e8%b7%af%e7%94%b1"></a>
可用的做法：IPv6 过桥，IPv4 继续路由
</h2><p><code>ebtables</code> 的 <code>BROUTING</code> 链里，<code>DROP</code> 不是把包扔掉，而是把这一帧从桥上拿回来，交给原来那块网卡的三层协议栈。于是可以：</p>
<ul>
<li><code>eth2.2</code> 加入 <code>br0</code></li>
<li>从 <code>eth2.2</code> 进来的 IPv4（<code>0x0800</code>）和 ARP（<code>0x0806</code>）在 <code>BROUTING</code> 里 <code>DROP</code>，NAT 和 <code>192.168.1.2</code> 还在 <code>eth2.2</code> 上</li>
<li>目的 MAC 是 WAN 口自己的 IPv6 单播也同样 broute，路由器自己的 SLAAC 地址还能用</li>
<li>其余 IPv6，包括发往 <code>ff02::1</code> 的 RA，在桥上转发</li>
<li><code>FORWARD</code> 链再丢掉穿越 WAN 口的 IPv4 和 ARP，避免内网广播跑到光猫上</li>
<li><code>br0</code> 的 <code>multicast_snooping</code> 设为 0。否则没有 MLD querier 时，RA 组播到不了其他口</li>
</ul>
<p>这台固件上 <code>nf_call_ip6tables</code> 本来就是 0，桥接的 IPv6 不会再被 <code>ip6tables</code> 的 <code>FORWARD DROP</code> 砍掉，所以不用改防火墙。</p>
<h2 id="第一次把口加进桥之后v4-和-v6-一起断了">
<a class="header-anchor" href="#%e7%ac%ac%e4%b8%80%e6%ac%a1%e6%8a%8a%e5%8f%a3%e5%8a%a0%e8%bf%9b%e6%a1%a5%e4%b9%8b%e5%90%8ev4-%e5%92%8c-v6-%e4%b8%80%e8%b5%b7%e6%96%ad%e4%ba%86"></a>
第一次把口加进桥之后，v4 和 v6 一起断了
</h2><p><code>brctl show</code> 里 STP 是开的，<code>forward_delay</code> 读出来是 <code>1500</code>，单位是百分之一秒，也就是 15 秒。新加入的 <code>eth2.2</code> 会先 listening，再 learning。端口状态不是 <code>3</code>（forwarding）时，内核不会走进 broute，规则计数器一直是 0，回包被丢掉。当时 ping 光猫、<code>223.5.5.5</code>、<code>2400:3200::1</code> 全失败。</p>
<p>把 <code>forward_delay</code> 写成 0 会报 <code>Numerical result out of range</code>，合法范围从 2 秒起。这台 3.4 内核也不方便给单个口做 edge。处理是关掉整座桥的 STP：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">brctl stp br0 off
</span></span></code></pre></td></tr></table>
</div>
</div><p>端口马上变成 forwarding。IPv4 和路由器自己的 IPv6 都恢复了。家用这台没有环路，STP 关掉可以接受；代价是以后如果网线环回，没有生成树兜底。</p>
<h2 id="有线验证">
<a class="header-anchor" href="#%e6%9c%89%e7%ba%bf%e9%aa%8c%e8%af%81"></a>
有线验证
</h2><p>抓 <code>eth2.1</code> 能看到光猫的 RA 原样过来：前缀 <code>/64</code>，<code>onlink</code> + <code>auto</code>，路由器寿命 1800 秒。Windows 有线网卡 SLAAC 出全局地址，<code>ping 2400:3200::1</code> 通，<code>curl -6 https://www.cloudflare.com</code> 返回 200。IPv4 仍是 <code>192.168.123.0/24</code>，没有变成光猫的 <code>192.168.1.0/24</code>。</p>
<p>RA 里带的 MTU 是 1900。Windows 把接口 MTU 钳在 1500。1400 字节的 IPv6 ping 通，1800 字节不通，和这条以太网的实际 MTU 一致。</p>
<h2 id="wifi-仍然没有-ipv6">
<a class="header-anchor" href="#wifi-%e4%bb%8d%e7%84%b6%e6%b2%a1%e6%9c%89-ipv6"></a>
WiFi 仍然没有 IPv6
</h2><p>有线已经在收 RA，2.4G 和 5G 没有。无线配置里 <code>IgmpSnEnable=1</code>，对应 nvram 的 <code>rt_IgmpSnEnable</code> 和 <code>wl_IgmpSnEnable</code>。Ralink / MT76x2 的 IGMP/MLD snooping 会丢掉还没有组成员的 IPv6 组播，<code>ff02::1</code> 的 RA 就在这里被吃掉。有线口不走这个驱动，所以不受影响。</p>
<p>当前生效，并写回 nvram：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">iwpriv ra0 <span class="nb">set</span> <span class="nv">IgmpSnEnable</span><span class="o">=</span><span class="m">0</span>
</span></span><span class="line"><span class="cl">iwpriv rai0 <span class="nb">set</span> <span class="nv">IgmpSnEnable</span><span class="o">=</span><span class="m">0</span>
</span></span><span class="line"><span class="cl">nvram <span class="nb">set</span> <span class="nv">rt_IgmpSnEnable</span><span class="o">=</span><span class="m">0</span>
</span></span><span class="line"><span class="cl">nvram <span class="nb">set</span> <span class="nv">wl_IgmpSnEnable</span><span class="o">=</span><span class="m">0</span>
</span></span><span class="line"><span class="cl">nvram commit
</span></span></code></pre></td></tr></table>
</div>
</div><p>主 SSID 关开一次 WiFi 就会发 Router Solicitation，光猫马上回 RA。访客 SSID 的 <code>NoForwardingMBCast=1</code>，组播本来就被禁，访客网络不会有 IPv6。</p>
<h2 id="重启后还在">
<a class="header-anchor" href="#%e9%87%8d%e5%90%af%e5%90%8e%e8%bf%98%e5%9c%a8"></a>
重启后还在
</h2><p>运行时的桥和 <code>ebtables</code> 重启就没了。脚本放在 <code>/etc/storage/ipv6_bridge.sh</code>，WAN up 的 <code>post_wan_script.sh</code> 和 <code>started_script.sh</code> 里各调一次，然后 <code>mtd_storage.sh save</code> 写进 Storage 分区。</p>
<p>脚本发现 <code>eth2.2</code> 已经在桥上、STP 已关、broute 规则还在时，不会重复刷规则，只会再补一次无线的 <code>iwpriv</code>。完整脚本：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span><span class="lnt">49
</span><span class="lnt">50
</span><span class="lnt">51
</span><span class="lnt">52
</span><span class="lnt">53
</span><span class="lnt">54
</span><span class="lnt">55
</span><span class="lnt">56
</span><span class="lnt">57
</span><span class="lnt">58
</span><span class="lnt">59
</span><span class="lnt">60
</span><span class="lnt">61
</span><span class="lnt">62
</span><span class="lnt">63
</span></code></pre></td>
<td class="lntd">
<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 class="nv">WAN</span><span class="o">=</span>eth2.2
</span></span><span class="line"><span class="cl"><span class="nv">BR</span><span class="o">=</span>br0
</span></span><span class="line"><span class="cl"><span class="nv">LOCK</span><span class="o">=</span>/tmp/ipv6_bridge.lock
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">wifi_ipv6<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">	iwpriv ra0 <span class="nb">set</span> <span class="nv">IgmpSnEnable</span><span class="o">=</span><span class="m">0</span> 2&gt;/dev/null
</span></span><span class="line"><span class="cl">	iwpriv rai0 <span class="nb">set</span> <span class="nv">IgmpSnEnable</span><span class="o">=</span><span class="m">0</span> 2&gt;/dev/null
</span></span><span class="line"><span class="cl">	ip link <span class="nb">set</span> ra0 promisc on allmulticast on 2&gt;/dev/null
</span></span><span class="line"><span class="cl">	ip link <span class="nb">set</span> rai0 promisc on allmulticast on 2&gt;/dev/null
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">i</span><span class="o">=</span><span class="m">0</span>
</span></span><span class="line"><span class="cl"><span class="k">while</span> ! mkdir <span class="s2">&#34;</span><span class="nv">$LOCK</span><span class="s2">&#34;</span> 2&gt;/dev/null<span class="p">;</span> <span class="k">do</span>
</span></span><span class="line"><span class="cl">	<span class="nv">i</span><span class="o">=</span><span class="k">$((</span>i+1<span class="k">))</span>
</span></span><span class="line"><span class="cl">	<span class="o">[</span> <span class="s2">&#34;</span><span class="nv">$i</span><span class="s2">&#34;</span> -gt <span class="m">15</span> <span class="o">]</span> <span class="o">&amp;&amp;</span> <span class="nb">exit</span> <span class="m">0</span>
</span></span><span class="line"><span class="cl">	sleep <span class="m">1</span>
</span></span><span class="line"><span class="cl"><span class="k">done</span>
</span></span><span class="line"><span class="cl"><span class="nb">trap</span> <span class="s1">&#39;rmdir &#34;$LOCK&#34; 2&gt;/dev/null&#39;</span> EXIT
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="o">[</span> -d <span class="s2">&#34;/sys/class/net/</span><span class="nv">$WAN</span><span class="s2">&#34;</span> <span class="o">]</span> <span class="o">||</span> <span class="nb">exit</span> <span class="m">0</span>
</span></span><span class="line"><span class="cl"><span class="o">[</span> -d <span class="s2">&#34;/sys/class/net/</span><span class="nv">$BR</span><span class="s2">&#34;</span> <span class="o">]</span> <span class="o">||</span> <span class="nb">exit</span> <span class="m">0</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">WANMAC</span><span class="o">=</span><span class="k">$(</span>cat /sys/class/net/<span class="nv">$WAN</span>/address<span class="k">)</span>
</span></span><span class="line"><span class="cl">wifi_ipv6
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="o">[</span> -d <span class="s2">&#34;/sys/class/net/</span><span class="nv">$WAN</span><span class="s2">/brport&#34;</span> <span class="o">]</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">	<span class="o">&amp;&amp;</span> <span class="o">[</span> <span class="s2">&#34;</span><span class="k">$(</span>cat /sys/class/net/<span class="nv">$BR</span>/bridge/stp_state<span class="k">)</span><span class="s2">&#34;</span> <span class="o">=</span> <span class="s2">&#34;0&#34;</span> <span class="o">]</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">	<span class="o">&amp;&amp;</span> <span class="o">[</span> <span class="s2">&#34;</span><span class="k">$(</span>cat /sys/class/net/<span class="nv">$BR</span>/bridge/multicast_snooping<span class="k">)</span><span class="s2">&#34;</span> <span class="o">=</span> <span class="s2">&#34;0&#34;</span> <span class="o">]</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">	<span class="o">&amp;&amp;</span> ebtables -t broute -L <span class="p">|</span> grep -q -- <span class="s2">&#34;-i </span><span class="nv">$WAN</span><span class="s2">&#34;</span><span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">	<span class="nb">exit</span> <span class="m">0</span>
</span></span><span class="line"><span class="cl"><span class="k">fi</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">/usr/sbin/brctl stp <span class="s2">&#34;</span><span class="nv">$BR</span><span class="s2">&#34;</span> off
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="m">0</span> &gt; /sys/class/net/<span class="nv">$BR</span>/bridge/multicast_snooping
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">ebtables -t broute -F
</span></span><span class="line"><span class="cl">ebtables -t broute -A BROUTING -i <span class="s2">&#34;</span><span class="nv">$WAN</span><span class="s2">&#34;</span> -p 0x0800 -j DROP
</span></span><span class="line"><span class="cl">ebtables -t broute -A BROUTING -i <span class="s2">&#34;</span><span class="nv">$WAN</span><span class="s2">&#34;</span> -p 0x0806 -j DROP
</span></span><span class="line"><span class="cl">ebtables -t broute -A BROUTING -i <span class="s2">&#34;</span><span class="nv">$WAN</span><span class="s2">&#34;</span> -p 0x86dd -d <span class="s2">&#34;</span><span class="nv">$WANMAC</span><span class="s2">&#34;</span> -j DROP
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">while</span> ebtables -D FORWARD -i <span class="s2">&#34;</span><span class="nv">$WAN</span><span class="s2">&#34;</span> -p 0x0800 -j DROP 2&gt;/dev/null<span class="p">;</span> <span class="k">do</span> :<span class="p">;</span> <span class="k">done</span>
</span></span><span class="line"><span class="cl"><span class="k">while</span> ebtables -D FORWARD -o <span class="s2">&#34;</span><span class="nv">$WAN</span><span class="s2">&#34;</span> -p 0x0800 -j DROP 2&gt;/dev/null<span class="p">;</span> <span class="k">do</span> :<span class="p">;</span> <span class="k">done</span>
</span></span><span class="line"><span class="cl"><span class="k">while</span> ebtables -D FORWARD -i <span class="s2">&#34;</span><span class="nv">$WAN</span><span class="s2">&#34;</span> -p 0x0806 -j DROP 2&gt;/dev/null<span class="p">;</span> <span class="k">do</span> :<span class="p">;</span> <span class="k">done</span>
</span></span><span class="line"><span class="cl"><span class="k">while</span> ebtables -D FORWARD -o <span class="s2">&#34;</span><span class="nv">$WAN</span><span class="s2">&#34;</span> -p 0x0806 -j DROP 2&gt;/dev/null<span class="p">;</span> <span class="k">do</span> :<span class="p">;</span> <span class="k">done</span>
</span></span><span class="line"><span class="cl">ebtables -A FORWARD -i <span class="s2">&#34;</span><span class="nv">$WAN</span><span class="s2">&#34;</span> -p 0x0800 -j DROP
</span></span><span class="line"><span class="cl">ebtables -A FORWARD -o <span class="s2">&#34;</span><span class="nv">$WAN</span><span class="s2">&#34;</span> -p 0x0800 -j DROP
</span></span><span class="line"><span class="cl">ebtables -A FORWARD -i <span class="s2">&#34;</span><span class="nv">$WAN</span><span class="s2">&#34;</span> -p 0x0806 -j DROP
</span></span><span class="line"><span class="cl">ebtables -A FORWARD -o <span class="s2">&#34;</span><span class="nv">$WAN</span><span class="s2">&#34;</span> -p 0x0806 -j DROP
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="o">[</span> ! -d <span class="s2">&#34;/sys/class/net/</span><span class="nv">$WAN</span><span class="s2">/brport&#34;</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">	/usr/sbin/brctl addif <span class="s2">&#34;</span><span class="nv">$BR</span><span class="s2">&#34;</span> <span class="s2">&#34;</span><span class="nv">$WAN</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="k">fi</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">i</span><span class="o">=</span><span class="m">0</span>
</span></span><span class="line"><span class="cl"><span class="k">while</span> <span class="o">[</span> -d <span class="s2">&#34;/sys/class/net/</span><span class="nv">$WAN</span><span class="s2">/brport&#34;</span> <span class="o">]</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">	<span class="o">&amp;&amp;</span> <span class="o">[</span> <span class="s2">&#34;</span><span class="k">$(</span>cat /sys/class/net/<span class="nv">$WAN</span>/brport/state<span class="k">)</span><span class="s2">&#34;</span> !<span class="o">=</span> <span class="s2">&#34;3&#34;</span> <span class="o">]</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">	<span class="o">&amp;&amp;</span> <span class="o">[</span> <span class="s2">&#34;</span><span class="nv">$i</span><span class="s2">&#34;</span> -lt <span class="m">10</span> <span class="o">]</span><span class="p">;</span> <span class="k">do</span>
</span></span><span class="line"><span class="cl">	<span class="nv">i</span><span class="o">=</span><span class="k">$((</span>i+1<span class="k">))</span>
</span></span><span class="line"><span class="cl">	sleep <span class="m">1</span>
</span></span><span class="line"><span class="cl"><span class="k">done</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">logger -t ipv6bridge <span class="s2">&#34;IPv6 bridge ready state=</span><span class="k">$(</span>cat /sys/class/net/<span class="nv">$WAN</span>/brport/state 2&gt;/dev/null<span class="k">)</span><span class="s2">&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>另外，这台 Padavan 上 <code>/sbin/reboot</code> 是指向 <code>rc</code> 的符号链接，不能把它当成普通的 <code>reboot</code> 命令。</p>
<h2 id="结果">
<a class="header-anchor" href="#%e7%bb%93%e6%9e%9c"></a>
结果
</h2><p>这不是正常的前缀委托。正常情况下内网应该拿到光猫另外委托的一段 <code>/64</code>，默认网关是 K2。现在内网和光猫 LAN 上的设备挤在同一个 <code>/64</code> 里，默认网关是光猫，K2 只负责把 IPv6 帧桥过去，IPv4 仍走 NAT。</p>
<ul>
<li>路由器 WAN：继续 SLAAC，IPv4 NAT 不变</li>
<li>有线和主 WiFi：使用光猫通告的同一个 <code>/64</code>，不经过 NAT66</li>
<li>前缀变化时不用改规则，RA 是原样桥过去的</li>
<li>交换芯片的 VLAN 保持 WAN/LAN 隔离，跨网段的 IPv6 必须走 CPU，IPv4 才能被 broute 留在路由栈上</li>
<li>代价是没有第二段前缀可分给访客或 IoT，邻居数量和 ND 都堆在光猫上，K2 的 <code>ip6tables</code> 也看不见这些桥接流量</li>
</ul>

        
        <hr><p>本文2026-10-05首发于<a href='https://cat.fjh1997.top/'>猫猫鱼的小窝</a>，最后修改于2026-10-05</p>]]>
      </description>
      
    </item>
    
  </channel>
</rss>
