ネットワーク関係

研究室VPNサービスを始動

ついに弊研究室にて固定IPのVPNサービスを始動しました。これに伴い関係各所におかれましてはうちの研究室PCへのアクセス方法が変更となります(詳しくは個別に連絡します)。

これまでは外部提供のVPNとしてInterlinkのマイIPでグローバルIPを固定した上で、研究室のワークステーションにはその固定したIPとメイネット(名城のネットワーク)からのみ接続できる形を取っていた。しかしこれには問題が2つあった。

1 自分以外は学外からアクセスできない

人に使わせることも見越してグローバルIPにしたのに肝心の他人はアクセスできない。大半の他者は学外にいるのだ。かといってこのためだけにVPN契約させるのも馬鹿みたいだ。

2 学内からは無条件にアクセスできる

たとえばJupyterHubを使ってもらうにあたり当然IDとPWでアクセス制限はかけているんだけど、学内アクセス(学生が普通に使える学内無線LANからも!)でIP指定するとログイン画面までは到達できてしまう。これは普通のことなのだが正直いって怖い。

ということで、自前オンプレでVPNを組んで、自由にアカウント発行してVPNを使わせられる環境をついに組んだのだ。(AWSで組むことももちろんできたのだが、その金を俺が払うのもなんか違うし、何より接続しっぱなしにされた時が怖い)

構築まで

使ったのはいつもの解析用PC(CentOS7)。グローバルIPは持ってるけどFortiGateのファイアウォールで割ときつめに送信元IP+ポート指定でアクセス絞ってます(ただし上記の通り学内だけざるになってた)。

やるべきことはそう多くはない。SoftEther入れて、デーモン登録して、firewall.dでポート開いて、FortiGateでもポート開く。それだけ。SoftEther入れてdaemon登録するあたりは結構いっぱい落ちてるので調べればいいし、firewalld-serviceは

$ systemctl start firewalld.service

で仮想ファイアウォール立ち上げて、

$ firewall-cmd  --add-service=vpnserver --zone=public --permanent

でサービス指定して穴開けるか、もしうまくいかないようなら

$ firewall-cmd --zone=public --permanent --add-port=443/tcp
$ firewall-cmd --zone=public --permanent --add-port=992/tcp
$ firewall-cmd --zone=public --permanent --add-port=1194/tcp
$ firewall-cmd --zone=public --permanent --add-port=5555/tcp

で個別にポート開けるか。これはSoftEther側のポート指定に合わせるけど、デフォルトのリスナーはこの4つ。できればサービス指定で開けたほうがいいとは思うけど。他のサービス経由で突っ込まれたら嫌だしね。

$ firewall-cmd --reload
$ firewall-cmd --list-all

できたら再読み込みして状態確認しとくこと。

FortiGateは設定画面入って左のメニューから新しくサービス追加で、SoftEtherとかって名前にしてTCPポートの443、992、1194、5555だけ設定、後はIPv4ポリシーの方でどのルールに適用するか選んでホワイトリスト形式で通す。

できたら外のネットワークからポートスキャンでもかけて、指定ポートにアクセスできるか確認しておくこと。

「PPPサーバへの接続を確立できませんでした」

自分用のアカウント作って試しに接続してIPが固定されていることを確認、後は細かい設定になる。ただ、iPhoneにせよMacにせよL2TP over IPSecで繋ぐのにどうもうまくいかない事案がたまにある。

「認証できませんでした」系のエラーが出たらID/PWが間違っているだけだし、「到達できませんでした」系のエラーなら(グローバルIP振ってる時点でIPに到達できないことは基本的にはないので)仮想(firewall.d)か物理(うちならFortiGate)、どちらかのポートが空いていなくて遮断されている確率が高い。

大体のWindowsデバイスはもうこれだけでアクセスできるし、なんだったらVPN Azureをオンにすれば秒で運用開始できるのだが、クライアントにMacとかiOSがいるとこれでは終わらない。多くの場合にエラーメッセージ「PPPサーバへの接続を確立できませんでした」が出る。これはグローバルもポートも突破してサーバーまで到達はできて認証もできたんだけど、そこからVPN接続が確立できなかった形になる。これはSoftEther側でSecureNATをオンにすれば解決する。SecureNATは非常に簡単にいうとVPNサーバー上に仮想ルーターを立ててそこから個別のクライアントデバイスにローカルIPを振る機能。

うちの場合はVPN AzureもダイナミックDNS(DDNS)もオフにしている。これは将来的に自分のドメインのサブドメインにVPN機能を付与して*****.jun-systems.infoみたいな感じでアクセスできるようにしたいから。おそらくAレコードとしてサブドメインにサーバーのグローバルIPを振るだけでできるはず。(今はドメイン管理がお名前.comなのにネームサーバーがさくらインターネットになっている関係でサブドメインがいじれないのでできない。近々管理移譲を申請するつもりでいる)

接続しっぱなし対策

名大でVPNを運用していた当時にもあった問題点として「VPNはいろんなことを意識せずに支えて便利なんだけど、一方で意識しなさすぎて接続を切り忘れる」というのがあった。これは確かに深刻な問題で、特に研究者みたいな「生活が全部仕事」のような人種は割とどこだろうと仕事のためにVPN繋いだりするので、そのままプライベートに戻って切り忘れることが往々にしてある。他人のYouTubeのトラフィックとかまで全部うちの解析PCを経由するのは避けたい。これはSoftEther上でコントロールする。

