ロードバランサーのソースIPの難問…プロキシプロトコルに入る

かつて恐竜が地球を闊歩していた頃、人類は岩やレイヤー4のDSRベースのロードバランサーといった道具を使って仕事を始めた。

当時、これらのツールはサーバーに到達できたので便利であったし、アプリケーション・サーバーに実際のクライアントのIPアドレスが表示されていることを確認するのも簡単だったので便利であった。

ロードバランサーはクライアントとアプリケーションの間に位置する。クライアント(はい、お願いします)かロードバランサーか?

これはかなり簡単で、いくつかの選択肢があった。

DSRモード – ダイレクト・サーバー・リターン。

  1. クライアントはロードバランサーに接続する。
  2. ロードバランサーはそれをクライアントのSourceIPでアプリケーションに送る。
  3. するとアプリケーションはクライアントに直接レスポンスを送る。おそらくSourceIPが外部IPであることに気づき、レスポンスをゲートウェイにルーティングし、レスポンスのロードバランサーをスキップするでしょう。

恐竜たちは、インフラストラクチャーで使用するリソースが少なく、アプリケーションが実際のクライアントIPを取得できるこのアプローチを好んだ。

欠点は、アプリサーバーと大元のサーバーで特別なネットワーク設定をする必要があることだ……ロードバランサーはレスポンスを受け取ったり見たりしないので、SSLやコンテンツの切り替えは窓の外だ。

もう1つの欠点は、LBはAppサーバーのパフォーマンスを把握できないため、よりパフォーマンスの高いサーバーへの負荷分散が難しくなることだ。ADCは最も応答が速い、あるいは最も接続が少ないものを使うことになる。(あるいは、ADCはSNMPを使ってこれを取得することもできる。

いずれにせよ、この仕組みは馬と荷車のように長年うまく機能してきたし、実際、戦車レースやいくつかの古いプロトコルのように、これが最良の選択肢である状況もまだある。

お次はこちら:

ゲートウェイモード

  • クライアントはロードバランサーに接続する。
  • ロードバランサーはそれをクライアントのSourceIPでApp Serverに送る。
  • アプリケーションはクライアントに直接レスポンスを送りますが、ロードバランサーを経由します。これはロードバランサーがレスポンスを受け取ることを意味します。

これはある意味ずっと良いが、ソフトウェアアップデートなど、Appサーバーからのすべての外部トラフィックはロードバランサーを経由するので、面倒になる。

ロードバランサーがスイッチのように見え、すべてが高速カップとストリング・ネットワーク・リンクで直接接続されていた頃は、このようなことがよくあった。

プロキシベースのロードバランシングのファーム化と利用を学ぶ男性

この頃、ネットワークとCPUのスピードが速くなり、プロキシという手法が見られるようになった。

私たちは、アプリケーションサーバーを騙すのではなく、ロードバランサーをソースIPとして使用することにしました。TCPのパフォーマンス、セキュリティ、ロードバランサー上で追加サービスを提供できることなど、多くの理由からそうしました。

しかし、狩猟採集からの脱却には大きな代償と困難が伴った。

クライアントIPをアプリケーションサーバーに送信する方法は?

幸運なことに、HTTPを使っている限り、Good Old HTTPは素晴らしい答えを持っていた。

X_Forwarded_For ヘッダー – ヘッダーにクライアントのIPを入れて送信することができます。

これはかなり単純なことなので、あまり詳しく説明しないが、誰でも簡単に設定できるヘッダーであると言っておけば十分だろう。また、複雑になることもある。例えば、ロードバランサーにすでにX_Forwareded_For IPが送られている場合はどうなるのか?それを使うべきか、それともソースIPを使ってそれを変えるべきか?これらは通常、まともなLBであれば設定可能だが、どれもセキュリティ上の考慮点などがある。

いずれにせよ、ウェブアプリがソースを必要とする場合、99%はこの方法で入手する(注:統計の99%は作り話です)。

他のプロトコルはどうなのか?

いくつかのプロトコルに特化したハックはあるが、より広く採用されている汎用的なものはない。

プロキシー・プロトコルが提案され、広く採用されるまでは。

プロキシプロトコルの説明

プロキシプロトコルは、転送されたリクエストに元のクライアントの接続詳細を 含むヘッダーを追加することでこの問題を解決する。

このプロトコルにはすでに2つのバージョンがある。

  • プロキシプロトコルv1:シンプルで人間が読めるテキスト形式を使用。
  • プロキシプロトコルv2:より効率的で、IPv6やUnixソケットアドレスなどの追加機能をサポートできるバイナリ形式を使用。

何が違うかというと、これを受け入れるように設定せずに有効にすると、ほとんどのアプリケーション・サーバーが壊れてしまうということだ。これは、Proxy Protocolが文字通りデータの先頭に必要な詳細を追加するからである。

しかし、導入は拡大しており、現在では多くのベンダーがこれをサポートしている。

例えばDNSプロキシには最適だ。

X_Forwardard_Forと同様、まだ決めなければならないことがある:

例えば、Proxy Protocolヘッダが表示された場合、ロードバランサーに何をさせたいですか?削除して新しいものを設定するのか、それともそのままにするのか。もしヘッダが送られることを期待していないのであれば、ヘッダを無視し、自分のヘッダを取得すべきです。

プロキシプロトコルはクライアントIPを取得する簡単な方法で、現在では広くサポートされています。

クラウドにおける高可用性について考えることにするよ!

About Jay Savoor