Allow unauthenticated access to non-admin LUA pages

In file lua_web.c, the code enforces authentication for every LUA page except admin/login, as explicitly stated:

I'm proposing that authorization should be enforced only for paths inside config.webserver.paths.webhome, so that the following becomes possible:

  1. Running Pi-hole on bare metal
  2. Setting webserver.serve_all = true in the config (or UI)
  3. Placing a test.lp file inside /var/www/html
  4. Running curl -v http://127.0.0.1/test

Expected behavior: Instead of a 302 redirect to /admin/login, I want a 200 OK response.

I get that Pi-hole isn't meant to function as a full-fledged web server, but wouldn't it be neat if this little tweak allowed just a bit more flexibility? :slight_smile:

Looking forward to your thoughts. Thanks for considering this!

You can do that currently with an html file:

root@pihole:/var/www/html# ls -la
total 11
drwxr-xr-x 3 root root  5 Jun  6 19:54 .
drwxr-xr-x 3 root root  3 Apr 16 02:46 ..
drwxr-xr-x 9 root root 42 Jun  2 01:39 admin
-rw-r--r-- 1 root root  0 Jun  6 19:53 test.html
-rw-r--r-- 1 root root  0 Jun  6 19:54 test.lp

root@pihole:/var/www/html# curl -I http://localhost/test.html
HTTP/1.1 200 OK
Cache-Control: max-age=3600
X-DNS-Prefetch-Control: off
Content-Security-Policy: default-src 'self' 'unsafe-inline';
X-Frame-Options: DENY
X-XSS-Protection: 0
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Access-Control-Allow-Headers: *
Access-Control-Allow-Methods: *
Content-Type: text/html
Last-Modified: Fri, 06 Jun 2025 19:53:58 GMT
Etag: "68434756.0"
Content-Length: 0
Accept-Ranges: bytes
Date: Fri, 06 Jun 2025 19:56:03 GMT
Connection: keep-alive

It's the .lp extension that causes the redirect:

root@pihole:/var/www/html# curl -I http://localhost/test.lp
HTTP/1.1 301 Moved Permanently
Location: /test
Cache-Control: max-age=3600
X-DNS-Prefetch-Control: off
Content-Security-Policy: default-src 'self' 'unsafe-inline';
X-Frame-Options: DENY
X-XSS-Protection: 0
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Access-Control-Allow-Headers: *
Access-Control-Allow-Methods: *
Content-Length: 0
Date: Fri, 06 Jun 2025 19:56:49 GMT
Connection: keep-alive

So it looks like anything with an .lp extension is converted to a path. Example http://localhost/test.lp is redirected to http://localhost/test which then is interpreted as being needed to go to the /admin/login path.

1 Like

I think this is a feasible change. Feel free to submit it as PR or I will try to do it sometime over the next days (but my own TODO list is very full)

1 Like

Simple enough to squeeze it in between two other things:

Please test if this does what you'd expect by running

sudo pihole checkout ftl tweak/server_all_no_auth

and then checking if this does what you'd expect it to do.

You can later go back to the stable version using

sudo pihole checkout ftl master
1 Like

It works perfect! You are a star, @DL6ER !

Thank you for squeezing it in :hugs:

Probably overextending here... Is there any way to generate a blank HTTP/1.1 204 No Content page from inside a LUA server page (.lp) ?

I'm trying to implement a local http://www.gstatic.com/generate_204 with nothing more than my trusty pi-hole.

You probably need to add some Lua code at the beginning of the file:

  mg.write("HTTP/1.0 204 No Content\r\n")

There are a few examples in civetweb repository, specially in tests directory: civetweb/test at master · civetweb/civetweb · GitHub

1 Like

Thank you for the hints :hugs: I was able to make it work with .lua files:

root@nanopi-r4s:/var/www/html# cat generate_204.lua
mg.write("HTTP/1.1 204 No Content\r\n")
mg.write("Content-Length: 0\r\n")
mg.write("Cross-Origin-Resource-Policy: cross-origin\r\n")
mg.write("\r\n")

root@nanopi-r4s:/var/www/html# curl -v http://127.0.0.1/generate_204.lua
*   Trying 127.0.0.1:80...
* Connected to 127.0.0.1 (127.0.0.1) port 80 (#0)
> GET /generate_204.lua HTTP/1.1
> Host: 127.0.0.1
> User-Agent: curl/7.88.1
> Accept: */*
>
< HTTP/1.1 204 No Content
< Content-Length: 0
< Cross-Origin-Resource-Policy: cross-origin
<
* Connection #0 to host 127.0.0.1 left intact

Unfortunately I don't know how to replicate the same outcome with .lp files:

root@nanopi-r4s:/var/www/html# cat generate_204.lp
<?
mg.write("HTTP/1.1 204 No Content\r\n")
mg.write("Content-Length: 0\r\n")
mg.write("Cross-Origin-Resource-Policy: cross-origin\r\n")
mg.write("\r\n")
?>
root@nanopi-r4s:/var/www/html# curl -v http://127.0.0.1/generate_204
*   Trying 127.0.0.1:80...
* Connected to 127.0.0.1 (127.0.0.1) port 80 (#0)
> GET /generate_204 HTTP/1.1
> Host: 127.0.0.1
> User-Agent: curl/7.88.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Cache-Control: no-cache, no-store, must-revalidate, private, max-age=0
< Expires: 0
< Pragma: no-cache
< X-DNS-Prefetch-Control: off
< Content-Security-Policy: default-src 'self' 'unsafe-inline';
< X-Frame-Options: DENY
< X-XSS-Protection: 0
< X-Content-Type-Options: nosniff
< Referrer-Policy: strict-origin-when-cross-origin
< Content-Type: text/html; charset=utf-8
< Date: Sat, 07 Jun 2025 17:07:17 GMT
< Connection: close
<
HTTP/1.1 204 No Content
Content-Length: 0
Cross-Origin-Resource-Policy: cross-origin

* Closing connection 0

The thing is that I need to serve a 204 No Content page from this specific path /generate_204 (no lua extension) and the .lp files make this possible.

I don't think it's possible right now due to limitations how Lua "Kepler style" pages are handles in CivetWeb. I don't see an easy way to get this fixed...

1 Like