0

All of my http > https redirects are working perfectly fine.

I have setup a separate sub-domain and port to use with PHPMyAdmin to access a MySQL DB so it is less likely to get be scanned by bots etc. The examples below are very demonstration purposes only.

The problem I have is if I enter the port used on the PHPMyAdmin sub-domain after the main domain without https prefixed so that it becomes http://example.com:8080, after what starts off as a timing out webpage, it eventually redirects me to the https site but on the sub-domain at https://phpmyadmin.example.com:8081.

How do I stop the main domain redirecting to the sub-domain and instead timeout as a typical server would? If someone was to guess every port at the main domain someone would eventually find the sub-domain.

/etc/apache2/sites-enabled/example.com

<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    ServerAdmin webmaster@example.com
    Redirect permanent / https://example.com
    DocumentRoot /var/www/example.com
    # <Directory />
    #     DirectoryIndex index.html index.php
    #     Require all denied
    #     Options FollowSymLinks
    #     AllowOverride All
    # </Directory>
    #ErrorLog ${APACHE_LOG_DIR}/error.log
    #CustomLog ${APACHE_LOG_DIR}/access.log combined    
</VirtualHost>

<VirtualHost *:443>
    ServerName example.com
    ServerAlias www.example.com
    ServerAdmin webmaster@example.com
    DocumentRoot /var/www/example.com
    # <Directory />
    #     DirectoryIndex index.html index.php
    #     Require all denied
    #     Options FollowSymLinks
    #     AllowOverride All
    # </Directory>
    #ErrorLog ${APACHE_LOG_DIR}/error.log
    #CustomLog ${APACHE_LOG_DIR}/access.log combined
    SSLEngine On
    SSLCertificateFile "/etc/ssl/certs/example.com.crt"
    SSLCertificateKeyFile "/etc/ssl/private/example.com.key"
    SSLCertificateChainFile "/etc/ssl/certs/example.com.ca-bundle"
</VirtualHost>


/etc/apache2/sites-enabled/phpmyadmin.example.com

<VirtualHost *:8080>
    ServerName phpmyadmin.example.com
    ServerAlias phpmyadmin.example.com
    Redirect permanent / https://phpmyadmin.example.com:8081
</VirtualHost>

<VirtualHost *:8081>
    ServerName phpmyadmin.example.com
    ServerAlias phpmyadmin.example.com
    DocumentRoot /usr/share/phpmyadmin
#    RewriteEngine On
#    RewriteCond %{HTTPS} off
#    RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
    <Directory />
        Require all denied
        Options FollowSymLinks
        AllowOverride All
    </Directory>
    LogLevel notice
    CustomLog /var/log/apache2/access.log combined
    ErrorLog /var/log/apache2/error.log
    Include /etc/phpmyadmin/apache.conf
    SSLEngine On
    SSLCertificateFile "/etc/letsencrypt/live/phpmyadmin.example.com/cert.pem"
    SSLCertificateKeyFile "/etc/letsencrypt/live/phpmyadmin.example.com/privkey.pem"
    SSLCertificateChainFile "/etc/letsencrypt/live/phpmyadmin.example.com/chain.pem"
</VirtualHost>

UPDATE 1

I think the problem is between the http to https redirect in general. By typing the HTTP port for the sub-domain onto the main domain instead, Apache's VirtualHost sees that as the initiator to redirect the http to https but totally ignores the domain is supposed to do it on. Is there a way I can isolate http to https redirect dependant on what domain prefixes it?

UPDATE 2

Are there any rewrite rules/conditions I could use on each of the http virtual hosts to only respond to the port it is listening on? My knowledge of rewrite rules etc are non-existent so I'm relying on good Google research skills to find me the write websites. I have stumbled upon this.

RewriteEngine On
RewriteCond %{HTTP_HOST} ^yourdomain\.com [NC]
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://www.yourdomain.com/$1 [R,L]

UPDATE 3

I've fixed the issue.

However, if I was to access the example URL http://example.com:8080 I get a 403 forbidden error message

Forbidden

You don't have permission to access this resource.

How would I get Apache to timeout the connection rather than just flat out refuse it?

The two VirtualHost files now become:

/etc/apache2/sites-enabled/example.com

<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    ServerAdmin webmaster@example.com
    DocumentRoot /var/www/example.com
    RewriteEngine On
    RewriteCond %{HTTP_HOST} example.com [NC]
    RewriteCond %{SERVER_PORT} 80
    RewriteRule ^(.*)$ https://www.example.com$1 [R,L]
    <Directory />
        DirectoryIndex index.html index.php
    </Directory>
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined    
</VirtualHost>

<VirtualHost *:443>
    ServerName example.com
    ServerAlias www.example.com
    ServerAdmin webmaster@example.com
    DocumentRoot /var/www/example.com
    <Directory />
    DirectoryIndex index.html index.php
    </Directory>
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
    SSLEngine On
    SSLCertificateFile "/etc/ssl/certs/example.com.crt"
    SSLCertificateKeyFile "/etc/ssl/private/example.com.key"
    SSLCertificateChainFile "/etc/ssl/certs/example.com.ca-bundle"
</VirtualHost>

/etc/apache2/sites-enabled/phpmyadmin.example.com

