IPv6 only ネットワーク を作ってみる

VMware Workstaion 12.5 を使って、複数の仮想マシンで構成されるネットワークを作っていきます。このネットワークは今流行の IPv6 only のネットワークにしてみたいと思います。この過程で NAT64/DNS64 をセットアップしていきます。

構成について

VMware Workstaion で新規仮想マシンを作る際に、ネットワーク接続を LAN セグメント で作成します。
外とやりとりを行う NAT64 の部分についてのみネットワークアダプタを2つ準備して、一方を NAT なり, ブリッジなりのタイプを設定して外との通信をできるようにします。
そして、作成した “LAN セグメント” の部分を IPv6 only のネットワークとします。ここに所属する仮想マシンは IPv6 のみをもって通信を行います。

これらの関係を図にすると以下のような感じになります。

IPv6 only ネットワークのキモはこの NAT64, DNS64 を担当する Linux サーバーということになります。図中では記入漏れていますが、このサーバーでは IPv6 の DHCP も担当させています。

お断りですが、IPv6 only といっても自分の現環境が IPv4 のみのネットワークのため、IPv6 で外部との通信を行う部分について 実験できずです。

NAT64/DNS64 とは

各所で詳しく説明されている部分なのでご存じの方も多いと思います。
要は IPv6 クライアントのために NAT64/DNS64 を担当している部分が IPv4/IPv6 の橋渡しを頑張ってくれるというものです。具体的には、 IPv6 クライアントからの要求により DNS64 が IPv4 での IP を取得してきますが、これを特定のプレフィックスをつけた状態で IPv6 のように見えるアドレスを生成してクライアントに返します。クライアントは返されたアドレスに対して接続を行いますが、 途中経路にある NAT64 により IPv4 のアドレスが取り出されて接続するという仕組みになっています。

そもそもこの構成は、IPv6 のみを提供する通信事業者が現れたときのことを想定しています。そのときにまだ IPv4 ネットワークは生き残っているでしょうし、そのときにはこのような仕組みで双方アクセスを可能にするといったことになるでしょう。

現在の iPhone のアプリ開発のためには IPv6 only network でも正しく動作することが求められています。IPv6 専用の環境ってそう遠くない未来の話になっているのかもしれません。

Linuxサーバー準備

キモである NAT64/DNS64 の Linux サーバーを構築します。ここでは Ubuntu 16.04 LTS (正確には 16.04.1) 64bit 版を使用しました。
まずは ネットワークインターフェースは1つで、NAT タイプで構築しておきます。

DNS64のセットアップ

unbound をインストールします。DNS64は 1.5 からのサポートとなっているようですが、 Ubuntu 16.04 の環境では apt でインストールされるものが 1.5 系で簡単にインストールできました。

$ sudo apt install unbound

設定ファイルを新規に作成します。ここでは、 /etc/unbound/unbound.conf.d/dns64.conf を作成して、中身を以下のように記入しました。

server:
  verbosity: 2
  pidfile: "/var/run/unbound.pid"
  use-syslog: yes
  module-config: "dns64 iterator"
  dns64-prefix: 64:ff9b::/96
  dns64-synthall: yes
  access-control: ::0/0 allow

forward-zone:
 name: "."
 forward-addr: 8.8.8.8

verbosity が 2 だったり use-syslog: yes にしているのは、うまく動かなかったときに、/var/log/syslog を確認するためです。設定が終わったら、サービスを再起動しておきます。

$ sudo systemctl restart unbound.service

動作確認

今回準備したサーバーに対して DNS 問い合わせを行ってみます。dig コマンドを使って確認するべきかもしれませんが、結果が見やすかったので host コマンドで確認してみました。

まず現時点で AAAA を持っていない yahoo.co.jp について Google の public DNS に問い合わせてみました。

$ host -t AAAA www.yahoo.co.jp 8.8.8.8
Using domain server:
Name: 8.8.8.8
Address: 8.8.8.8#53
Aliases: 

www.yahoo.co.jp is an alias for www.g.yahoo.co.jp.

これを今回準備した Unbound 経由で問い合わせてみます。

