Closed48

GL.iNet Flint 2 (OpenWrt 21) で Biglobe の IPv6オプションに対応させる

ピン留めされたアイテム
BonyChopsBonyChops

一旦速報的にうまく行った方法を書いてcloseとします。
アドカレで記事を出す予定なので、出たらそっちをみてください。

記事

記事を書きました!こちらをみてください↓

https://blog.b7s.dev/2025/12/20/glinet-map-e/

手順

  • GL.iNet の管理パネル
    • Network -> IPv6 で Passthrough, auto
    • GL.iNet v4.8.2, v4.8.3 あたりを使用している場合、または下記を全てやってうまくいかない場合
      • ネットワーク → ネットワークアクセラレーションを無効
  • 以降はluci
  • System -> Administration -> SSH-keysで公開鍵を設定しておくと便利
  • SSHで次を実行
    • 接続: ssh root@ルータIP -> 初期設定で入力したパスワードを入力
    • opkg update --no-check-certificate && opkg install map ca-certificates --no-check-certificate && echo "Restarting network..." &&/etc/init.d/network restart
  • WAN6: deviceを正しい物理インタフェース(eth1など)にする
  • 設定手順5からやる -> https://blog.osakana.net/archives/11679
  • 下記ファイルを修正、追記する
/lib/netifd/proto/map.sh
root@GL-MT6000:/lib/netifd/proto# diff -u map.sh.backup map.sh
--- map.sh.backup	2025-11-04 23:43:03.795701517 +0900
+++ map.sh	2025-11-05 20:23:43.314717265 +0900
@@ -140,6 +140,8 @@
 	      json_add_string snat_ip $(eval "echo \$RULE_${k}_IPV4ADDR")
 	    json_close_object
 	  else
+      local MARK_BASE=0x00100000       # ここから開始
+       local MARK_MASK=0x0fff0000       # 上位 12bit だけ使用
+       local mark=${MARK_BASE}
 	    for portset in $(eval "echo \$RULE_${k}_PORTSETS"); do
               for proto in icmp tcp udp; do
 	        json_add_object ""
@@ -147,11 +149,13 @@
            json_add_string target SNAT
            json_add_string family inet
            json_add_string proto "$proto"
+          json_add_string mark "$(printf '0x%08x' "${mark}")/${MARK_MASK}"
            json_add_boolean connlimit_ports 1
            json_add_string snat_ip $(eval "echo \$RULE_${k}_IPV4ADDR")
            json_add_string snat_port "$portset"
 	        json_close_object
               done
+             mark=$((mark + 0x00010000))
 	    done
 	  fi
 	  if [ "$maptype" = "map-t" ]; then
  • Network -> Firewall -> Custom Rulesに以下を設定
/etc/firewall.user
# /etc/firewall.user から呼ばれる前提

# --- 並行実行ガード(すでに誰かが実行中なら即終了) ---
LOCKDIR=/var/run/mape_nth.lock
if ! mkdir "${LOCKDIR}" 2>/dev/null; then
  # 他プロセスが実行中 or 直前に完了
  exit 0
fi
trap 'rmdir "${LOCKDIR}"' EXIT

EVERY=15
MARK_MASK=0x0fff0000
MARK_BASE=0x00100000
LANIF=br-lan

# 代表マーク(i=0 → MARK_BASE, prob=1/15)で“導入済み”を判定
check_prerouting() {
  iptables -t mangle -C PREROUTING -i "$LANIF" \
    -m conntrack --ctstate NEW \
    -m mark --mark 0x0/${MARK_MASK} \
    -m statistic --mode random --probability 0.066667 \
    -j MARK --set-xmark $(printf "0x%08x" "${MARK_BASE}")/${MARK_MASK} 2>/dev/null
}

check_output() {
  iptables -t mangle -C OUTPUT \
    -m conntrack --ctstate NEW \
    -m mark --mark 0x0/${MARK_MASK} \
    -m statistic --mode random --probability 0.066667 \
    -j MARK --set-xmark $(printf "0x%08x" "${MARK_BASE}")/${MARK_MASK} 2>/dev/null
}


add_prerouting_rules() {
  for i in $(seq 0 14); do
    # i ごとに 0x00010000 ずつ増やす
    local mark_val=$((MARK_BASE + (i << 16)))
    local hex
    hex=$(printf "0x%08x" "${mark_val}")

    # 残りバケット数 = 15 - i
    # 各バケットが最終的に 1/15 になるように、
    # 「残りに対する確率」 = 1 / (15 - i) にしておく
    local prob
    case "$i" in
      0)  prob="0.066667" ;;  # 1/15
      1)  prob="0.071428" ;;  # 1/14
      2)  prob="0.076923" ;;  # 1/13
      3)  prob="0.083333" ;;  # 1/12
      4)  prob="0.090909" ;;  # 1/11
      5)  prob="0.100000" ;;  # 1/10
      6)  prob="0.111111" ;;  # 1/9
      7)  prob="0.125000" ;;  # 1/8
      8)  prob="0.142857" ;;  # 1/7
      9)  prob="0.166667" ;;  # 1/6
      10) prob="0.200000" ;;  # 1/5
      11) prob="0.250000" ;;  # 1/4
      12) prob="0.333333" ;;  # 1/3
      13) prob="0.500000" ;;  # 1/2
      14) prob="1.000000" ;;  # 1/1(残りは全部ここ)
    esac

    iptables -t mangle -A PREROUTING -i "$LANIF" \
      -m conntrack --ctstate NEW \
      -m mark --mark 0x0/${MARK_MASK} \
      -m statistic --mode random --probability "${prob}" \
      -j MARK --set-xmark ${hex}/${MARK_MASK}
  done
}

add_output_rules() {
  for i in $(seq 0 14); do
    local mark_val=$((MARK_BASE + (i << 16)))
    local hex
    hex=$(printf "0x%08x" "${mark_val}")

    local prob
    case "$i" in
      0)  prob="0.066667" ;;
      1)  prob="0.071428" ;;
      2)  prob="0.076923" ;;
      3)  prob="0.083333" ;;
      4)  prob="0.090909" ;;
      5)  prob="0.100000" ;;
      6)  prob="0.111111" ;;
      7)  prob="0.125000" ;;
      8)  prob="0.142857" ;;
      9)  prob="0.166667" ;;
      10) prob="0.200000" ;;
      11) prob="0.250000" ;;
      12) prob="0.333333" ;;
      13) prob="0.500000" ;;
      14) prob="1.000000" ;;
    esac
  done
}

