LoginSignup
5
4

More than 3 years have passed since last update.

SSL証明書でIPアドレスからホスト名が漏れる

Last updated at Posted at 2020-02-21

IPアドレスからWebサーバの名前がわかるよー

下の結果は、curl でIPアドレスにHTTPSでアクセスしただけです。

% curl -v https://198.51.100.15/
*   Trying 198.51.100.15...
* Connected to 198.51.100.15 (198.51.100.15) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/pki/tls/certs/ca-bundle.crt
  CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=devel.keys.jp
*  start date: Jun 30 12:37:10 2020 GMT
*  expire date: Sep 28 12:37:10 2020 GMT
*  subjectAltName does not match 198.51.100.15
* SSL: no alternative certificate subject name matches target host name '198.51.100.15'
* Closing connection 0
* TLSv1.3 (OUT), TLS alert, close notify (256):
curl: (60) SSL: no alternative certificate subject name matches target host name '198.51.100.15'

わかりますか?

* Server certificate:
*  subject: CN=devel.keys.jp
*  start date: Jun 30 12:37:10 2020 GMT
*  expire date: Sep 28 12:37:10 2020 GMT
*  subjectAltName does not match 198.51.100.15

Apache httpd のバーチャルホスト機能を使ってHTTPSサーバを複数ホストしている場合、IPアドレスでアクセスした場合 一番最初に定義されたバーチャルホストが使われる ので、その証明書を使って検証することになっています。

アスタリスクはすべてのアドレスにマッチしますので、主サーバはリクエストを扱いません。www.example.com は 最初にあるため、優先順位は一番高くなり、default もしくは primary のサーバと考えることができます。つまり、リクエストがどの ServerName ディレクティブにもマッチしない場合、 一番最初の VirtualHost により扱われます。
https://httpd.apache.org/docs/2.4/ja/vhosts/examples.html

いやそれは困る…

場合によっては困る場合もあるでしょう。
その場合、バーチャルホストの一番最初の定義に、ダミーの設定を挟むことで回避できます。

_default.conf
<VirtualHost _default_:443>
    LogFormat "%h %l %u %t ¥"%r¥" %>s %b ¥"%{Referer}i¥" ¥"%{User-Agent}i¥"" combined
    CustomLog logs/ssl_access_log combined

    Redirect 403 /

    SSLEngine on
    SSLCertificateFile conf.d/dummy.crt
    SSLCertificateKeyFile conf.d/dummy.key
</VirtualHost>

バーチャルホストをファイルごとに分けている場合、以下のように先頭にアンダーバーを付けたファイルがあれば最初に読み込まれます。
あるいは ssl.conf の最後に書いてもいいかもですね。

 $ ls -la /etc/httpd/conf.vhosts.d
total 8
drwxr-xr-x 2 keys keys   48 Feb  4 10:15 ./
drwxr-xr-x 7 root root  138 Jan 31 18:06 ../
-rw-rw-r-- 1 keys keys 1062 Feb  3 13:49 _defailt.conf
-rw-rw-r-- 1 keys keys 1092 Jan 31 23:21 devel.keys.jp.conf

この設定で使うSSL証明書は自己署名証明書(オレオレ証明書)です。
CSRを作るときは Common Name だけ入力すれば大丈夫です。証明書の CN フィールドは、グローバルで設定した ServerName にしないと httpd の起動時に怒られるみたいです。

$ openssl genrsa 2048 > dummy.key
Generating RSA private key, 2048 bit long modulus (2 primes)
........+++++
.......................................................................+++++


$ openssl req -new -key dummy.key > dummy.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:localhost
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

$ openssl x509 -days 3650 -req -signkey dummy.key < dummy.csr > dummy.crt
Signature ok
subject=C = AU, ST = Some-State, O = Internet Widgits Pty Ltd, CN = localhost
Getting Private key

これでもう一度試してみると…

$ curl -v https://198.51.100.15/
*   Trying 198.51.100.15...
* Connected to 198.51.100.15 (198.51.100.15) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/pki/tls/certs/ca-bundle.crt
  CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (OUT), TLS alert, unknown CA (560):
* SSL certificate problem: self signed certificate
* Closing connection 0
curl: (60) SSL certificate problem: self signed certificate
More details here: https://curl.haxx.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

自己署名証明書だ、と言って怒られて処理が終わります。

これでホスト名が漏れることを防ぐことができました。しかしもう一つ、問題が残っています。

“Redirect 403 /”

ブラウザが止めようとなんと言おうと、自己署名証明書を無視してアクセスすることはできます。
curl に --insecure (自己署名証明書を無視するオプション)を付けてアクセスしてみます。

% curl --insecure https://198.51.100.15/
<html>

<head>
<title>hoge</title>
</head>

<body>
<p1>Hoge!</p1>
</body>

</html>

この場合も先頭のバーチャルホストの内容が使われます。そこからホスト名やサービスの内容が漏れる場合もあるでしょう。

これを防ぐには、先の設定ファイルにはあらかじめ書いておきましたが、一行追加しておくと防げます。

Redirect 403 /

すると、IPアドレスでのアクセスはすべて 403 になり、見えなくなります。

$ curl --insecure https://198.51.100.15/
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don't have permission to access this resource.</p>
</body></html>
5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4