$ host -t AAAA www.yahoo.co.jp localhost
Using domain server:
Name: localhost
Address: 127.0.0.1#53
Aliases: 

www.yahoo.co.jp is an alias for www.g.yahoo.co.jp.
www.g.yahoo.co.jp has IPv6 address 64:ff9b::b74f:c64f
www.g.yahoo.co.jp has IPv6 address 64:ff9b::b74f:c674
www.g.yahoo.co.jp has IPv6 address 64:ff9b::b74f:83d4
www.g.yahoo.co.jp has IPv6 address 64:ff9b::b74f:179e

このように IPv4 アドレスの頭に設定したプレフィックスがついた IPv6 アドレスが返るようになっています。

DHCPv6のセットアップ

IPv6 の仕組みでは RA(Router Advertisement) によりアドレスを割り当てることが可能です。デフォルトゲートウェイやネットワークアドレスの情報をルータから各機器にセットすることができるようになっています。しかし今回は各クライアントに対して DNS64 のサーバー情報も降らせたいので DHCPv6 を準備することにしました。

アダプタの追加

この先の動作確認ためには、2つめのネットワークアダプタを追加する必要があります。ここで2つめのネットワークアダプタを作成して、IPv6 専用の LANセグメントに所属させておきます。

また、動作確認のためには、クライアントも存在した方がいいので IPv6 only の LAN セグメントのみに所属した環境を作っておくこともオススメします。ひとまず Ubuntu 16.04.1 を標準インストールした仮想マシンを準備したとして話を進めていきます。

radvd

IPv6 アドレスを配るための IPv6 Router Advertisement Daemon (radvd)をインストールします。

$ sudo apt install radvd

IPv6 の forwarding が有効になっているかを確認します。

$ sysctrl net.ipv6.conf.all.forwarding
net.ipv6.conf.all.forwarding = 0

上記のように 0 だった場合には無効となっているので、以下のコマンドで有効化します。

$ sudo sysctl -w net.ipv6.conf.all.forwarding=1
net.ipv6.conf.all.forwarding = 1

これを忘れると radvd を起動したときにうまくいかず、悩まされます。忘れたときには syslog に以下のメッセージが出ているのですが、自分が試したときには標準出力コンソールに出てくれず、気付くのに時間がかかりました。

 * radvd will *not* be started.
 

この設定を永続化するために設定ファイル(/etc/sysctl.conf) を編集します。
Ubuntu 16.04 の環境ではコメントアウトされていたので、net.ipv6.conf.all.forwarding=1 が書かれた行を有効化しました。

# Uncomment the next line to enable packet forwarding for IPv6
#  Enabling this option disables Stateless Address Autoconfiguration
#  based on Router Advertisements for this host
net.ipv6.conf.all.forwarding=1

続いて radvd のための設定ファイルを作ります。 /etc/radvd.conf ファイルを新規作成してください。

$ sudo nano -w /etc/radvd.conf

interface ens37 {
  AdvSendAdvert on;
  MinRtrAdvInterval 3;
  MaxRtrAdvInterval 10;
  prefix fc01:0:0:1::/64 {
    AdvOnLink on;
    AdvAutonomous on;
  };
};

上記のように設定してみました。インターフェースは各自の環境に合わせたものに変更してください。
ここでは ifconfig で確認したインターフェースで、 IPv6 側のネットワークのほうのものを設定しています。

本体ならば事業者から割り当てられるIPv6 プレフィックスを上記のプレフィックス部分に設定した方が IPv6 ルータらしくなると思いますが、
ここでは閉じたIPv6 世界でもあるので、プライベートアドレス相当のものをつけてみました。
iPhone 開発用の Mac El Capitan の NAT64/DNS64 の事例にならうのであれば、プレフィックス部分には、 “2001:2:0:aab1::/64” を設定することも考えられます。

サービスの起動・再起動を行います。

$ sudo systemctl restart radvd.service 

起動成功のメッセージが出ていても念のため syslog でのエラー確認もしておきましょう。

