I have several sites on a single server, and an SSL certificate.

The problem is that i need to redirect all sites from https to http except one, which should be the only site using https. Say, https-subsite.mainsite.ru for example.

There are some links on this site that appear in search for sites that shouldn't use https, like https://https-subsite.mainsite.ru?eee=11&sd=1 and https://other-non-https.mainsite.ru for example), which follow to nowhere.

I think they follow to port 443 which has DocumentRoot for 443 /var/www/blah/data/www/https-subsite.mainsite.ru - its DocumentRoot for only one site that should use https. (See config below.)

I tried to redirect a single site from https to http manually, like this:

<VirtualHost *:443 > 
    ServerName other-non-https.mainsite.ru
    ServerAlias *.other-non-https.mainsite.ru
    Redirect 301 / other-non-https.mainsite.ru
</VirtualHost>

and it works, so that https://other-non-https.mainsite.ru goes to http://other-non-https.mainsite.ru and all is OK. I can copy this for another sites, but seems like a a bad idea.

Is there another, better way to redirect non https sites to their http addresses? (Like with a single rule, instead of a different virtual host for each site.)

My httpd.conf:

<Directory /var/www/blah/data/www/mainsite.ru>
    Options -ExecCGI -Includes
    php_admin_value open_basedir "/var/www/blah/data:."
    php_admin_flag engine on
</Directory>

<Directory /var/www/blah/data/www/https-subsite.mainsite.ru>
    Options -ExecCGI -Includes
    php_admin_value open_basedir "/var/www/blah/data:."
    php_admin_flag engine on
</Directory>

<Directory /var/www/blah/data/www/other-non-https.mainsite.ru>
    Options -ExecCGI -Includes
    php_admin_value open_basedir "/var/www/blah/data:."
    php_admin_flag engine on
</Directory>

<Directory /var/www/blah/data/www/othernonhttps.ru>
    Options -ExecCGI -Includes
    php_admin_value open_basedir "/var/www/blah/data:."
    php_admin_flag engine on
</Directory>

NameVirtualHost *:80
NameVirtualHost *:443

#first site with https

<VirtualHost *:443 >
    SSLCertificateChainFile /var/www/httpd-cert/blah/https-subsite.mainsite.ru.bundle
    SSLCertificateFile /var/www/httpd-cert/blah/https-subsite.mainsite.ru.crt
    SSLCertificateKeyFile /var/www/httpd-cert/blah/https-subsite.mainsite.ru.key
    SSLEngine on
    ServerName https-subsite.mainsite.ru
    CustomLog /var/www/httpd-logs/https-subsite.mainsite.ru.access.log combined
    DocumentRoot /var/www/blah/data/www/https-subsite.mainsite.ru
    ErrorLog /var/www/httpd-logs/https-subsite.mainsite.ru.error.log
    ServerAdmin webmaster@https-subsite.mainsite.ru
    ServerAlias www.https-subsite.mainsite.ru
    SuexecUserGroup blah blah
    AddType application/x-httpd-php .php
    php_admin_value open_basedir "/var/www/blah/data:.:/usr/share/pear:/usr/share/php"
    php_admin_value upload_tmp_dir "/var/www/blah/data/mod-tmp"
    php_admin_value session.save_path "/var/www/blah/data/mod-tmp"
</VirtualHost>

<VirtualHost *:80 >
    ServerName https-subsite.mainsite.ru
    CustomLog /var/www/httpd-logs/https-subsite.mainsite.ru.access.log combined
    DocumentRoot /var/www/blah/data/www/https-subsite.mainsite.ru
    ErrorLog /var/www/httpd-logs/https-subsite.mainsite.ru.error.log
    ServerAdmin webmaster@https-subsite.mainsite.ru
    ServerAlias www.https-subsite.mainsite.ru
    SuexecUserGroup blah blah
    AddType application/x-httpd-php .php
    php_admin_value open_basedir "/var/www/blah/data:.:/usr/share/pear:/usr/share/php"
    php_admin_value upload_tmp_dir "/var/www/blah/data/mod-tmp"
    php_admin_value session.save_path "/var/www/blah/data/mod-tmp"
</VirtualHost>

<VirtualHost *:80 >
    ServerName mainsite.ru
    CustomLog /var/www/httpd-logs/mainsite.ru.access.log combined
    DocumentRoot /var/www/blah/data/www/mainsite.ru
    ErrorLog /var/www/httpd-logs/mainsite.ru.error.log
    ServerAdmin webmaster@mainsite.ru
    ServerAlias www.mainsite.ru
    SuexecUserGroup blah blah
    AddType application/x-httpd-php .php .php3 .php4 .php5 .phtml
    AddType application/x-httpd-php-source .phps
    php_admin_value open_basedir "/var/www/blah/data:."
    php_admin_value sendmail_path "/usr/sbin/sendmail -t -i -f webmaster@mainsite.ru"
    php_admin_value upload_tmp_dir "/var/www/blah/data/mod-tmp"
    php_admin_value session.save_path "/var/www/blah/data/mod-tmp"
