YAMAHA RTX1200でMAP-Eした(けどやめた)

事の始まり

So-netでIPoE(IPv6)オプションを利用していたのだが、先日こんなお知らせが届いた。

v6プラスはJPNEが提供するサービスで、IPv4 over IPv6の技術としてはMAP-Eを使っている模様。
IPoE(IPv6)オプションを利用していた時は(公式には情報は何もなかったが)DS-liteでmfeedと繋げてIPv4 over IPv6をすることができた。
今回、方式が変わるのでその対応をしてみた、という話である。
使用機器はYAMAHAのRTX1200。

YAMAHA RTX1200でMAP-E

といっても先人がいろいろと情報を出してくれている。

基本は上記ページの通りにすればよい。
ただ、自身に割り振られたIPv6アドレスによってゲートウェイのアドレス、利用可能なポート番号が変わるのでそこは注意しないといけない。
このあたりの詳細は下記ページに書いてある。

これでIPv6アドレスから各種パラメータを導き出すことが可能になったのだが、割り振られたIPv6アドレスが変わったりするとまたパラメータを導出しなくてはならない。
恐らくIPv6アドレスが変わることはないだろうとは思うが、変わらない保証はない。
変わるたびに手動で導出するのは面倒だったので、割り振られたIPv6ネットワークを引数で与えるとRTX1200のMAP-E関連の設定を出力してくれるスクリプトを作成した。
MAP-Eの仕様については下記資料を参考にした。

スクリプトはこちら。PSIDオフセットとEAビット長は現在の状況からの推測。

#!/usr/bin/python3
# -*- coding: utf-8 -*-

#########################################
# RTX1200用MAP-EのNAT設定出力スクリプト #
#########################################

import sys
from ipaddress import *

ra_net = IPv6Network(sys.argv[1])

## RTXの設定用
# NAT Descriptor番号の開始番号
ndesc = 600000

# Tunnelの番号
tunnel = 1

# 指定可能なポート範囲の個数
# see: http://www.rtpro.yamaha.co.jp/RT/manual/rt-common/nat/nat_descriptor_masquerade_port_range.html
max_portrange_num = 3

## MAP-Eのパラメータ
# Port-set ID Offset
psid_offset = 4

# BRのIPv6アドレス
br_ipv6_addr = IPv6Address("2404:9200:225:100::64")

# Mapping Rule Tableの情報
# (rule_ipv6_prefix, rule_ipv4_prefix, ea_bits_length)
map_rule = [
( IPv6Network("240b:10::/31"),  IPv4Network("106.72.0.0/15"), 25 ),
( IPv6Network("240b:12::/31"),  IPv4Network("14.8.0.0/15"),   25 ),
( IPv6Network("240b:250::/31"), IPv4Network("14.10.0.0/15"),  25 ),
( IPv6Network("240b:252::/31"), IPv4Network("14.12.0.0/15"),  25 ),
]

rule_v6_net = None
rule_v4_net = None
ea_bits_len = None

# Mapping Rule Tableとのマッチング
for rule in map_rule:
if ra_net[0] in rule[0]:
rule_v6_net = rule[0]
rule_v4_net = rule[1]
ea_bits_len = rule[2]
break

if rule_v6_net is None:
print("No matched rules.")

# MAP-E IPv4アドレス、CE IPv6アドレス、PSIDの算出
ea_bits = (int(ra_net[0]) >> (128 - rule_v6_net.prefixlen - ea_bits_len)) & \
((1 << ea_bits_len) - 1) psid_len = ea_bits_len - (32 - rule_v4_net.prefixlen) v4_suffix = ea_bits >> psid_len
map_ipv4_addr = rule_v4_net[0] + v4_suffix
psid = ea_bits & ((1 << psid_len) - 1)
ce_ipv6_addr = ra_net[0] + (int(map_ipv4_addr) << 24) + (psid << 8)

# Port-setの算出
portset = []
prefix_len = 16 - (psid_len + psid_offset)
for i in range(1, 2 ** prefix_len):
port_min = (i << (psid_len + psid_offset)) + (psid << psid_offset)
port_max = port_min + 2 ** psid_offset - 1
portset.append((port_min, port_max))

# output config
descs = []
for i in range(int(len(portset) / max_portrange_num) + 1):
if i * max_portrange_num == len(portset):
break

start_i = i * max_portrange_num
end_i = start_i + max_portrange_num

print("nat descriptor type %d masquerade" % ndesc)
print("nat descriptor address outer %d %s" % (ndesc, str(map_ipv4_addr)))
print("nat descriptor address inner %d auto" % ndesc)
print("nat descriptor masquerade port range %d %s" % \
(ndesc, \
" ".join(map(lambda x: "-".join(map(str, x)), portset[start_i:end_i]))))
print("nat descriptor timer %d 600" % ndesc)
print("nat descriptor timer %d tcpfin 30" % ndesc)
descs.append(ndesc)
ndesc += 1

print("tunnel select %d" % tunnel)
print("tunnel encapsulation ipip")
print("tunnel endpoint address %s %s" % (ce_ipv6_addr, br_ipv6_addr))
print("ip tunnel nat descriptor %s" % " ".join(map(str, descs)))

これの出力を使ってMAP-EによるIPv4 over IPv6の実現はできたのだが、Webサイトを見ていると結構な確率で応答が遅かったりタイムアウトしたりしていた。
原因はポートの枯渇であると容易に推測できた。何せ240個しかIPマスカレードに使えるポートがないのである。OSやらアプリやらWebサイトやらが裏でいろいろなところに繋いでいる昨今ではすぐなくなっても仕方がない。
RTX1200にログインして確認してみると、IPマスカレードの状況はこんな感じだった。

> show nat descriptor masquerade port summary 
Interface Desc Num Outer Address Used / All
------------------- ---------- --------------------------- -----------
PP[01](1) 1 ipcp/aaa.bbb.ccc.ddd 3/20000
TUNNEL[1](1) 600000 xxx.yyy.zzz.www 48/ 48
TUNNEL[1](2) 600001 xxx.yyy.zzz.www 48/ 48
TUNNEL[1](3) 600002 xxx.yyy.zzz.www 48/ 48
TUNNEL[1](4) 600003 xxx.yyy.zzz.www 48/ 48
TUNNEL[1](5) 600004 xxx.yyy.zzz.www 48/ 48
------------------- ---------- --------------------------- -----------

pp 1はPPPoEなので無視。TUNNELがMAP-Eのもの。
見事に使い切っている。いや、何度かやり直してちょうど使い切ってた瞬間のをコピペしたのだけど。
それでもブラウザのタブをせいぜいが10個くらい開いた程度のものである。
スマホやiPad、その他インターネットに繋がるデバイスがあるところではこんなものでは使い物にならないので泣く泣くIPv4通信をPPPoE経由に戻したのである。

Rev.14系以降のファームウェア(RTX1200はRev.10系)ではポートセービングIPマスカレードという機能があって、これを使えばこの問題は解決されるようだ。
市販のv6プラス対応ルータも恐らく同様の機能を有しているのであろう。
しかしRTX1200にはその機能はないのである。
さらばMAP-E。さらばv6プラス。

余談

先週からいろいろと試行錯誤している間に、RTX1210では公式にv6プラス対応のファームウェアが出ていた。

RTX1200にもファームウェアアップデートが出ているが、v6プラス対応もポートセービングIPマスカレード追加も書いてないのでRTX1200だと使い物にならないままだろう。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください