Apache2 Too Many Redirects in HTTPS Rewrite Virtual Host

37 Views Asked by At

I keep getting too many redirects on one of my virtual hosts, but not the other. I'm sure there is some very small error I made I just don'r recognize. I've attached both Apache2 site configs below. I've tried several different versions of the rewrite conditions, and nothing has changed. I restart apache each time. The rewrite rules that make the most sense to me are these, which due to OR precedence should be (www.stage OR stage) AND HTTPS=OFF by my calculations. It appears the HTTPS check never occurs though? And I'm entirely confused why a direct copy of the working config doesn't work for this new site.

                RewriteCond %{SERVER_NAME} =www.stage.example.com [OR]
                RewriteCond %{SERVER_NAME} =stage.example.com
                RewriteCond %{HTTPS} off
                RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]

I have several sites running in microk8s pods on the server with Apache2 and the virtual hosts pass the traffic to the appropriate port. The main difference between the two sites is one is written in PHP (working) and the new one is in DJango. But I have another site that is a working site in Django, so I doubt that is the issue.

# example.com.config
# Staging branch, unstable wip
# Config also includes 2 other virtual hosts for dev and main as well
<VirtualHost *:80>
        ServerName stage.example.com
        ServerAlias www.stage.example.com

        # Rewrite logs show up in these log files, so I know it's happening in
        # this virtual host.
        ErrorLog ${APACHE_LOG_DIR}/ex-stage-error.log
        CustomLog ${APACHE_LOG_DIR}/ex-stage-access.log combined
        ProxyPass / http://localhost:30102/
        ProxyPassReverse / http://localhost:30102/

        <IfModule mod_rewrite.c>
                RewriteEngine on

                RewriteCond %{SERVER_NAME} =www.stage.example.com
                RewriteCond %{HTTPS} off
                RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]

                RewriteCond %{SERVER_NAME} =stage.example.com
                RewriteCond %{HTTPS} off
                RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
        </IfModule>
</VirtualHost>
<VirtualHost *:443>
        ServerName stage.example.com
        ServerAlias www.stage.example.com

        RequestHeader set X-Forwarded-Proto https
        ProxyPreserveHost On

        ErrorLog ${APACHE_LOG_DIR}/ex-stage-error.log
        CustomLog ${APACHE_LOG_DIR}/ex-stage-access.log combined

        ProxyPass / http://localhost:30102/
        ProxyPassReverse / http://localhost:30102/

        Include /etc/letsencrypt/options-ssl-apache.conf
        SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
</VirtualHost>
# example2.com.conf
# All three of the virtual hosts in this file work as expected.
# I tried copying over the rewrite conditions directly, and nothing changed.
# Main branch, stable production release
<VirtualHost *:80>
        ServerName example2.com
        ServerAlias www.example2.com

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        ProxyPass / http://localhost:30090/
        ProxyPassReverse / http://localhost:30090/
RewriteEngine on
RewriteCond %{SERVER_NAME} =example2.com [OR]
RewriteCond %{SERVER_NAME} =www.example2.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
<VirtualHost *:443>
        ServerName example2.com
        ServerAlias www.example2.com
        RequestHeader set X-Forwarded-Proto https
        ProxyPreserveHost On

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        ProxyPass / http://localhost:30090/
        ProxyPassReverse / http://localhost:30090/
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
</VirtualHost>

Update 1711053348

Here are the error logs, it appears to be one block that repeats and I don't see the rewrite to http from https anywhere.

