さくらのクラウドでのIPv6対応

#概要
さくらのクラウドでIPv6対応を行うという機会があったので、必要な対応についてまとめます。
なお現時点(2018年8月)では全てのインフラ機器についてIPv6対応がされているわけではないようです。今後対応される可能性もあるので、あくまで参考事例として最新のドキュメントを確認してください。

#TL;DR
結構IPv4と同じようにいかない所が多く辛いです。ハマるポイントを先に知りたい場合は下の[#ハマる所のまとめ](#ハマる所のまとめ)を読んでください。

#IPv6対応の大まかな手順
IPv4で接続できているサーバーをIPv6でも接続できるようにするのがゴールです。
基本的に以下のような手順になるかと思います。

1. IPv6アドレスの取得
2. ネットワーク機器の設定
3. サーバーの設定
4. ミドルウェアの設定
5. アプリケーションの設定
6. DNSの設定
7. 検証

#さくらのクラウドでの対処
##環境
今回は以下のような環境で行いました。
よくあるロードバランサで複数サーバーに振り分けており、WebサーバーはubuntuでPHPのアプリケーションを動かしています。

### 構成
  - ロードバランサ
  - ルーター+スイッチ
  - クラウドサーバ（Ubuntu16.4）

### ミドルウェア
  - nginx1.10
  - php-fpm7.0
  - php7.0

## IPv6アドレスの取得
[IPv6アドレス | さくらのクラウド](https://manual.sakura.ad.jp/cloud/network/switch/ipv6.html)
公式ドキュメントに準じて、ルータ＋スイッチでIPv6アドレス割り当て機能を使えば割り当てられます。IPv6アドレス割り当て範囲が確認できるので、その中から割り当てるIPを決めます。割り当て範囲が

```
XXXX:XXXX:XXXX:XXXX::4〜
```

として、ネットワークマスクが

```
XXXX:XXXX:XXXX:XXXX::0/64
```

だと

```
XXXX:XXXX:XXXX:XXXX:0000:0000:0000:0004 - XXXX:XXXX:XXXX:XXXX:ffff:ffff:ffff:ffff
```

までが使用可能になります。今回はXXXX:XXXX:XXXX:XXXX::4を割り当てIPとします。

なお、今回はルータ＋スイッチに繋がっていたから良いものの共有セグメントに繋がっているサーバーについては現状IPv6を利用できないようです。ルータ＋スイッチを挟むか、IPv6をIPv4に変換するようなプロクシを挟む必要があります。

## ネットワーク機器の設定
まず、ロードバランサは現状IPv6に対応していません。。。振り分けをしたいのであればDNSラウンドロビンにし、ロードバランサを経由しないようにするしかありません。
ルータ＋スイッチについてはIPv6アドレス取得を既に行なっているので設定不要です。IPv4の時の様にどのIPに接続するかの指定はなく、現状逆引きのみ設定できるようです。必要であれば逆引き設定を行ってください。

## サーバーの設定
### ファイヤウォール
今回はubuntuでufwを使っています。Webサーバーなので80と443は全許可になってますが、デフォルトでIPv4とIPv6両方に対応されてました。IPv4のみの設定になっている部分があれば対処が必要かと思います。

### ネットワーク
サーバーのネットワーク設定をします。
以下Ubuntu16での例になります。既にIPv4での設定があるので、それに追記します。

```/etc/network/interfaces
# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
auto eth0
iface eth0 inet static
address XXX.XXX.XXX.XXX
netmask XXX.XXX.XXX.XXX
gateway XXX.XXX.XXX.XXX

#ここから先を追記
iface eth0 inet6 static
address XXXX:XXXX:XXXX:XXXX::4
netmask 64
gateway fe80::1
```

ネットワークを再起動します。なお実際にやった時はサーバーを再起動してしまったのですが、以下のコマンドでもいけたかもしれません。

```
ifdown eth0 && ifup eth0
```

余談ですが、ubuntu18でも同様の対応をやったのですが、ubuntu18からnetplanを使っており設定方法が全く違うので注意が必要です。設定及び再起動は以下のようになります。

```/etc/netplan/01-netcfg.yaml
network:
  ethernets:
    eth0:
      addresses:
        - XXX:XXX:XXX:XXX/28
        - XXXX:XXXX:XXXX:XXXX::4/64
      dhcp4: 'no'
      dhcp6: 'no'
      gateway4: XXX:XXX:XXX:XXX
      gateway6: fe80::1
      nameservers:
        addresses:
          - XXX:XXX:XXX:XXX
          - XXX:XXX:XXX:XXX
        search:
          - localdomain
  renderer: networkd
  version: 2
```

```
netplan apply
```

## ミドルウェアの設定
今回nginx1.10だったのですが、ビルド時にオプション指定しておらずビルドをし直す必要がありました。。。1.10の時点だとwith-ipv6というオプションをつける必要がありましたが、現行の最新(1.15.2)では既にこのオプションはdeprecatedになってます。今回はnginxのバージョンをあげて対処をしました。

またnginxのコンフィグも
listen 80;
の記述に加え
listen [::]:80;
の記述が必要です。(443についても同様)。設定して再起動します。

## アプリケーションの設定
ここは特段何も必要がないはずなのですが、今回の場合IPv4を前提としたロジックが一部組まれており対処が必要でした。。。IPで国を判定したり、権限設定をしたり等IPで何かを判別する処理がある場合は注意が必要です。

## DNSの設定
ここに関しては、さくら関係なくDNSのレコード設定をすれば良いはずです。
DNS設定でAAAAレコードを設定してください。
ただし既に本番で動いているアプリケーションに関しては設定が反映されたタイミングからIPv6でのアクセスが来だすのでこの時点で IPv6でのアクセスができている事を確認する必要があります。

## 検証
IPv6が使える回線でテストできればなんら問題はないのですが、残念ながらそうではありませんでした。
今回は別途IPv6が使えるサーバーを立てて、そこにsquidを入れてIPv4->IPv6に変換できるプロキシを作成して対処しました。記事が長くなるのでここはいずれ別記事にまとめます。
ドメインの検証だけであれば以下でも可能です。
http://ipv6-test.com/validate.php

# ハマる所のまとめ
実際に困った所、困らなかった所含めハマるポイントをまとめると以下のようになります。

- ロードバランサはIPv6対応していない。振り分けはDNSラウンドロビンでやるしかない。
- 共有セグメントだとIPv6使えない。ルータ＋スイッチに繋ぐしかない。
- ミドルウェア（今回nginx1.10）がIPv6対応していない。最悪ビルドし直し、少なくとも設定の変更は必要。
- アプリケーションがIPv4前提でバグる。対処が必要。
- 現在の回線がIPv4接続オンリーで検証できない。プロクシを立てるか外部のツールを使うしかない。

# 感想
アプリの審査に落ちるからちょっとIPv6対応してよという所から軽く始まり、さくらのクラウドもIPv6対応しているみたいだしまあ大丈夫だろうと対応を始めたのですが、思っている以上にトラブルがあり時間を取られました。実際に本番稼働していてかつメンテナンス状態にできないorしづらいシステムだとさらに大変だと思います。余裕を持って取り組むことをお勧めします。