Nginxがhttpsプロトコルを使用して未定義のサーバー名のリクエストを処理しないようにするにはどうすればよいですか?.
次の設定は、通常のhttpリクエストに対してこれを機能させます。 nginx構成のHost headers
と等しい空のserver_name
を含むリクエストの接続をリセットします。
server {
listen 80;
server_name "";
return 444;
}
明確にするために更新:
ただし、https経由のリクエストが空のHost header
で送信された場合、サーバーはデフォルトのsslサポートサーバーブロックのhtmlを提供します。これをどのように回避できますか?
空のHost header
-htmlが提供されない、接続リセット(戻り444)を使用したhttpリクエストの場合とまったく同じ動作を実現したいと思います。
このようなhttpsリクエストをブロックし、https接続で前述の動作を実現する適切な方法は何でしょうか? (適切なSSL証明書を使用しないでください。これは、実際のサーバードメインのスパマーにヒントを与えるだけです。)
2015年13月3日更新
Nginxの前にhaproxyを設定して配置する
strict-sni
私の問題を完全に解決しました。
SSLの仕組みの性質上、SSL/TLSハンドシェイクは、目的のホスト名がWebサーバーに渡される前に実行されます。つまり、使用されているドメイン名に関係なく、サイトにアクセスしようとすると、デフォルトの(最初の)証明書が使用されます。
これは、Apacheとnginxの両方に当てはまります。
Apache Wiki から:
原則として、同じIPアドレスとポートで複数のSSL仮想ホストをホストすることはできません。これは、暗号化層を設定するための正しい証明書を選択するために、Apacheがホストの名前を知っている必要があるためです。ただし、要求されるホストの名前は、暗号化されたコンテンツの一部であるHTTP要求ヘッダーにのみ含まれます。したがって、暗号化がすでにネゴシエートされた後まで使用できません。つまり、正しい証明書を選択できず、クライアントは証明書の不一致警告を受け取り、中間者攻撃に対して脆弱になります。
nginxドキュメント から:
この構成では、ブラウザは、要求されたサーバー名に関係なく、デフォルトのサーバーの証明書、つまりwww.example.comを受け取ります。これは、SSLプロトコルの動作が原因です。ブラウザがHTTPリクエストを送信する前にSSL接続が確立され、nginxはリクエストされたサーバーの名前を知りません。したがって、デフォルトのサーバーの証明書のみを提供する場合があります。
この問題をどのように解決できますか?
最も簡単な解決策は、保護したいサイトごとに別々のIPアドレスを使用することです。
これが不可能な場合は、 サーバー名表示 (SNI、 RFC 6066 )を使用して問題を解決できる可能性があります。これにより、ブラウザはハンドシェイク中にドメイン名をサーバーに渡すことができます。
NginxとApacheはどちらもSNIをサポートしています。 nginx SNIの詳細は documentation で確認できます。
SNIはドメイン名にのみ使用でき、IPアドレスには使用できないことに注意してください。この問題に対処するようにWebサーバーを構成するときは、特別な予防策を講じて、IPへの要求が適切に処理されるようにする必要があります。
SNIではドメイン名のみを渡すことができますが、リクエストにリテラルIPアドレスが含まれている場合、一部のブラウザーはサーバーのIPアドレスをその名前として誤って渡すことがあります。これに頼るべきではありません。
Apache Wikiには実装 [〜#〜] sni [〜#〜] に関するいくつかの情報があります。しかし、彼らのドキュメンテーションでさえ、このソリューションは完璧ではないことをアドバイスしています。
SSLで名前ベースの仮想ホストを使用すると、さらに複雑なレイヤーが追加されます。 SNI拡張がなければ、それは一般的に不可能です(ただし、仮想ホストのサブセットは機能する可能性があります)。 SNIでは、セキュリティが確実に維持されるように、構成を慎重に検討する必要があります。
そうは言っても、この構成は通常の仮想ホストほど単純ではないことがわかります。さらに問題の解決策を考え出すには、構成の詳細と、IPのみの要求が送信された場合の予想される動作を知る必要があります。
一般に、構成されていないドメインまたはIP要求を「ブロック」するには、それをデフォルトのサイトとして構成してから、エラーの表示、リダイレクト、終了などを行います。
これらのリクエストがSSL接続内にある場合でも(例:https-Requests)、ホストヘッダーを含まないHTTPリクエストを拒否することを理解している場合。これらは古いスタイルのHTTP/1.0リクエストであり、HTTP/1.1はホストヘッダーを必要としますが、ほとんどのHTTP/1.0クライアントもすでにそれを送信しています。これらのクライアントのブロックは、次の方法で実行できます。
if ( $http_Host = '' ) {
return 444;
}
しかし、クライアントがジャンクまたはIPアドレスを含むホストヘッダーを使用している場合、これは役に立ちません。したがって、ホストヘッダーに期待値が含まれていることを確認することをお勧めします(ボーナスとして、これはDNSリバインド攻撃にも役立ちます)。
if ( $http_Host !~* ^(example\.com|www\.example\.com)$ ) {
return 444;
}
@int_uaと同じ方法を使用しましたが、少し注意が必要です。
RSAおよびECDSAをTLS認証方式として使用するようにnginxを構成しましたが、デフォルトサーバー用のDSA証明書を発行しました。
利用可能な暗号スイートがないため、TLSハンドシェイクはページを提供する前に失敗します。
私はそれがあなたが設定したものと同じ結果を持っていると思います(HAproxy strict-sni)そして私の方法がより良いパフォーマンスを持っていると信じています。
あなたは私の設定の結果を見ることができます:
無効なSNI: https://207.246.127.148/
(ホストをこのIPアドレスに設定して、結果を表示することもできます)
有効なSNI: https://cloud.jemmylovejenny.tk/
有効なSNIリンクは上記と同じIPアドレスを指します
ここに私の設定を示します:
SSL構成
(openssl equal ciphers patch を使用したため、暗号は少し奇妙です...設定はそのままでもかまいませんが、DSS暗号!)
#Protocols
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
#
#Key Exchange
ssl_ecdh_curve X25519:P-256:P-384:P-224:P-521;
ssl_dhparam /var/SSL/DH-param.pem;
#
#Cipher Suites
ssl_ciphers "[TLS_AES_128_GCM_SHA256|TLS_CHACHA20_POLY1305_SHA256]:[TLS_AES_256_GCM_SHA384|TLS_AES_128_CCM_8_SHA256|TLS_AES_128_CCM_SHA256]:[ECDHE-ECDSA-CHACHA20-POLY1305|ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256|DHE-RSA-CHACHA20-POLY1305]:[ECDHE-ECDSA-AES256-GCM-SHA384|ECDHE-RSA-AES256-GCM-SHA384]:[ECDHE-ECDSA-AES128-SHA|ECDHE-RSA-AES128-SHA]:[ECDHE-ECDSA-AES256-SHA|ECDHE-RSA-AES256-SHA]:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA";
ssl_prefer_server_ciphers on;
デフォルトのサーバー構成
##
# General
##
# Listen
listen 8080 default_server;
listen 8443 ssl spdy http2 default_server;
#
# Server Name
server_name _;
##
# SSL Settings
##
#
# Certificate
# DSA
ssl_certificate /var/SSL/certificates/DEFAULT.dsa.crt;
ssl_certificate_key /var/SSL/keys/DEFAULT.dsa.key;
root /var/www/html/nginx/;
DSAキーはOpenSSLから生成され、証明書は自分のPKIから発行されます。必要に応じて、この証明書を使用できます。
(この証明書はnginxサーバーから送信されることはないため、キーの長さや有効期間など、この証明書のすべては無意味です)
証明書:
-----BEGIN CERTIFICATE-----
MIIFrjCCBJagAwIBAgIUHVfGi/SP2d/B4vbxZSKSVEpSoGEwDQYJKoZIhvcNAQEL
BQAwgYExCzAJBgNVBAYTAkNOMSMwIQYDVQQKDBpKZW1teUxvdmVKZW5ueSBQS0kg
U2VydmljZTEeMBwGA1UECwwVcGtpLmplbW15bG92ZWplbm55LnRrMS0wKwYDVQQD
DCRKZW1teUxvdmVKZW5ueSBTSEEyIFNlY3VyZSBTZXJ2ZXIgQ0EwHhcNMTgwMTAx
MDAwMDAwWhcNMTkxMjMxMjM1OTU5WjAiMSAwHgYDVQQDDBdERUZBVUxUIFNTTCBD
RVJUSUZJQ0FURTCCAbcwggEsBgcqhkjOOAQBMIIBHwKBgQCVcFt4xWkIBtiN/Xay
O7Ls5EjBCFckvyBQpRJ5wmjrxepQbUK9xmiXmpkXOsEYHy14UQXswzKPBWiHsNDs
8apFoGAvjBxSg9Y07wd5VBnhBGvqd0VmD92eKAFW1sZZVoSrLwizfIde0sj9bZCD
KICt/0jdz0QGBZzXTtd4MOcjUQIVAPD9cVtRAdD6al8v/SV2YVQHZmafAoGBAI+A
tCrjcvK0PFILpwpGD/3gJI8o2oxKoPjjE3SM9b4mrN/2ixEGgGiXHOrEyZ7IgSjf
1Z6X2nuN+IgsNdJAZjNbnuacxbu4z5FmnO6i9IRXEqtKNzONeHJSG+7w7zUPfsPT
8sTxHU0Z5ynjiLz4GcnO5LVcMNbf2uEsl41fObB4A4GEAAKBgHOFoU8xns0qMFLz
h3ZiYScs2Rznw7xeo2HbM8hGI9zKWRoV49f9V2vHFjdPSLkPbzgoSqOxmGD7UZep
W0TcsSPVKIuKBw07vvJkpUG8U71mcedNN5+fNbIcgjKdTlIIbrEFYRFG6zrIcZ3/
WArPchw3RC+SRrBXW8+27T4+0PMao4IB5TCCAeEwHwYDVR0jBBgwFoAU4BPpj9H7
K19wMi69RQ9t6BLyNOcwHQYDVR0OBBYEFFrpB6sLpQwodD7KWPssHj0fkqjCMAkG
A1UdEQQCMAAwDgYDVR0PAQH/BAQDAgeAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggr
BgEFBQcDAjBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3Jscy5wa2kuamVtbXls
b3ZlamVubnkudGsvU0hBMlNlY3VyZVNlcnZlckNBLmNybDCBggYDVR0gBHsweTBt
BglghkgBpKInAQIwYDAtBggrBgEFBQcCARYhaHR0cHM6Ly9wa2kuamVtbXlsb3Zl
amVubnkudGsvY3BzMC8GCCsGAQUFBwICMCMaIWh0dHBzOi8vcGtpLmplbW15bG92
ZWplbm55LnRrL3JwYTAIBgZngQwBAgEwgYYGCCsGAQUFBwEBBHoweDAtBggrBgEF
BQcwAYYhaHR0cDovL29jc3AucGtpLmplbW15bG92ZWplbm55LnRrMEcGCCsGAQUF
BzAChjtodHRwOi8vY2FjZXJ0cy5wa2kuamVtbXlsb3ZlamVubnkudGsvU0hBMlNl
Y3VyZVNlcnZlckNBLmNydDAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4IB
AQCtgVPw2KLT/ntVYZE8AL71C0R1gsn9MKoqD6asaM16qK60G7YK8qC2I/5wWXAr
+zVeegvU/73qWq66DnIF333uZz3aeaXoIEfDRcfePVzWTG62cO2fPyTWyIczaPFf
NqQqoukM3UeBM0yIRSbiyRAFoyz0TWhdgSDXGrG+X5EvUnH6J+umnt/PNGaNnz1f
eXJBh79UnmCpMI6rW+7UG4F60xxQ/RQeRZZt//Ze5YzIDRjUQpXQ1a+9cHuPT8EY
Ft4xe4q5FgMVTBsu1zAfA/ViSDlHWAO8oioKkYDYHqYmLT6ERSoXNVK6WbNh4mem
AaF8T8DKQTHD5GKFBJSSkvF7
-----END CERTIFICATE-----
キー:
-----BEGIN DSA PRIVATE KEY-----
MIIBuwIBAAKBgQCVcFt4xWkIBtiN/XayO7Ls5EjBCFckvyBQpRJ5wmjrxepQbUK9
xmiXmpkXOsEYHy14UQXswzKPBWiHsNDs8apFoGAvjBxSg9Y07wd5VBnhBGvqd0Vm
D92eKAFW1sZZVoSrLwizfIde0sj9bZCDKICt/0jdz0QGBZzXTtd4MOcjUQIVAPD9
cVtRAdD6al8v/SV2YVQHZmafAoGBAI+AtCrjcvK0PFILpwpGD/3gJI8o2oxKoPjj
E3SM9b4mrN/2ixEGgGiXHOrEyZ7IgSjf1Z6X2nuN+IgsNdJAZjNbnuacxbu4z5Fm
nO6i9IRXEqtKNzONeHJSG+7w7zUPfsPT8sTxHU0Z5ynjiLz4GcnO5LVcMNbf2uEs
l41fObB4AoGAc4WhTzGezSowUvOHdmJhJyzZHOfDvF6jYdszyEYj3MpZGhXj1/1X
a8cWN09IuQ9vOChKo7GYYPtRl6lbRNyxI9Uoi4oHDTu+8mSlQbxTvWZx5003n581
shyCMp1OUghusQVhEUbrOshxnf9YCs9yHDdEL5JGsFdbz7btPj7Q8xoCFFfXTHSl
C7tdLJO9vQFcyKMhU8TU
-----END DSA PRIVATE KEY-----