skip to Main Content

I’m using virtualmin with apache. Configured varnish, and want to terminate ssl with apache.
Apache is listening two ports 443 & 8080
varnish listening port 80

Error that I’m facing:

http to https redirect issue in apache sites. When request is https://example.com no issue, but when request is http://example.com, it doesn’t redirects to https.

Here’s my apache ssl config:

SuexecUserGroup "#1010" "#1006"
ServerName example.com
ServerAlias www.example.com
ServerAlias mail.example.com
ServerAlias webmail.example.com
ServerAlias admin.example.com
ServerAlias autoconfig.example.com
ServerAlias autodiscover.example.com

DocumentRoot /home/biolink/public_html

ErrorLog /var/log/virtualmin/example.com_error_log
CustomLog /var/log/virtualmin/example.com_access_log combined

ScriptAlias /cgi-bin/ /home/biolink/cgi-bin/
ScriptAlias /awstats/ /home/biolink/cgi-bin/
ScriptAlias /AutoDiscover/AutoDiscover.xml /home/biolink/cgi-bin/autoconfig.cgi
ScriptAlias /Autodiscover/Autodiscover.xml /home/biolink/cgi-bin/autoconfig.cgi
ScriptAlias /autodiscover/autodiscover.xml /home/biolink/cgi-bin/autoconfig.cgi

DirectoryIndex index.html index.htm index.php index.php4 index.php5

<Directory /home/biolink/public_html>
    Options -Indexes +IncludesNOEXEC +SymLinksIfOwnerMatch +ExecCGI
    allow from all
    AllowOverride All Options=ExecCGI,Includes,IncludesNOEXEC,Indexes,MultiViews,SymLinksIfOwnerMatch
    Require all granted
    AddType application/x-httpd-php .php
    AddHandler fcgid-script .php
    AddHandler fcgid-script .php7.4
    AddHandler fcgid-script .php8.2
    FCGIWrapper /home/biolink/fcgi-bin/php7.4.fcgi .php
    FCGIWrapper /home/biolink/fcgi-bin/php7.4.fcgi .php7.4
    FCGIWrapper /home/biolink/fcgi-bin/php8.2.fcgi .php8.2
</Directory>

<Directory /home/biolink/cgi-bin>
    allow from all
    AllowOverride All Options=ExecCGI,Includes,IncludesNOEXEC,Indexes,MultiViews,SymLinksIfOwnerMatch
    Require all granted
</Directory>

RewriteEngine on
RewriteCond %{HTTP_HOST} =webmail.example.com
RewriteRule ^(?!/.well-known)(.*) https://example.com:20000/ [R]
RewriteCond %{HTTP_HOST} =admin.example.com
RewriteRule ^(?!/.well-known)(.*) https://example.com:10000/ [R]

SSLEngine on
SSLCertificateFile /home/biolink/ssl.cert
SSLCertificateKeyFile /home/biolink/ssl.key
SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1

<Files awstats.pl>
    AuthName "example.com statistics"
    AuthType Basic
    AuthUserFile /home/biolink/.awstats-htpasswd
    require valid-user
</Files>

Alias /dav /home/biolink/public_html

<Location /dav>
    DAV on
    AuthType Basic
    AuthName "example.com"
    AuthUserFile /home/biolink/etc/dav.digest.passwd
    Require valid-user
    ForceType text/plain
    Satisfy All
    RemoveHandler .php
    RemoveHandler .php7.4

    RewriteEngine off
</Location>

<Location /git>
    DAV on
    AuthType Basic
    AuthName example.com
    AuthUserFile /home/biolink/etc/git.basic.passwd
    Require valid-user
    Satisfy All
    RedirectMatch ^/git$ http://example.com/git/gitweb.cgi
    RedirectMatch ^/git/$ http://example.com/git/gitweb.cgi

    RewriteEngine off
    AddHandler cgi-script .cgi
</Location>

SSLCACertificateFile /home/biolink/ssl.ca
RemoveHandler .php
RemoveHandler .php7.4
RemoveHandler .php8.2
IPCCommTimeout 2001

FcgidMaxRequestLen 1073741824
Redirect /mail/config-v1.1.xml /cgi-bin/autoconfig.cgi
Redirect /.well-known/autoconfig/mail/config-v1.1.xml /cgi-bin/autoconfig.cgi

ProxyPreserveHost On
ProxyPass / http://127.0.0.1:80/
RequestHeader set X-Forwarded-Port "443"
RequestHeader set X-Forwarded-Proto "https"

I used hitch to terminate ssl with below vcl config, it properly redirects to https – no issue. But with apache ssl termination, error of too many redirects loop.

VCL config:

sub vcl_recv {

if (std.port(server.ip) != 443) {
set req.http.location = "https://" + req.http.host + req.url;
return(synth(301));
}

    if (!req.http.X-Forwarded-Proto) {
        if(std.port(server.ip) == 443) {
            set req.http.X-Forwarded-Proto = "https";
        } else {
            set req.http.X-Forwarded-Proto = "https";
        }
    }

}
sub vcl_synth {

    if (resp.status == 301 || resp.status == 302) {
        set resp.http.location = req.http.location;
        return (deliver);
    }
}

Help me out in resolving my issue.

2

Answers


  1. Op says: When request is https://example.com no issue, but when request is http://example.com, it doesn’t redirects to https.

    As simple as adding a specific virtualhost for it:

    <Virtualhost *:80>
    ServerName example.com
    ServerAlias www.example.com
    ServerAlias mail.example.com
    ServerAlias webmail.example.com
    ServerAlias admin.example.com
    ServerAlias autoconfig.example.com
    ServerAlias autodiscover.example.com
    
    RewriteEngine on
    RewriteRule ^/(.*) https://%{HTTP_HOST}/$1 [R=301,L]
    <Virtualhost>
    
    Login or Signup to reply.
  2. If i understand your configuration well, you have:

    • a varnish answering on HTTP 80
    • apache httpd answering on HTTPS 443

    You want to have:

    • a cache on HTTPS contents via varnish
    • an hard redirect telling end-user to use HTTPS (i.e. a 301 someurl:80 to https://someurl:443)

    in your case, on the varnish side you have

    if (std.port(server.ip) != 443) {
    set req.http.location = "https://" + req.http.host + req.url;
    return(synth(301));
    }
    

    That tells varnish "if you’re not answering on IP:443, redirects it to 443"

    and then

        if (!req.http.X-Forwarded-Proto) {
          if(std.port(server.ip) == 443) {
            set req.http.X-Forwarded-Proto = "https";
          } else {
            set req.http.X-Forwarded-Proto = "https";
          }
        }
    

    Telling varnish, "if the request is coming with x-forwarded-proto, considers it"
    But in your case, varnish should always answer on port 80, so only the 1st test is consider, so you might have endless loops.

    Something like the following code for the VCL might do the job

    sub vcl_recv {
    
      if (!req.http.X-Forwarded-Proto) {
        # the test might be useless
        # your varnish is probably configured to answer on 80 only
        # (and apache httpd on IP:443)
        if(std.port(server.ip) == 443) {
            set req.http.X-Forwarded-Proto = "https";
        } else {
            set req.http.X-Forwarded-Proto = "http";
        }
      }
    
      if (req.http.X-Forwarded-Proto != "https") {
        set req.http.location = "https://" + req.http.host + req.url;
        return(synth(301));
      }
    }
    
    sub vcl_synth {
      if (resp.status == 301 || resp.status == 302) {
        set resp.http.location = req.http.location;
        return (deliver);
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search