IP制限を減らす取り組み

Fumihiro Ito
May 30 · 11 min read

モンスト事業本部SREグループの伊藤です。
普段はモンストに関するシステムの改善・運用を様々な面から行っています。

今回もサービスの直接的な改善ではないですが、ツール等のIP制限を減らす取り組みについてご紹介します。
サービスの直接的な改善もいつか書ければなと思っております。

皆さんはIP制限をしているツール等はいくつくらいありますでしょうか?
モンストにも歴史的経緯でIP制限されたツールや、特に制限されていないツール(!)までいくつもありました。
自作のツール以外にも開発や運用で使っているツールのフロントエンドなども合わせると30以上のツールがあります。

運用で使うツールはアラート対応などでオフィスにいない時でもどこからでもスマートに見れると嬉しいです。
特にサーバーのメトリクスは移動中に見れると対応しているメンバーにアドバイスができたり非常に助かります。

これまではオフィスのIPからのみアクセスできるようにしておき、VPN接続をするか、sshでフォワーディングするかのどちらかをしていました。
これでは移動中に簡単に見れませんし、見れるようになるまで時間がかかります。
なので重大そうなアラート対応に移動中に遭遇した場合はスクリーンショットをSlackで共有してもらうなどしていました。

今はこの煩わしさを解消するために全てのツールをインターネットからアクセスできるようにしています。

もちろん認証もなくインターネットに公開してしまっては情報の漏洩にしかなりません。
ですので適切に認証を行い安全にインターネットのどこからでもアクセスできるようにしています。

IP制限のよくないところ

とにかく更新を忘れます。
複数のツールがあると一箇所にまとめることが不可能だったり、細かい制御を行うためにバラバラに記述されることがよくあります。
そうすると大体どこかの更新を忘れます。

制限されたIPからのアクセスは無条件で信頼できるものとして扱ってしまいがちという問題もあります。
オフィスにある端末は全て会社により管理されていますがそれだけで本当に全てのアクセスを信頼できるものでしょうか?

同じオフィスでも部門が違えば見えて欲しくない場合もあります。
IP制限ではそのような 誰がどの情報にアクセスできるか をコントロールすることができません。

またオフィス外の特定の場所からのアクセスを許可したい場合、その場所が固定IPになっている必要があります。
これは場合によっては難しい条件となり運用が大変になることがしばしばあります。

今までのプロキシ

今までもツール等をセキュリティグループの後ろで直接提供していたわけではなく、一段別のプロキシを挟む構成になっていました。
このプロキシでIP制限を実施していました。

このプロキシに認証機能があれば安全にインターネットのどこからでもアクセスできてよさそうです。

BeyondCorp

皆さんは BeyondCorp という単語を聞いたことがありますか?

BeyondCorpとはGoogleが提唱しているセキュリティモデルです。
オフィスのネットワークは安全、オフィスのネットワークだから安全という前提を捨てアクセス元を信頼せずデバイスやユーザの認証を行うことで結果的にユーザ(従業員)はどこからでもアクセスできツール側もより安全になる、というものです。

この考え方を大いに参考にして、そのようなプロキシを 自作することにしました。

自作しない場合

実はこのようなプロキシは自作しない、もしくは実装量を大幅に減らしても実現することができます。

例えば nginx の ngx_http_auth_request_module はプロキシ部分を大幅に簡単に実装できるでしょう。
このような機構はnginxだけではなくApacheやCaddy Serverにもあります。

クラウドのマネージドサービスで実現するという方法もあります。
GCPであれば Cloud Identity-Aware Proxy が、AWSであれば Application Load Balancer で実現できるでしょう。

他にもOktaが提供するものやSaaS等もあります。

ですがこれらでは求める要件を全て満たすことができませんでした。

プロキシの自作

しばらく前から認証を行うプロキシについては考えていたので実装するにはいいタイミングということで自作しました。

実装するにあたって

  • 全アクセスをTLSで暗号化する
  • 権限の管理を楽にする
  • 人間以外のアクセスもサポートする
  • 認証局は自作しない

の4つは必ず実現したい要件です。

そこで以下のような自作のプロキシを実装しています。

自作プロキシの部分はL7のリバースプロキシとして振る舞い、プライベートネットワーク外へプロキシする際はフォワードプロキシを通ります。
フォワードプロキシはアドレスを固定にするために入れてあり、バックエンド側はそのIPからのアクセスのみ許可すれば自作プロキシ経由からのアクセスに絞れます。
このフォワードプロキシを使うかどうかはリバースプロキシの設定に記述することができ、必要な時だけ使うことができるようになっています。

自作プロキシは全てGoで実装されており各コンポーネントともにKubernetes上で動作しています。(バックエンドの各ツールは除く)

SSL/TLS

インターネットのどこからでもアクセスできるようにするということは通信経路が全て信頼できないものであるため、E2Eの暗号化は必須です。

時代の流れとしても多くのサイトでSSL/TLS通信をするようになってきているのでこれは迷いなく必須要件です。

また加えてサーバー証明書の更新の自動化も必須要件です。
ACMEプロトコルで容易に証明書の発行と更新ができるようになったので最初から対応できているとプロキシ自体の運用が楽になります。

後述しますがマネージドなロードバランサーによるTLS終端は今回は使えません。
自作したプロキシが暗号化を解く必要があります。

OpenID Connect

ユーザーの認証はOpenID Connectで行うことにしました。

認証するユーザーの管理を少しでも楽にするために会社のアカウント管理と紐付けるためです。
紐付けてしまえば退職された際でも特別な作業が必要なく、一括でアクセスができなくなります。

