2

I'd like to serve (httpd) either 404s or 200s instead of 403s.

I found a way to redirect and change 403s so they become 404s but I'm not trying to replace 403s altogether but rather where they are presented in the place of [forbidden] directory listings.

I figured a way to do this would be adding a last-resource index file when all others fail and find some way of using httpd's virtual file/location/directory/etc hierarchies to automatically place such file in every virtual host and directory that would map to a single real resource so even if a directory is empty httpd would go:

 [𐄂] index.html
 [𐄂] index.php
 [𐄂] Default.html (← I never got this one)
 [𐄂] index.htm (← ...or this one)
 [βœ“] lastDitchEffort.html β†’ {alias/rw/etc}/var/www/something/{200|404|somethingElse}.html

To be clear, symlinks would not be created at all, httpd would just consider this "magic" index file always available regardless of place, like Alias/AliasMatch but for files.

Can this be done?

Or, alternatively, is there a way to rewrite a 403 to another status but only when a directory is being attempted to be listed?

2
  • I'm unclear on the question. Are you just trying to customise the 403 error message to look like a 404 one or something else? I also notre there is a fairly standard apache pattern for "if the file/directory cant be found, display another page - im guessing thats not what you want either?
    – davidgo
    Commented Jan 11, 2022 at 21:23
  • "place such file in every virtual host" - Are you looking for a server-wide solution or just per vHost/site?
    – MrWhite
    Commented Jan 12, 2022 at 0:48

1 Answer 1

3

The "403 Forbidden" you are referring to is triggered by mod_autoindex when requesting a directory when directory listings (mod_autoindex) are disabled and there is no DirectoryIndex document.

It's generally not a good idea to serve a 200 OK for these requests, unless you are serving some content at this URL. (But if you are serving content then you wouldn't be getting a 403.) The viable alternative is to serve a 404 instead.

There are several ways to do this...

Remove mod_autoindex

Since the 403 is triggered by mod_autoindex then arguably the simplest way to resolve this, if you have access to the server config, is to remove/disable mod_autoindex from the server. This will result in a 404 being triggered instead of a 403.

However, depending on your server config/distro, you might have directives that are dependent on mod_autoindex that aren't enclosed in <ifModule autoindex_module> wrappers - so these will need to be removed (or wrapped in <IfModule>). See the following question on ServerFault: https://serverfault.com/questions/925561/disabling-mod-autoindex-dies-on-autoindex-conf-being-replaced

Override the response inside the 403 ErrorDocument

ErrorDocument 403 /eDocs/e403.php

Inside your custom 403 error document you could test if the request is for a directory and whether a DirectoryIndex document is present in that directory and if not then override the response, setting a 404 status. Server-side scripting like PHP is required.

Use mod_rewrite to force a 404

Using mod_rewrite you could forcefully serve a 404 when a directory is requested and the DirectoryIndex document is not present in that directory.

RewriteEngine On

RewriteCond %{DOCUMENT_ROOT}/$1 -d
RewriteCond %{DOCUMENT_ROOT}/$1/index.html !-f
RewriteCond %{DOCUMENT_ROOT}/$1/index.php !-f
RewriteRule ^/?(.+?)/?$ - [R=404]

From mod_rewrite we do not know what documents have been set as the DirectoryIndex, so it's a case of checking each one as required.

This could be used in the main server config, if it should be protected from being overridden by .htaccess.

Use a final DirectoryIndex (and optional Alias) - "last resort index file"

Similar to what you were suggesting...

Although this would be more for if you wanted to serve content (200 OK) at this URL. (And this would be trivial to override in .htaccess - if that is a concern.)

The DirectoryIndex arguments/documents don't need to be relative to the current directory, they can be root-relative. So you can end on a resource that is always found. For example:

DirectoryIndex index.html index.php /index.php

The above will serve /index.php from the document root if index.html and index.php were not found in the requested directory.

Alternatively, you could specify a "virtual" URL-path and include an Alias in the server config to a different location entirely. This would allow you to use the same config for all vHosts on the server, without the file actually being present in each vHost. For example:

DirectoryIndex index.php /last-resort/index.php

In the main server config:

Alias /last-resort /some/central/location

<Directory /some/central/location>
    Require all granted
</Directory>
1
  • I solved it by accident using a combination of AliasMatch and adding as in the subdir index file "...dex.html <aliasedPath>/404.html". Nowhere it says you can't use subdirectories, IDK why I thought that. But this exactly the kind of answer I was looking for and why I'm always open for suggestions, this answer is a guide on what need to learn straight away, with examples too. BTW, in the mean I also found mod_status, have you used it? It's perfect for automation, I was still playing with it but it'll have to postpone it so I dive on your list first--thanks!
    – Vita
    Commented Jan 13, 2022 at 19:26

Your Answer

By clicking β€œPost Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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