<VirtualHost *:8080>
    ServerName phpmyadmin.example.com
    ServerAlias phpmyadmin.example.com
    RewriteEngine On
    RewriteCond %{HTTP_HOST} phpmyadmin.example.com [NC]
    RewriteCond %{SERVER_PORT} 8080
    RewriteRule ^(.*)$ https://phpmyadmin.example.com:8081$1 [R,L]
</VirtualHost>

<VirtualHost *:8081>
    ServerName phpmyadmin.example.com
    ServerAlias phpmyadmin.example.com
    DocumentRoot /usr/share/phpmyadmin
    <Directory />
        DirectoryIndex index.html index.php
    </Directory>
    LogLevel notice
    CustomLog /var/log/apache2/access.log combined
    ErrorLog /var/log/apache2/error.log
    Include /etc/phpmyadmin/apache.conf
    SSLEngine On
    SSLCertificateFile "/etc/letsencrypt/live/phpmyadmin.example.com/cert.pem"
    SSLCertificateKeyFile "/etc/letsencrypt/live/phpmyadmin.example.com/privkey.pem"
    SSLCertificateChainFile "/etc/letsencrypt/live/phpmyadmin.example.com/chain.pem"
</VirtualHost>
willowen100
  • 31
  • 2
  • 10
  • what's on port 16081 ? – Tom Sep 24 '20 at 16:50
  • You can see the pattern of redirects being sent back to the brower using developer tools. usually right click, "inspect", and then switch to the network tab in firefox/chrome – Tom Sep 24 '20 at 16:53
  • @TomH I've updated the question. I accidentally left it in from my actual virtualhost – willowen100 Sep 24 '20 at 17:02
  • If I understand your update correctly, you want to do something different depending on whether the request is to `http://phpmyadmin.example.com:8080` or `http://example.com:8080`. However that's exact what the other VirtualHost would do. – Tom Sep 24 '20 at 20:58
  • @TomH Yes if the request goes to `http://phpmyadmin.example.com:8080` then PHPMyAdmin will load as normal. Requests going to `http://example.com:8080` shouldn't do anything at all and eventually timeout. – willowen100 Sep 24 '20 at 21:02
  • So the problem is, a timeout occurs at the point of initiating the connection, in the network stack after the initial SYN packet, no service responds on that port, or a firewall drops the SYN. However by the time apache is involved, the client has sent TCP SYN packet, and the server has responded SYNACK, and the client has sent ACK+HTTP data. It's too late for apache to allow the request to timeout at that point. Apache could return a 404 error – Tom Sep 24 '20 at 21:19
  • actually, thinking about it, apache could redirect to some non-existing location, and that would cause a timeout... I'll update the answer – Tom Sep 24 '20 at 21:20
  • Directory directive is a path in the OS, all your configurations to that tag in / are being applied to all directories in the operative system, not good. – Daniel Ferradal Sep 25 '20 at 15:14

1 Answers1

0

personally, I would favour a solution using either a firewall, or ssh port forwarding and localhost, to expose the phpmyadmin service in a secure manner to trusted hosts, and definitely use decent authentication rather than "obscurity security". However to try to answer the question at hand...

Because you only have one VirtualHost on each port, the first one defined becomes the default for requests to that port, regardless of whatever domain name is set in ServerName and ServerAlias.

<VirtualHost *:8080>
    ServerName phpmyadmin.example.com
    ServerAlias phpmyadmin.example.com
    Redirect permanent / https://phpmyadmin.example.com:8081/
</VirtualHost>

This is going to match any request to *:8080, including:

and redirect them to the service on port 8081.

In order to differentiate the requests, I would add a second VirtualHost on port 8080 which catches everything else (including http://example.com:8080), and redirects it somewhere non-existing which would cause a timeout.

<VirtualHost *:8080>
    ServerName example.com
    # redirect to somewhere non-existing will cause timeout
    Redirect permanent / https://192.168.99.99/
</VirtualHost>

<VirtualHost *:8080>
    ServerName phpmyadmin.example.com
    ServerAlias phpmyadmin.example.com
    Redirect permanent / https://phpmyadmin.example.com:8081/
</VirtualHost>

(note that the default one needs to come first)

Note:

How do I stop the main domain redirecting to the sub-domain and instead timeout as a typical server would?

Unfortunately, by the time apache has received the request and is processing it, the point at which it can tell whether the request is to http://phpadmin.example.com:8080 or http://example.com:8080, it is too late for apache itself to drop the initial connection and cause a timeout.

I would generally use a firewall for this purpose, either directly in iptables, or ufw/firewalld depending on your distribution, to limit access to port 8080 to only known trusted hosts.

Update: using mod_security

It looks like it might be possible to use the mod_security module to simulate the timeout: https://serverfault.com/a/401592/47650

so something like this would send a FIN packet to drop the connection after the request header was processed...

<VirtualHost *:8080>
  ServerName example.com
  SecRuleEngine On
  SecAction id:1,phase:1,nolog,drop
</VirtualHost>

<VirtualHost *:8080>
    ServerName phpmyadmin.example.com
    ServerAlias phpmyadmin.example.com
    Redirect permanent / https://phpmyadmin.example.com:8081/
</VirtualHost>

https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual-%28v2.x%29#drop

Tom
  • 11,176
  • 5
  • 41
  • 63