既存のツールでは自前でアカウント管理をしており、退職処理の煩雑さや漏れなども気になっていました。
それを解決するためにもOpenID Connectによる認証は外せません。

RBAC

部署など会社組織を権限管理のベースとしてしまうと組織変更のたびに大きく改修する必要があり現実的ではありません。
一方何らかのモデルがない場合も権限管理が煩雑になってしまい時間が経つにつれ誰も分からないという状態になってしまいます。

そこで権限管理にはRole-based access control(RBAC)を実装しています。

人間以外のアクセス

人間がブラウザでアクセスする場合は 人間を認証 すればいいのでそこまで大変ではありません。
ですが我々の座席の近くにはメトリクスを常に表示しているディスプレイがあり、このようなマシンではアクセスしている人間を認証することができません。
他にもbot等プログラムからアクセスすることも十分に考えられます。

このような人間を認証できない場合はデバイスとして認証することにしました。

クライアント証明書認証で実装することでOpenID Connectを使わない認証を実現しています。
ただ、大半のユーザはクライアント証明書認証を使わないのでなるべく証明書の選択画面等を見せないように、余計なクリック等をしなくても済むようにしています。
これはプロキシを介してアクセスするのがリテラシの高いエンジニアだけではなく、どのような人でも説明なしに使えるようにするためです。

そのためにTLSの Server Hello の後に送られる Certificate Request メッセージにCAのSubjectも入れています。
Subjectが入っていると最近のブラウザ(macOSだとHigh Sierra以上のSafari 12以上)であれば、該当する証明書が入ってない場合何も表示せずそのまま継続します。
(試した限りではそのような挙動をしました。普段TLSとブラウザの仕様を細部まで追いかけているわけではないので間違っている可能性もあります。他にもChromeやIE・Edge等でも試しています)
これで大半のユーザにはクライアント証明書認証があるということを知られなくて済みます。
(極一部のユーザは通信をキャプチャしてCertificate Requestメッセージを発見するかもしれませんがそれくらいリテラシがある人であればこちらの意図を察してくれるだろうと期待できますしそうやって気が付かれたとしても問題ではありません。)

本来であればこのクライアント証明書認証を第一の認証方法として使う方がベストでしょう。
しかしアクセスする人のデバイスに証明書を入れそれらを管理しないといけないという大変さを考慮し、これをプライマリの認証方法としていません。

認証局を実装したくはなかったのですがこればかりは仕方ありません。
クライアント証明書認証に限り認証局を実装しています。

Webhook

このプロキシはGitHubのWebhookも通ります。

Webhookの場合、クライアント証明書認証もできないのでここだけはヘッダーの署名を検証しそれでアクセスを許可しています。
Webhookは特定のパスにしかこないのでヘッダーの署名を検証してアクセスできるのはそのパスだけに限定しています。

そのためシークレットが漏れ任意の署名が作れるようになったとしてもWebhookのエンドポイントのみがアクセスできるようになるだけです。
ただしこのエンドポイントに脆弱性があり、任意の情報が抜き出せたりするかもしれません。
その場合、Webhookのエンドポイントにアクセスできる限りリスクを排除できないのでここは利便性を取りそのリスクは受け入れています。

SSH

サーバーにSSHでログインして行う作業というのはなかなかなくせませんしモンストにもいっぱいあります。
なくしていく方がいいのは間違いないのですが完全になくすにはまだしばらく時間がかかることでしょう。
それまでの間、SSHもプロキシを通してインターネットのどこからでもアクセスできるようになっている方が便利です。

そこでSSHもプロキシを通すようにしました。
この仕組みについては説明するとかなり長くなるので割愛しますが、ユーザーはローカルにCLIツールをインストールすることでSSHもプロキシを通してインターネットのどこからでも行うことができるようになります。

CLIツールのインストールはGoで書かれたバイナリが一つだけなのでパスの通ったところに置くだけでよく簡単です。

導入した後の変化

どこからでもツールに平等にアクセスできるというのは考えていた以上に快適になります。
自分が今どこのネットワークに繋がっているのか考えなくてもよくなります。
Slackで共有されるリンクをそのまま何もせずに開けますし、もし認証情報の有効期限が切れていたら認証画面へリダイレクトされその後ちゃんと戻ってきます。

自作のツールは認証機構をプロキシに全て預けられるのもツール側の実装が少なくて済むので便利です。
プロキシされてくるリクエストのヘッダーにはユーザーの情報が付加されており、それをデコードすればそのまま使えるのであまり難しいことを考えなくても済みます。
(ヘッダーの署名を検証するにはそれなりに知識が必要ですがミドルウェア等で1回実装すれば使いまわせます)

まとめ

社内ツールにインターネットのどこからでもアクセスできるようにするための工夫について簡単にご紹介しました。
プロキシの実装の詳細を説明していくととても長くなってしまいますので今回は簡単な紹介にとどめます。

セキュリティ対策だからといって利便性を落としてしまうとユーザーはそれをバイパスする方法を見つけてしまったり使わない方向に力が働いてしまいます。
なので 利便性も向上させセキュリティも向上させる ことが大事だと思いそれを実現できるように実装するよう気をつけています。

プロキシの内部でもそれなりに面白いことをやっていますし、プロキシ全体としてもそれなりに面白いものになりつつあるのではないかなと思っています。
更に深い部分での工夫とかはいつかどこかでお話する機会があればご紹介いたします。

mixi developers

Thanks to Koji Kita and Emi Sugita

Fumihiro Ito

Written by

Software Engineer at Mixi, inc.

mixi developers

ミクシィグループのエンジニアやデザイナーによるブログです。

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade