毎度の如くAzureで構築
こういったVPNを自分で構築する際にはコスパの良いAmazon AWSが使われることが多いが、二番煎じは面白くないのでMicrosoft Azure上に構築してみたい。
...というのは建前で、実際のところは毎月1万円分支給されているMicrosoft Azureクーポンを使いたいだけ。
Azureで自前構築したら安くても1500円はかかるから、これが無料になるのはありがたい。というかクーポンがもったいない。
なお、中国VPNは月500円程度の安い業者が複数存在しており、接続の速度や安定性などの品質は自前のものと比較にならないほど良いため、実用性を考えると自前で構築するメリットはほとんどない。ただクーポンがもったいn(略)
Dockerファイルを試す
ShadowSocksR構築時にDockerコンテナをもとに構築する方法が楽だったため、ここに公開されているDockerイメージをソースとしてAzureにコンテナーインスタンスを作成してみた。
プロビジョニングには成功したようなのだが、いざ起動しようとしてもエラーが出て起動しない。
原因を色々と探ってみたものの、AzureもDockerも知識が乏しくワケワカメ。
ここで時間を浪費するのも嫌なのでコンテナーで何とかするのを諦め、仮想マシンを作成して一から構築することに。
仮想マシンを作成する
Azure上でで仮想マシンの構築はOpenConnectでのVPN構築時に実践済みなので詳細は割愛する。
Azure PortalのGUIに従ってポチポチするだけなのでそこまで難しくはない。
OS
OSはLinux(Ubuntu)を選択。バージョンは20.04がインストールされた。
注:Ubuntu MinimalではなくUbuntu Serverを選ぶこと。
VMシリーズ
VMシリーズはB1s (CPU1コア、メモリ1GB)で1500円/月、 B2s(CPU2コア、メモリ4GB)で6000円/月あたりが許容範囲内。
価格表と相談しながら初めは最小構成で作成して、パワー不足なら大きくしてもいいかもしれない。
ネットワーク
仮想マシンの作成が完了したら、ドメイン(FQDN)の設定を忘れずにしておこう。
マシンの概要「DNS 名」の所に値が表示されていればOK。
注:例えば「example.japaneast.cloudapp.azure.com」など。
また、「ネットワーク」の受信ポートの規則にHTTPとHTTPSの受信を許可する設定もしておこう。
一通り設定してUbuntuマシンが起動するようになったら、こちらのサイトを参考にTrojan-GFWをインストールする。
仮想マシンにTrojan-GFWをインストール
正直、上記サイトの通りにコマンドを打つだけで構築できてしまったので特筆することはないのだが、元サイトの消滅に備える意味も込めて手順を簡単に日本語訳を記載しておく。
※各コマンドは管理者権限が必要な場合があるため、適宜頭に「sudo」をつけて実行している。
~以下翻訳~
1. サーバー側
1.1. 前提条件
サーバーと一緒にドメイン名が必要になる。ドメイン名からサーバーを指すDNS Aレコードを設定すること。ここではドメイン名は example.com とし、ホスト名は www.example.com とする。
※訳注:Azureでは設定したFQDN(DNS名)=ドメイン名=ホスト名と考えればいい。
1.2. 偽装用Webサイトの作成
Nginxをインストールして起動する。
CentOS:
yum install nginx -y
systemctl enable nginx
systemctl start nginx
Debian or Ubuntu:
sudo apt install nginx -y
sudo systemctl enable nginx
sudo systemctl start nginx
注:インストールできない場合、先に sudo apt-get update を実行するとよい。
下記ファイルを開きNginxの設定ファイルを開く。
CentOS: /etc/nginx/nginx.conf
Debian or Ubuntu: /etc/nginx/sites-available/default
サーバー名を設定する。ホスト名が www.example.com の場合、下記のように設定する。
server_name www.example.com;
注:ファイルを開いて「server_name」で検索すると当該箇所を発見できる。
ファイルを保存してNginxを再起動する。
sudo nginx -t
sudo systemctl restart nginx
systemctl status nginx
Webサーバーにサンプルページを追加する。
CentOS:
yum install wget zip unzip -y
wget https://github.com/arcdetri/sample-blog/archive/master.zip
unzip master.zip
cp -rf sample-blog-master/html/* /usr/share/nginx/html/
Debian or Ubuntu:
sudo apt install zip unzip -y
wget https://github.com/arcdetri/sample-blog/archive/master.zip
unzip master.zip
cp -rf sample-blog-master/html/* /var/www/html/
注:コピー時にPermission deniedエラーが出る場合、頭にsudo をつける
http://www.example.com にアクセスして偽装用のWebサイトが表示されることを確認する。
1.3. SSL証明書を取得する
Let's Encryptで無料のSSL証明書を取得する。
CentOS 8:
yum install epel-release -y
yum install certbot python3-certbot-nginx -y
certbot certonly --nginx
Debian or Ubuntu:
sudo apt install certbot python3-certbot-nginx -y
sudo certbot certonly --nginx
上記以外: EFF Certbotページを確認のこと。
https://certbot.eff.org/
Certbotプロンプトに応答する
・メールアドレスを入力する
・ a を入力して同意する
・ y or n を入力してメールアドレスの共有可否に応答する
・証明書が必要なホスト数を入力する
Let's EncryptのSSL証明書は90日間有効なので、90日ごとに自動更新するように設定する。
CentOS 8:
echo "0 0,12 * * * root python3 -c 'import random; import time; time.sleep(random.random() * 3600)' && certbot renew -q" | sudo tee -a /etc/crontab > /dev/null
Debian or Ubuntu:
certbot renew --dry-run
CentOS 8と同じコマンドでよい
Let's Encryptの証明書と鍵を読み込み可能に設定し、Let's Encryptディレクトリを実行可能にする
sudo chmod -R +rx /etc/letsencrypt
これでWebサーバーの設定は完了。
1.4. Trojanをインストールする
リポジトリからTrojanをインストールする。
CentOS 8:
yum config-manager --set-enabled PowerTools
yum install trojan -y
Debian 10+ or Ubuntu 20.04+:
sudo apt install trojan -y
1.5. SystemDサービスを作成
systemd serviceファイルを /etc/systemd/system/trojan.service に作成する
[Unit]
Description=trojan
Documentation=man:trojan(1) https://trojan-gfw.github.io/trojan/config https://trojan-gfw.github.io/trojan/
After=network.target network-online.target nss-lookup.target mysql.service mariadb.service mysqld.service
[Service]
Type=simple
StandardError=journal
User=nobody
AmbientCapabilities=CAP_NET_BIND_SERVICE
ExecStart=/usr/bin/trojan /etc/trojan/config.json
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=1s
[Install]
WantedBy=multi-user.target
systemd serviceファイルを保存する。
1.6. Trojanを設定する
/etc/trojan/config.json にあるTrojanの設定ファイルを編集する。サンプル値は適宜置き換えること。
password1 に独自のパスワードを設定し、続くコンマを削除する
password2 の行を削除する。
certの行に証明書ファイルを指定する。例:/etc/letsencrypt/live/www.example.com/fullchain.pem
keyの行にキーファイルを指定する。例:/etc/letsencrypt/live/www.example.com/privkey.pem
ファイルを /etc/trojan/config.json に保存する。
1.7. Trojanの設定
再起動の度にTrojanが自動で立ち上がるよう設定する。
sudo systemctl enable trojan
sudo systemctl start trojan
trojanが正常に実行されていることを確認する
systemctl status trojan
Trojanがポート443を、Nginxがポート80をListenしていることを確認する。
ss -tulpn
注:↑このコマンドは叩いてもよく分からなかったので無視した
2. クライアント側
最新版のTrojan for Windows をダウンロードし、ZIPを解凍する。
trojanフォルダ内のconfig.jsonを下記のように編集する。
remote_addr にはホスト名を設定する(例: www.example.com )
password1 にはサーバー側で設定したパスワードを入力する
ファイルを保存してテキストエディタを閉じる。
Win+rキーを押してcmdと入力し、OKを押してコマンドプロンプトを起動する。
trojanフォルダに移動する。
cd Downloads\trojan-1.16.0-win\trojan
Trojanを起動する。
trojan
[WARN] trojan service (client) started at 127.0.0.1:1080 と表示されたら、Trojanはポート1080をListenしていることを意味する。
コマンドプロンプトを開いたまま、次のステップへ移る。
ブラウザの設定を変更して、ポート1080をListenしているTrojanを使うように変更する。
Firefoxでは、三本線メニューから設定を選択し、ネットワーク設定の設定を開き、手動プロキシ設定、SOCKS Host 127.0.0.1、Port 1080、SOCKS v5と設定しOKをクリックする。
Chromeでは、Chrome WebストアからSwitchyOmega by FelisCatusをインストールしてブラウザにプロキシ設定が可能。ホスト127.0.0.1、ポート1080でSOCKS5 プロキシを使用するよう設定する。
ブラウザでIP Chickenにアクセスし、IPアドレスがサーバーのIPアドレスであることを確認する。
Trojan使用終了後はコマンドプロンプトを閉じ、ブラウザのプロキシ設定をオフにする。
~翻訳おわり~
上手く行かない場合、手動でtrojanを起動してみる
admin@U2204:~$ trojan
Welcome to trojan 1.16.0
[2023-09-02 07:33:15] [FATAL] fatal: bind: Permission denied
[2023-09-02 07:33:15] [FATAL] exiting. . .
↑sudoをつけてないためエラーが出ているが、systemctl から起動する場合はroot権限で実行されるため問題ないはず。
rootで動かしても上記エラーになる場合は、下記コマンドの実行漏れでLet's Encryptの証明書と鍵ファイルにアクセスできていない可能性あり。
sudo chmod -R +rx /etc/letsencrypt
他のエラー
admin@U2204:~$ trojan
Welcome to trojan 1.16.0
[2023-09-02 08:02:43] [FATAL] fatal: /etc/trojan/config.json(9): expected value
[2023-09-02 08:02:43] [FATAL] exiting. . .
↑このエラーは /etc/trojan/config.json 編集時にpassword1の後のカンマを消し忘れている等、jsonファイルの書き方がおかしい時に出る。
AndroidクライアントはIgniterがダメだった
Androidでは Igniterという公式(?)クライアントがあるのだが、どう設定をしても接続できなかった。
いくらトライしても接続できないかエラーが出てダメなので諦めて放置していた。
何度かトライしいるうちにアプリ側の問題のような気がしてきたので、PlayストアからTrojanやHowdy Trojan VPNといった別のクライアントを使ってみたらすんなり接続ができた。
Androidからも接続元IPと位置情報がAzureのものになっていることを確認。
実地テストはいつになるやら
これで Trojan-GFWを使ったトンネリングは成功したが、実際に金盾を回避できるかどうかは現地に行ってみないと分からない。
これが一番の問題で、いつ現地に行けるようになるのか全く分からない。一応は国際線の本数が少しずつ増えてくるなど、非常にゆっくりではあるが入国緩和の方向に向かっているようだが、コロナ前のように自由に行き来できていた頃に戻るまではまだまだ時間がかかりそうだ。それまでに金盾が進化しないことを切に願う。
Let's Encryptの証明書更新
(記事を途中まで書いて下書きのまま)3か月が過ぎた今日、いきなりエラーが出てVPNに繋がらなくなった。
"certificate verify error"が出ている。何となく証明書関係の問題と想像がつく。
3か月は90日。そうだ、「Let's EncryptのSSL証明書は90日間有効」と記載があった...。
上の翻訳記事では、Ubuntuなら下記のコマンドでいいと書いてあったが
certbot renew --dry-run
今になって思えば、このコマンドだけで90日ごとに更新処理が走るとは思えない。
おそらくCentOSの場合と同様、crontabに登録するやら何やらしてやらないといけないだろう。
久々にAzure仮想マシンにログイン
とりあえず作業するためにログインを...と思ったが、どうやってログインするか忘れてしまっていた。
「接続」タブからSSH接続するんだっけ?
でもネットワークセキュリティの設定を変更してSSHの許可をしないといけないらしい。
前回そんな設定したっけ?してないよなぁ・・・。
あ、左メニューの一番下に「シリアルコンソール」があるんだった。これだ。
んで、ログインして......ログインユーザーもパスワードも忘れちゃった。不覚。
左メニューの「テンプレートのエクスポート」から"osProfile"を探し、"adminUsername"にユーザー名があることを知る。
パスワードは根性で思い出した。
実は左メニューの「パスワードのリセット」から新しい管理者ユーザーの作成やリセットができる。
リセットするつもりでここにパスワードを入力してみたら最低文字数があることに気づき、それをヒントに思い出すことができた。それでもダメならリセットすればいいし。
諸々を更新する
ようやくログインしたら「更新があるからupdateしとけよ~」とメッセージが出たので
sudo apt upgrade
sudo apt update
を実行したのだが、update時にCertbotでエラーが出る。
どうやら今のUbuntu向けのちょうどいい更新ファイルがないみたい。色々と試したが更新できなかったので一旦無視。
とりあえずapt upgradeを走らせたのでVMを再起動して、ようやく証明書の更新をすることに。
証明書の更新
上の翻訳記事を参考に
sudo certbot renew --dry-run
を実行したら証明書を更新することができた。かんたん。
("--dry-run"ついてるけどええんか...ええみたいやわ。不思議)
Trojanクライアントの再起動をする必要もなく、またVPN機能が元気に動き出した。
次の更新時期までにcrontab等で自動化を図りたいが、多分ズボラのまままた3か月後に同じことをするだろうな...という思いから、ちょっと詳しめに記録を残しておくことにした。
誰かの役に立てば幸いだが、多分将来の自分が読むことになるだろうな...。
コメントする