# 既存チェック→未導入なら投入
check_prerouting || add_prerouting_rules
check_output    || add_output_rules
  • /etc/init.d/network restart
BonyChopsBonyChops

最終目標

  • IPoE(MAP-E) と PPPoE の共存
  • IPv4, IPv6サイトに接続できる
  • 安定したインターネットライフ(ニチバン対策)
  • NAT6は使わない
  • 上記の設定を安定して再現できる様になる

現状

  • NAT6を用いればIPv6を安定して接続できる
  • IPv4はMAP-Eを用いて接続できる様になった、ただし接続があまりにも遅い
    • 原因はポートの枯渇(ニチバン問題)かと思ったけど後述の症状がどうもそうっぽくない
    • ルータでで実行する curl -4 --http1.1 -L github.com は正常、LAN内クライアント(mac)だとbodyが途中で止まり、そのまま待ち状態になる
    • -> これのせいで後続のリクエストが詰まる
    • 通常 1 HTTPリクエストは1ポートを使うはずなのでニチバンっぽくない
  • NAT6をやめてNative(およびそれっぽい方法)でIPv6の割り当てをすると、前述の止まる現象が起きる
    • curl -6 --http1.1 -L facebook.com
    • ということはニチバンっぽくない
    • GPT: PMTU(MSS)問題っぽい?
    • どっかで検証したけど上記は違うことがわかった
  • OpenWrt 21.04, 64bitにつきwan6pdを用いた静的アドレス定義が必要[1]

現状一番うまくいく設定

古い内容です
:::message
NAT6使ってる
:::
  • GL.iNet の管理パネルで Network -> IPv6 で NAT6, auto
  • 以降はluci
  • opkg update --no-check-certificate && opkg install map ca-certificates --no-check-certificate && /etc/init.d/network restart
  • これやる -> https://github.com/fakemanhk/openwrt-jp-ipoe/discussions/2, ただし:
    • DHCPv6-Service: server
    • RA flags: R, A
  • WAN6: deviceを正しい物理インタフェース(eth1など)にする
  • 設定手順5からやる -> https://blog.osakana.net/archives/11679
  • 自分用メモ: /etc/config/network は gist.github.com
脚注
  1. https://kameneko.medium.com/openwrt-mapcalc-issues-on-64-bit-architecture-openwrtの64bitアーキテクチャで-mapcalcが適切に動かない話-map-e-494a39674998 ↩︎

BonyChopsBonyChops

現時点で一番うまくいく方法を追記

  • GL.iNet の管理パネルで Network -> IPv6 で Passthrough, auto
  • 以降はluci
  • System -> Administration -> SSH-keysで公開鍵を設定しておくと便利
  • SSHで次を実行
    • 接続: ssh root@ルータIP -> 初期設定で入力したパスワードを入力
    • opkg update --no-check-certificate && opkg install map ca-certificates --no-check-certificate && echo "Restarting network..." &&/etc/init.d/network restart
  • WAN6: deviceを正しい物理インタフェース(eth1など)にする
  • 設定手順5からやる -> https://blog.osakana.net/archives/11679
  • 下記ファイルを修正、追記する
/lib/netifd/proto/map.sh
root@GL-MT6000:/lib/netifd/proto# diff -u map.sh.backup map.sh
--- map.sh.backup	2025-11-04 23:43:03.795701517 +0900
+++ map.sh	2025-11-05 20:23:43.314717265 +0900
@@ -140,6 +140,8 @@
 	      json_add_string snat_ip $(eval "echo \$RULE_${k}_IPV4ADDR")
 	    json_close_object
 	  else
+      local mark=16                # 例: 0x0010 から開始(任意。被らなければOK)
+      local MARK_MASK=0x0fff       # 下位 12bit だけでマッチさせる
 	    for portset in $(eval "echo \$RULE_${k}_PORTSETS"); do
               for proto in icmp tcp udp; do
 	        json_add_object ""
@@ -147,11 +149,13 @@
            json_add_string target SNAT
            json_add_string family inet
            json_add_string proto "$proto"
+           json_add_string mark "$(printf '0x%04x' "$mark")/${MARK_MASK}"
            json_add_boolean connlimit_ports 1
            json_add_string snat_ip $(eval "echo \$RULE_${k}_IPV4ADDR")
            json_add_string snat_port "$portset"
 	        json_close_object
               done
+              mark=$((mark + 1))
 	    done
 	  fi
 	  if [ "$maptype" = "map-t" ]; then
  • Network -> Firewall -> Custom Rulesに以下を設定
/etc/firewall.user
# /etc/firewall.user から呼ばれる前提

# --- 並行実行ガード(すでに誰かが実行中なら即終了) ---
LOCKDIR=/var/run/mape_nth.lock
if ! mkdir "${LOCKDIR}" 2>/dev/null; then
  # 他プロセスが実行中 or 直前に完了
  exit 0
fi
trap 'rmdir "${LOCKDIR}"' EXIT

EVERY=15
MASK=0x0fff
LANIF=br-lan

# 代表マーク(packet 0 → 0x10)で“導入済み”を判定
check_prerouting() {
  iptables -t mangle -C PREROUTING -i "$LANIF" \
    -m conntrack --ctstate NEW \
    -m mark --mark 0x0/${MASK} \
    -m statistic --mode nth --every ${EVERY} --packet 0 \
    -j MARK --set-xmark 0x10/${MASK} 2>/dev/null
}

check_output() {
  iptables -t mangle -C OUTPUT \
    -m conntrack --ctstate NEW \
    -m mark --mark 0x0/${MASK} \
    -m statistic --mode nth --every ${EVERY} --packet 0 \
    -j MARK --set-xmark 0x10/${MASK} 2>/dev/null
}

add_prerouting_rules() {
  for i in $(seq 0 14); do
    hex=$(printf "0x%x" $((0x10 + i)))
    iptables -t mangle -A PREROUTING -i "$LANIF" \
      -m conntrack --ctstate NEW \
      -m mark --mark 0x0/${MASK} \
      -m statistic --mode nth --every ${EVERY} --packet $i \
      -j MARK --set-xmark ${hex}/${MASK}
  done
}

add_output_rules() {
  for i in $(seq 0 14); do
    hex=$(printf "0x%x" $((0x10 + i)))
    iptables -t mangle -A OUTPUT \
      -m conntrack --ctstate NEW \
      -m mark --mark 0x0/${MASK} \
      -m statistic --mode nth --every ${EVERY} --packet $i \
      -j MARK --set-xmark ${hex}/${MASK}
  done
}

