NAS、各種サーバ、メーラー/プリンタ/スキャナ共有マシンとして運用中のRaspberry Pi 2 Model B/Raspbian BusterとAndroidスマホ双方にWireGuardをインストール、VPN/Virtual Private Network環境を構築しようと思ったらできなかった話。
スマホで外から(公衆Wi-Fiやモバイルネットワークにおいて)仮想専用線であるVPNを使ってセキュアに自宅のネットワークを使うこと、自作ホームオートメーション化機器を遠隔地から安全に操作することが目的です。
コロナ禍でリモートが当たり前のようになった今日この頃、VPNよりゼロトラスト(ZTNA/Zero Trust Network Access)だ!なんて声も聞こえますが、行動範囲もアクセス数も限られる個人ならVPNで充分ですし、それを超える時は他のVPNサービスを利用するもよし。
どちらにせよ、前提としてセキュリティを意識した運用が大切ですよね、って、それはそれで容易くはないんですが。
ちなみにオープンソースでフリーのWireGuardは、OpenVPNと異なり、カーネル組み込みで高速、ポイント to ポイント方式のVPNアプリかつ、通信プロトコルと言われています。
Raspberry Pi/スマホにSoftEther/OpenVPN互換でVPN接続及び、LAN内アクセスもできました。
が、WireGuardでは、未だできず...([接続できました]のメッセージや鍵アイコンは表示される、が...つながっていないっぽい...)。
尚、本家OpenVPNより高速を謳うSoftEther VPNのOpenVPN互換プロトコルだけあって、接続に数秒かかることはあっても、接続後、遅いと感じることはない、というか、タイムラグなどもないですし、充分、高速だと思います。
LAN内アクセスするにあたり、PostUpとして[iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -j MASQUERADE]、PostDownとして[iptables -t nat -D POSTROUTING -s 10.0.0.0/24 -j MASQUERADE]が欠けていたっぽい...。
でも、LAN内アクセスできなくてもVPNサーバであるラズパイにVPN接続できていれば、パブリックIPアドレスの確認はできますよね?いや、ラズパイにしかアクセスできないってことは、スマホはローカルネットワーク上に存在しない、してもアクセスできないわけで、パブリックIP表示するアプリも使えない...ってことになって、できないのか...?
ということは、このルーティング設定さえ追記すれば(と言ってもwireguard削除したから一からだけど)、いけるのか...?
ん?LANアクセスできない状態でラズパイにアクセス?ssh?VPN接続できたただけでVPNサーバであるラズパイの操作まではできない?またも混乱...。
何れにしても今試してみる気にはなれない...。
先のルーティングを追記して再チャレンジしてみましたが、やはり、スマホで[接続されました]となり、鍵アイコンも表示されるものの、パブリックIPは違うし、ssh接続もできませんでした...。
あ、ufwでポートは開けたけど、10.0.0.0/24からのルート開け忘れた...から?でも、wireguard削除しちゃったし、さすがに、もうやる気になれない...、SoftEtherがあるからいいや...。
とは言え、気になるので再々チャレンジ、そこを再設定してみましたが、やはり、あっさり鍵アイコン表示はされるもpingも通らず、LAN接続できず。
そもそもWireGuardの場合、wg0用の仮想IP10.0.0.0/24から別のセグメントのLANのIPってどういう仕組みで接続できるようになるのか理解できていないのですが、クライアントというか接続側の例えば、AllowedIPs = 0.0.0.0/0だけでいけるもの?どこもこれしか書いて気がするんですが、ブリッジ設定は、iptables設定だけでよいの?だとしたら、そこが間違ってるのかな?とか、もしかしてルータ設定とか、他に必要な設定があるのかも?なんて思ってみたり。
ぬー、LAN接続できない理由知りたい...。
Raspberry Pi 2で探してインストールに関しては、基本、adrianmihalko / raspberrypiwireguardをそのまま実行させて頂きました。
Raspberry Pi(ラズベリーパイ/Razupai)のOS Raspbian Busterのリポジトリには、wireguardパッケージがないのでRaspbianのベースであるDebian unstable版などwireguardパッケージのあるリポジトリを追記、aptのパッケージ選択優先順を適宜設定、パッケージ認証、アップデートしてリポジトリを反映後、WireGuardをインストールして再起動しておきます。
キーサーバーも変更する必要があるでしょうが、buster-backportsでも良かったですかね。
WireGuardの設定については、IPv6は使っていませんが、基本、How to setup a VPN server using WireGuard (with NAT and IPv6)を参考に行なうことにしました。
WireGuardは、一対多、多対多も可能ですが、基本、P2P/Peer to Peerというか、Point to PointのルーティングやブリッジによるVPN/Virtual Private Network実装であり、相互にVPN接続できることを想定していることもあり、端末ごとにWireGuardをインストールする必要があります。
よって、まず、プライベートキー(≒秘密鍵)とパブリックキー(公開鍵)を生成するわけですが、対象端末それぞれに各々生成、作成し、自端末のプライベートキーと相手端末のパブリックキーを相互に持つ恰好となります。
ここでは、端末としてRaspberry Pi 2 BとAndroidスマホを使いますが、WireGuardは、Windows/macOS/Linux/Android/iOSなどあらゆるものに対応しているのでパソコン間でもなんでもOKです。
プライベートキーの生成には、wg genkey、パブリックキー(公開鍵)の生成には、wg pubkeyコマンドを使います。
サーバとして使っているRaspberry Pi 2 Model B用とスマートフォン用のプライベートキー(.key)ファイル、パブリックキー(.pub)ファイルをそれぞれ作成します(ファイル名は任意)。
ディレクトリを作ったのは、散らからないように以外に意味はありません。
様々な状況を思い浮かべるのは面倒なのでなんですが、他のユーザーがいる環境なら、このように各ファイルは、所有者のみが、読み取りできるように権限を変更しておくのが賢明でしょうかね。
WireGuardの設定ファイル格納用に/etc/wireguardディレクトリ、そこに[Interface]と[Peer]から成るネットワークインタフェース(ごと)の構成ファイルを作成します。
ネットワークインタフェース名は、後述の設定と整合性がとれる前提で任意ですが、ここでは、wg0としています。
IPアドレスというかネットワークセグメントも仮想なのでIPアドレス値の範囲内かつ、後述の設定と矛盾がない前提で自由に設定できますが、バッティングする可能性が多分にある為、ローカルネットワークとはセグメントを変える必要があります。
WireGuard用にルータで開放することになるポートは、空いていれば、何でも可、外と接続しているルーターでWANからLAN方向へ開放する必要があるのでデフォルト(51820)ではない方がベターでしょう。
IPマスカレード(NAPT/Network Address Port Translation)によってWANとLAN間のTCP/IPネットワーク境界にあるルータ(または、ゲートウェイ)がパケットヘッダに含まれるIPアドレスとポート番号を双方向宛にそれぞれ自動変換、データを中継して疎通させるためのコマンドを指定しておきます。
ファイアウォールにiptablesを、もしくはiptablesのラッパとも言うべきufwを使っていれば、iptablesパッケージはインストール済みでしょう。
その際、指定してあるネットワークインタフェースeth0は、ifconfig等で確認できるローカルネットワーク上の今回は、Raspberry Piが実際に使用しているものを指定します。
続いてスマホ用のファイルを作っておきます。
一方が、パソコンやラズパイなら、このようにスマホ用にも作成しておくとファイル参照かQRコード化して撮影すれば済み、スマホでの入力を回避できるので後が楽という意味でここで作成したに過ぎません。
よって、このファイルも、わかれば、どこにあっても構いません。
DNS行というかDNSサーバは、Interface側がスマホなどモバイルデバイスの場合に必要で?機能している有効なものであれば、何を使うかは自由ですが、外部とつなげるために必須のようです。
Peer側のAllowedIPsは、0.0.0.0/0で無制限、セグメントを複数指定する場合は、カンマ区切りで指定(VPN用だけだとNASやVNC、CUPS等々に接続できず、実用上、意味がないので)。
Endpointは、接続したい先の(外側から見える)パブリックIPアドレスとWireGuard用のポート番号。
自身は、スマホにPublic IPをインストールし確認しました。
最初は、ルータのポートを開ける為、ルータの設定画面にアクセスすることから、グローバルIPも参照でき、実は、使う機会はそんなになくて不要なんですけどね。
これでqrencodeパッケージをインストールすれば、この設定ファイルを引数にQRコードを生成できるのですが、自身の環境では、ターミナル上にブラインド状に(分断されて)表示されたり、.pngファイルとして出力・保存すると壊れていると言われてあらゆるアプリで開けなかったりしたので後述のような方法でスマホにこの設定ファイルを転送することにしました。
気づけば、GUIでしょうが、Debianのリポジトリには、qreatorやqtqrがあり、これを使う手もありました。
っていうか、qreatorすごい、Wi-FiのSSID/PASSPHRASEのみならず、URL/ジオロケーション(位置情報)/発信とメッセージ送信/テキスト/名刺情報などもQRコードにできる...。
続いてWireGuardにおいてLANからWANへトラフィックを通過させるべく、フォーワーディングを有効にする為、稼働中にカーネルパラメータを変更できるsysctl用の構成ファイル/etc/sysctl.confのこの2つの行をアンコメント(先頭の#をとって有効にする)。
ただ、リンク先にあるように今後は、/etc/sysctl.confではなく、/etc/sysctl.d/99-sysctl.confに書くべきことのようです。
Raspbianでは、ありがたいことにシムリンクが張られていて/etc/sysctl.confへの変更が、/etc/sysctl.d/99-sysctl.confに反映されていました。
これを知らなければ、仮にRaspbianが対応してくれていなければ、原因不明のまま、WireGuard導入に躓いていたかもしれません。
ここまできたら、直接、外につながるルータの管理画面にログインし、設定ファイルに設定したWireGuard用のポート(デフォルトは51820)を開放しておきます。
プロトコルはUDP(今のところWireGuardはUDPのみ対応)、WANからLANへのトラフィックを許可します。
尚、自身の環境では、グローバルIPは固定ではない一方、使用中の光ONU + ルータにもVPN機能があり、それもあってか、グローバルIPが変わった時に登録メールに通知をしてくれる仕組みがあるので、スマホにメールが届くように設定しました(変更されたことを、また、変更後のIPを知らないとVPNアクセスできなくなるので)。
ちなみに1度はスマホからの接続もうまくいった使用中の光ONU + ルータに付属のVPN機能、日を改めてアクセスしようとしたら、どうにもできず、原因不明のまま、WireGuardに乗り換えることにした次第。
/etc/wireguard/wg0.confで決めた仮想ネットワークインタフェースでWireGuardを起動します。
ネットワークインタフェースを引数に起動します。
systemctl start/systemctl enableしてシステム起動時に自動起動するように設定しておきます(本来、startはログイン中にサービス開始するものですが、なぜか、自動起動のenableは実行しなくてもenableになったものの、行儀よく)。
が、自身は、ここでエラーに見舞われ、[Support] Unable to bring up wg0 #1175に救われました。
WireGuardは、カーネルに(モジュールを)組み込むことで高速化を実現できているとのこと、冒頭でラズパイのカーネルヘッダーをインストールしたものの、うまく、組み込めていなかったようで[dpkg-reconfigure wireguard-dkms]して再起動したところ、エラーが解消されました。
dkms/Dynamic Kernel Module Support。
ちなみに再チャレンジしてみたら、wireguard-dkmsがないと言われ、apt installしてみるとdkmsもなく、一緒にインストールされました。
それから、dpkg-reconfigure wireguard-dkmsすると[kernel headers for this kernel does not seem to be installed.]でスキップされるのみ、再起動して改めてsystemctl start wg-quick@wg0でエラーなくサービスが開始されました。
再々チャレンジしてみたら、昨日、dkmsもautoremoveでアンインストールされたはずなのに、dkmsはあり、wireguard-dkmsがないと言われ、apt install、再起動して改めてsystemctl start wg-quick@wg0で正常にスタート。
スマホにWireGuardをインストールします。
起動すると[+]アイコンがあるのでタップすると設定にあたり、[ファイルから]/[QRコードから]/[一から入力]の旨の選択肢が表示されます。
どれでも構いませんが、自身の場合、前述の通り、QRコード化がうまくいかなかったのでWireGuardのスマホ用構成ファイルを読み込む方法をとるべく[ファイル]を選択し、指定しました。
ちなみに自身の手持ちのスマホのOSは、AndroidでSamba共有にアクセスできるGhost Commander/Ghost Commander - Samba plugin、Debianを入れてsshを利用できるようにしたUserLAnd、Webアクセスも可能なAirDroidなどを入れてあるのでパソコンとスマホ間でWiFi(無線)越しのファイル転送も簡単です。
自宅やオフィスで検証している場合、スマホのWiFiを切ってモバイルデータをONにしておきます。
設定後にスマホのWireGuardを起動するとVPN名とON/OFFのスライダがあるのでタップして有効にします。
ほどなくしてスマホの通知領域に鍵アイコンが表示されれば、成功です。
自身のスマホでは、通知領域を画面上からスワイプして広げないと鍵アイコンが見えませんでした(展開した最上段にありました)。
尚、AndroidでWireGuardをインストール・設定すると[設定] => [ネットワークとインターネット] => [詳細設定] => [VPN]をタップすれば、[WireGuard]があり、そこからON/OFFや設定することができます。
ちなみにモバイル通信経由でVPNして自宅やオフィスのWi-Fiローカルネットワークに入ってもモバイル通信を経てVPNに入っていることからモバイル通信のデータとみなされるのでデータ通信量制限対策やデータ通信量抑制の対策にはなりません。
ん?WireGuardでVPNはできているのに、VPN越しのssh/scp、samba、vnc...がつながらない...、ファイアウォール(ufw)を止めてもダメ、調査中...。
タイミング的に自身が利用中のプロバイダOCNでは、2020/06に全面導入されたといいつつ、PR-400KI使用中の我が家では、OCN v6アルファ(無料?プラス500円/月?)への申込みが必要らしき、IPoE(IPv4 over IPv6)が怪しさ満載...。
スマホからのVPNできていた光ONU + ルータのVPN機能に至っては、久しぶりにやってみたら、登録済みの設定で、当然、VPNを有効にチェックして[設定]、完了しても、なぜか、VPN自体できなくなったし...。
ただ、スマホ買ったの2020年の9月末でVPNしてみてできたのは、それからちょっとしてからだから関係ないのかな...それとも後述のルーターのファームウェア更新含め、一斉対応じゃなくて順次対応で時期が被った|時期をまたいだ可能性もある?
ちなみに仮にOCN v6アルファ申し込んで対応完了しちゃうとOCNドットフォン/050IP電話も使えなくなるらしい。
その一方でルータにログインすると[IPv6ファイアウォール機能]が[有効]/[IPv6セキュリティのレベル]が[標準]になっているようで、そのままだと「NTT東日本・NTT西日本のフレッツ光ネクスト網内で折り返す通信は許容し、その他のIPv6通信を使用したインターネット側からの通信を拒否します。」ということっぽく、これが特にひっかかります。
IPoE機器を申し込めば、使えるっぽい中、IPoEパケットフィルタ設定/IPv6ファイアウォールが有効、セキュリティ機能が標準になっている、結果、その他のIPv6通信を使用したインターネット側からの通信を拒否ってどういうこと!?
今のところ、WireGuardの設定でIPv6は使っていないというか、WireGuard用の仮想のIPv6ってどうやって用意すればよいのでしょう?仮想のIPv4を変換?というわけでIPv6は使っていないつもりなのですが、そうだとしたら、関係ない?
それともIPv6ファイアウォールを無効にしておかないとダメ?
というわけで、今のまま、IPv6ファイアウォールを無効にしてみましたが、状況は全く変わらず、これの影響ではないのかな...。
もっとわかりやすい説明希望。
もう1つ気になるのが、グローバルIP生指定でよいのか、DDNS使わないとだめなのか。
というのもスマホのグローバルIP表示アプリで確認したところ、WireGuardでVPNを張る前と後でなぜかグローバルIPが変わるから...なんどやっても前と後は、別のグローバルIPになりつつ、それぞれ前は前、後は後で同一のグローバルIP。
自身の認識では、VPNを介して自宅のローカルネットワークに入れば、ローカル環境の(外とつながっているルーターに割り当てられた)グローバルIPと同一なはずと思っているのですが、勘違いしてる?
あ、モバイル通信からのVPNは、モバイル契約している先のグローバルIPで、ローカルと同一にはならないのか?でもそれってローカルに入れていないような...VPNはただのトンネルですよね...?
何れにせよ、DDNS使えば、解消する?
ローカルだけでなく、仮想IPに対しても双方ともpingも通らないんですよね...、ルーターのpingの応答を有効にするをチェックしてもダメ、少なくともスマホへは通ると思ったのですが。
137〜139あたりだったか?のポートを開けないとダメ?
あ、一から全部やり直したら、逆は相変わらず、ダメも、なぜか、モバイルデータ使用+WireGuardのスマホからパソコン(WireGuard指定IntefaceのAddress 10.0.0.1)には、pingが通りましたが、WireGuard同士での疎通ですよね?まさか、どこぞの組織や個人のところに到達したわけじゃないですよね?
っていうか、[ip route add アドレス/サブネット via ゲートウェイ dev デバイス名]すると必ずフリーズするんですよね...強制的に電源落として起動みたいな...ルーティングできてないってことでしょうから、pingどころか、何も通りませんよね、で、これってなんででしょ?
あれ?スマホでWireGuardが、[接続されました]を以てVPN確立したと思ってたけど、これ自体勘違い?あ、いや、鍵アイコンあるから勘違いじゃないか...。
でも、ルータで開放したポート削除して閉じてもVPN張れるんですが、ufwで許可してるから?
やっぱり、WireGuardが鍵アイコンも表示させつつ、[接続されました]って自己主張してるだけで、実は、VPN接続できてない?
WireGuardは、IPv6も対応している...、イコール、IPoEも対応している?から問題ないけど?我が家がIPoE機器を入手していないから、中途半端な状態でWireGuardでのVPNができない...とか?
うわ、脳内、とっちらかってる...。
WireGuardを使うにあたっては、必須というわけではないものの、外からのトラフィックを受け付けるべく、VPNポートを開放した結果、VPN以外へのアクセスも許可しているので、自身は、これを機にufwでファイアウォールを設定することにしました。
そこで間抜けな話をひとつ。
ufwインストール後、いきなり、sudo ufw enableしたと思ったら、別件でラズパイがフリーズ、強引に電源OFFして起動してみたら、SSHアクセスできない...、Sambaにもアクセスできない...、UPnP/DLNA越しに音楽も聴けない...なんでなんでと一瞬、焦りましたが、ポートにアクセスできていないってことは、ufwで何も設定せずにenableしてしまったからだ!と気づきました。
そういうわけでマウントはできたのでパソコンにつないでマウント、/マウントポイント/etc/ufw/ufw.confの[ENABLED=yes]を[ENABLED=no]にしてアンマウント、ラズパイにつなげて起動したら無事SSH接続できましたとさ。