1

I am trying to create Apache virtualhost that is closed for all IP addresses with exception of one IP address and two URLs that should be publicly accessible.

<IfModule mod_ssl.c>
<VirtualHost *:443>
    ServerName example.com
    ServerAdmin [email protected]
    DocumentRoot "/var/www/example.com/app/webroot"

    <Directory "/var/www/example.com/app/webroot">
        Options FollowSymLinks Includes ExecCGI
        AllowOverride All
        ErrorDocument 403 "https://example.com/403.php"
        DirectoryIndex index.php
    </Directory>

    <Location "/foo/bar/">
          Require all granted
    </Location>

    <Location "/.well-known/">
        Require all granted
    </Location>

    <Location "/">
          Require ip 1.2.3.4
    </Location>

    SSLProxyEngine on   
    ProxyPreserveHost On
    ProxyRequests Off
    ProxyPass           /api/ https://host.docker.internal:8443/api/ connectiontimeout=5 timeout=300
    ProxyPassReverse    /api/ https://host.docker.internal:8443/api/

    SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
    Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>

I've tried to change order of Location tags, but all requests are redirected to ErrorDocument directive value.

URL /foo/bar/ is rewrited by .htaccess located in DocumentRoot (for testing purposes I tried to remove .htaccess with no effect).

Apache version:

  • Server version: Apache/2.4.59 (Debian)
  • Server built: 2024-04-05T12:02:26

Apache runs in a Docker container, but it probably has no meaning for the problem.

Q: What is wrong with the configuration?

2 Answers 2

3

There were two problems in my configuration:

  1. As @sotirov mentioned, <Location> tags are processed by order of presence - correct order should be: restrict all access to certain IP addresses and by following <Location> tags allow access to specified locations.

  2. Rewrited URLS - my url /foo/bar/ is rewrited in .htaccess to index.php, and in this situation URL is not matched by <Location "/foo/bar/"> location. When I use real physical file <Location "/foo.bar"> location tag works as expected.

1
  • 1
    Congrats on figuring it out by yourself, +1 from me. I suspected that part 2 can be problematic too, but the documentation mentioned that <Location> is processed after the .htaccess. I suppose, it depends on what the .htaccess file is doing :)
    – sotirov
    Commented May 27 at 14:49
2

Wrong order of Location sections

According to the official Apache 2.4 Documentation, <Location> sections are processed in the order they appear in the configuration file, after the <Directory> sections and .htaccess files are read, and after the <Files> sections.

The Require ip 1.2.3.4 in the <Location "/"> section restricts access to only that IP, but the other <Location> sections should override this for the specific paths. The correct order should be:

<Location "/">
    Require ip 1.2.3.4
</Location>

<Location "/foo/bar/">
    Require all granted
</Location>

<Location "/.well-known/">
    Require all granted
</Location>

Location with trailing slash /

Another problem may be the slash / you have at the end of your specified location. According to the official Apache 2.4 Documentation, the enclosed directives will be applied to the request if the path component of the URL meets any of the following criteria:

  • The specified location matches exactly the path component of the URL.
  • The specified location, which ends in a forward slash, is a prefix of the path component of the URL (treated as a context root).
  • The specified location, with the addition of a trailing slash, is a prefix of the path component of the URL (also treated as a context root).

In the example below, where no trailing slash is used, requests to /private1, /private1/ and /private1/file.txt will have the enclosed directives applied, but /private1other would not.

<Location "/private1">
    #  ...
</Location>

In the example below, where a trailing slash is used, requests to /private2/ and /private2/file.txt will have the enclosed directives applied, but /private2 and /private2other would not.

<Location "/private2/">
    # ...
</Location>

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .