プロキシサーバをGoからRustに置き換えた話
はじめに
/icons/hr.icon
はじめまして、kiokulessと申します。Securify開発チームでエンジニアをやっています。弊社が提供しているSecurifyはSaaSで提供しているWebアプリケーションの脆弱性診断ツールです。私の所属しているスキャナチームではどのようなペイロードで脆弱性診断したかをDBやGCSに保存するためにプロキシサーバを用いています。今回はGoで実装されたプロキシサーバをRustに置き換えた話について書きます。今回言及するRust製のプロキシサーバは現在本番環境に用いていないのですが、近いうちにリリース予定です。
プロキシサーバについて
/icons/hr.icon
役割は以下の通りです。ここで言うスキャナは診断するペイロードを送るワーカーで、全てのリクエストはプロキシサーバを経由させます。
スキャナからHTTPリクエストを受け付ける
リクエスト情報をDBに保存する
診断先にリクエストを送る
レスポンスを受け取りリクエストに紐づくようDBに保存する
レスポンスをスキャナに返す
といったようにシンプルなコンポーネントです。
https://scrapbox.io/files/657923d4b8538b0023436d33.png
最初はGoで作ったPoCで良かったのですが、HTTP/2に対応していないという問題点が出ました。
HTTP/2について
/icons/hr.icon
HTTP/2対応はマストで、理由は以下のとおりです。
GoとHTTP/2に関してですが、もちろん普通のサーバ/クライアントには対応をしています。しかしながらプロキシサーバに使っていたライブラリが http.Hijacker という net/http内で定義されているインターフェースに依存していて、その http.Hijacker インターフェースがHTTP/2に対応をしていない状態になっていました。 これらはIssueとしてGitHubの公式リポジトリにまだOpenされている状態です
そしてRustへ
/icons/hr.icon
前述したようにプロキシサーバがそんなに複雑なコンポーネントでもないので、思い切ってGoから違う言語に移植することを決めました。実装言語としての要件はgRPCとHTTP/2プロキシサーバを扱えれば何でも良かったのですが、アサインされた私がRustである程度チームから信頼をいただいていたことからRustで実装することになりました。いつか仕事でRustを書きたいな〜とぼんやり考えてはいましたが、まさかのタイミングで叶ってとても嬉しかったです。
GoからRustに置き換える話となるとdiscordの記事のようにGCパフォーマンスが問題になるケースが一番有名なのですが、今回はどちらの実装でも基準を満たしていたので細かく言及はしません。むしろパフォーマンス以外でも置き換えることが全然あるよ、という話でした。私の所属しているスキャナチームは筋が通っていれば、使用率が低いテクノロジースタックも積極的に検討・採用をするチームなので日々知らない技術を学ぶことができる刺激的な場所です。