しばらくして自身のアドレスを確認してみましょう。 IPv6 アドレスが先ほど指定したプレフィックスで設定されているようなら成功しています。

$ ip addr show
...
3: ens37:  mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:56:34:12 brd ff:ff:ff:ff:ff:ff
    inet6 fc01::1:ccd2:38e9:18fb:6487/64 scope global temporary dynamic 
       valid_lft 86400sec preferred_lft 14400sec
    inet6 fc01::1:1e3f:939f:b4e7:8645/64 scope global mngtmpaddr noprefixroute dynamic 

上記の確認を同じ IPv6 セグメントに設定した他のマシンからも行い、プレフィックスが同じ IPv6 アドレスが設定されているか確認してみましょう。
また、互いに得られたアドレスに対して ping6 を打ってみるのも動作確認としてやりたくなりますね。

DHCPv6 のセットアップ

isc-dhcp-server をインストールして使用します。ただこの ISC 開発が停止されるそうで、後継は KEA-DHCP というものらしいですが、情報の多さからここでは isc-dhcp-server を使っていきます。

$ sudo apt install isc-dhcp-server

クライアントからの DNS サーバーとして本サーバーを使用するため、IPアドレスの固定を行っておきます。ipアドレスの固定のために /etc/network/interfaces を編集しました。

auto ens37
iface ens37 inet6 static
  address fc01:0:0:1::1
  netmask 64

続いて /etc/default/isc-dhcp-server を開きます。編集するのは OPTIONS, INTERFACES の部分です。インターフェースの指定は各自環境に合わせて読み替えてください

OPTIONS="-6"
INTERFACES="ens37"

/etc/dhcp/dhcpd6.conf を開いて以下のように編集します。

default-lease-time 600;
max-lease-time 7200;

subnet6 fc01:0:0:1::/64
{
  option dhcp6.name-servers fc01:0:0:1::1;
}

ここでは DHCP の割り振るサブネットの指定と DNS サーバーとしてのアドレスを設定しています。そのため、今までに指定した値と同じものをそれぞれに設定する必要があります。

カラのファイルを作っておきます。

$ sudo touch /var/lib/dhcp/dhcpd6.leases

DHCPの起動時に失敗する場合には、この作成したファイルのパーミッションが悪い可能性があります。
エラー時には root.dhcpd の所有権になっているかを確認しましょう。

そして、先ほどの radvd の設定ファイルを再度編集します。

# /etc/radvd.conf
interface ens37 {
  AdvSendAdvert on;
  MinRtrAdvInterval 3;
  MaxRtrAdvInterval 10;
  AdvOtherConfigFlag on;
  
  prefix fc01:0:0:1::/64 {
    AdvOnLink on;
    AdvAutonomous on;
    AdvRouterAddr on;
  };
};

これで radvd と DHCP サーバーの再起動を行います。

$ sudo systemctl restart radvd
$ sudo systemctl restart isc-dhcp-server

サーバーが起動してうまく DHCPv6 が機能しているかを確認します。
自分自身で確認ができないので、別の仮想マシンから確認します。

前に準備しておいた別の仮想マシン Ubuntu をここで再起動して、この DHCP サーバーからアドレスやDNS情報が取れるかを確認します。

ネットワークマネージャから情報を表示させてみると以下のようになっていました。
アドレスと、DNSの情報が今回設定してきた DHCP サーバーからのものになっていれば成功です。

この状態だとこのクライアントから先ほどの host コマンドによる名前解決もそのまま使えるようになっています。このとき、 IPv4 ホストのアドレスが 64:ff9b:xxxx で表示されていれば DNS64 の機能が有効であることも確認できるかと思います。

NAT64のセットアップ

この NAT64 のセットアップが終われば各IPv6 only ネットワークに属するクライアントから IPv4 へのアクセスが可能になります。この NAT64 の機能を提供する Jool を使用して、設定を行います。これで IPv6 only network を構成するシステムが完成します。

Jool に必要になるパッケージを先にインストールします。

$ sudo apt install git dkms build-essential pkg-config autoconf libnl-3-dev libnl-genl-3-dev

続いて Jool のソースを取得して dkms でインストールを行います。