# 既存チェック→未導入なら投入
check_prerouting || add_prerouting_rules
check_output    || add_output_rules
BonyChopsBonyChops
BonyChopsBonyChops

コントリビューションチャンス、ただし環境構築がかなりだるいかも

BonyChopsBonyChops

何が何だかわからなすぎるので買った
インターネットを使いたいだけなのに...
https://www.lambdanote.com/products/v6plus

BonyChopsBonyChops

日本の場合IPoEで繋ぐ際の接続先(BR)はISPではなくVNE(p3)、そしてそれらは日本に3社しかない(p4)のですぐに分かりそう
Biglobeの場合はJPIXってことでいいんだろうか

BonyChopsBonyChops

p86

光電話の契約がない場合、フレッツ網からRAが提供される/64のセグメントにおいて、ルータはIPv6パススルーを行います。そのため、ユーザが利用するパソコンなどの機器から見ると、そのルータはL3の構造上は透明な存在になります。

BonyChopsBonyChops

読破
とりあえずDHCPv6-PDではなくRAで構成するのが正しそうというのはわかった

BonyChopsBonyChops

あとは curl -4 -L github.com がLANでのみbodyが途切れる問題を解消したい

BonyChopsBonyChops

GPT:

「ルータ発の通信は正常、LAN端末からだと途切れる」 という差分は、ほぼ次のどれかに絞れます。

  1. MSSクランプが効いていない(または対象外)
    ルータ自身の発信トラフィックはforwardチェーンを通らないため、MSSクランプの有無に左右されません。一方、LAN→WANの転送はクランプが効いていないとLAN端末がMSS 1460のまま握り、MAP-Eの実効MTUより大きいペイロードで詰まりやすいです。
    → ルータでOK・LANでNGという差分はクランプ未適用が最有力。
  2. フローオフロードの相性
    ルータ発はオフロード経路を通らないことが多い一方、LAN→WANはSW/HWフローオフロードを通って挙動が変わるケースがあります。
    → LANでだけ症状が出るなら、オフロードの影響も有力。
  3. HTTP/2の違い
    ルータの curl(ビルドやTLS実装の違い)では HTTP/1.1 でしゃべっていて問題が出ないが、LAN端末の curl/ブラウザは HTTP/2 で大きいフレームを多用し、PMTUD/MSS不整合が表面化して止まる、という差もありがち。
    → プロトコル差で症状が揺れるときも本質は(1)(2)が根っこ。
BonyChopsBonyChops
  • mssを手動で変えたり、ルータとLAN端末の両者でhttp1.1, http2を試したけど変化なし
  • fix_mtu は有効
  • オフロードはすでに無効

MTU, MSS関連の問題じゃない気がするなあ

BonyChopsBonyChops

牛歩ながら前進はしたけど連休で直せんかったなあ
明日はパケット見る or ニチバン対策

BonyChopsBonyChops
  • https://zenn.dev/link/comments/d539744d967d10 で使われるようなfirewall.userは冒頭でnatをフラッシュしている
  • GL.iNetの独自のfirewallルール(後で追記)がほぼ全てを司っており、こいつが最優先で適用されるよう、謎技術で /etc/init.d/firewall restart の標準出力後に適用されるようになっている
  • つまりカスタムルールのflushが効いていない可能性がある
  • レースコンディション?
BonyChopsBonyChops

そもそも仮にFlush効いたとしても元の(GL.iNetの)設定見た方が良さそうだわ
このルール適用時にv4, v6が繋がらなくなる症状からすれば競合か設定ミスのどちらもあり得る

BonyChopsBonyChops

GPT:

GL.iNet の mangle ルールが0xf000 ビットをポリシー用に使っており(set-xmark 0x8000/0xf000 など)、接続確立の途中で mark の上位ビットが付与されます。
ところがあなたの -m mark --mark $mark はマスク無し=完全一致なので、上位ビットが付いた瞬間にもう一致しません。その結果、POSTROUTING の SNAT で mark が合わずヒットしない→「効かない」になります。
対策をするなら --mark $mark/0x0fff のようにマスク指定で下位ビットだけを判定すべきです。

BonyChopsBonyChops

どうやらGL.iNet (要出典) は上位 0xf000bitを何らかの識別に使っているらしい。
これがある以上、別で任意にmarkを設定しても、 --set-xmark 0x8000/0xf000 等で 0xf000 が上書きされてしまうことで、markがうまく動いていなかったらしい (by GPT)

root@GL-MT6000:/lib/netifd/proto# iptables-save | grep xmark
-A TUNNEL100_ROUTE_POLICY -m comment --comment "last sort default policy" -m mark --mark 0x0/0xf000 -j MARK --set-xmark 0x8000/0xf000
-A TUNNEL201_LOCAL_POLICY -m comment --comment "process policy" -m connmark --mark 0x0/0xf000 -m mark --mark 0x0/0xf000 -m owner --gid-owner 10000 -j MARK --set-xmark 0x8000/0xf000
-A wan_in_new_mark -i eth1 -p tcp -m conntrack --ctstate NEW -m connmark ! --mark 0x8000/0xf000 -m comment --comment eth1_in_new_connmark -j CONNMARK --set-xmark 0x8000/0xf000
-A wan_in_new_mark -i eth1 -p udp -m conntrack --ctstate NEW -m connmark ! --mark 0x8000/0xf000 -m comment --comment eth1_in_new_connmark -j CONNMARK --set-xmark 0x8000/0xf000
-A wan_in_new_mark -i eth1 -p icmp -m conntrack --ctstate NEW -m connmark ! --mark 0x8000/0xf000 -m comment --comment eth1_in_new_connmark -j CONNMARK --set-xmark 0x8000/0xf000
-A wan_in_new_mark -i map-wan6_map -p tcp -m conntrack --ctstate NEW -m connmark ! --mark 0x8000/0xf000 -m comment --comment map-wan6_map_in_new_connmark -j CONNMARK --set-xmark 0x8000/0xf000
-A wan_in_new_mark -i map-wan6_map -p udp -m conntrack --ctstate NEW -m connmark ! --mark 0x8000/0xf000 -m comment --comment map-wan6_map_in_new_connmark -j CONNMARK --set-xmark 0x8000/0xf000
-A wan_in_new_mark -i map-wan6_map -p icmp -m conntrack --ctstate NEW -m connmark ! --mark 0x8000/0xf000 -m comment --comment map-wan6_map_in_new_connmark -j CONNMARK --set-xmark 0x8000/0xf000

