Certain error codes not displaying error page

1. Caddy version (caddy version):

v2.5.0 h1:eRHzZ4l3X6Ag3kUt8nj5IxATprhqKq/wToP7OHlXWA0=

2. How I run Caddy:

Nothing fancy, just the Caddy packages for Ubuntu. Currently on 20.04

a. System environment:

I use systemd to run Caddy (i.e. systemctl start/stop/restart caddy)

b. Command:

See above

c. Service/unit/compose file:

I don’t know where this is unfortunately. I know I haven’t changed it though.

d. My complete Caddyfile or JSON config:

{
	admin off
}
(logging) {
	log {
		output file /var/log/caddy/caddy.log {
			roll_size 15mb
			roll_keep 20
		}
	}
}
(errors) {
	handle_errors {
		root * /var/www/internal/errors
		rewrite * /{http.error.status_code}.html
		file_server
	}
}
(php) {
	php_fastcgi unix//run/php/php8.1-fpm.sock
}
www.telesphoreo.me {
	import logging
	redir https://telesphoreo.me{uri}
}
telesphoreo.me {
	import logging
	import errors
	import php
	root * /var/www/telesphoreo.me
	file_server browse
	encode gzip zstd
        @denied path /assets/ /old_html/* /new_html/* /recyclebin/* /nitrogen/ /wave/
	respond @denied 403
}
blog.telesphoreo.me {
	import logging
	import php
	root * /var/www/blog.telesphoreo.me
	file_server
	encode gzip
}
db2.telesphoreo.me {
	import logging
	import php
	root * /usr/share/phpmyadmin
	file_server
}
nexus.telesphoreo.me {
	reverse_proxy http://localhost:8082
}
panel.telesphoreo.me {
	import logging
	php_fastcgi unix//run/php/php8.0-fpm.sock
	root * /var/www/pterodactyl/public
	file_server
	header X-Content-Type-Options nosniff
	header X-XSS-Protection "1; mode=block"
	header X-Robots-Tag none
	header Content-Security-Policy "frame-ancestors 'self'"
	header X-Frame-Options DENY
	header Referrer-Policy same-origin
	request_body {
		max_size 100m
	}
	respond /.ht* 403
}
pictochat.telesphoreo.me {
	import logging
	reverse_proxy http://localhost:8080
}
wordle.telesphoreo.me {
	import logging
	root * /var/www/wordle.telesphoreo.me/games/wordle
	file_server
	encode gzip
}
ci.plex.us.org {
	reverse_proxy http://localhost:8081
}
docs.plex.us.org {
	import logging
	redir https://plex.us.org{uri}
}
httpd.plex.us.org {
	import logging
	reverse_proxy 172.18.0.1:27192
}
plex.us.org {
	import logging
	root * /var/www/plexus.org/build
	respond /updater/check/ "1.0.3"
	file_server
}
forum.plex.us.org {
	import logging
	import php
	root * /var/www/forum.plexus.org/public
	file_server
	header /assets {
		+Cache-Control "public, must-revalidate, proxy-revalidate"
		+Cache-Control "max-age=25000"
		Pragma "public"
	}
	respond /.ht* 403
}
www.smokes-crystal.rocks {
        import logging
        redir https://smokes-crystal.rocks{uri}
}
smokes-crystal.rocks {
        import logging
        import errors
        root * /var/www/smokes-crystal.rocks
        file_server
}

3. The problem I’m having:

Basically, Error 404 codes are working, but Error 403 codes aren’t. I have it setup so it should return the error pages I’ve made instead of the default Chome. If you go to https://telesphoreo.me/404 for example, this is a page that does not exist. It correctly shows the error 404 page. However, if I go to a URL I’ve restricted such as https://telesphoreo.me/recyclebin, it will show the Chrome error 403 page. I can’t figure out why the same code for handling 404 doesn’t work on 403. It’s also important to note that if you add a directory to respond to 403 that doesn’t exist, it will actually (correctly) return 404. It’s technically correct that something that doesn’t exist is 404, but it ignores that I told it specifically to return 403.

4. Error messages and/or full log output:

Here’s a log of a 403 occuring

{"level":"error","ts":1651467493.0210693,"logger":"http.log.access.log1","msg":"handled request","request":{"remote_ip":"X.X.X.X","remote_port":"21212","proto":"HTTP/2.0","method":"GET","host":"telesphoreo.me","uri":"/recyclebin/","headers":{"Cf-Ipcountry":["US"],"User-Agent":["Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Safari/537.36"],"Sec-Ch-Ua":["\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"101\", \"Google Chrome\";v=\"101\""],"Sec-Ch-Ua-Platform":["\"macOS\""],"Cf-Connecting-Ip":["45.79.1.27"],"Accept-Encoding":["gzip"],"Sec-Fetch-User":["?1"],"Cookie":[],"Cdn-Loop":["cloudflare"],"Sec-Fetch-Mode":["navigate"],"Sec-Ch-Ua-Mobile":["?0"],"Upgrade-Insecure-Requests":["1"],"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"],"X-Forwarded-Proto":["https"],"Cf-Visitor":["{\"scheme\":\"https\"}"],"Sec-Fetch-Site":["none"],"Sec-Fetch-Dest":["document"],"Accept-Language":["en-US,en;q=0.9"],"X-Forwarded-For":["X.X.X.X"],"Cf-Ray":["704e2e35284e93d9-DFW"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"telesphoreo.me"}},"user_id":"","duration":0.00009629,"size":0,"status":403,"resp_headers":{"Server":["Caddy"],"Content-Type":[]}}

Here’s one of a 404

{"level":"error","ts":1651467413.3765965,"logger":"http.log.access.log1","msg":"handled request","request":{"remote_ip":"X.X.X.X","remote_port":"53448","proto":"HTTP/2.0","method":"GET","host":"telesphoreo.me","uri":"/404","headers":{"Cf-Ray":["704e2c436b8aa9f7-DFW"],"X-Forwarded-Proto":["https"],"Cf-Visitor":["{\"scheme\":\"https\"}"],"Accept-Encoding":["gzip"],"Cdn-Loop":["cloudflare"],"Cf-Ipcountry":["US"],"X-Forwarded-For":["X.X.X.X"],"User-Agent":["curl/7.79.1"],"Accept":["*/*"],"Cf-Connecting-Ip":["X.X.X.X"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"telesphoreo.me"}},"user_id":"","duration":0.00014789,"size":946,"status":404,"resp_headers":{"Server":["Caddy"],"Etag":["\"rahx6rqa\""],"Content-Type":["text/html; charset=utf-8"],"Last-Modified":["Sun, 17 Apr 2022 18:11:15 GMT"],"Accept-Ranges":["bytes"],"Content-Length":["946"]}}

