IPv6プラス環境におけるIPv4ポート公開設定

# TL;DR

1. IPv6プラスを有効にすると確かにフレッツ光の混雑を避けることができる（実測4Mbps→75Mbps）が，任意のポートを外部公開（あるいはポート開放，転送，…）することはできない．
2. しかし適切に設定を行えば，混雑回避の恩恵を受けつつ，ポートの外部公開を行うことは可能である．
3. 逆に設定の意味を理解していないと，ポートの解放はできても混雑回避の恩恵は受けられず元の木阿弥になりかねない．

# はじめに

フレッツ光の混雑解消のためにIPv6プラス（[JPNE](http://www.jpne.co.jp/service/v6plus/), [wikipedia](https://ja.wikipedia.org/wiki/V6%E3%83%97%E3%83%A9%E3%82%B9)）を使おう…という[記事](https://internet.watch.impress.co.jp/docs/column/shimizu/1082052.html)が増えたように思うが，一方で「ポート転送によるサーバの外部公開ができない」という指摘も目にする．そこで自らの環境である

* フレッツ光においてIPv6プラス契約をしている．
* サーバ（web, ssh, ...）をIPv4で外部公開するために，ポート転送をしたい．
* ひかり電話対応ホームゲートウェイ（以下HGWと略記．実際にはPR-500KIを使用した）を使っている．

を対象として問題点と解決法を整理する．

# お断り

一晩でエイヤッと調べた内容なので，事実誤認があるかもしれません．なおこの記事はあくまでも「IPv6プラス」について述べたものです．フレッツ光のプロバイダによっては別方式でIPv6接続を提供しています．

※2023-01-01追記　下記の記事・サイトが参考になります．
* [ASCII JP - IPv6とv6プラスの“怪しいウワサ”は本当か？ ファクトチェック](https://ascii.jp/elem/000/004/054/4054082/)
* [ASCII JP - 続・v6プラスの“怪しいウワサ”は本当か？ ファクトチェック](https://ascii.jp/elem/000/004/119/4119250/)
* [IPv4/IPv6接続判定ページ](https://kiriwake.jpne.co.jp/)
  * 実際にIPv6プラスで接続できているかどうかチェックしてくれます．

# 何が問題なのか？

結論から言うと，IPv6プラスを契約した場合，**IPv4アドレスは割り当てられるが，どのポートを転送（外部公開）できるかはプロバイダ側から指定される**．したがって

1. 特定のポートで待ち受けることが期待されるサーバは公開できない．これには２通りのケースが存在する．
    * 一般公開するためには標準的なポートを使うことが望ましい場合．HTTP(80)やHTTPS(443)など．
    * プロトコルとしてポートを変更することが想定されていない場合．PPTP(1723)やL2TP/IPsec(500, 1701, 4500)など．
2. 一方で，指定された（標準とは異なる）ポートで公開しても差し支えないサーバは問題ない．
    * 自分専用など一般公開ではない場合．SSH(22)やOpenVPN(1194), SSTP(443)など．
        * [WireGuard, OpenVPNをつかってIPv6プラス環境でも外出先からひかり電話を使う方法](https://qiita.com/nbhr/items/52da5651e3bfcf2eab60)
        * ただし一般的ではないポート番号への外部通信を許可していないネットワーク環境から接続する場合には，「公開はできているが，出先のネットワークからは接続できない」という状況に陥る可能性がある．たとえばSSHサーバをポート12345番で公開したとして，出先のネットワークがそのポート12345番への外部通信を遮断している場合など．この場合は「1. 特定のポートで～」に該当することになる．

といえる．前者は

1. IPv4のPPPoEを必要な範囲で復活させる，あるいは
2. [ngrok](https://ngrok.com/) のようなサービスを使う

ことで，後者はそのままMAP-Eの利用可能ポートを使用することで解決できる．

## 背景

IPv6プラスを契約すると，IPv4接続はMAP-E方式によるIPv4 over IPv6になる（その結果IPv4 PPPoEの速度低下を避けることができる）．このとき，IPv4接続は多くの利用者でグローバルIPv4アドレスを共有したNATになる．そのため各利用者が好き勝手にポートを指定して（たとえばhttp用のポート80番）自分に転送することを許すようには設計されていない．

しかしMAP-E方式では「各利用者が任意のポートを転送する」ことは許さないものの，「機械的に決められた，ほかの利用者と衝突しない特定のポートを転送する」ことは許されるように設計されている．これがHGWで**利用可能ポート**と呼ばれるポート番号であり，合計240個割り当てられる[^1]．なおこのポート番号はフレッツ契約が続く限り固定される（後述）．

[^1]: IIJなどDS-LITE方式ではこのようなポートが用意されない（らしい）．MAP-E方式ではHGWがNATを行うのに対して，DS-LITEではプロバイダ側でNATをするから？（未確認）

したがってこの利用可能ポートの範囲で公開すれば用をなすのか，あるいは別のポートで公開したいのか，によって解決方法が異なる．

# 方法１：どうしても特定のポートで公開したいのでIPv4 PPPoEを復活させる

上記利用可能ポート以外の，例えば80番など特定のポート番号で外部公開をするためにはIPv4 PPPoEを復活させるしかない（要確認）が，この場合は「どのパケットをIPv4 PPPoEにルーティングするか」が重要になる．

つまりもともとフレッツ光の混雑を避けるためにIPv4 over IPv6を使っていたにもかかわらず，ほとんどの通信をIPv4 PPPoEにルーティングしてしまっては本末転倒である…

## 方法1-1：HGWでIPv4 PPPoEを復活させる（非推奨）

IPv4 over IPv6を停止すると，再びIPv4 PPPoEが有効になり（有効にしなければIPv6サイトにしか接続できない），任意のポートを転送できる．ただしこの場合，IPv6対応サイト（Googleなど）への接続はIPv6接続となるものの，IPv4のみ対応のサイト（ほとんどのサイト）へは従来のPPPoE接続になる．つまり混雑回避を目的としている場合には意味をなさないが，検証用あるいは速度低下を受け入れる場合のために設定方法を述べる．

1. http://192.168.1.1:8888/t/ を開き「IPv4設定」ボタンを押す　⇒　http://192.168.1.1:8888/enabler.ipv4/frame に遷移する
2. 左のメニューから「高度な設定」を選択
3. 右に表示された「IPv4の一時停止」の「機能停止」にチェックを入れて「設定」ボタンを押す
4. IPv6プラス導入前と同様に，設定画面 http://192.168.1.1/ にて改めてポート転送の設定を行う


## 方法1-2：別ルータでIPv4 PPPoEをする

いくつかのサイトで紹介されているように，IPv4 PPPoEに対応したルータを別途導入し，公開したいサーバからのトラフィックのみをIPv4 PPPoE側に流せばよい．なおこの方式であればMAP-EではなくDS-LITE方式のIPv4 over IPv6でも対応できる．

参考になるサイト：
* https://tabikumo.com/ipoe_dslite_conf/
* https://bike8615.blogspot.jp/2017/11/v6_20.html

## 方法1-2-1：個別機器（Raspberry Piなど）でIPv4 PPPoEをする

特殊例として，仮に公開したいサーバが１台だけの場合，別ルータでPPPoEを行ってその配下に公開したいサーバを置くのではなく，そのサーバ自身がPPPoEセッションを張ってもよい．例えばRaspberry Pi（というよりもdebian系）であれば，

```
$ sudo apt-get install pppoe pppoeconf
$ sudo pppoeconf
```

として，PPPoEのユーザ名とパスワードを設定すればよい．この時点で

```
$ ip addr show ppp0
```

でPPPoEに割り当てられたIPv4アドレスを確認できるはず．またデフォルトゲートウェイがeth0のままかもしれないので，もしppp0にしたいなら`/etc/ppp/ip-up.d/99gateway`など適当なスクリプトを作って直接設定する必要がある．

この方法の場合，たとえばSSHサーバを所望のポート（本来の22番，[SSLH](https://github.com/yrutschle/sslh)を使って443番，など）で公開することができる．

ただしppp0は直接インターネットに公開されるため，適当なパケットフィルタを設定することが望ましい．例えば[ufw](https://help.ubuntu.com/community/UFW)を使うなら，

```
$ sudo apt-get install ufw
$ sudo ufw limit 22
$ sudo ufw enable
```

など．

# 方法２：MAP-Eの「利用可能ポート」を使う

1. http://192.168.1.1:8888/t/ を開き「IPv4設定」ボタンを押す　⇒　http://192.168.1.1:8888/enabler.ipv4/frame に遷移する
2. 左のメニューから「静的NAPT設定」を選択
3. 右に表示された「公開対象ポート」，「宛先アドレス」，「宛先ポート」を適切に設定する

なお利用可能ポートは上記の「IPv4設定」画面に表示される．また下記のコメントによると，このポートはIPv6のプレフィックスから自動計算され，またフレッツ契約が続く限りは変更されない．

https://mao.5ch.net/test/read.cgi/isp/1502319985/958

> 利用可能ポートは一契約あたり240個(61440個/256人)に制限されていて、下記の通りIPv6/64プリフィックス第4フィールド上位byteの数値(下記式ではXXとした)で割り当てが管理されている。 
> プリフィックスは契約者固有なのでXXも同様。 
> 
> ・IPv6/64プリフィックスとXX 
> ----:----:----:XX--::/64 
> 
> ・利用可能ポート番号 
> Hex(aXXb) 
> a=1～F 
> b=0～F 
> XX=00～FF 
> 
> ※XX=00の場合(aで)15分割されたうちの最初(a=0)の範囲は 4096～4111 となる 
> ※まずは診断くん( http://re.pdata.jp/ ) で自分のXXを確認してみよう

つまり最小値`X_0 = 0x1XX0`が自分のIPv6プレフィックスから決まると，あとは

* `X_0`～`X_0 + 15` (= `0x1XXF`)
* `X_0 + 4096` (= `0x2XX0`) ～ `X_0 + 4096 + 15` (= `0x2XXF`)
* ...

と4096おきに16個ずつのブロックでポートが指定される．実際に手元のIPv6アドレスから計算すると，たしかにHGW画面に表示された利用可能ポートと一致した．

# まとめ

以上をまとめると，各方法のメリット・デメリットは以下のようになる．手元環境では方法２に落ち着いた．方法１より明らかにダウンロード速度が速い．

|   |1-1: HGWでIPv4 PPPoE|1-2: 別ルータでIPv4 PPPoE|2: MAP-Eの利用可能ポート|
|:--|:-------------------|:-----------------------|:----------------------|
|公開できるポート|任意|任意|指定された240個のみ|
|必要な機材|HGW|別ルータ|HGW|
|混雑回避|×（IPv4パケットはすべて従来のPPPoEセッションに流れる）|〇（公開したいトラフィックのみIPv4 PPPoE側に流れる．ほかのパケットはIPv6側）|◎（すべてIPv6側に流れる）|
|スピードテスト結果[^2]|DL:4.44Mbps, UL:302.8Mbps（ngn.ppp.infoweb.ne.jp経由）|未検証（原理的にはPPPoEで公開したポートについては左，それ以外の通信は右の結果になるはず）|DL:75.2Mbps, UL:301.5Mbps (v4.enabler.ne.jp経由)|

[^2]: 2018年1月14日（日），夜10:30ごろに[Googleのインターネット速度テスト](https://www.google.co.jp/search?q=スピードテスト)にて計測