https://gist.github.com/anonymous/0fdec75fa20a7f1ce4806391d6b0429b

上記にmaskを与えてうまくうごくようにした (by GPT)

/lib/netifd/proto/map.sh
root@GL-MT6000:/lib/netifd/proto# diff -u map.sh.backup map.sh
--- map.sh.backup	2025-11-04 23:43:03.795701517 +0900
+++ map.sh	2025-11-05 20:23:43.314717265 +0900
@@ -140,6 +140,8 @@
 	      json_add_string snat_ip $(eval "echo \$RULE_${k}_IPV4ADDR")
 	    json_close_object
 	  else
+      local mark=16                # 例: 0x0010 から開始(任意。被らなければOK)
+      local MARK_MASK=0x0fff       # 下位 12bit だけでマッチさせる
 	    for portset in $(eval "echo \$RULE_${k}_PORTSETS"); do
               for proto in icmp tcp udp; do
 	        json_add_object ""
@@ -147,11 +149,13 @@
            json_add_string target SNAT
            json_add_string family inet
            json_add_string proto "$proto"
+           json_add_string mark "$(printf '0x%04x' "$mark")/${MARK_MASK}"
            json_add_boolean connlimit_ports 1
            json_add_string snat_ip $(eval "echo \$RULE_${k}_IPV4ADDR")
            json_add_string snat_port "$portset"
 	        json_close_object
               done
+              mark=$((mark + 1))
 	    done
 	  fi
 	  if [ "$maptype" = "map-t" ]; then
/etc/firewall.user
iptables -t mangle -A PREROUTING -m statistic --mode nth --every 15 --packet  0 -j MARK --set-mark 0x10/0xfff
iptables -t mangle -A PREROUTING -m statistic --mode nth --every 15 --packet  1 -j MARK --set-mark 0x11/0xfff
iptables -t mangle -A PREROUTING -m statistic --mode nth --every 15 --packet  2 -j MARK --set-mark 0x12/0xfff
iptables -t mangle -A PREROUTING -m statistic --mode nth --every 15 --packet  3 -j MARK --set-mark 0x13/0xfff
iptables -t mangle -A PREROUTING -m statistic --mode nth --every 15 --packet  4 -j MARK --set-mark 0x14/0xfff
iptables -t mangle -A PREROUTING -m statistic --mode nth --every 15 --packet  5 -j MARK --set-mark 0x15/0xfff
iptables -t mangle -A PREROUTING -m statistic --mode nth --every 15 --packet  6 -j MARK --set-mark 0x16/0xfff
iptables -t mangle -A PREROUTING -m statistic --mode nth --every 15 --packet  7 -j MARK --set-mark 0x17/0xfff
iptables -t mangle -A PREROUTING -m statistic --mode nth --every 15 --packet  8 -j MARK --set-mark 0x18/0xfff
iptables -t mangle -A PREROUTING -m statistic --mode nth --every 15 --packet  9 -j MARK --set-mark 0x19/0xfff
iptables -t mangle -A PREROUTING -m statistic --mode nth --every 15 --packet 10 -j MARK --set-mark 0x1a/0xfff
iptables -t mangle -A PREROUTING -m statistic --mode nth --every 15 --packet 11 -j MARK --set-mark 0x1b/0xfff
iptables -t mangle -A PREROUTING -m statistic --mode nth --every 15 --packet 12 -j MARK --set-mark 0x1c/0xfff
iptables -t mangle -A PREROUTING -m statistic --mode nth --every 15 --packet 13 -j MARK --set-mark 0x1d/0xfff
iptables -t mangle -A PREROUTING -m statistic --mode nth --every 15 --packet 14 -j MARK --set-mark 0x1e/0xfff

iptables -t mangle -A OUTPUT -m statistic --mode nth --every 15 --packet  0 -j MARK --set-mark 0x10/0xfff
iptables -t mangle -A OUTPUT -m statistic --mode nth --every 15 --packet  1 -j MARK --set-mark 0x11/0xfff
iptables -t mangle -A OUTPUT -m statistic --mode nth --every 15 --packet  2 -j MARK --set-mark 0x12/0xfff
iptables -t mangle -A OUTPUT -m statistic --mode nth --every 15 --packet  3 -j MARK --set-mark 0x13/0xfff
iptables -t mangle -A OUTPUT -m statistic --mode nth --every 15 --packet  4 -j MARK --set-mark 0x14/0xfff
iptables -t mangle -A OUTPUT -m statistic --mode nth --every 15 --packet  5 -j MARK --set-mark 0x15/0xfff
iptables -t mangle -A OUTPUT -m statistic --mode nth --every 15 --packet  6 -j MARK --set-mark 0x16/0xfff
iptables -t mangle -A OUTPUT -m statistic --mode nth --every 15 --packet  7 -j MARK --set-mark 0x17/0xfff
iptables -t mangle -A OUTPUT -m statistic --mode nth --every 15 --packet  8 -j MARK --set-mark 0x18/0xfff
iptables -t mangle -A OUTPUT -m statistic --mode nth --every 15 --packet  9 -j MARK --set-mark 0x19/0xfff
iptables -t mangle -A OUTPUT -m statistic --mode nth --every 15 --packet 10 -j MARK --set-mark 0x1a/0xfff
iptables -t mangle -A OUTPUT -m statistic --mode nth --every 15 --packet 11 -j MARK --set-mark 0x1b/0xfff
iptables -t mangle -A OUTPUT -m statistic --mode nth --every 15 --packet 12 -j MARK --set-mark 0x1c/0xfff
iptables -t mangle -A OUTPUT -m statistic --mode nth --every 15 --packet 13 -j MARK --set-mark 0x1d/0xfff
iptables -t mangle -A OUTPUT -m statistic --mode nth --every 15 --packet 14 -j MARK --set-mark 0x1e/0xfff
BonyChopsBonyChops

うまく捌けている様に見える(ただし設定がなぜか重複しているが)