5. What I already tried:

I don’t have a good idea on where to start unfortunately. What I used to do before having the error handling code was actually remove the read permission for everyone on the folder itself. Part of the reason it’s sort of confusing is because I want people to have access to specific files if they know the URL, but not be able to list the whole directory. It’s also a problem if I remove the permission because if it’s asset files or something, it refuses to load on the webpage itself. So right now all the permissions are “normal” where everyone has read access to the folder. If the permissions are removed, it still returns the Chrome default error 403 page. While I would never go back to Apache, I preferred their granular control of limiting indexing / viewing of specific directories with .htaccess. I unfortunately don’t know how to test different error codes to see if it’s specifically 403 that doesn’t return the page.

ls -la
total 64
drwxr-xr-x 2 root root 4096 Jun 22  2021 .
drwxr-xr-x 3 root root 4096 Jun 22  2021 ..
-rw-r--r-- 1 root root  881 Jun 22  2021 400.html
-rw-r--r-- 1 root root  869 Jun 22  2021 401.html
-rw-r--r-- 1 root root  866 Jun 22  2021 403.html
-rw-r--r-- 1 root root  946 Apr 17 13:11 404.html
-rw-r--r-- 1 root root  891 Jun 22  2021 405.html
-rw-r--r-- 1 root root  941 Jun 22  2021 415.html
-rw-r--r-- 1 root root  785 Jun 22  2021 418.html
-rw-r--r-- 1 root root  861 Jun 22  2021 423.html
-rw-r--r-- 1 root root  886 Jun 22  2021 426.html
-rw-r--r-- 1 root root  911 Jun 22  2021 451.html
-rw-r--r-- 1 root root  864 Jun 22  2021 500.html
-rw-r--r-- 1 root root  868 Jun 22  2021 503.html
-rw-r--r-- 1 root root  917 Jun 22  2021 505.html
-rw-r--r-- 1 root root  926 Jun 22  2021 507.html

Here’s a listing of all the errors that are currently set up. I can’t think of anything to rename it to to yield different results. If I rename the working 404.html to something invalid (like test.html), it will return the default Chrome page. This leads me to believe a similar thing is happening here, but I genuinely can’t figure out what to name it to.

Appreciate any help. I seriously appreciate Caddy and the people behind it. You guys are awesome and have saved me an insane amount of trouble and time with Linux administration.

6. Links to relevant resources:

https://telesphoreo.me/404 ← should return 404
https://telesphoreo.me/recyclebin ← should return 403

Using respond directly writes a response, it doesn’t trigger an error.

If you want to trigger an error, use the error directive:

To clarify, non-200 HTTP status responses are not errors, they’re still just responses. An error is specifically triggered either from Go code as a Go error, or via the error directive (which emits a Go error).

1 Like