とりあえず仮想HUBのユーザー管理でユーザーを作成したら、設定右上のセキュリティポリシーに入り、VPN Clientの自動切断を設定する。別に何回連続で繋ぎ直してもらっても一向に構わないので、とりあえず30分(=1800秒)で自動切断するように設定。

後は多重ログイン制限とかその辺を設定するのもあり。自分の利用はMacBookにiPad Proにといろんなところから多重ログインは当然許可するけど、他人に関しては同時接続は禁止するのが妥当だろうなあ。帯域幅とかまでがっつり設定できるのは素晴らしい。後はなんかあったときのためにログ取る(=モニタリングする)か迷ってるぐらいかな。

そしてユーザーごとにアクセスに使えるデバイスのMACアドレスを事前に指定しておけたりすると最高で、それはたぶん仮想HUB内のアクセスリスト項目から設定できる。どっからどう見ても登録が面倒くさいが。

あと本当にできれば証明書認証にしたかった。無料版のSoftEtherではできないっぽいからこれは諦めるけどね。

後は出先からのアクセスが絶妙に遅いのだが、これはひとえにテザリングのせいなのでいい加減IIJからdocomoに移る。めんどくさくてやれていないが。

追記:重大な問題が起きた

家のネット環境からは接続できたので安心して外に出たのだが、外からIIJでテザリングしたらつながらなかった。…それは困る。元々InterlinkのマイIPのVPNが出先からテザリングでも繋がっていたので今回のVPNでもまあ大丈夫だろうと思っていたのだけれど、iPhone、iPadのどっちでテザリングしてもつながらないどころかそもそもiOS単体からの直接的なVPNすら繋がらない。

以下の通りIIJのぶち切れアナウンスとして、(時期は少し古いものの)テザリング+L2TP over IPsecでのVPN接続は一応動くようなことが書いてある。

ただ気になるのは、IIJ公式の以下の内容

NAT環境になっていること自体は承知の上だ。クライアント側がNAT内部にある場合はSoftEther側で突破してくれるのでこれは一般的に問題ない。一方VPNサーバー自体がルーター内部にある時にはNATトラバーサルの関係でUDP500と4500のポートを開けておかなければいけないけど、グローバル環境に直接晒されている今回は問題ではない。

んーーーー。この感じだとキャリアをdocomoに戻したからってどうこうなるような話でもないような気がするなあ。docomo回線を借り受けるにあたってIIJがAPNで使ってるルートの問題とかなのであればdocomoに移行するだけで解決するかもしれないけど…

Interlink VPNの契約は継続だろうか。

参考までに

macOSでVPNに接続するときには詳細設定から「詳細なログ」の出力ができる。これは/var/log/ppp.logに吐かれる。

家で繋がったときのログ

Thu Dec 26 06:55:13 2019 : publish_entry SCDSet() failed: Success!
Thu Dec 26 06:55:13 2019 : publish_entry SCDSet() failed: Success!
Thu Dec 26 06:55:13 2019 : l2tp_get_router_address
Thu Dec 26 06:55:13 2019 : l2tp_get_router_address 192.168.10.1 from dict 1
Thu Dec 26 06:55:13 2019 : L2TP connecting to server '***.***.***.***' (***.***.***.***)...
Thu Dec 26 06:55:13 2019 : IPSec connection started
Thu Dec 26 06:55:13 2019 : IPSec phase 1 client started
Thu Dec 26 06:55:13 2019 : IPSec phase 1 server replied
Thu Dec 26 06:55:14 2019 : IPSec phase 2 started
Thu Dec 26 06:55:14 2019 : IPSec phase 2 established
Thu Dec 26 06:55:14 2019 : IPSec connection established
Thu Dec 26 06:55:14 2019 : L2TP sent SCCRQ
Thu Dec 26 06:55:14 2019 : L2TP received SCCRP
Thu Dec 26 06:55:14 2019 : L2TP sent SCCCN
Thu Dec 26 06:55:14 2019 : L2TP sent ICRQ
Thu Dec 26 06:55:14 2019 : L2TP received ICRP

外でつながらなかったときのログ

Thu Dec 26 11:16:06 2019 : publish_entry SCDSet() failed: Success!
Thu Dec 26 11:16:06 2019 : publish_entry SCDSet() failed: Success!
Thu Dec 26 11:16:06 2019 : l2tp_get_router_address
Thu Dec 26 11:16:06 2019 : l2tp_get_router_address 172.20.10.1 from dict 1
Thu Dec 26 11:16:06 2019 : L2TP connecting to server '***.***.***.***' (***.***.***.***)...
Thu Dec 26 11:16:06 2019 : IPSec connection started
Thu Dec 26 11:16:06 2019 : IPSec phase 1 client started
Thu Dec 26 11:16:16 2019 : IPSec connection failed

見比べれば一目瞭然で、要はIPsecのPhase1ネゴシエーションを投げたときにサーバーから返答が返ってきていないのだ。

だからこういうエラーが返ってくる。完全にサーバー側からの応答が返ってきていない。

親父のdocomo回線のiPhone借りてテストしてみるかー…それで使えそうなら急いでdocomoに変えよう…