root@GL-MT6000:/lib/netifd/proto# iptables -t mangle -L -v -n --line-numbers
Chain PREROUTING (policy ACCEPT 17720 packets, 6984K bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1     1206  482K MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            statistic mode nth every 15 MARK xset 0x10/0xfff
2     1196  458K MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            statistic mode nth every 15 packet 1 MARK xset 0x11/0xfff
3     1194  387K MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            statistic mode nth every 15 packet 2 MARK xset 0x12/0xfff
4     1193  490K MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            statistic mode nth every 15 packet 3 MARK xset 0x13/0xfff
5     1191  506K MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            statistic mode nth every 15 packet 4 MARK xset 0x14/0xfff
6     1190  517K MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            statistic mode nth every 15 packet 5 MARK xset 0x15/0xfff
7     1190  493K MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            statistic mode nth every 15 packet 6 MARK xset 0x16/0xfff
8     1190  533K MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            statistic mode nth every 15 packet 7 MARK xset 0x17/0xfff
9     1189  455K MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            statistic mode nth every 15 packet 8 MARK xset 0x18/0xfff
10    1189  471K MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            statistic mode nth every 15 packet 9 MARK xset 0x19/0xfff
11    1188  396K MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            statistic mode nth every 15 packet 10 MARK xset 0x1a/0xfff
12    1187  479K MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            statistic mode nth every 15 packet 11 MARK xset 0x1b/0xfff
13    1187  539K MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            statistic mode nth every 15 packet 12 MARK xset 0x1c/0xfff
14    1186  431K MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            statistic mode nth every 15 packet 13 MARK xset 0x1d/0xfff
15    1186  380K MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            statistic mode nth every 15 packet 14 MARK xset 0x1e/0xfff
16       0     0 CONNMARK   udp  --  *      *       0.0.0.0/0            0.0.0.0/0            connmark match  0x0/0xf000 udp dpt:3053 CONNMARK save mask 0xf000
17    1095 72486 CONNMARK   udp  --  *      *       0.0.0.0/0            0.0.0.0/0            connmark match  0x0/0xf000 udp dpt:53 CONNMARK save mask 0xf000
18    1199  481K MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            statistic mode nth every 15 MARK xset 0x10/0xfff
19    1194  457K MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            statistic mode nth every 15 packet 1 MARK xset 0x11/0xfff
20    1192  388K MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            statistic mode nth every 15 packet 2 MARK xset 0x12/0xfff
21    1191  490K MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            statistic mode nth every 15 packet 3 MARK xset 0x13/0xfff
22    1189  505K MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            statistic mode nth every 15 packet 4 MARK xset 0x14/0xfff
23    1188  516K MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            statistic mode nth every 15 packet 5 MARK xset 0x15/0xfff
24    1188  493K MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            statistic mode nth every 15 packet 6 MARK xset 0x16/0xfff
25    1188  533K MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            statistic mode nth every 15 packet 7 MARK xset 0x17/0xfff
26    1188  455K MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            statistic mode nth every 15 packet 8 MARK xset 0x18/0xfff
27    1188  472K MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            statistic mode nth every 15 packet 9 MARK xset 0x19/0xfff
28    1188  395K MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            statistic mode nth every 15 packet 10 MARK xset 0x1a/0xfff
29    1187  477K MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            statistic mode nth every 15 packet 11 MARK xset 0x1b/0xfff
30    1187  539K MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            statistic mode nth every 15 packet 12 MARK xset 0x1c/0xfff
31    1186  433K MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            statistic mode nth every 15 packet 13 MARK xset 0x1d/0xfff
32    1186  379K MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            statistic mode nth every 15 packet 14 MARK xset 0x1e/0xfff
BonyChopsBonyChops

だだ、これをやってもcurlが途中で止まってしまう問題は直らなかった...

BonyChopsBonyChops

-i br-lan, --set-xmark を追加してforでやる版 (GPT)

/etc/firewall.user
# 下位12bitだけを使って 15分割 (0x10..0x1e)。上位4bit(0xf000)は GLルール用に保持。
# LAN発 → PREROUTING(br-lan限定)
for i in $(seq 0 14); do
  hex=$(printf "0x%x" $((0x10 + i)))
  iptables -t mangle -A PREROUTING -i br-lan \
    -m statistic --mode nth --every 15 --packet $i \
    -j MARK --set-xmark ${hex}/0x0fff
done

# ルータ自身の発信 → OUTPUT
for i in $(seq 0 14); do
  hex=$(printf "0x%x" $((0x10 + i)))
  iptables -t mangle -A OUTPUT \
    -m statistic --mode nth --every 15 --packet $i \
    -j MARK --set-xmark ${hex}/0x0fff
done
BonyChopsBonyChops

記事にするときは適用前のログも見せてどう変わったかがわかるようにしたい

BonyChopsBonyChops

重複回避版

/etc/firewall.user
# /etc/firewall.user から呼ばれる前提

# --- 並行実行ガード(すでに誰かが実行中なら即終了) ---
LOCKDIR=/var/run/mape_nth.lock
if ! mkdir "${LOCKDIR}" 2>/dev/null; then
  # 他プロセスが実行中 or 直前に完了
  exit 0
fi
trap 'rmdir "${LOCKDIR}"' EXIT

EVERY=15
MASK=0x0fff
LANIF=br-lan

# 代表マーク(packet 0 → 0x10)で“導入済み”を判定
check_prerouting() {
  iptables -t mangle -C PREROUTING -i "$LANIF" \
    -m conntrack --ctstate NEW \
    -m mark --mark 0x0/${MASK} \
    -m statistic --mode nth --every ${EVERY} --packet 0 \
    -j MARK --set-xmark 0x10/${MASK} 2>/dev/null
}

check_output() {
  iptables -t mangle -C OUTPUT \
    -m conntrack --ctstate NEW \
    -m mark --mark 0x0/${MASK} \
    -m statistic --mode nth --every ${EVERY} --packet 0 \
    -j MARK --set-xmark 0x10/${MASK} 2>/dev/null
}

add_prerouting_rules() {
  for i in $(seq 0 14); do
    hex=$(printf "0x%x" $((0x10 + i)))
    iptables -t mangle -A PREROUTING -i "$LANIF" \
      -m conntrack --ctstate NEW \
      -m mark --mark 0x0/${MASK} \
      -m statistic --mode nth --every ${EVERY} --packet $i \
      -j MARK --set-xmark ${hex}/${MASK}
  done
}

add_output_rules() {
  for i in $(seq 0 14); do
    hex=$(printf "0x%x" $((0x10 + i)))
    iptables -t mangle -A OUTPUT \
      -m conntrack --ctstate NEW \
      -m mark --mark 0x0/${MASK} \
      -m statistic --mode nth --every ${EVERY} --packet $i \
      -j MARK --set-xmark ${hex}/${MASK}
  done
}

# 既存チェック→未導入なら投入
check_prerouting || add_prerouting_rules
check_output    || add_output_rules
BonyChopsBonyChops
root@GL-MT6000:~# tcpdump -i br-lan -n -v 'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack == 0 and dst host 23.220.75.245'
tcpdump: listening on br-lan, link-type EN10MB (Ethernet), capture size 262144 bytes
15:53:39.652538 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 64)
    192.168.8.240.62513 > 23.220.75.245.443: Flags [SEW], cksum 0x02e9 (correct), seq 1736895990, win 65535, options [mss 1460,nop,wscale 6,nop,nop,TS val 772967533 ecr 0,sackOK,eol], length 0

