気の向くままに辿るIT/ICT/IoT
webzoit.net
ハードウェア

Raspberry Pi/スマホにWireGuardでVPN

ウェブ造ホーム前へ次へ
サイト内検索
カスタム検索
Raspberry Piって?

Raspberry Pi/スマホにWireGuardでVPN

Raspberry Pi/スマホにWireGuardでVPN

2021/01/05

 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アプリかつ、通信プロトコルと言われています。

2021/01/10

 Raspberry Pi/スマホにSoftEther/OpenVPN互換でVPN接続及び、LAN内アクセスもできました。

 が、WireGuardでは、未だできず。

 尚、本家OpenVPNより高速を謳うSoftEther VPNのOpenVPN互換プロトコルだけあって、接続に数秒かかることはあっても、接続後、遅いと感じることはない、というか、タイムラグなどもないですし、充分、高速だと思います。

  1. ラズパイにWireGuardをインストール
  2. WireGuardの設定
  3. ルーターのポートを開放
  4. WireGuardの起動
  5. スマホにWireGuardをインストール
  6. スマホからVPN接続
  7. VPN越しにLANに接続できない!?

ラズパイにWireGuardをインストール

raspbian@raspberrypi:~$ sudo apt update && sudo apt upgrade -y
raspbian@raspberrypi:~$ sudo vi /etc/apt/sources.list.d/deb_unstable.list
...
# リポジトリ追加
deb http://deb.debian.org/debian/ unstable main
...
raspbian@raspberrypi:~$ sudo apt install dirmngr
raspbian@raspberrypi:~$ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 8B48AD6246925553
raspbian@raspberrypi:~$ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 04EE7237B7D453EC
raspbian@raspberrypi:~$ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 7638D0442B90D010
raspbian@raspberrypi:~$ sudo vi /etc/apt/preferences.d/limit-unstable
# これらの行がなければ、追記
Package: *
Pin: release a=unstable
Pin-Priority: 150
raspbian@raspberrypi:~$ sudo apt update
raspbian@raspberrypi:~$ sudo apt install -y wireguard
raspbian@raspberrypi:~$ sudo reboot

 Raspberry Pi 2で探してインストールに関しては、基本、adrianmihalko / raspberrypiwireguardをそのまま実行させて頂きました。

 Raspberry Pi(ラズベリーパイ/Razupai)のOS Raspbian Busterのリポジトリには、wireguardパッケージがないのでRaspbianのベースであるDebian unstable版などwireguardパッケージのあるリポジトリを追記、aptのパッケージ選択優先順を適宜設定、パッケージ認証、アップデートしてリポジトリを反映後、WireGuardをインストールして再起動しておきます。

 キーサーバーも変更する必要があるでしょうが、buster-backportsでも良かったですかね。

WireGuardの設定

 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コマンドを使います。

raspbian@raspberrypi:~$ mkdir .wireguard
raspbian@raspberrypi:~$ cd .wireguard
raspbian@raspberrypi:~$ wg genkey | tee raspberrypi.key | wg pubkey > raspberrypi.pub
raspbian@raspberrypi:~$ wg genkey | tee smartphone.key | wg pubkey > smartphone.pub
raspbian@raspberrypi:~$ ls
raspberrypi.key raspberrypi.pub smartphone.key smartphone.pub
raspbian@raspberrypi:~$ chmod 600 raspberrypi.*
raspbian@raspberrypi:~$ chmod 600 smartphone.*
raspbian@raspberrypi:~$

 サーバとして使っているRaspberry Pi 2 Model B用とスマートフォン用のプライベートキー(.key)ファイル、パブリックキー(.pub)ファイルをそれぞれ作成します(ファイル名は任意)。

 ディレクトリを作ったのは、散らからないように以外に意味はありません。

 様々な状況を思い浮かべるのは面倒なのでなんですが、他のユーザーがいる環境なら、このように各ファイルは、所有者のみが、読み取りできるように権限を変更しておくのが賢明でしょうかね。

