.htaccess redirect only executes after browser war

2019-02-13 06:16发布

问题:

I have a rewrite rule which forces HTTPS and www. The SSL certificate is for the www version of the site. The entire site needs to be HTTPS.

The problem is that if the request is https://example.com/ the browser displays a warning page before the redirect can execute. ('This Connection is Untrusted' in Firefox and 'This is probably not the site that you are looking for!' in Chrome)

If the user adds an exception in Firefox or ignores the error in Chrome, the rewrite rule executes and they are redirects to the www version of the site with a 100% secure page.

RewriteEngine on

RewriteCond %{HTTP_HOST} ^example.com$ [OR]
RewriteCond %{HTTPS} !on
RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L]

RewriteCond %{HTTP_HOST} ^www.example.com$
RewriteCond %{HTTPS} !on
RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L]

I've been testing the rules on the site as well as on http://martinmelin.se/rewrite-rule-tester/

How can I get the redirect to execute before the browser warning?

回答1:

The redirection from https://example.com to https://www.example.com can only happen after the client has made an initial successful request to https://example.com.

This is because HTTPS is HTTP over TLS/SSL (see RFC 2818), which first establishes the SSL/TLS connection before any HTTP traffic is sent. mod_rewrite will always apply after the SSL/TLS connection is established. Not doing so would actually be a security issue, since an attacker could rewrite and redirect the client before the certificate has been verified. Even if the TLS upgrade was within HTTP (RFC 2817, which is virtually never used/supported and is not https), you would still want the redirection to come from a trusted entity.

For this initial connection to work, the server at https://example.com must have a certificate valid for example.com, otherwise, this connection won't even happen (and the server won't send a redirection response).

To achieve your goal, you need requests for https://example.com to present a certificate valid for example.com and requests for https://www.example.com to present a certificate valid for www.example.com.

There are two solutions:

  • Using two distinct certificates for each hosts, either by using distinct IP addresses or by using Server Name Indication. The downside here is that not all clients support SNI, even if it's getting more common.
  • Using a single certificate that is valid for both example.com and www.example.com. This can be achieved by getting a certificate with multiple Subject Alternative Name (SAN) DNS entries (it won't work with just *.example.com since the dot isn't part of the wildcard pattern).

The latter is certainly the easiest solution. It's quite common for CAs to issue certificates that have SAN entries for both example.com and www.example.com when you apply for one or the other, sometimes without an extra fee.



回答2:

This post addresses your issue, and provides the following answer:

You'll need a cert for example.com if you want to avoid the invalid cert problem. For security reasons, redirects prior to authentication are not permitted.

Another option might be to get a wildcard cert, which would allow you to match for *.example.com. (Apparently this won't work. Thanks @Giel)

You could make http://example.com/ redirect to https://www.example.com/, but that may not help you if you already have users visiting https://example.com/.