root@GL-MT6000:~# tcpdump -i map-wan6_map -n -v 'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack == 0 and dst host 23.220.75.245'
tcpdump: listening on map-wan6_map, link-type LINUX_SLL (Linux cooked v1), capture size 262144 bytes
15:53:39.652648 IP (tos 0x0, ttl 63, id 0, offset 0, flags [DF], proto TCP (6), length 64)
    133.201.138.160.14751 > 23.220.75.245.443: Flags [SEW], cksum 0x76d2 (correct), seq 1736895990, win 65535, options [mss 1420,nop,wscale 6,nop,nop,TS val 772967533 ecr 0,sackOK,eol], length 0

適切なMTU:1460でmssが1420としたとき、
LANが1460を提案→map-wan6_mapに出る際に1420になっているのを確認。つまりMSSの問題ではないことがここで証明できた

BonyChopsBonyChops

enひかりに乗り換えるという元も子もない解決策を目にした。
もうしばらく頑張ってみてダメそうなら乗り換えも検討かなー

BonyChopsBonyChops

BiglobeというよりMAP-Eがいけない(MAP-Eというよりルータがいけない)

BonyChopsBonyChops

久しぶりにやろうと思ったらv6繋がらんと思ってよく確認したらWi-Fiと有線LANの両者でオフになってた
OSあげた影響?

BonyChopsBonyChops

少しずつ問題が見えてきた