$ git clone https://github.com/NICMx/Jool.git
$ sudo dkms install Jool

ユーザースペースアプリというものがあるので、これも準備します。

$ cd Jool/usr
$ ./autogen.show
$ ./configure
$ make 
$ sudo make install

以下のコマンドで起動します。pool4=自分のIPv4 アドレス、pool6 に指定しているのは先につけたプレフィックス値となっています。

sudo modprobe jool pool6=64:ff9b::/96 pool4=192.168.243.138

jool コマンドで 現在のセッション情報を確認することができます。

$ sudo jool -s

動作確認

ようやく IPv6 only ネットワークのために必要なサーバーが構築できました。IPv6 ネットワークにいる他クライアントを再起動してみて適当にアクセスしてみましょう。

クライアントは IPv6 の世界で動いており、IPv4 のアドレスを持ちません。
しかし内部では名前解決で特定プレフィックスのついた一見 IPv6 アドレスが返ってきて、これを元に NAT64 経由して IPv4 経由でのアクセスが実行され結果が表示されると思います。

この状態を NAT64 のマシンでjool コマンドにより確認してみるとセッション情報が出てきます。

 :
 :
---------------------------------
(V6_FIN_RCV) Expires in 1 hours, 41 minutes
Remote: 183.79.249.252#http	fc01::1:9c6b:89af:5ca2:194e#41520
Local: 192.168.243.138#41437	64:ff9b::b74f:f9fc#80
---------------------------------
(V6_FIN_RCV) Expires in 1 hours, 41 minutes
Remote: 183.79.249.124#https	fc01::1:9c6b:89af:5ca2:194e#46284
Local: 192.168.243.138#48473	64:ff9b::b74f:f97c#443
---------------------------------
(V6_FIN_RCV) Expires in 1 hours, 41 minutes
Remote: 182.161.72.66#http	fc01::1:9c6b:89af:5ca2:194e#32906
Local: 192.168.243.138#57274	64:ff9b::b6a1:4842#80
---------------------------------
  (Fetched 20 entries.)

UDP:
---------------------------------
  (empty)

ICMP:
---------------------------------
  (empty)

試しに、 クライアントで Ubuntu の言語パックを入れて日本語の環境を整えてみましたが問題なく処理を行うことができました。

ブラウジングも問題なくできますが、実際のところは IPv4 のため、以下のように KAME Project で確認してみるとこのようになります。

経路の確認

自分が長らく気付かなかったポイントです。route -n コマンド実行を使ってよく経路を確認するのですが、これが IPv6 の情報を表示せず、IPv4 の設定をしていない場合では全く情報を出さないのでしばらく悩まされました。

正しくは route -A inet6 とオプションを指定して実行することが必要でした。これで経路の確認が以下のように表示されました。

$ route -A inet6 
Kernel IPv6 routing table
Destination                    Next Hop                   Flag Met Ref Use If
fc01:0:0:1::/64                ::                         U    100 2   429 ens33
fe80::/64                      ::                         U    256 0     0 ens33
::/0                           fe80::20c:29ff:fe04:3434   UG   100 2     3 ens33
::/0                           ::                         !n   -1  1  2083 lo
::1/128                        ::                         Un   0   2     2 lo
fc01::1:9c6b:89af:5ca2:194e/128 ::                         Un   0   3 47180 lo
fe80::466:d82:ab79:288c/128    ::                         Un   0   3   111 lo
ff00::/8                       ::                         U    256 2   285 ens33
::/0                           ::                         !n   -1  1  2083 lo

まとめ

長くなりましたが、 IPv6 のネットワークを構築することが出来ました。
また外側は IPv4 のままですが、NAT64/DNS64 を準備することで、IPv6 Only なネットワークからも、各ウェブへのアクセスも出来るようになりました。割とスムーズにこのようなものが構築でき、十分実用になってきている IPv6 について、時期尚早という言葉はもう使えないなということを実感しますね。ちゃんと勉強しなくては、と思いました。

サーバー構築
すらりんをフォローする
すらりん日記

コメント

タイトルとURLをコピーしました