raspbian@raspberrypi:~$ sudo mkdir /etc/wireguard
raspbian@raspberrypi:~$ sudo vi /etc/wireguard/wg0.conf
[Interface]
# VPN用仮想ネットワークIPアドレス
# Raspberry Pi
Address = 10.0.0.1/24
# WireGuard用ポート(51820はデフォルト)
ListenPort = 51820
# Raspberry Pi用の秘密鍵
PrivateKey = raspberrypi.keyの内容
# PostUp/WireGuard起動直後、PostDown/WireGuard終了直後に実行するルーティング用コマンド
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
 
[Peer]
# スマホ用の公開鍵
PublicKey = smartphone.pubの内容
# VPN用仮想ネットワークセグメントで疎通可能なIPアドレス
AllowedIPs = 10.0.0.2/32
raspbian@raspberrypi:~$

 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が実際に使用しているものを指定します。

raspbian@raspberrypi:~$ vi ~/.wireguard/smartphone.conf
[Interface]
# VPN用仮想ネットワークIPアドレス
# スマホ
Address = 10.0.0.2/32
# スマホ用の秘密鍵
PrivateKey = smartphone.keyの内容
DNS = 8.8.8.8
 
[Peer]
# Raspberry Pi用の公開鍵
PublicKey = raspberrypi.pubの内容
# アクセス可能なネットワークアドレス範囲(0.0.0.0/0だと何でもあり)
AllowedIPs = 10.0.0.1/32, 192.168.0.0/24
Endpoint = 1.2.3.4:51820
raspbian@raspberrypi:~$

 続いてスマホ用のファイルを作っておきます。

 一方が、パソコンやラズパイなら、このようにスマホ用にも作成しておくとファイル参照かQRコード化して撮影すれば済み、スマホでの入力を回避できるので後が楽という意味でここで作成したに過ぎません。

 よって、このファイルも、わかれば、どこにあっても構いません。

 DNS行というかDNSサーバは、Interface側がスマホなどモバイルデバイスの場合に必要で?機能している有効なものであれば、何を使うかは自由ですが、外部とつなげるために必須のようです。

 Peer側のAllowedIPsは、0.0.0.0/0で無制限、セグメントを複数指定する場合は、カンマ区切りで指定(VPN用だけだとNASやVNC、CUPS等々に接続できず、実用上、意味がないので)。

 Endpointは、接続したい先の(外側から見える)パブリックIPアドレスとWireGuard用のポート番号。

 自身は、スマホにPublic IPをインストールし確認しました。

 最初は、ルータのポートを開ける為、ルータの設定画面にアクセスすることから、グローバルIPも参照でき、実は、使う機会はそんなになくて不要なんですけどね。

 これでqrencodeパッケージをインストールすれば、この設定ファイルを引数にQRコードを生成できるのですが、自身の環境では、ターミナル上にブラインド状に(分断されて)表示されたり、.pngファイルとして出力・保存すると壊れていると言われてあらゆるアプリで開けなかったりしたので後述のような方法でスマホにこの設定ファイルを転送することにしました。