[Thu Mar 21 19:54:42.104070 2024] [rewrite:trace2] [pid 457040:tid 140525785032256] mod_rewrite.c(480): [client 172.68.27.206:30746] 172.68.27.206 - - [stage.example.com/sid#7fceced53528][rid#7fcecc36c0a0/initial] init rewrite engine with requested uri /
[Thu Mar 21 19:54:42.104115 2024] [rewrite:trace3] [pid 457040:tid 140525785032256] mod_rewrite.c(480): [client 172.68.27.206:30746] 172.68.27.206 - - [stage.example.com/sid#7fceced53528][rid#7fcecc36c0a0/initial] applying pattern '^' to uri '/'
[Thu Mar 21 19:54:42.104131 2024] [rewrite:trace4] [pid 457040:tid 140525785032256] mod_rewrite.c(480): [client 172.68.27.206:30746] 172.68.27.206 - - [stage.example.com/sid#7fceced53528][rid#7fcecc36c0a0/initial] RewriteCond: input='stage.example.com' pattern='=www.stage.example.com' => not-matched
[Thu Mar 21 19:54:42.104139 2024] [rewrite:trace3] [pid 457040:tid 140525785032256] mod_rewrite.c(480): [client 172.68.27.206:30746] 172.68.27.206 - - [stage.example.com/sid#7fceced53528][rid#7fcecc36c0a0/initial] applying pattern '^' to uri '/'
[Thu Mar 21 19:54:42.104147 2024] [rewrite:trace4] [pid 457040:tid 140525785032256] mod_rewrite.c(480): [client 172.68.27.206:30746] 172.68.27.206 - - [stage.example.com/sid#7fceced53528][rid#7fcecc36c0a0/initial] RewriteCond: input='stage.example.com' pattern='=stage.example.com' => matched
[Thu Mar 21 19:54:42.104157 2024] [rewrite:trace4] [pid 457040:tid 140525785032256] mod_rewrite.c(480): [client 172.68.27.206:30746] 172.68.27.206 - - [stage.example.com/sid#7fceced53528][rid#7fcecc36c0a0/initial] RewriteCond: input='off' pattern='off' => matched
[Thu Mar 21 19:54:42.104183 2024] [rewrite:trace2] [pid 457040:tid 140525785032256] mod_rewrite.c(480): [client 172.68.27.206:30746] 172.68.27.206 - - [stage.example.com/sid#7fceced53528][rid#7fcecc36c0a0/initial] rewrite '/' -> 'https://stage.example.com/'
[Thu Mar 21 19:54:42.104192 2024] [rewrite:trace2] [pid 457040:tid 140525785032256] mod_rewrite.c(480): [client 172.68.27.206:30746] 172.68.27.206 - - [stage.example.com/sid#7fceced53528][rid#7fcecc36c0a0/initial] explicitly forcing redirect with https://stage.example.com/
[Thu Mar 21 19:54:42.104201 2024] [rewrite:trace1] [pid 457040:tid 140525785032256] mod_rewrite.c(480): [client 172.68.27.206:30746] 172.68.27.206 - - [stage.example.com/sid#7fceced53528][rid#7fcecc36c0a0/initial] redirect to https://stage.example.com/ [REDIRECT/301]
# newline added here
[Thu Mar 21 19:54:42.146666 2024] [rewrite:trace2] [pid 457040:tid 140525776639552] mod_rewrite.c(480): [client 172.68.27.206:30746] 172.68.27.206 - - [stage.example.com/sid#7fceced53528][rid#7fcecc3680a0/initial] init rewrite engine with requested uri /
[Thu Mar 21 19:54:42.146695 2024] [rewrite:trace3] [pid 457040:tid 140525776639552] mod_rewrite.c(480): [client 172.68.27.206:30746] 172.68.27.206 - - [stage.example.com/sid#7fceced53528][rid#7fcecc3680a0/initial] applying pattern '^' to uri '/'
[Thu Mar 21 19:54:42.146707 2024] [rewrite:trace4] [pid 457040:tid 140525776639552] mod_rewrite.c(480): [client 172.68.27.206:30746] 172.68.27.206 - - [stage.example.com/sid#7fceced53528][rid#7fcecc3680a0/initial] RewriteCond: input='stage.example.com' pattern='=www.stage.example.com' => not-matched
[Thu Mar 21 19:54:42.146714 2024] [rewrite:trace3] [pid 457040:tid 140525776639552] mod_rewrite.c(480): [client 172.68.27.206:30746] 172.68.27.206 - - [stage.example.com/sid#7fceced53528][rid#7fcecc3680a0/initial] applying pattern '^' to uri '/'
[Thu Mar 21 19:54:42.146723 2024] [rewrite:trace4] [pid 457040:tid 140525776639552] mod_rewrite.c(480): [client 172.68.27.206:30746] 172.68.27.206 - - [stage.example.com/sid#7fceced53528][rid#7fcecc3680a0/initial] RewriteCond: input='stage.example.com' pattern='=stage.example.com' => matched
[Thu Mar 21 19:54:42.146731 2024] [rewrite:trace4] [pid 457040:tid 140525776639552] mod_rewrite.c(480): [client 172.68.27.206:30746] 172.68.27.206 - - [stage.example.com/sid#7fceced53528][rid#7fcecc3680a0/initial] RewriteCond: input='off' pattern='off' => matched
[Thu Mar 21 19:54:42.146739 2024] [rewrite:trace2] [pid 457040:tid 140525776639552] mod_rewrite.c(480): [client 172.68.27.206:30746] 172.68.27.206 - - [stage.example.com/sid#7fceced53528][rid#7fcecc3680a0/initial] rewrite '/' -> 'https://stage.example.com/'
[Thu Mar 21 19:54:42.146746 2024] [rewrite:trace2] [pid 457040:tid 140525776639552] mod_rewrite.c(480): [client 172.68.27.206:30746] 172.68.27.206 - - [stage.example.com/sid#7fceced53528][rid#7fcecc3680a0/initial] explicitly forcing redirect with https://stage.example.com/
[Thu Mar 21 19:54:42.146755 2024] [rewrite:trace1] [pid 457040:tid 140525776639552] mod_rewrite.c(480): [client 172.68.27.206:30746] 172.68.27.206 - - [stage.example.com/sid#7fceced53528][rid#7fcecc3680a0/initial] redirect to https://stage.example.com/ [REDIRECT/301]

The rewrite condition is inserted by certbot on a ubuntu server installed via snap. I changed the 80 virtual host to the following:

<VirtualHost *:80>
        ServerName stage.example.com
        ServerAlias www.stage.example.com

        ErrorLog ${APACHE_LOG_DIR}/ex-stage-error.log
        CustomLog ${APACHE_LOG_DIR}/ex-stage-access.log combined
        Redirect permanent / https://stage.example.com/
</VirtualHost>

And there are now no redirects in the error log, just the access one:

172.71.166.203 - - [21/Mar/2024:20:38:10 +0000] "GET / HTTP/1.1" 301 622 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 OPR/108.0.0.0"
172.71.166.203 - - [21/Mar/2024:20:38:10 +0000] "GET / HTTP/1.1" 301 621 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 OPR/108.0.0.0"
172.71.166.203 - - [21/Mar/2024:20:38:10 +0000] "GET / HTTP/1.1" 301 621 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 OPR/108.0.0.0"
... 20 times

No traffic reaches the Django pod, but I can curl localhost:30102 and get the expected page from the application.

Update 1711119001

So it seems that this configuration is sending all traffic to 80 instead of 443. I sent an https request via curl and got a redirect from port 80.

curl https://stage.example.com
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>301 Moved Permanently</title>
</head><body>
<h1>Moved Permanently</h1>
<p>The document has moved <a href="https://stage.example.com/">here</a>.</p>
<hr>
<address>Apache/2.4.52 (Ubuntu) Server at stage.example.com Port 80</address>
</body></html>

The updated config file looks like this:

<VirtualHost *:80>
        ServerName      stage.example.com
        ServerAlias www.stage.example.com

        ErrorLog ${APACHE_LOG_DIR}/taf-stage-error.log
        CustomLog ${APACHE_LOG_DIR}/taf-stage-access.log combined
        Redirect permanent / https://stage.example.com/
</VirtualHost>
<VirtualHost *:443>
        ServerName      stage.example.com
        ServerAlias www.stage.example.com

        RequestHeader set X-Forwarded-Proto https
        ProxyPreserveHost On

        ErrorLog ${APACHE_LOG_DIR}/taf-stage-error.log
        CustomLog ${APACHE_LOG_DIR}/taf-stage-access.log combined

        ProxyPass / http://localhost:30102/
        ProxyPassReverse / http://localhost:30102/
</VirtualHost>
1

There are 1 best solutions below

0
bbg On

Per their documentation, the problem was enabling Cloudflare HTTP to HTTPS, and redirecting HTTP to HTTPS in my apache configuration as well.