LoginSignup
4
6

More than 3 years have passed since last update.

OpenWrtのMAP-E ルータ構築 [iptablesについて]

Posted at

(前置き経緯)
自宅のネット環境がPPPoE接続で、通常利用でそれほど支障はなかったのですが、macOS更新ダウンロードで3時間以上は絶えられなくなり、IPv6接続に切り替えました。
市販のコンパクトな4千円程度の小さなWifiルータを試しましたが、ルーターの起動も遅い、動作も遅い、なにか固まるような動き、小型アンテナで電波は強くとも距離が飛びません。
Raspberry Pi 2Bで構築のルータ(PPPoE接続)+長いアンテナのついたWifiルータ のほうが快適でした。そこで、IPv4 over IPv6環境も自前でブロードバンドルーターを構築するに至りました。

(環境)  Raspberry Pi 2B 用   OpenWrt 19.07.4 をインストール構築。
イメージの場所 https://openwrt.org/toh/raspberry_pi_foundation/raspberry_pi

あちこち参考にさせていただきましたが、結果として自前でルータ構築できたことに感謝です。

OpenWrt標準では、完全ではないので、追加修正が必要です。
MAP-E技術、OpenWrtのmapeセットアップに関しては、多くの先人たちの説明に譲ります。

(参考) https://qiita.com/s_ponta/items/5652a7be49198288ae61
(参考) https://ktaka.blog.ccmp.jp/2020/05/linuxipv6-ipoe.html
(参考) https://blog.mamemaki.com/entry/2019/12/15/171104

パケットmark付けのiptablesについて自分なりに補います。

(OpenWrt) Firewall - Custom Rules 用

先人たちのコードを修正して、ルール用のテーブルのテキストを吐き出すように次を作成しました。
次の実行結果テキストをカスタムルールに貼り付け適用するものです。

echo-iptables.sh
#!/bin/sh

createMAPE()
{
 if [ "$1" = "OCNV" ] ; then
    divNum=64
    startPort=1024
  fi

  if [ "$1" = "V6P" ] ; then
    divNum=16
    startPort=4096
  fi

  rule=1
  startMark=9
  Every=`expr $divNum - 1`

  while [ $rule -lt $divNum ] ; do
    mark=`expr $rule + $startMark`
    pn=`expr $rule - 1`
    portl=`expr $rule \* $startPort + $PSID \* 16`
    portr=`expr $portl + 15`
    echo  "iptables -t nat -A prerouting_lan_rule -m statistic --mode nth --every $Every --packet $pn -j MARK --set-mark $mark"
    echo  "iptables -t nat -A OUTPUT -o map-tnl -m statistic --mode nth --every $Every --packet $pn -j MARK --set-mark $mark"    #output_wan_ruleだとバグな感じで適用されませんので、「OUTPUT -o map-tnl」とします。
  done
}

# あなたの環境に書き換えてください。
BR='xxxx:xxx:xxxx::x'
CE='xxxx:xxxx:xxxx:xxxx:xx:xxxx:xxx:xxx'    # xで適当に隠します。
IP4='xxx.xx.xx.xx'
PSID='x'

createMAPE OCNV
#createMAPE V6P

BR CE IPV4 PSID の求め方は「MAP-E計算」で検索かけて、1ページ目を一通りチェックします。

私の環境が、今はOCNバーチャルコネクトなので、ここでは createMAPE OCNV を走らせます。

markの番号は 10進数の10からはじめています。0以上ならよさそうです。paketは0からのようです。
paket分散は計算でキリの良い64したくなりますが、0〜62 の 63個です。間違うとロスするタイミングがときどきありそうです。常に --every 63 になるように $Every を当てています。

OpenWrt カスタムルール用の考慮

-A PREROUTING や -A OUTPUT の チェイン指定でも動作はするようですが、全部インターフェースの出入りに適用されてしまいますので、いくらか動きが遅いです。次のチェインを指定します。

