2006-03-28 違う名前で出ています
■ https リバースプロキシーサーバの作り方
はじめに
ひょんなことからhttpsを使うリバースプロキシーサーバを作ることになりました.個人情報を含んだ通信は暗号化すべき,なんて世の中の流れに乗ったわけです.で今回はそのメモ.今回作ったプロキシーはクライアントとの間をhttpsで通信しますが,サーバとの間はhttpsを使うものと,httpを使うものの2種類を実現します.ざっと絵に描くとこんな感じ.数字はポート番号です.
--- https ---> 443 --- https ---> 443 サーバA
クライアント リバースプロキシー
--- https ---> 8443 --- http ---> 80 サーバB
apacheをコンパイル
今回は,リバースプロキシーをnetbsd3.0上で作ってみました.netbsdを選んだ理由は特にありません.以前使っていたので他のOSより慣れてる,というぐらいでしょうか.まぁ,それはともかく,apache2.2をダウンロードして展開,configureを以下の引数で実行してからmake, make installしました.
./configure --prefix=/usr/local/http_proxy --enabe-rewreite \ --enable-proxy --with-mpm=prefork --enable-ssl --with-ssl=/usr/local/ssl
httpd.confでの設定
昔からimport文なんてあったかなぁ,と思いつつ書いてみたのが以下の設定になります.実際にはコメント文なんかが沢山あるんですが,ここでは一切省いています.
ServerRoot "/usr/local/http_proxy" User daemon Group daemon <Directory /> Options FollowSymLinks AllowOverride None Order deny,allow Deny from all </Directory> ErrorLog logs/error_log LogLevel warn Include conf/extra/httpd-mpm.conf Include conf/extra/httpd-default.conf Include conf/extra/httpd-ssl.conf
やろうとしているのは,
の2点です.CLFのフォーマットは以下のようになっています.
| Format | 意味 |
|---|---|
| %h | リモートホストIPアドレス |
| %l | identで得たクライアントアイデンティティ |
| %u | http認証で得たリモートユーザ名 |
| %t | 受付時刻 |
| %r | リクエストの最初の行 |
| %>s | status |
| %b | httpヘッダを除くレスポンスのバイト数 |
httpd-default.confとhttpd-mpm.confはデフォルトをそのまま使ったので,個々では説明を省略します.
httpd-ssl.conでの設定
ここが本題の設定になります.間違ってる箇所があったら指摘していただけるとうれしいです.ちなみにIPアドレスを明示しているのは,デフォルトの設定ではIPv6用のポートも開いてしまうので,それを防ごうとしているからです.
SSLRandomSeed startup file:/dev/urandom 1024
Listen 10.10.10.10:443
Listen 10.10.10.10:8443
AddType application/x-x509-ca-cert .crt
AddType application/x-pkcs7-crl .crl
SSLPassPhraseDialog exec:/usr/local/http_proxy/conf/pp-filter
SSLSessionCache shmcb:/usr/local/http_proxy/logs/ssl_scache(512000)
SSLSessionCacheTimeout 300
SSLMutex file:/usr/local/http_proxy/logs/ssl_mutex
<VirtualHost 10.10.10.10:443>
DocumentRoot "/usr/local/http_proxy/htdocs"
ServerName proxy.foo.co.jp:443
ServerAdmin proxymaster@foo.co.jp
ErrorLog /usr/local/http_proxy/logs/error443_log
SSLEngine on
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:-LOW:-SSLv2:-EXP
SSLCertificateFile /usr/local/http_proxy/conf/server.crt
SSLCertificateKeyFile /usr/local/http_proxy/conf/private_key.pem
BrowserMatch ".*MSIE.*" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
CustomLog /usr/local/http_proxy/logs/ssl_request443_log \
"%t %h %{SSL_PROTOCOL}x %{Cookie}i \"%r\" %b"
SSLProxyEngine On
RewriteEngine On
RewriteRule ^(.*) https://serverA.foo.co.jp$1 [P]
</VirtualHost>
<VirtualHost 10.10.10.10:8443>
DocumentRoot "/usr/local/http_proxy/htdocs"
ServerName proxy.foo.co.jp:8443
ServerAdmin proxymaster@foo.co.jp
ErrorLog /usr/local/http_proxy/logs/error8443_log
SSLEngine on
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:-LOW:-SSLv2:-EXP
SSLCertificateFile /usr/local/http_proxy/conf/server.crt
SSLCertificateKeyFile /usr/local/http_proxy/conf/private_key.pem
BrowserMatch ".*MSIE.*" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
CustomLog /usr/local/http_proxy/logs/ssl_request8443_log \
"%t %h %{SSL_PROTOCOL}x %{Cookie}i \"%r\" %b"
RewriteEngine ON
ProxyPreserveHost On
ServerName proxy.foo.co.jp:8443
RewriteRule ^(.*) http://serverB.foo.co.jp$1 [P]
</VirtualHost>
いくつかポイントを絞って説明します.
SSLPassPhraseDialog exec:/usr/local/http_proxy/conf/pp-filter
秘密鍵にパスフレーズをつけていると,apache起動時に毎回パスフレーズの入力を求められます.セキュリティを確保するためには当然な方法ですが,メンドクサイ.そのため,パスフレーズを自動的に入力しています.pp-filerの中身はこんな感じになります.
#!/bin/sh echo PASSPHRASE
簡単すぎですね.ちなみに,pp-filterはrootを所有者にしてアクセス権を700にしておくことをお勧めします.
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:-LOW:-SSLv2:-EXP
SSLCipherSuiteは奥深い話で,とても一言では書けません.ニゲだ.Pound の SSL セキュリティレベルを制限(上げる)方法 :: drk7jpがSSLCipherSuiteに詳しく書いているので,そちらを参考にしてください.
CustomLog /usr/local/http_proxy/logs/ssl_request443_log \
"%t %h %{SSL_PROTOCOL}x %{Cookie}i \"%r\" %b"
ログのフォーマットをCLFとはちょっと変更してみました.
| Format | 意味 |
|---|---|
| %t | 受付時間 |
| %h | リモートホストIPアドレス |
| %{SSL_PROTOCOL}x | mod_sslで使える拡張フォーマット,環境変数を表示 |
| %{Cookie}i | リクエストヘッダ中の値 |
| %r | リクエスト最初の行 |
| %b | httpヘッダを除くレスポンスのバイト数 |
クライアントとの間で使っているSSLのバージョンとクッキーが正しく流れているかどうかを確認するために使っています.
SSLProxyEngine On RewriteEngine On RewriteRule ^(.*) https://serverA.foo.co.jp$1 [P]
ここいら辺がリバースプロキシーの核になります.httpsでサーバにアクセスするためには,SSLProxyEngineをOnにする必要があります.
RewriteEngine ON ProxyPreserveHost On ServerName proxy.foo.co.jp:8443 RewriteRule ^(.*) http://serverB.foo.co.jp$1 [P]
httpでサーバにアクセスする場合にはSSLProxyEngineを使う必要はありません.この例ではProxyPreserveHostとServerNameというディレクティブを設定しています.これはServerBがホストヘッダの値を元に処理を行なっているために設定した項目です.お使いの環境では必要ないかもしれません.バーチャルホストの例 - Apache HTTP サーバに説明が記載されています.
終わりに
プロキシーの設定は大変です.何が大変と言って,サーバにバグがあればプロキシーがおかしいんじゃないかと責められるし,クライアントの環境設定にミスがあれば,やっぱりプロキシーがおかしいんじゃないかと責められます.でも,疑いを晴らそうと思ってがんばると,ログのフォーマットについて妙に詳しくなるというすばらしい(?)メリットが待っているのです.はぁ〜
- 460 http://www.9203.net/~takech/pukiwiki/index.php?Apache/Apache2/SSL Reverse Proxy
- 380 http://211.5.227.51/~y-matsui/MovableType/archives/2008/04/https.html
- 345 http://www.google.co.jp/search?q=SSLProxyEngine&ie=utf-8&oe=utf-8&rls=org.mozilla:en-US:official&client=firefox-a
- 261 http://www.google.co.jp/search?sourceid=navclient&hl=ja&ie=UTF-8&rls=GGLD,GGLD:2005-25,GGLD:ja&q=dsadd+group+-members
- 96 http://www.google.co.jp/search?q=SSLProxyEngine&lr=lang_ja&ie=utf-8&oe=utf-8&rls=org.mozilla:ja:official&client=firefox
- 95 http://www.9203.net/pukiwiki/index.php?Apache/Apache2/SSL Reverse Proxy
- 91 http://kamiyn.spaces.live.com/blog/cns!5BB0A706A97A84BA!3266.entry
- 90 http://www.google.co.jp/search?hl=ja&source=hp&q=sslproxyengine&lr=&aq=0&oq=SSLproxy
- 80 http://unixluser.org/diary/?03290928
- 76 http://www.google.co.jp/search?sourceid=navclient-ff&ie=UTF-8&rls=GGGL,GGGL:2005-09,GGGL:ja&q=colinux+再インストール