</VirtualHost>

<VirtualHost *:80 >
    ServerName othernonhttps.ru
    CustomLog /var/www/httpd-logs/othernonhttps.ru.access.log combined
    DocumentRoot /var/www/blah/data/www/othernonhttps.ru
    ErrorLog /var/www/httpd-logs/othernonhttps.ru.error.log
    ServerAdmin webmaster@othernonhttps.ru
    ServerAlias www.othernonhttps.ru
    SuexecUserGroup blah blah
    AddType application/x-httpd-php .php .php3 .php4 .php5 .phtml
    AddType application/x-httpd-php-source .phps
    php_admin_value open_basedir "/var/www/blah/data:."
    php_admin_value sendmail_path "/usr/sbin/sendmail -t -i -f webmaster@othernonhttps.ru"
    php_admin_value upload_tmp_dir "/var/www/blah/data/mod-tmp"
    php_admin_value session.save_path "/var/www/blah/data/mod-tmp"
</VirtualHost>

<VirtualHost *:80 >
    ServerName other-non-https.mainsite.ru
    CustomLog /var/www/httpd-logs/other-non-https.mainsite.ru.access.log combined
    DocumentRoot /var/www/blah/data/www/other-non-https.mainsite.ru
    ErrorLog /var/www/httpd-logs/other-non-https.mainsite.ru.error.log
    ServerAdmin webmaster@other-non-https.mainsite.ru
    ServerAlias www.other-non-https.mainsite.ru
    SuexecUserGroup blah blah
    AddType application/x-httpd-php .php .php3 .php4 .php5 .phtml
    AddType application/x-httpd-php-source .phps
    php_admin_value open_basedir "/var/www/blah/data:."
    php_admin_value sendmail_path "/usr/sbin/sendmail -t -i -f webmaster@other-non-https.mainsite.ru"
    php_admin_value upload_tmp_dir "/var/www/blah/data/mod-tmp"
    php_admin_value session.save_path "/var/www/blah/data/mod-tmp"
</VirtualHost>
  • Are you quite sure you want to do this? You do realise you'll need a publicly-signed certificate for each site that you wish to so redirect, don't you (unless you want the user to have to click-through a self-signed certificate warning, and if they're going to do that, you might as well just not run an HTTPS listener at all). – MadHatter Feb 19 '15 at 9:45
  • That is exactly what im talking about! If user clicks a self-signed certificate warning they're starting to call 443 port, but there are no rules in httpd.conf for this site except port 80 so user just will see an empty page, that is bad. And i don't need a publicly-signed certificate for each site, obviousely. – derkien Feb 19 '15 at 15:10
  • It is far from obvious that you will not. In fact, it's fairly obvious to me that you will. Your comment that "If user clicks a self-signed certificate warning they're starting to call 443 port" is way off; if they get as far as a certificate warning, they started talking to port 443 some time ago. – MadHatter Feb 19 '15 at 22:08
  • The fact is that user have warning message that sertificate is expired, so user clicks goaway and goes blank page, otherwise he goes to nowhere because there is no rule for site's 443 port as i said above. Only what i want is redirect him after that to http. I wrote one way i can do this above (to write a virtualhost 433 rule for site i need to redirect) so after user click 'ok im accepting sertificate' he goes to http instead, but not before he recieve warning (and in my case let it be that way). I don't know another proper way to do that. What more iformation can i give you to help me? – derkien Feb 20 '15 at 9:36
  • Are you OK with the user having to click through an "invalid certificate" warning? – MadHatter Feb 20 '15 at 10:43

We are going around in circles in the comment thread above, so let me state this clearly for you in the form of an answer: once your users have entered an HTTPS URL in their browser, they are committed to having an HTTPS transaction with a server that has a properly-signed certificate matching the hostname they've entered before they can do anything else at all. Anything that goes wrong with that - no listener on port 443, wrong hostname in certificate, expired or self-signed certificate - will generate an error for the user. Those errors arise when the HTTPS connection is first made, long before any redirection instructions can be passed back by the server. Things have to be this way, or HTTPS would be completely pointless.

You don't say this explicitly, but I'm assuming you've only got one IP address. The perfect case for you is SNI, combined with valid, publicly-signed certificates for each host so hosted. Anything less than that will generate problems for your users, and your only choice is which problem(s) it will create.

If you don't mind the users having to click through self-signed certificate warnings, then SNI coupled with self-signed certificates for all of your hosts except the one that has a publicly-valid certificate is probably your best bet.

If neither of the above are acceptable, please be clearer about what error(s) your users are prepared to tolerate. And let me finish by repeating one last time: if you aren't prepared to get publicly-signed certificates for all your virtual sites, support SNI, and require SNI support from your users, you cannot do this without your users experiencing some kind of error.

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.