• 締切済み

透過型プロキシのHTTPS通信

現在,自作の透過型HTTP/HTTPSプロキシを開発中です. プロキシとしての動作は単にクライアント・サーバ間のデータ受け渡しを行うだけなのですが,現在,透過型の実現で困っております. 透過型の実現には,iptablesを利用し,宛先ポート80番のデータの宛先ポート番号を3128番(本プロキシ)に変換し,本システムにデータを送信しています.HTTPの場合はこれで問題ないのですが,HTTPSの場合が問題です. HTTPSの場合はSSLハンドシェイク等,通常のHTTPとは違う手順を行わなければならないので,HTTP,HTTPSどちらで通信するのかをあらかじめ知る必要があります. クライアントのWebブラウザでプロキシの指定を行う場合(透過型ではない)のHTTPS通信は,クライアントからCONNECTリクエストが実行された場合のみ,HTTPS通信処理へ分岐させればいいのですが,透過型の場合は,クライアントからそのメソッドが実行されず,さらにiptablesによって宛先ポート番号も3128番に書き換えられているため,HTTP通信なのかHTTPS通信なのかを判別することができません. これを実現するためには,どのような方法があるのでしょうか? 透過型プロキシでHTTPS通信をサポートする製品(Webフィルタリングソフト等)はたくさん存在しているため,実現は可能だと考えられるのですが,どのように実現されているのでしょうか? 考えられるひとつの方法としては,HTTP用を3128番,HTTPS用を3129番ポートで実行しておいて,iptablesで80ならば3128,430ならば3129等と振り分ける方法が挙げられますが,どうでしょうか. よろしくお願いいたします.

みんなの回答

  • Lchan0211
  • ベストアンサー率64% (239/371)
回答No.5

No.4の回答は、あらかじめ決まったSSLサーバを対象としていることを 前提にしているので、無視してください。 No.4のお礼に書かれている説明を読んで、不特定(任意)のSSLサーバを 対象としていることがわかりました。確かにこの方法で通常プロキシは 可能だし、透過プロキシについても原理的には可能だと思います。 ただ、通常のiptablesを使ったのではやはり実現は無理だと思います。 もしかするとtproxyパッチを当てて、それに対応した処理をすれば 可能になるかもしれません。 http://www.balabit.com/support/community/products/tproxy のDocumentationを読んでみてください。 「Make it possible for a process to listen to connections on a foreign address.」を使えば、もしかしたら可能かもしれません。 これでダメなら、他にiptablesを拡張するようなカーネルパッチを 探してみるとよいと思います。 ちなみに、httpsのデフォルトポート番号は430でなく443です。

sabakanntoka2
質問者

お礼

そうですか.通常のiptablesではやはり無理ですか・・・・. tproxyパッチについてもう少し調べてみます. >ちなみに、httpsのデフォルトポート番号は430でなく443です。 そうですね^^; 間違っていました. 色々ありがとうございました. 大変参考になりました.

  • Lchan0211
  • ベストアンサー率64% (239/371)
回答No.4

>>例えば、オレオレ証明書のルート証明書をブラウザにインストールさせて、 > あらかじめ接続予定のSSLサーバと同じCN名を持つ証明書をオレオレ証明書で作って、 > それをプロキシサーバに登録しておくとかやっているのでしょうか? >そうです.そのような手法で実現しております. なるほど。つまり、任意のSSLサーバでなく、特定のSSLサーバ(偽のオレオレ証明書 作成済みのSSLサーバ)を対象とし、その通信データを透過プロキシで盗み見したい わけですね。 であれば、接続先のSSLサーバ毎にiptablesの変換ポート番号を別々に用意し、 それぞれのポート毎に使用する証明書を変えればよいのではないでしょうか? ちなみに、SSLで暗号化したデータには、アカウントパスワードやカード番号等、 他人が見てはいけない秘密データが入っている場合が多いことは認識していますよね? アクセスした本人やSSLサーバ管理者でない第三者がその秘密データを盗み見た場合、 不正アクセス行為で捕まる場合もあるということを認識していますよね?

sabakanntoka2
質問者

お礼

多大なアドバイスありがとうございます. >あらかじめ接続予定 というよりも,クライアントからCONNECTリクエストを受信したのち,本来のCONNECT先のホスト名のサーバとSSLハンドシェイクを行って,サーバ証明書を取得し,それと同じCNを持つ証明書をつくり,プロキシが署名します.で,それを使ってクライアントとsslハンドシェイクします.クライアントには,プロキシの署名が信頼できるものだとするために,ルート証明書をインストールしておきます.つまり,プロキシはCONNECTが来るまで,どのサーバに接続するかしらないということです. >であれば、接続先のSSLサーバ毎にiptablesの変換ポート番号を別々に用意し、 >それぞれのポート毎に使用する証明書を変えればよいのではないでしょうか? すいません.ここはよく理解できませんでした. もう少し具体的に説明していただけると幸いです. 理解力がなくてすいません. よろしくお願いいたします.

  • Lchan0211
  • ベストアンサー率64% (239/371)
回答No.3

