Pound の SSL セキュリティレベルを制限(上げる)方法
最近、会社のセキュリティーレベルを上げるべくいろいろな活動がされています。で、最近きたお達しが、Web サーバの SSL の暗号レベルの強化。具体的に言うと、今となっては時代遅れな SSLv2 を許可せず、SSLv3 にすると言うもの。そして、暗号強度の弱い暗号化を許可しないという2点です。
普段、SSL のレベルなんて気にしてネットをやっている方は数少ないと思いますが、IE や FireFox のオプションで指定可能です。例えば、IE だとこんなかんじです。
通常、SSLv2 にチェックがついていると思います。ここで、SSLv2 のチェックを外せば、より暗号強度の強い暗号方式をサーバ側に要求して SSL 通信をすることができます。
クライアント側の設定はこれで完了ですが、サーバ側も当然ながら設定が必要です。
デフォルトの設定(何も設定しない場合)で許可される暗号方式
通常の場合、サーバには OpenSSL を入れているかと思います。OpenSSL でオプション無しの場合に許可される暗号方式は下記の通りです。openssl ciphers -v DHE-RSA-AES256-SHA SSLv3 Kx=DH Au=RSA Enc=AES(256) Mac=SHA1 DHE-DSS-AES256-SHA SSLv3 Kx=DH Au=DSS Enc=AES(256) Mac=SHA1 AES256-SHA SSLv3 Kx=RSA Au=RSA Enc=AES(256) Mac=SHA1 EDH-RSA-DES-CBC3-SHA SSLv3 Kx=DH Au=RSA Enc=3DES(168) Mac=SHA1 EDH-DSS-DES-CBC3-SHA SSLv3 Kx=DH Au=DSS Enc=3DES(168) Mac=SHA1 DES-CBC3-SHA SSLv3 Kx=RSA Au=RSA Enc=3DES(168) Mac=SHA1 DES-CBC3-MD5 SSLv2 Kx=RSA Au=RSA Enc=3DES(168) Mac=MD5 DHE-RSA-AES128-SHA SSLv3 Kx=DH Au=RSA Enc=AES(128) Mac=SHA1 DHE-DSS-AES128-SHA SSLv3 Kx=DH Au=DSS Enc=AES(128) Mac=SHA1 AES128-SHA SSLv3 Kx=RSA Au=RSA Enc=AES(128) Mac=SHA1 RC2-CBC-MD5 SSLv2 Kx=RSA Au=RSA Enc=RC2(128) Mac=MD5 DHE-DSS-RC4-SHA SSLv3 Kx=DH Au=DSS Enc=RC4(128) Mac=SHA1 EXP-KRB5-RC4-MD5 SSLv3 Kx=KRB5 Au=KRB5 Enc=RC4(40) Mac=MD5 export EXP-KRB5-RC4-SHA SSLv3 Kx=KRB5 Au=KRB5 Enc=RC4(40) Mac=SHA1 export KRB5-RC4-MD5 SSLv3 Kx=KRB5 Au=KRB5 Enc=RC4(128) Mac=MD5 KRB5-RC4-SHA SSLv3 Kx=KRB5 Au=KRB5 Enc=RC4(128) Mac=SHA1 RC4-SHA SSLv3 Kx=RSA Au=RSA Enc=RC4(128) Mac=SHA1 RC4-MD5 SSLv3 Kx=RSA Au=RSA Enc=RC4(128) Mac=MD5 RC4-MD5 SSLv2 Kx=RSA Au=RSA Enc=RC4(128) Mac=MD5 KRB5-DES-CBC3-MD5 SSLv3 Kx=KRB5 Au=KRB5 Enc=3DES(168) Mac=MD5 KRB5-DES-CBC3-SHA SSLv3 Kx=KRB5 Au=KRB5 Enc=3DES(168) Mac=SHA1 RC4-64-MD5 SSLv2 Kx=RSA Au=RSA Enc=RC4(64) Mac=MD5 EXP1024-DHE-DSS-DES-CBC-SHA SSLv3 Kx=DH(1024) Au=DSS Enc=DES(56) Mac=SHA1 export EXP1024-DES-CBC-SHA SSLv3 Kx=RSA(1024) Au=RSA Enc=DES(56) Mac=SHA1 export EXP1024-RC2-CBC-MD5 SSLv3 Kx=RSA(1024) Au=RSA Enc=RC2(56) Mac=MD5 export KRB5-DES-CBC-MD5 SSLv3 Kx=KRB5 Au=KRB5 Enc=DES(56) Mac=MD5 KRB5-DES-CBC-SHA SSLv3 Kx=KRB5 Au=KRB5 Enc=DES(56) Mac=SHA1 EDH-RSA-DES-CBC-SHA SSLv3 Kx=DH Au=RSA Enc=DES(56) Mac=SHA1 EDH-DSS-DES-CBC-SHA SSLv3 Kx=DH Au=DSS Enc=DES(56) Mac=SHA1 DES-CBC-SHA SSLv3 Kx=RSA Au=RSA Enc=DES(56) Mac=SHA1 DES-CBC-MD5 SSLv2 Kx=RSA Au=RSA Enc=DES(56) Mac=MD5 EXP1024-DHE-DSS-RC4-SHA SSLv3 Kx=DH(1024) Au=DSS Enc=RC4(56) Mac=SHA1 export EXP1024-RC4-SHA SSLv3 Kx=RSA(1024) Au=RSA Enc=RC4(56) Mac=SHA1 export EXP1024-RC4-MD5 SSLv3 Kx=RSA(1024) Au=RSA Enc=RC4(56) Mac=MD5 export EXP-KRB5-RC2-CBC-MD5 SSLv3 Kx=KRB5 Au=KRB5 Enc=RC2(40) Mac=MD5 export EXP-KRB5-DES-CBC-MD5 SSLv3 Kx=KRB5 Au=KRB5 Enc=DES(40) Mac=MD5 export EXP-KRB5-RC2-CBC-SHA SSLv3 Kx=KRB5 Au=KRB5 Enc=RC2(40) Mac=SHA1 export EXP-KRB5-DES-CBC-SHA SSLv3 Kx=KRB5 Au=KRB5 Enc=DES(40) Mac=SHA1 export EXP-EDH-RSA-DES-CBC-SHA SSLv3 Kx=DH(512) Au=RSA Enc=DES(40) Mac=SHA1 export EXP-EDH-DSS-DES-CBC-SHA SSLv3 Kx=DH(512) Au=DSS Enc=DES(40) Mac=SHA1 export EXP-DES-CBC-SHA SSLv3 Kx=RSA(512) Au=RSA Enc=DES(40) Mac=SHA1 export EXP-RC2-CBC-MD5 SSLv3 Kx=RSA(512) Au=RSA Enc=RC2(40) Mac=MD5 export EXP-RC2-CBC-MD5 SSLv2 Kx=RSA(512) Au=RSA Enc=RC2(40) Mac=MD5 export EXP-RC4-MD5 SSLv3 Kx=RSA(512) Au=RSA Enc=RC4(40) Mac=MD5 export EXP-RC4-MD5 SSLv2 Kx=RSA(512) Au=RSA Enc=RC4(40) Mac=MD5 export
ご覧の通り、暗号強度が 40 bit のものとかが平気であります。40 nit の暗号化方式は、RSA 社主催の暗号解読コンテストで既に 1998 年に破られています。当時のスペックで解読に数時間程度しかかからないようです。
128 bit の暗号化方式は未だ解読された例がないので、OpenSSL の暗号化方式をオプションで制限してあげる必要があります。具体的には、次のようなオプションで暗愚強度の高い方式のみに制限することができます。
openssl ciphers -v 'ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:-LOW:-SSLv2:-EXP:-eNULL' DHE-RSA-AES256-SHA SSLv3 Kx=DH Au=RSA Enc=AES(256) Mac=SHA1 DHE-DSS-AES256-SHA SSLv3 Kx=DH Au=DSS Enc=AES(256) Mac=SHA1 AES256-SHA SSLv3 Kx=RSA Au=RSA Enc=AES(256) Mac=SHA1 KRB5-DES-CBC3-MD5 SSLv3 Kx=KRB5 Au=KRB5 Enc=3DES(168) Mac=MD5 KRB5-DES-CBC3-SHA SSLv3 Kx=KRB5 Au=KRB5 Enc=3DES(168) Mac=SHA1 EDH-RSA-DES-CBC3-SHA SSLv3 Kx=DH Au=RSA Enc=3DES(168) Mac=SHA1 EDH-DSS-DES-CBC3-SHA SSLv3 Kx=DH Au=DSS Enc=3DES(168) Mac=SHA1 DES-CBC3-SHA SSLv3 Kx=RSA Au=RSA Enc=3DES(168) Mac=SHA1 DHE-RSA-AES128-SHA SSLv3 Kx=DH Au=RSA Enc=AES(128) Mac=SHA1 DHE-DSS-AES128-SHA SSLv3 Kx=DH Au=DSS Enc=AES(128) Mac=SHA1 AES128-SHA SSLv3 Kx=RSA Au=RSA Enc=AES(128) Mac=SHA1 DHE-DSS-RC4-SHA SSLv3 Kx=DH Au=DSS Enc=RC4(128) Mac=SHA1 KRB5-RC4-MD5 SSLv3 Kx=KRB5 Au=KRB5 Enc=RC4(128) Mac=MD5 KRB5-RC4-SHA SSLv3 Kx=KRB5 Au=KRB5 Enc=RC4(128) Mac=SHA1 RC4-SHA SSLv3 Kx=RSA Au=RSA Enc=RC4(128) Mac=SHA1 RC4-MD5 SSLv3 Kx=RSA Au=RSA Enc=RC4(128) Mac=MD5
ちなみに、暗号スイートを指定には、以下のキーワードが使用できます。(参考:UNIXの部屋 検索:openssl)
DEFAULT デフォルトの暗号スイート。ALL:!ADH:RC4+RSA:+SSLv2:@STRENGTH と同じ ALL 使用可能な全ての暗号スイート。ただし eNULL を除く COMPLEMENTOFDEFAULT ALL に含まれるが DEFALUT には含まれない暗号スイート COMPLEMENTOFALL 使用可能であるが ALL に含まれない暗号スイート。つまり eNULL HIGH 共通鍵暗号方式の鍵長が 128bit より大きい暗号スイート MEDIUM 共通鍵暗号方式の鍵長が 128bit の暗号スイート LOW 共通鍵暗号方式の鍵長が 56bit または 64bit の暗号スイート EXP, EXPORT 米国外に輸出可能な暗号スイート EXPORT40 米国外に輸出可能で共通鍵暗号方式の鍵長が 40bit の暗号スイート EXPORT56 米国外に輸出可能で共通鍵暗号方式の鍵長が 56bit の暗号スイート AES 共通鍵暗号方式に AES を使った暗号スイート 3DES 共通鍵暗号方式に 3DES を使った暗号スイート DES 共通鍵暗号方式に DES を使った暗号スイート RC4 共通鍵暗号方式に RC4 を使った暗号スイート RC2 共通鍵暗号方式に RC2 を使った暗号スイート IDEA 共通鍵暗号方式に IDEA を使った暗号スイート MD5 ハッシュアルゴリズムに MD5 を使った暗号スイート SHA1, SHA ハッシュアルゴリズムに SHA1 を使った暗号スイート ADH 認証に 匿名 DH (Anonymous Diffie-Hellman) を使った暗号スイート DH 認証に DH (Diffie-Hellman) を使った暗号スイート。ADH を含む
Apache で SSL 暗号強度の制限をする方法
ssl.conf を下記のように変更します。パラメータについては、akr流(2006-02-04) の記事を参考にさせて頂きました。# SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:-eNULL SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:-LOW:-SSLv2:-EXP:-eNULL
Apache の場合は、http://www.modssl.org/docs/2.8/ssl_reference.html#ToC9 の SSLCipherSuite に設定方法について詳しく記載されているので、情報として困ることは無いと思います。
Pound + SSL 構成で SSL 暗号強度の制限をする方法
Apache 1 系+Apach 2 系で動的コンテンツを静的コンテンツを Pound を用いたリバースプロキシ構成て効率的に処理させる方法をとっている方も多いかと思います。そのような構成の場合、Pound で SSL を処理するわけですが、Pound の SSL の暗号強度の設定に関するドキュメントがほぼ皆無でした。ドキュメントとソースを追いながら設定方法がわかりました。設定自体は意外と簡単で、
# ListenHTTPS *,443 /usr/local/pound/cert.pem ListenHTTPS *,443 /usr/local/pound/cert.pem ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:-LOW:-SSLv2:-EXP:-eNULL
これだけです。ドキュメントにも
1行だけ、さらぁ〜と書いてあるので全然気がつかないですよね。ネットで調べても情報が全然ありませんし。
一応ソースを追ってみますと(実は、先にソースを追ってからドキュメントをみて、ここかぁ〜と思ったわけですが。)
Config.c の 393 行あたり・・・
if(matches[3].rm_so < matches[3].rm_eo) { lin[matches[3].rm_eo] = '\0'; if((ciphers[n_https] = strdup(lin + matches[3].rm_so)) == NULL) { logmsg(LOG_ERR, "ListenHTTPS CIPHER config: out of memory - aborted"); exit(1); } } else ciphers[n_https] = NULL; n_https++;
Pound.c の 624 行あたり・・・
if(ciphers[i]) SSL_CTX_set_cipher_list(ctx[i], ciphers[i]); SSL_CTX_set_tmp_rsa_callback(ctx[i], RSA_tmp_callback);
が、pound.cfg 内の ListenHTTPS パラメータを解読する部分な訳ですが、第3パラメータつまりは、暗号化方式を制限する [ciphers] を OpenSSL の API の一つである SSL_CTX_set_cipher_list に渡していることがわかります。
OpenSSL API の仕様から SSL_CTX_set_cipher_list 部分を抜粋
SSL_CTX_set_cipher_list, SSL_set_cipher_list - choose list of available SSL_CIPHERs
SYNOPSIS DESCRIPTION
#include
int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str);
int SSL_set_cipher_list(SSL *ssl, const char *str);
SSL_CTX_set_cipher_list() sets the list of available ciphers for ctx using the control string str. The format of the string is described in ciphers(1).
The list of ciphers is inherited by all ssl objects created from ctx.
SSL_set_cipher_list() sets the list of ciphers only for ssl.
より詳しい解説は、の SSL_CTX_set_cipher_list API についての仕様をどうぞ。
コメントやシェアをお願いします!
dragOn
> 通常、SSLv2 にチェックがついていると思います。ここで、
> SSLv2 のチェックを外せば、より暗号強度の強い暗号方式を
> サーバ側に要求して SSL 通信をすることができます。
サーバに SSLv2 の要求をしないだけで、より暗号強度の
強い暗号方式を要求することはありません。
サーバ側の実装では、 RFC に従えば最も暗号強度の強い
暗号方式を採用するので、SSLv2 の実装しかないサーバとの
通信ができるか、できないかの問題です。
上美谷
ciphers における +,-,! の意味について:
http://x68000.q-e-d.net/~68user/unix/pickup?openssl
Apacheが標準配布している SSLCipherSuite が + を利用して接続しているのは
暗号スイートを足すというよりは「優先順位を指定している」という側面が
強いように思われます。そもそも最初に ALL を指定しているわけで。
OpenSSLの実装を将来も信用しつつ弱い暗号化を排除するなら
ALL:!LOW:!SSLv2:!EXP:!ADH
TLS規格を信用するなら
TLSv1:!LOW:!SSLv2:!EXP:!ADH
どちらも信用しないなら
AES:RC4:3DES:!LOW:!SSLv2:!EXP:!ADH
というように思いました。含まれるスイートの種類はいずれも
ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:-LOW:-SSLv2:-EXP:-eNULL と同じです。
優先順位は違って来ますが。
drk
k.daibaさん>ご指摘有り難うございます。確かに+eNULLはマズイですね。ってことで、+eNULLは消すのが正しいと思います。デフォルトで-eNULLのようなので、あえて-eNULLと指定する必要もないようですね。
ちなみに、+eNULLとした場合、暗号化を行わない通信"も"許可できるって意味だと理解してます。なので、IEやFireFoxで通常要求されるSSL通信では通常問題にならないと思ってはいるのですが、ない方が良いでしょうね。
ソースを見てみると、+eNULLでの通信要求が合った場合は、
const EVP_CIPHER *EVP_enc_null(void)
{
return(&n_cipher);
}
なメソッドに行くので、確かに暗号無しでそのまま文字列を返すことは間違いなさそうです。
k.daiba
SSLCipherSuiteを"ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:-LOW:-SSLv2:-EXP:+eNULL"と設定されていますが,最後の"+eNULL"は余計ではないでしょうか.
http://www.modssl.org/docs/2.8/ssl_reference.html#ToC9
を見ると,"eNULL"を指定すると,"Cipher Encoding Algorithm"が"No encoding"になるので,通信路暗号化を行なわない状態になると思うのですが