人間とウェブの未来

「ウェブの歴史は人類の歴史の繰り返し」という観点から色々勉強しています。

プロセスのオーナ情報をTCPオプションヘッダに書き込むに至った背景とアプローチの補足

hb.matsumoto-r.jp

上記のリンクの昨日書いた記事のスコープや前提、及び、ユースケースがわかりにくかったので、以下にそれらをもう少し詳細に書こうと思います。コメントやアドバイスをすでに頂いた方はありがとうございます。

まず、この手法にいたった課題について説明してきます。 これまでWebホスティングサービス(レンタルサーバ)のように、WordPressのようなWebアプリケーションを配置するための領域(一般ユーザで利用するテナント)を貸し出すようなプラットフォームサービスにおいて、低価格化を実現するために単一のサーバにどれだけ高集積にテナントを収容するかという検討がなされてきました。

そんな中、テナント単位でプロセスを用意したり、IPアドレスをはじめとした個別リソースの紐付けを極力行わずに、共有のデータベースミドルウェアを使い、できるだけリソースを共有するような方式、例えばApacheのVirtualHostなどが採用されてきました。これによって、メモリ32GBぐらいのサーバに数万から10万ホストぐらいまで収容できるようになりました。プライベートIPアドレスや静的な情報を各テナントに紐付けると、10万ホスト収容の場合はそれ相当の数の静的な設定が必要になり、例えばApacheのVirtualHostの場合だと、それだけで4GBぐらいのworkerプレセスになります。そうなると、clone()に1秒ぐらいかかったりと大幅にCGIなどの性能低下やリソース逼迫が生じることとなり、そこも動的な設定にするなどの提案がなされてきました。

一方、そのようにリソースを共有するような方式をとると、プロセスの権限をテナントへのリクエストに応じていかに適切かつ動的に分離しつつ、Webアプリケーションの実行性能を落とさないかという点が課題になります。そこで、スレッド単位で権限を分離する方式などいくつか提案されてきました。しかし、そのような状況でも、Webサーバが持つ脆弱性やシステムにおける権限分離の穴などによって、特定のテナントから別のテナントのファイルを読み込めたりする問題がこれまでに何度も繰り返されてきました。

例えば、数年前にあったのは、とあるテナントのWebアプリが脆弱性なのによってのっとられたとします。その上で、そのテナントからシンボリックリンクを読みたい別のテナントのスクリプトファイルに対して.htmlなどに張り替え、Webサーバからは単に静的ファイルとして表示させるようにし、Webサーバのシンボリックリンクチェックがシステムコールレベルでアトミックに行われないこととマルチプロセス(スレッド)であることを利用して、特定テナントから何度か試行することでファイルを覗き見るような所謂TOCTOUな手法によってファイルを覗き見されるようなことがありました。また、ホスティング環境で提供しているライブラリやApacheにロードしているモジュールの脆弱性などによって、意図せず同一OS上でread権限を持つ複数のファイルの閲覧ができる問題などがありました。そして、その漏れた情報がどこかのサイトで共有され、とあるタイミングで特定のテナントからデータを抜かれるといった事象もありました。現在ではそれらを解決するための権限分離手法を沢山提案・実装してきたので、随分と強固になってきたと思いますが、依然として日々様々なインシデントが生じています。

各テナントはサービス利用者に一般ユーサで利用できる領域を貸し出しており、そこで公開されていWebアプリケーションをプラットフォームサービス事業者としてメンテするわけにはいかず、各テナントには脆弱性があり、そこが踏み台にされる前提で、そうなってもセキュリティ上の問題が起きないようなプラットフォーム基盤を構築する必要があります。また、WordPressをはじめとした、スクリプトファイルにかかれているID/PASSを抜こうという攻撃が特に多く、踏み台となったテナントから各テナントのID/PASSの認証情報が仮に漏れたとしても、それぞれのテナントを乗っ取らない限りにおいてはその認証情報を使えないようにしたいという多層防御の仕組みを検討していました。

そこで要件をまとめると、

  • テナントが収容されるサーバがフロントにあり、テナントから利用する共有データベースが後ろのプライベートネットワークで繋がっているようなホスティングシステム構成において
  • 接続元のIPアドレスが共有され、各テナントのWebアプリケーションが利用するデータベースミドルウェアを共有し、OSの各種リソースを共有するような低価格で提供される高集積マルチテナント環境でも
  • 仮に各テナントの各種スクリプトが利用するデータベースのID/PASSのような認証情報がシステムの脆弱性によって漏れたとしても
  • 収容サーバの特定のプロセスからのデータベースアクセスでない限りID/PASS認証を通さず
  • 収容サーバの接続元プロセスがユーザランドで正しい接続元プロセスかのように詐称できない(自身を証明する識別子を扱わせない)
  • IPアドレスベースよりもより粒度の細かいプロセスベースでの接続元プロセスの検証方式

を考えた結果、昨日に書いた記事のアプローチに繋がりました。

また、実装についてもeBPFを検討していたのですが、TCPオプションヘッダをいじるようなeBPFの使い方が以下の論文ぐらいで、これをためそうとしたところ論文に記載されているフックポイントなどはまだ見当たらず、論文がその提案であるということろで止まっており、今の所公開されているLinuxでは実現ができなさそう?に思ったのでカーネルモジュールで実装しています。

もしここについても、eBPFでこんなふうにできるよ、というのがあればご教示いただけると幸いです。