root@GL-MT6000:~#  iptables -t nat    -L POSTROUTING -n -v --line-numbers
Chain POSTROUTING (policy ACCEPT 3 packets, 336 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1      173 12091 postrouting_rule  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* !fw3: Custom postrouting rule chain */
2        0     0 SNAT       icmp --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x100000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 0 */ to:133.201.138.160:6544-6559
3        9   576 SNAT       tcp  --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x100000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 1 */ to:133.201.138.160:6544-6559
4        0     0 SNAT       udp  --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x100000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 2 */ to:133.201.138.160:6544-6559
5        0     0 SNAT       icmp --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x110000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 3 */ to:133.201.138.160:10640-10655
6        9   552 SNAT       tcp  --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x110000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 4 */ to:133.201.138.160:10640-10655
7        0     0 SNAT       udp  --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x110000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 5 */ to:133.201.138.160:10640-10655
8        0     0 SNAT       icmp --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x120000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 6 */ to:133.201.138.160:14736-14751
9        9   576 SNAT       tcp  --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x120000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 7 */ to:133.201.138.160:14736-14751
10       0     0 SNAT       udp  --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x120000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 8 */ to:133.201.138.160:14736-14751
11       0     0 SNAT       icmp --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x130000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 9 */ to:133.201.138.160:18832-18847
12       9   576 SNAT       tcp  --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x130000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 10 */ to:133.201.138.160:18832-18847
13       0     0 SNAT       udp  --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x130000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 11 */ to:133.201.138.160:18832-18847
14       0     0 SNAT       icmp --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x140000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 12 */ to:133.201.138.160:22928-22943
15       6   384 SNAT       tcp  --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x140000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 13 */ to:133.201.138.160:22928-22943
16       0     0 SNAT       udp  --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x140000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 14 */ to:133.201.138.160:22928-22943
17       1    84 SNAT       icmp --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x150000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 15 */ to:133.201.138.160:27024-27039
18       8   512 SNAT       tcp  --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x150000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 16 */ to:133.201.138.160:27024-27039
19       0     0 SNAT       udp  --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x150000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 17 */ to:133.201.138.160:27024-27039
20       0     0 SNAT       icmp --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x160000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 18 */ to:133.201.138.160:31120-31135
21       6   360 SNAT       tcp  --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x160000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 19 */ to:133.201.138.160:31120-31135
22       0     0 SNAT       udp  --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x160000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 20 */ to:133.201.138.160:31120-31135
23       0     0 SNAT       icmp --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x170000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 21 */ to:133.201.138.160:35216-35231
24      12   752 SNAT       tcp  --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x170000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 22 */ to:133.201.138.160:35216-35231
25       0     0 SNAT       udp  --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x170000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 23 */ to:133.201.138.160:35216-35231
26       0     0 SNAT       icmp --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x180000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 24 */ to:133.201.138.160:39312-39327
27       7   490 SNAT       tcp  --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x180000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 25 */ to:133.201.138.160:39312-39327
28       0     0 SNAT       udp  --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x180000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 26 */ to:133.201.138.160:39312-39327
29       0     0 SNAT       icmp --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x190000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 27 */ to:133.201.138.160:43408-43423
30       7   448 SNAT       tcp  --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x190000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 28 */ to:133.201.138.160:43408-43423
31       0     0 SNAT       udp  --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x190000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 29 */ to:133.201.138.160:43408-43423
32       0     0 SNAT       icmp --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x1a0000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 30 */ to:133.201.138.160:47504-47519
33       4   232 SNAT       tcp  --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x1a0000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 31 */ to:133.201.138.160:47504-47519
34       0     0 SNAT       udp  --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x1a0000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 32 */ to:133.201.138.160:47504-47519
35       0     0 SNAT       icmp --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x1b0000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 33 */ to:133.201.138.160:51600-51615
36       3   192 SNAT       tcp  --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x1b0000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 34 */ to:133.201.138.160:51600-51615
37       0     0 SNAT       udp  --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x1b0000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 35 */ to:133.201.138.160:51600-51615
38       0     0 SNAT       icmp --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x1c0000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 36 */ to:133.201.138.160:55696-55711
39       4   256 SNAT       tcp  --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x1c0000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 37 */ to:133.201.138.160:55696-55711
40       0     0 SNAT       udp  --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x1c0000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 38 */ to:133.201.138.160:55696-55711
41       0     0 SNAT       icmp --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x1d0000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 39 */ to:133.201.138.160:59792-59807
42       0     0 SNAT       tcp  --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x1d0000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 40 */ to:133.201.138.160:59792-59807
43       0     0 SNAT       udp  --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x1d0000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 41 */ to:133.201.138.160:59792-59807
44       0     0 SNAT       icmp --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x1e0000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 42 */ to:133.201.138.160:63888-63903
45       5   320 SNAT       tcp  --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x1e0000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 43 */ to:133.201.138.160:63888-63903
46       0     0 SNAT       udp  --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x1e0000/0xfff0000 #conn dst/32 <= 16 /* !fw3: ubus:wan6_map[map] nat 44 */ to:133.201.138.160:63888-63903
47      57  3744 LOG        all  --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            mark match 0x0/0xfff0000 LOG flags 0 level 4 prefix "MAPE_POST_WARN "
48       8   784 zone_lan_postrouting  all  --  *      br-lan  0.0.0.0/0            0.0.0.0/0            /* !fw3 */
49       0     0 zone_wan_postrouting  all  --  *      eth1    0.0.0.0/0            0.0.0.0/0            /* !fw3 */
50      65  4937 zone_wan_postrouting  all  --  *      map-wan6_map  0.0.0.0/0            0.0.0.0/0            /* !fw3 */

外界に出る際は46番目までで処理されるはず。よって、本来は何も発火しないはずの47番目のルールを追加してみる。

iptables -t nat -I POSTROUTING 47 \
    -o map-wan6_map \
    -m mark --mark 0x0/${MARK_MASK} \
    -j LOG --log-prefix "${POST_LOG_PREFIX}" --log-level warning

github.comにcurlし、接続が始まらないタイミングでlogreadしてみる

root@GL-MT6000:~# logread | grep MAPE_POST_WARN | grep 20.27
Sun Nov 23 20:38:29 2025 kern.warn kernel: [ 9533.278994] MAPE_POST_WARN IN= OUT=map-wan6_map SRC=192.168.8.240 DST=20.27.177.113 LEN=64 TOS=0x00 PREC=0x00 TTL=63 ID=0 DF PROTO=TCP SPT=59170 DPT=443 WINDOW=65535 RES=0x00 SYN URGP=0 MARK=0x8000
Sun Nov 23 20:38:29 2025 kern.warn kernel: [ 9533.534781] MAPE_POST_WARN IN= OUT=map-wan6_map SRC=192.168.8.240 DST=20.27.177.113 LEN=64 TOS=0x00 PREC=0x00 TTL=63 ID=0 DF PROTO=TCP SPT=59171 DPT=443 WINDOW=65535 RES=0x00 SYN URGP=0 MARK=0x8000
Sun Nov 23 20:42:23 2025 kern.warn kernel: [ 9767.006889] MAPE_POST_WARN IN= OUT=map-wan6_map SRC=192.168.8.240 DST=20.27.177.113 LEN=84 TOS=0x00 PREC=0x00 TTL=63 ID=13114 PROTO=ICMP TYPE=8 CODE=0 ID=38237 SEQ=0 MARK=0x8000
Sun Nov 23 20:43:18 2025 kern.warn kernel: [ 9822.100368] MAPE_POST_WARN IN= OUT=map-wan6_map SRC=192.168.8.240 DST=20.27.177.113 LEN=64 TOS=0x00 PREC=0x00 TTL=63 ID=0 DF PROTO=TCP SPT=59262 DPT=80 WINDOW=65535 RES=0x00 CWR ECE SYN URGP=0 MARK=0x8000
Sun Nov 23 20:43:40 2025 kern.warn kernel: [ 9844.152741] MAPE_POST_WARN IN= OUT=map-wan6_map SRC=192.168.8.240 DST=20.27.177.113 LEN=64 TOS=0x00 PREC=0x00 TTL=63 ID=0 DF PROTO=TCP SPT=59268 DPT=443 WINDOW=65535 RES=0x00 CWR ECE SYN URGP=0 MARK=0x8000

特定のmarkですり抜けが発生してるようだ。ただし、接続が確立され、途中でbodyが止まる問題が発現している際にはここのログは増えない
つまり、 ルール貫通 問題ともう一つ何か別の問題の問題が発生している可能性が高い。

BonyChopsBonyChops

完璧なやつができた
元のやつで約35%のパケットをこぼしている点もどっかで触れたい
自分用のLOGがまだ刺さっているので注意

/etc/firewall.user
# --- 並行実行ガード(すでに誰かが実行中なら即終了) ---
LOCKDIR=/var/run/mape_nth.lock
if ! mkdir "${LOCKDIR}" 2>/dev/null; then
  # 他プロセスが実行中 or 直前に完了
  exit 0
fi
trap 'rmdir "${LOCKDIR}"' EXIT

EVERY=15
MARK_MASK=0x0fff0000
MARK_BASE=0x00100000
LANIF=br-lan

# ログ用
PRE_LOG_PREFIX="MAPE_PRE_WARN "
POST_LOG_PREFIX="MAPE_POST_WARN "

# 代表マーク(i=0 → MARK_BASE, prob=1/15)で“導入済み”を判定
check_prerouting() {
  iptables -t mangle -C PREROUTING -i "$LANIF" \
    -m conntrack --ctstate NEW \
    -m mark --mark 0x0/${MARK_MASK} \
    -m statistic --mode random --probability 0.066667 \
    -j MARK --set-xmark $(printf "0x%08x" "${MARK_BASE}")/${MARK_MASK} 2>/dev/null
}

check_output() {
  iptables -t mangle -C OUTPUT \
    -m conntrack --ctstate NEW \
    -m mark --mark 0x0/${MARK_MASK} \
    -m statistic --mode random --probability 0.066667 \
    -j MARK --set-xmark $(printf "0x%08x" "${MARK_BASE}")/${MARK_MASK} 2>/dev/null
}


add_prerouting_rules() {
  for i in $(seq 0 14); do
    # i ごとに 0x00010000 ずつ増やす
    local mark_val=$((MARK_BASE + (i << 16)))
    local hex
    hex=$(printf "0x%08x" "${mark_val}")

    # 残りバケット数 = 15 - i
    # 各バケットが最終的に 1/15 になるように、
    # 「残りに対する確率」 = 1 / (15 - i) にしておく
    local prob
    case "$i" in
      0)  prob="0.066667" ;;  # 1/15
      1)  prob="0.071428" ;;  # 1/14
      2)  prob="0.076923" ;;  # 1/13
      3)  prob="0.083333" ;;  # 1/12
      4)  prob="0.090909" ;;  # 1/11
      5)  prob="0.100000" ;;  # 1/10
      6)  prob="0.111111" ;;  # 1/9
      7)  prob="0.125000" ;;  # 1/8
      8)  prob="0.142857" ;;  # 1/7
      9)  prob="0.166667" ;;  # 1/6
      10) prob="0.200000" ;;  # 1/5
      11) prob="0.250000" ;;  # 1/4
      12) prob="0.333333" ;;  # 1/3
      13) prob="0.500000" ;;  # 1/2
      14) prob="1.000000" ;;  # 1/1(残りは全部ここ)
    esac

    iptables -t mangle -A PREROUTING -i "$LANIF" \
      -m conntrack --ctstate NEW \
      -m mark --mark 0x0/${MARK_MASK} \
      -m statistic --mode random --probability "${prob}" \
      -j MARK --set-xmark ${hex}/${MARK_MASK}
  done

  # デバッグ用ログ(必要な時だけ有効化)
  iptables -t mangle -A PREROUTING \
    -i br-lan \
    -s 192.168.8.240 \
    -d 20.27.177.113 \
    -j LOG --log-prefix "MAPE_PRE_WARN " --log-level warning
}

