連載 しきぶろぐ開設の道筋
- v6プラス(DS-Lite)環境下でIPv4/IPv6両対応の自宅サーバーを公開する
- ラズパイにWordPressを導入する
- AWS Route53 でドメインを取得し、DDNS っぽく運用する
- ブログをcertbotでHTTPS対応する
しばらく何にも使われず眠っていた Raspberry Pi 4B (2GB) でブログを公開しようと思い立った式部。「一年無料」の広告に踊らされて楽天ひかりを契約し、高速インターネットに歓喜していた数か月前には思いも至らなかった、IPv6環境におけるサーバー公開の困難が次々と式部を襲う!
きっかけ
かねてからブログを公開してみたいと思っていたので、せっかくならばとクラウド全盛期のご時世にあえて自宅サーバーを使ったブログ公開に挑戦しました。
なんとなく、ポート開放で80番を開ければいいものとタカをくくっていましたが、世はIPv4からIPv6への移行期。自宅のインターネットがIPv6環境であったことから、不勉強なりに聞きかじった知識が全く通用せず想像以上の泥沼に嵌りましたが、なんとか公開にこぎつけたので、ここに一部始終をまとめておきます。参考までに、我が家のインターネット環境は以下の通り。
- 楽天ひかり
- ひかり電話等の契約はナシ
- 無線LANルーターは、楽天推奨の「クロスパス対応」ルーター
実現したいこと
- ラズパイ4Bを自宅サーバーとする
- サーバーに対してIPv4環境・IPv6環境の両方からアクセスできる
- PCやスマホなどサーバー以外の機器は、混雑しにくいIPv6経由でインターネットにつながる
ネットワーク構成
無線LANルーターの上流にスイッチングハブ(L2スイッチ)を挟んで、WAN側をルーターとラズパイの2方向に繋ぎこむことが特徴です。IPv6パケットは無線LAN経由でラズパイのWi-Fiインターフェース(wlan0)に出入りする一方、IPv4パケットはラズパイが eth1 上に構築したPPPoEセッション(ppp0)に出入りする構成になっています。これにより、IPv4/v6両方の環境からラズパイにアクセスできます。
なお、ラズパイのオンボードLAN端子である eth0 はパケットキャプチャの用途で今後使おうと思っていたので、USB-Ethernetアダプタで増設した有線LANインターフェイス eth1 をスイッチングハブに接続しました。
ラズパイの準備
すでにラズパイの初期設定が終わっており、SSHやVNCで操作できるものとします。この章はラズパイを持っていれば済んでいる場合も多いと思うので手短に。
IPアドレス固定
今回は図のとおり、ラズパイのIPアドレスを 192.168.0.64 としました。こちらのページにそって、IPv4アドレス、デフォルトゲートウェイ、DNSサーバを固定しました。
SSHの公開鍵認証化とポート番号変更
これもラズパイの初期設定の一環で済んでいることが多いです。ラズパイのコマンドラインを外部から操作するツールであるSSHについて、セキュリティの観点からパスワード認証を無効化し公開鍵認証に切り替えます。また、ポート番号をデフォルトの22番から変更することで安全性を高めます。こちらのページにそって実行しました。
ファイアウォールの設定
次章の「ルーターの設定」を終えるとラズパイを含む自宅内のネットワークが外部に公開されるので、不正なアクセスを防ぐためにファイアウォールを導入します。
ファイアウォールアプリ ufw の導入
sudo apt install ufw
最初は無効であることを確認
ファイアウォールの設定手順として、「まず全てのアクセスを遮断」→「必要な物のみ許可」を辿ります。最初にファイアウォールが無効であることを確認して設定を始めないと、ラズパイへのSSH接続もろとも遮断されるので気を付けます。
sudo ufw status
Status: inactive
と出ればOKです。
公開したいポートからのアクセスを許可
まずは全てのポートの接続を拒否します。
sudo ufw default deny
必要なポートだけを開放していきます。今回開放したのは、
- SSH:自分で変更したポート番号
- VNC:5900番(ローカル環境からのみ許可)
- HTTP:80番
- HTTPS:443番
の4つです。使うコマンドは以下の2つです。後者はポート番号への接続をローカルからのみ許可します。
sudo ufw allow [ポート番号] sudo ufw allow from 192.168.0.0/24 to any port [ポート番号]
ファイアウォールを有効化します。
sudo ufw enable
ラズパイを再起動すると、ファイアウォールが有効になります。sudo ufw status
で確認しました。
$ sudo ufw status To Action From -- ------ ---- xxxxx ALLOW Anywhere 5900 ALLOW 192.168.0.0/24 80 ALLOW Anywhere 443 ALLOW Anywhere xxxxx (v6) ALLOW Anywhere (v6) 80 (v6) ALLOW Anywhere (v6) 443 (v6) ALLOW Anywhere (v6)
なおラズパイ以外のPCについても、OSが提供するファイアウォールがデフォルトで有効になっていると思いますが、念のため確認しましょう。
IPv6環境からのアクセス
まず、ラズパイに対してIPv6環境からアクセスできるようにします。目標は、図のような経路でIPv6パケットを通すことです。
ルーターの設定でIPv6パケットフィルタを無効化する
一般的なルーターでは、セキュリティ確保のためインターネット側からのアクセスを遮断する機能(IPv6パケットフィルタ)が有効になっています。外部にホームページを公開するためには、この機能を無効化します。我が家のIODATA製品の場合、設定画面の「セキュリティ」>「IPv6 SPI」を「無効」にします。以上により、ルーター配下の機器がIPv6インターネットに対して野ざらしとなり、IPv6アドレスが分かればアクセスできる状態になります。
疎通確認
ラズパイのIPv6アドレスを確認します。
$ ifconfig wlan0 wlan0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.0.64 netmask 255.255.255.0 broadcast 192.168.0.255 inet6 fe80::23c5:73d3:c1ba:53e0 prefixlen 64 scopeid 0x20<link> inet6 2001:f70:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx prefixlen 64 scopeid 0x0<global>
inet6 と書かれたもののうち、fe80 から始まるものではないほうがグローバルIPv6アドレスです。このアドレスを使えば世界中どこからでもラズパイに繋がるはずなので、試します。
PCをテザリングで4G回線に繋ぎ、PCとラズパイが別ネットワークにある状況で、先ほど調べたラズパイのグローバルIPアドレスにpingします(スマホの回線がIPv6に対応している必要があります。4Gで ipv6-test.com にアクセスすると確認できます)
C:\Users\user>ping 2001:f70:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx
応答があれば成功です。これで、ラズパイにIPv6環境からアクセスすることができました!
[column] IPv6アドレスは原則いつもグローバル
IPv4では、宅外との通信はルーターのWAN側に対してISPから一つだけ割り当てられてたグローバルIPアドレスによって行われています。いっぽう宅内LANに存在するPCやスマホには、192.168 から始まるプライベートIPアドレスが機器ごとに割り当てられており、例えば宅内PCからインターネットに向かって送出したパケット(送信元アドレスは192.168.xx.xx)は、ルーターの NAT (Network Address Translation) と呼ばれる機能で送信元アドレスがグローバルIPアドレスに書き換えられてインターネットへと送り出されます。逆に、外部からルーターへやってきたパケットは、宅内LAN側の機器が送出したリクエストに対する応答に限ってLAN内へと通され、そうでないものはルーターによって遮断されます。これでは外部からやってきたパケット(HTTPを公開するなら80、マイクラのサーバーなら25565、etc)がLAN内の機器へと到着できないので、俗にいう「ルーターのポート開放」を行い、特定のポートに対する通信をLAN内へと通すことで、外部からのアクセスを可能にします。
ところがIPv6の世界では、いくつかの方法によって各機器に設定されたIPv6アドレスは、ルーターでNATが行われず、インターネットに対してやり取りするアドレスとしてそのまま用いられます。ためしに IPv6 test に家からアクセスすると、IPv4ではipconfig
で見える自分のIPアドレスとは異なるアドレスからのアクセスとなっていますが、IPv6では自分の一時IPv6アドレスがそのまま見えています。なお、一時IPv6アドレスではない無印のIPv6アドレスは、端末のMACアドレスから生成される端末固有のもので容易に追跡ができてしまうので、インターネットへのアクセスには定期的に変更される一時IPアドレスが使われるようです。
何はともあれ、原理上は自分のIPv6アドレスがインターネットに対して野ざらしなので、外出先からでも IPv6 アドレスひとつで簡単にアクセスできるのです。
IPv4環境からのアクセス
世の中にはIPv4しか使えない環境も多く存在します(たとえば通学先の学内ネットワークはIPv6非対応です)ので、IPv4環境からもラズパイにアクセスできるようにします。
ところが我が家のような IPv4 over IPv6 方式の下では、俗に言うルーターのポート開放ができないそうです。したがって、IPv4環境から発せられたラズパイへのアクセスを無線LANルーター経由でラズパイに届けることはできないのです。
対応策を探しまくった結果、「ラズパイでPPPoEセッションを張り、IPv4環境からのアクセスはPPPoEで受ける」方針で実装することにしました。楽天ひかりがIPoEとPPPoEの併用可能との情報に救われました。
ラズパイのPPPoE接続設定
こちらのサイトの受け売りなので私が書く必要ないかもしれません……。
pppoeパッケージのインストールと設定
pppoe, pppoeconf をインストール。
sudo apt install pppoe pppoeconf -y
pppoeconf を実行します。
sudo pppoeconf
PPPoEセッションを利用可能なネットワークインターフェイス(NIC)を自動で見つけて設定を進めてくれます。全部YesかOKで答えれば問題ありませんでした。途中、PPPoE接続用のユーザー名とパスワードを聞かれるので、ISPから受け取ったログイン情報を手元に準備しておきましょう。
ウィザードが終了したら、
ip addr show ppp0
で正しく接続できたか調べます。
5: ppp0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1454 qdisc pfifo_fast state UNKNOWN group default qlen 3 link/ppp inet xxx.xxx.xxx.xxx peer yyy.yyy.yyy.yyy/32 scope global ppp0 valid_lft forever preferred_lft forever
このように、ppp0 インターフェイスにIPv4アドレスが付与されたら成功です。この xxx.xxx.xxx.xxx が、ラズパイに対して付与されたグローバルIPv4アドレスです! うまく行かない場合はラズパイを再起動しましょう。私は再起動しないとちゃんと接続できませんでした。
手動接続・切断
以下のコマンドで可能です。注意点として、PPPoEセッション数の上限は1~2セッション/user なので、何回も pon
しないように気を付けます。再接続したい場合は一度 poff
してから pon
します。
pon dsl-provider # 接続 poff # 切断
PPPoE接続時にデフォルトルートを変更
このままの状態だと、ppp0に到着したパケットに対する返答がppp0ではなくデフォルトのwlan0から出ていってしまうため、IPv4経由で本ブログにアクセスしてきた人が返答を認識できず、ブログを表示できません。そこで、ppp0経由で到着したパケットに対する返答をppp0経由でインターネットに返すよう、ルーティングテーブルを編集します。PPPoEへの接続時に自動実行されるシェルスクリプトを作成します。
sudo nano /etc/ppp/ip-up.d/10dsl-provider
内容は以下の通りです。仕組みについての詳しい解説は、こちらのページに譲ります。超大雑把にまとめると、
- 「200番」というIDのルーティングテーブルを作成し、デフォルトルートを、ネットワークインターフェイス「dev ppp0」を出発し「$PPP_REMOTE」を経由するようにしなさい
- 「$PPP_LOCAL」からマシンに入ってきたパケットは、ルーティングテーブル200番に従ってルーティングしなさい。このルールの優先度は200です(元々登録されているルールより優先度が高いので、こちらが優先される)
なお $PPP_LOCAL, $PPP_REMOTE
は 10dsl-provider 実行時に pon が渡す環境変数なので、このスクリプトを単体で実行しても何も起きません。
#!/bin/sh ip route add default via "$PPP_REMOTE" dev ppp0 table 200 ip rule add from "$PPP_LOCAL" table 200 prio 200
実行権限を与えて完了です。
sudo chmod 755 /etc/ppp/ip-up.d/10dsl-provider
参考にしたサイト
先人の方々の丁寧な解説に幾度となく助けられました。ブラウザの履歴の中から、特に参考になったサイトをピックアップしておきます。
- 【パクろう】ラズパイでファイアーウォールを設定する方法 | sukiburo
- ufw の設定について簡潔にまとまっている
- v6プラス環境からRaspberry Pi 4でIPv4 PPPoE接続するには | 日記というほどでも
- ラズパイPPPoEによる実施例①。完全にここに倣いました、感謝
- V6プラス環境で、ラズパイでPPPoE接続 | taiyakon
- ラズパイPPPoEによる実施例②
- WM×LI:【pppoeconf】 Raspberry Pi で PPPoE 接続する
- ラズパイPPPoEによる実施例③。pppoeconfが裏で何をやっているのか書いてある。ユーザー名をタイポして繋がらなかったときに重宝した。/etc/ppp/chap-secrets, /etc/ppp/pap-secrets, /etc/ppp/peers/dsl-provider の3か所に書かれたユーザ名を修正した
- /etc/ppp/ip-up.d/hoge – 揮発性のメモ2
- pppoe の環境変数がまとまっている
- IPoE回線で自宅サーバーを公開する – 方向
- v6プラス(IPoE MAP-E)とPPPoEを併用する(ルーターが非対応の場合) – 方向
- ルーター2台体制+スイッチングハブによる実施例①
- 最初に見つけたサイト。これが糸口になった
- 楽天ひかり回線でIPoEとPPPoEを併用 | MYモノコトブログ
- ルーター2台体制+スイッチングハブによる実施例②
- ルータ2台体制によって自宅サーバにIPv4でもIPv6でもアクセスできるようにした – コンちゃんの「無いなら作ればいいじゃない!」
- ルーター2台体制+PPPoEパススルーによる実施例①
- 末尾に参考になるサイトが沢山まとまっており、リンク集としても素晴らしい
- 楽天ひかりのIPv6を使いながら、ポート転送する | 開拓辞書
- ルーター2台体制+PPPoEパススルーによる実施例②
- 同じサブネットへのNIC 2枚指し、またはソースルーティングのおはなし – (ひ)メモ
- 今回構成した、1台のマシンに2つのネットワークインターフェイスが存在する構成でのルーティングについて、まさに知りたかったことがまとまっていた
更新履歴
- 2022/9/10 ソースルーティングの設定を編集
- 2022/9/23 ルーティングテーブルの番号を修正
ピンバック: AWS Route53 でドメインを取得し、DDNS っぽく運用する【しきぶろぐ開設の道筋(3)】 – しきぶろぐ