> Webブラウザにプロキシを指定する(+ルート証明書のインストール)方法では,この目的は達成できたのですが えっ!?こんなので本当に通常プロキシがSSL暗号化前の 全リクエスト・レスポンスのデータの内容を取得できるんですか? なんか説明していない前提条件があるんじゃないでしょうか? (その前提ががわかれば、透過型についてもアドバイスできるかもしれません。) 例えば、オレオレ証明書のルート証明書をブラウザにインストールさせて、 あらかじめ接続予定のSSLサーバと同じCN名を持つ証明書をオレオレ証明書で作って、 それをプロキシサーバに登録しておくとかやっているのでしょうか? それとも、接続先のSSLサーバの本当のサーバ証明書(+秘密鍵)を プロキシサーバに登録したりしているのでしょうか? そのあたりを細工しないと、ブラウザが意図している接続先の証明書と異なる証明書が プロキシサーバから渡されるため、証明書不正の警告(接続先不一致)が ブラウザに出ると思いますけど。

sabakanntoka2
質問者

お礼

返信ありがとうございます. >例えば、オレオレ証明書のルート証明書をブラウザにインストールさせて、  あらかじめ接続予定のSSLサーバと同じCN名を持つ証明書をオレオレ証明書で作って、  それをプロキシサーバに登録しておくとかやっているのでしょうか? そうです.そのような手法で実現しております. この方法は透過型でも同じで大丈夫だと思うのですが,問題は宛先ipがiptablesにより変更されることですね.

  • Lchan0211
  • ベストアンサー率64% (239/371)
回答No.2

最後の質問に答えていませんでしたので別の観点で追伸します。 > 考えられるひとつの方法としては,HTTP用を3128番,HTTPS用を3129番ポートで実行しておいて, > iptablesで80ならば3128,430ならば3129等と振り分ける方法が挙げられますが,どうでしょうか. これで振り分けることはできますが、振り分けて何がしたいんでしょうか? 通常のプロキシのCONNECTメソッドと同様にそのままスルーしたいだけなんだったら、 プロキシしないで最初からTCP/IPレベルのルーティングしちゃえばいいだけでしょ? 通常のプロキシのCONNECTメソッドは、宛先がプロキシサーバに向いている通信を 本来のhttpsサーバに接続させるためにあります。透過型プロキシ構成で、 クライアントが本来の宛先に通信しようとしているのだから、最初から TCP/IPレベルのルーティングで接続しちゃえばいいだけでしょってことです。

sabakanntoka2
質問者

お礼

説明不足ですみません. 私の提案した方法も実現できない問題点がありました. HTTPの透過型を実現する方法として,現在,80番にきたものの宛先アドレス,ポート番号をプロキシのものに変換するルールをiptables上に作り,その結果プロキシに送信されたリクエストのHost情報(HTTPレベル)を基に,サーバへTCPコネクションを張りに行っています. ところが,HTTPSの場合,クライアントは430番にSSLハンドシェイクを仕掛けてきます.それをiptablesで同じように宛先ipアドレスを変換した場合,プロキシが受信するデータの中には,本来の接続先サーバの情報は入っていないことになります.なので,この方法では,プロキシがどこの接続先に接続すればいいかわからず,処理ができなくなります. 説明べたで本当に申し訳ありませんが,NICを2枚利用し,クライアントのブラウザでプロキシを指定する必要がないという条件で,HTTPS通信の中身を保存できるようなプロキシを作成したいと考えております. よろしくお願いします.

  • Lchan0211
  • ベストアンサー率64% (239/371)
回答No.1

アクセス元のユーザが知らないところで、任意のhttpsサーバの 中間に入って勝手にユーザの通信内容を見たり、それを元に フィルタリングしたりすることはできません。 それができてしまったらSSLによる秘密通信の意味がなくなり、 大きなセキュリティ問題になります。 (第三者攻撃が可能になってしまいます。) そもそも、なぜSSL通信を透過型プロキシで処理したいのでしょうか? データの内容が暗号化されていて中身が秘密である以上、 透過プロキシ対象から外して、あとはTCP/IPレベルのルーティングと パケットフィルタリングで制御すればよいだけだと思いますけど? 通信データ内容をチェックできない限り外部にアクセスさせない方針で あれば、https通信そのものを禁止とする必要があります。 特定のWebサーバをガードしたり代理したりする目的で、 Webサーバの前段にSSLを処理する透過型リバースプロキシーサーバを 立てることは可能です。その場合、リバースプロキシサーバに 元のWebサーバの証明書と秘密鍵ををインストールする必要があります。

sabakanntoka2
質問者

お礼

早速の返信ありがとうございます. >アクセス元のユーザが知らないところで 私の説明不足でした.申し訳ありません.透過型でない方に関しては,クライアントにあらかじめプロキシのルート証明書をインストールしてもらって,プロキシはクライアントからのCONNECTリクエスト後に,自身が作り出した証明書でクライアントとSSLハンドシェイクするように動かしていました. 私の目的は,HTTP/HTTPS通信を利用した全リクエスト・レスポンスのデータの保持です.ここでいうデータというのは暗号化していない状態のものです.Webブラウザにプロキシを指定する(+ルート証明書のインストール)方法では,この目的は達成できたのですが,プロキシを指定することなく,ルート証明書のインストールのみでこの機能を実現したいと考えています.

関連するQ&A