raspbian@raspberrypi:~$ vi /etc/sysctl.conf
...
net.ipv4.ip_forward=1
...
net.ipv6.conf.all.forwarding=1
...
raspbian@raspberrypi:~$

 続いてWireGuardにおいてLANからWANへトラフィックを通過させるべく、フォーワーディングを有効にする為、稼働中にカーネルパラメータを変更できるsysctl用の構成ファイル/etc/sysctl.confのこの2つの行をアンコメント(先頭の#をとって有効にする)。

raspbian@raspberrypi:~$ vi /etc/sysctl.d/99-sysctl.conf
net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1
raspbian@raspberrypi:~$

 ただ、リンク先にあるように今後は、/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に乗り換えることにした次第。

WireGuardの起動

raspbian@raspberrypi:~$ sudo wg-quick up wg0
raspbian@raspberrypi:~$

 /etc/wireguard/wg0.confで決めた仮想ネットワークインタフェースでWireGuardを起動します。

 ネットワークインタフェースを引数に起動します。

raspbian@raspberrypi:~$ sudo systemctl start wg-quick@wg0
raspbian@raspberrypi:~$ sudo systemctl enable wg-quick@wg0
...
Failed to start WireGuard via wg-quick(8) for wg0
...
raspbian@raspberrypi:~$ systemctl status wg-quick@wg0.service
...
Active: failed (Result: exit-code)
...
raspbian@raspberrypi:~$ sudo dpkg-reconfigure wireguard-dkms
raspbian@raspberrypi:~$ sudo reboot

 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をインストール

 スマホにWireGuardをインストールします。

 起動すると[+]アイコンがあるのでタップすると設定にあたり、[ファイルから]/[QRコードから]/[一から入力]の旨の選択肢が表示されます。

 どれでも構いませんが、自身の場合、前述の通り、QRコード化がうまくいかなかったのでWireGuardのスマホ用構成ファイルを読み込む方法をとるべく[ファイル]を選択し、指定しました。

 ちなみに自身の手持ちのスマホのOSは、AndroidでSamba共有にアクセスできるGhost Commander/Ghost Commander - Samba plugin、Debianを入れてsshを利用できるようにしたUserLAnd、Webアクセスも可能なAirDroidなどを入れてあるのでパソコンとスマホ間でWiFi(無線)越しのファイル転送も簡単です。

スマホからVPN接続

 自宅やオフィスで検証している場合、スマホのWiFiを切ってモバイルデータをONにしておきます。

 設定後にスマホのWireGuardを起動するとVPN名とON/OFFのスライダがあるのでタップして有効にします。

 ほどなくしてスマホの通知領域に鍵アイコンが表示されれば、成功です。

 自身のスマホでは、通知領域を画面上からスワイプして広げないと鍵アイコンが見えませんでした(展開した最上段にありました)。

 尚、AndroidでWireGuardをインストール・設定すると[設定] => [ネットワークとインターネット] => [詳細設定] => [VPN]をタップすれば、[WireGuard]があり、そこからON/OFFや設定することができます。

 ちなみにモバイル通信経由でVPNして自宅やオフィスのWi-Fiローカルネットワークに入ってもモバイル通信を経てVPNに入っていることからモバイル通信のデータとみなされるのでデータ通信量制限対策やデータ通信量抑制の対策にはなりません。

VPN越しにLANに接続できない!?

 ん?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パケットフィルタ設定(IPoE)
IPv6パケットフィルタ設定機能にて、IPv6通信に関するファイアウォール機能の「有効」/「無効」の設定、及びIPv6通信のセキュリティレベルを「標準」/「高度」の二種類から選択することができます。
 
IPv6ファイアウォール機能が「有効」でかつ、セキュリティレベルが「標準」の場合、NTT東日本・NTT西日本のフレッツ光ネクスト網内で折り返す通信(NTT東日本・NTT西日本との契約により可能となるもの)は許容し、その他のIPv6通信を使用したインターネット側からの通信を拒否します。
※セキュリティレベルが「高度」の場合は、NTT東日本・NTT西日本のフレッツ光ネクスト網内で折り返す通信(NTT東日本・NTT西日本との契約により可能となるもの)を拒否します。
 
IPv6ファイアウォール機能を「無効」にした場合、NTT東日本・NTT西日本のフレッツ光ネクスト網内で折り返す通信(NTT東日本・NTT西日本との契約により可能となるもの)を許容し、かつその他のIPv6を使用したインターネット側からの通信を許容します。
IPv6ファイアウォール機能を「無効」にした場合、IPv6パケットフィルタ設定(IPv6 PPPoE)も無効となりますのでご注意ください。
IPv6ファイアウォール機能を「無効」に設定することで、LANに接続した機器が危険にさらされる可能性がありますので、設定する際は十分注意してください。

 その一方でルータにログインすると[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.10.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接続できましたとさ。

ウェブ造ホーム前へ次へ