REROUTING OUTPUT
適用先 LAN の入り WAN の出
チェイン prerouting_lan_rule output_wan_rule が適用され
ないので OUTPUT -o map-tnl

(重要)OpenWrt 19.07.4において、output_wan_ruleは、バグのようで適用されませんので、OUTPUT -o map-tnl を直接指定する必要がありました。

(参考)インターフェースの名称は lan wan tnl を使っています。これに連動してチェイン名も変わるかもしれません。

/etc/config/network
config interface 'lan'
~省略
config interface 'wan'
~省略
config interface 'tnl'
~省略

チェイン名をiptables-saveで内容確認、探してください。
たとえば、prerouting_xxxx_ruleで、xxxxがインターフェース名になっていると予想します。

root@OpenWrt:~# iptables-save

以上を踏まえ、カスタムルールに追加するiptablesが得ました

出力されたこれらをコピーしてOpenWrtの Network -> Firewall -> Custom Rules に貼り付け適用します。

iptables -t nat -A prerouting_lan_rule -m statistic --mode nth --every 63 --packet 0 -j MARK --set-mark 10
iptables -t nat -A OUTPUT -o map-tnl -m statistic --mode nth --every 63 --packet 0 -j MARK --set-mark 10
.
.
.
iptables -t nat -A prerouting_lan_rule -m statistic --mode nth --every 63 --packet 62 -j MARK --set-mark 72
iptables -t nat -A OUTPUT -o map-tnl -m statistic --mode nth --every 63 --packet 62 -j MARK --set-mark 72

POSTROUTING についても mark 追加対応

POSTROUTINGは /lib/netifd/proto/map.shで作られています。ipv4 over ipv6トンネルに抜けていくPOSTROUTINGも分散させるために、次のようにmarkをつけます。同じ値の範囲:0x0a(10)〜0x48(72)になるようにします。

修正箇所

/lib/netifd/proto/map.sh

130行目あたり

    json_add_array firewall
      if [ -z "$(eval "echo \$RULE_${k}_PORTSETS")" ]; then
        json_add_object ""
          json_add_string type nat
          json_add_string target SNAT
          json_add_string family inet
          json_add_string snat_ip $(eval "echo \$RULE_${k}_IPV4ADDR")
        json_close_object
      else
        local mark=17     # ■■ 追加 ■■
        for portset in $(eval "echo \$RULE_${k}_PORTSETS"); do
          for proto in icmp tcp udp; do
              json_add_object ""
              json_add_string type nat
              json_add_string target SNAT
              json_add_string family inet
              json_add_string proto "$proto"
              json_add_string mark "$mark"     # ■■ 追加 ■■
    # ■■ コメントアウト ■■   json_add_boolean connlimit_ports 1
              json_add_string connlimit_ports "1"     # ■■ 追加 ■■
              json_add_string snat_ip $(eval "echo \$RULE_${k}_IPV4ADDR")
              json_add_string snat_port "$portset"

               json_close_object
           done
           mark=`expr $mark + 1`        # ■■ 追加 ■■
        done
      fi


再起動すれば完了です。

iptables-save で確認すれば、POSTROUTINGで「-m mark --mark 0xa」〜「-m mark --mark 0x48」の範囲で追加されています。

-A POSTROUTING -o map-tnl -p tcp -m mark --mark 0xa -m connlimit --connlimit-upto 16 --connlimit-mask 32 --connlimit-daddr -m comment --comment "!fw3: ubus:tnl[map] nat 0" -j SNAT --to-source xxx.xx.xx.xx:1056-1071
.
.
.
-A POSTROUTING -o map-tnl -p tcp -m mark --mark 0x48 -m connlimit --connlimit-upto 16 --connlimit-mask 32 --connlimit-daddr -m comment --comment "!fw3: ubus:tnl[map] nat 187" -j SNAT --to-source xxx.xx.xx.xx:64544-64559

これで通信が途切れたり、繋がらないようなことは少し減ると思います。

4
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
6