add_output_rules() {
  for i in $(seq 0 14); do
    local mark_val=$((MARK_BASE + (i << 16)))
    local hex
    hex=$(printf "0x%08x" "${mark_val}")

    local prob
    case "$i" in
      0)  prob="0.066667" ;;
      1)  prob="0.071428" ;;
      2)  prob="0.076923" ;;
      3)  prob="0.083333" ;;
      4)  prob="0.090909" ;;
      5)  prob="0.100000" ;;
      6)  prob="0.111111" ;;
      7)  prob="0.125000" ;;
      8)  prob="0.142857" ;;
      9)  prob="0.166667" ;;
      10) prob="0.200000" ;;
      11) prob="0.250000" ;;
      12) prob="0.333333" ;;
      13) prob="0.500000" ;;
      14) prob="1.000000" ;;
    esac

    iptables -t mangle -A OUTPUT \
      -m conntrack --ctstate NEW \
      -m mark --mark 0x0/${MARK_MASK} \
      -m statistic --mode random --probability "${prob}" \
      -j MARK --set-xmark ${hex}/${MARK_MASK}
  done
}
BonyChopsBonyChops

最後の最後で思わずXに投稿してしまったけど原因判明
こいつのせいでした
https://x.com/BonyChops/status/1992893240400581113?s=20

BonyChopsBonyChops

軽く経緯を書いておくと、LANでパケットキャプチャしてみたところ本来は流れるべきでないパケットが流れ込んでいました(Destは192.168.x.xであるべきなのに、ネットワークのグローバルIP)。

L3の問題なのでiptablesのミスで起きているとは考えづらく、luciで確認するoffloadingも無効だったので、うーんという感じだったのですが、

https://docs.gl-inet.com/router/en/4/interface_guide/network_acceleration/

↑ どうやらGL.iNetの独自実装Offloading (Network Acceleration) があるらしく、、、無効にしたら通りました 😇😇

BonyChopsBonyChops

スレッドをよく読むと、上記は既に解決してそうな流れなので新しくスレッドをたてるか、別のスレッドを調べる必要があるかもしれない。

BonyChopsBonyChops

上記ではとりあえず繋がるところまでは持っていけたが、現状Symmetric NAT的な動きをする。
これは、新しい接続に対して完全randomなportが割り当てられるようになっているからであり、その接続元LANクライアントに対する接続が可能なportが毎回変わってしまう。
これではゲーム等で相性が悪い

Port-restricted NATをしたければhmarkを使うといいらしい、下記が参考になる。
https://www.ymstmsys.jp/blog/2025/02/09/
これも参考になる
https://turgenev.hatenablog.com/entry/2024/04/23/031222

BonyChopsBonyChops

あっさり完成

/etc/firewall.user
# --- 並行実行ガード(すでに誰かが実行中なら即終了) ---
LOCKDIR=/var/run/mape_nth.lock
if ! mkdir "${LOCKDIR}" 2>/dev/null; then
  exit 0
fi
trap 'rmdir "${LOCKDIR}"' EXIT

# MAP-E 用:ポートセット数
EVERY=15

# fwmark のうち、MAP-E 用に使うビットマスク
MARK_MASK=0x0fff0000

# MAP-E で使う mark のベース値
# 例: 0x00100000, 0x00200000, ... と 0x00010000 刻みで 15 個使う想定
MARK_BASE=0x00100000

# HMARK の mod 値
# hash(tuple) % HM_MOD + MARK_BASE の結果のうち、
# MARK_MASK 部分がちょうど 15 個のバケットに割り当たるように
# EVERY * 0x00010000 としている
HM_MOD=$((EVERY * 0x00010000))

# MAP-E で mark を振りたい入口インタフェースたち
IFACES="br-lan wgserver"

PRE_LOG_PREFIX="MAPE_PRE_WARN "
POST_LOG_PREFIX="MAPE_POST_WARN "

# すでに HMARK ルールが入っているかチェック
check_prerouting_one() {
  local ifname="$1"
  iptables -t mangle -C PREROUTING -i "$ifname" \
    -m conntrack --ctstate NEW \
    -m mark --mark 0x0/${MARK_MASK} \
    -j HMARK \
      --hmark-tuple src,srcport,proto \
      --hmark-mod "${HM_MOD}" \
      --hmark-offset "${MARK_BASE}" \
    2>/dev/null
}

# PREROUTING に HMARK ルールを追加
add_prerouting_rules_one() {
  local ifname="$1"

  # 入口インタフェース ifname から入ってきた「新規」通信で、
  # まだ MAP-E 用の mark が振られていないものに対して、
  # src,srcport,proto ベースで安定したハッシュを fwmark に設定する。
  iptables -t mangle -A PREROUTING -i "$ifname" \
    -m conntrack --ctstate NEW \
    -m mark --mark 0x0/${MARK_MASK} \
    -j HMARK \
      --hmark-tuple src,srcport,proto \
      --hmark-mod "${HM_MOD}" \
      --hmark-offset "${MARK_BASE}"
}

# 既存チェック→未導入なら投入(インタフェースごと)
for ifname in $IFACES; do
  check_prerouting_one "$ifname" || add_prerouting_rules_one "$ifname"
done
このスクラップは28日前にクローズされました