ミャンマーからFacebookを使うために、さくらのVPSでWireGuardサーバを作った話
はじめまして、佐々木です。
さくらのナレッジのネタにはなったことはあるのですが、書くのは初めてです。
現在お仕事の関係でミャンマーにいるのですが、2月1日に政変がありバタバタしています。そしてその影響でFacebookとTwitterに接続できなくなってしまいました。でもなぜかミャンマーの人々は普通にFacebookにいろいろ投稿してるんですよね。私も接続できるようにしたいので、さくらのVPS上にVPNサーバを作ってみました。
目次
やりたいこと
実現したいことは以下。
- 遮断されにくいVPNサーバを用意したい
- イケてる新しいVPNソフトウェアを使ってみたい
ミャンマー国内のネットワークからはFacebookが使えなくなってしまったけれど、他の国からは普通にアクセスができる。なので、VPN(Virtual Private Network)という技術を使って、物理的にはミャンマーにいるのだけど、ネットワーク的には他の国からアクセスしている、という状況を作れば接続できるようになる。
VPNは既にいろいろな接続サービスがある。遮断したい側から見ると、大量のユーザーがいるサービスは止めたくなると思うし、止めるのは簡単にできちゃうのよね。なので、自前の野良VPNサービスであれば遮断されにくいかな、と思ったのが今回のVPNサーバを立てたモチベーションの1つ。
そしてVPNを実現するソフトウェアはいくつかあるんだけれど、最近出てきたWireGuardがとても良いので、これを使いたかった。WireGuardはモダンな言語で書かれていて、余分な機能がなくシンプル、そしてスループットが速い。UDP上で通信できるので、経路途中のルータで止められたりしにくい。
最近のウェブ通信は、UDPの443番ポートも使われるようになってきていて、通信を遮断したい側だとしても、このポートは多分閉じられないと思うんだよね。なので今回は、UDPの443番ポートを使うように設定した。
さくらのVPSを準備
サーバはさくらのVPSを利用。プラン選択では、一番小さいものを選んでセットアップ。OSは標準OSから、Ubuntu 20.04 (amd64)を選択。
さくらのVPSのカスタマイズはとても良くできていて、iptablesとfail2banで不正アクセスから守るような設定があらかじめ入っている。でも個人的には、外部からのアクセス制限は、ufwを使うのが好きなので、毎回手で外してたのよね。
ただ今回は、セットアップする時にスタートアップスクリプトにufwというのが選択できるようになっているのに気付いた。これを選択すると、最初から ufw が使えるようになっていたよ。
こういう細かい進化がとても嬉しい。最初に入っている設定を見ると、22番ポートへのアクセスだけが有効になっている。
$ sudo ufw status ... To Action From -- ------ ---- 22 ALLOW Anywhere 22 (v6) ALLOW Anywhere (v6)
良くできてるなあ、と一瞬思ったんだけど、ちょっと惜しい。この設定だと UDP/22 も許可されてるけど、SSH用にはTCPだけで良いはず。そして複数回の失敗で接続できなくなる limit も設定したい。
なので、以下のコマンドでそのような設定を入れて、
sudo ufw limit ssh
以下のコマンドで元から入っている2つのルールを削った。
ufw status numbered ufw delete <不要なルール番号=「22」と「22 (v6)」の行番号>
コマンドで確認すると、SSHの制限はこのようになった。
$ sudo ufw status Status: active< To Action From -- ------ ---- 22/tcp LIMIT Anywhere 22/tcp (v6) LIMIT Anywhere (v6)
WireGuardのインストール
インストールは次のaptコマンドでサクっと完了(途中の確認画面では Y を入力してエンター)。
sudo apt update apt install wireguard-dkms wireguard-tools
WireGuardの設定: 鍵の作成
WireGuardでVPN接続をするには、サーバ側とクライアント側それぞれに鍵ペアを用意する必要がある。この鍵ペアはサーバ内のどこで作っても良いんだけれど、今回はあまり考えずに、/etc/wireguard/ の下に作ることにする。/etc/wireguard 以下は root 権限がないと見られないので、root権限で作業。本当は root 権限では作業はできるだけ避けたほうが良いんだけど、まあ個人用だし、ということで手を抜いている。
まずは root になって、作業ディレクトリに移動。
sudo -s cd /etc/wireguard
サーバ用とクライアント用の鍵ペアファイルを作成。
wg genkey | tee server_private_key | wg pubkey > server_public_key wg genkey | tee client_private_key | wg pubkey > client_public_key chmod 600 *_key
実際の設定で使用するのは、作成したファイル自身ではなく、それぞれのファイル内に書かれた文字列(なので、ファイルはサーバのどこに置いても良い)。そのため、それぞれのファイル内の文字列を画面に表示させて、手元のパソコン上でエディタ等にコピーしておく。
cat server_private_key cat server_public_key cat client_private_key cat client_public_key
WireGuardの設定: サーバ側の設定
WireGuardサーバ側の設定ファイルを作成する。
この設定ファイルは、/etc/wireguard/ 以下に書く必要がある。
vi /etc/wireguard/wg0.conf
設定ファイルの中に、先程作成した鍵ペアのうち、サーバ側の秘密鍵(server_private_key の中身)、クライアント側の公開鍵(client_public_key)を記述する。WiteGuardのインターフェース名は何でも良いんだけど、wg[0-9]みたいなのが一般的なようなのでwg0として作成する。通信で利用するポート番号は443を使用。
クライアントからの通信を処理するには、NATを設定し、サーバのインターフェースからインターネット側に出す必要があるので、iptablesでそのような設定を入れる。「PostUp」「PostDown」行で、サーバのインターフェースは、さくらのVPSだと「ens3」になっていると思うけれど、一応確認してから設定したほうが良い(編集部注:さくらのクラウドの場合は「eth0」を指定)。VPN接続で利用するアドレス空間は、10.200.200/24を使うことにして、サーバ側は1、クライアント側は2を使うこととした。
設定は以下のような感じになる。
[Interface] Address = 10.200.200.1/24 SaveConfig = true PrivateKey = <サーバ側の秘密鍵server_private_key内の文字列> ListenPort = 443 PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o ens3 -j MASQUERADE PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o ens3 -j MASQUERADE [Peer] PublicKey = <クライアント公開鍵client_public_key内の文字列> AllowedIPs = 10.200.200.2/32
設定できたら、WireGuardを起動。
wg-quick up wg0
ステータスは以下で確認できる。
wg
OS起動時に自動的に起動するようにしておく。
systemctl enable wg-quick@wg0
WireGuardの設定: クライアント側の設定
クライアント側の設定を作成する。この設定ファイル(今回はclient.confという名称)はWireGuardサーバ側では利用しないので、どこに置いても良いんだけれど、考えるのが面倒なのと、今までの流れ的に /etc/wireguard/ 以下に作ってしまうよ。
vi /etc/wireguard/client.conf
設定ファイルの中の鍵ペアには、サーバ側設定では使わなかったクライアント側の秘密鍵(client_private_keyの中身)、サーバ側の公開鍵(server_public_key)を記述。
以下の設定では DNSは 8.8.8.8 を指定しているけど、このキャッシュDNSサーバを使うと、アクセスできない有用なサイトもある。本当は、さくらインターネットが用意しているDNSキャッシュサーバを指定したら良いと思う。私が立てたVPSだと、133.242.0.3、133.242.0.4 を指定するべき、なのだろうけど、ぶっちゃけ手抜きだ。
設定は以下のような感じになる。
[Interface] PrivateKey = <クライアント秘密鍵client_private_keyの中身> Address = 10.200.200.2 DNS = 8.8.8.8 [Peer] PublicKey = <サーバ側の公開鍵server_public_keyの中身> AllowedIPs = 0.0.0.0/0 Endpoint = <サーバのIPアドレス>:443
この設定はクライアント側で使うことになるので、QRコードに変換しておく。
QRコードを作成するための qrencode コマンドをインストールする。
sudo apt install qrencode
qrencodeコマンドでQRコードを作成する(ターミナルなどの端末が UTF8 の文字列を解釈できる必要あり)。
qrencode -t ANSIUTF8 < /etc/wireguard/client.conf
あるいは、pngファイルを作成したかったら -o オプションでファイル名を指定する。
qrencode -o client.png -t PNG < /etc/wireguard/client.conf
OS側の設定
カーネルパラメータを変更してパケットフォワーディングを有効にする。
sudo vi /etc/sysctl.conf
以下のコメントを外す。
net.ipv4.ip_forward = 1 net.ipv6.conf.all.forwarding = 1
カーネルパラメータを再読みこみ。
sudo sysctl -p
ufwで443/udpを受信できるようにする。
sudo ufw allow 443/udp
これでサーバ側の準備はすべて完了。
Androidから使ってみる
AndoroidスマホからWireGuardを使う場合は Google Play からアプリをインストールする(編集部注:iOSはApp StoreからWireGuardアプリをインストールできます)。
インストール後に右下のプラスマークをクリックすると新しい接続を作成できるので、先程作成したQRコードを読みこませると、設定が自動的に入力される。
早速繋いでみると、ミャンマーでも無事にFacebookが見られるようになりましたよ!!!!
もっと別の方法
WireGuardはシンプルなので他のVPNより設定やトラブルシュートは楽だとは思う。でもやっぱりちょっと設定するのはハードルが高いなあ、という人のために、tailscaleというWireGuardの設定を作って繋いでくれる、という面白いサービスがある。ある程度までは無料で使えるので興味があれば試してみると面白いと思う。
そして、VPNサーバを自前で立てるのはちょっと、という人は、けしからん人達が作っている、VPN Gateという公開VPN中継サーバを使ってみると良いと思う。
現在のユーザーの状況を見ると、ミャンマーからも沢山使われてるんだなあ、というのがわかる。けしからん人達は本当に偉いと思う。
VPNでは解決できないこと
VPNで繋がってFacebookも無事に見られて良かった良かった、と思ってたんだけど、2月15日突然、午前1時から午前9時までインターネットが使えなくなってしまったよ。やられた時の絶望感はかなりハンパない感じ。香川県にいる中学生の気分ってこんな感じなんだろうなあ、とか思いつつ。そもそもなんでこんなに絶望するんだろうなあ、絶望しないためにはどうすれば良いんだろうなあ、みたいなことを考える時間ができた。
おそらく絶望した理由は以下かな、と思っている。
- 人は人と繋がりたいと思っている
- 今のインターネットは、人と人を繋ぐ手段として大きな役割を担っている
- それを特権を持った人に突然切られてしまった
そしてそれを防ぐためには、以下のようなことを考えないといけないのかな。
- 特権を持った人がヤバいことをしないような、社会的仕組みを作る
- 特権を持った人が大事なところを切ってもなんとかなるような、技術的基盤を作る
ネットワークが切れてもある程度使える、データの信頼性が保たれる、そんなインフラって、きっとさくらインターネット研究所の超固体型データセンターコンセプトの研究範囲だよね? 研究所の中に人には頑張って欲しいなあ、とぶん投げて筆を置きたいと思います。