Configure Lighttpd to serve Foris and Luci only to specific clients

I am hosting some web services behind my Omnia. So I have port 80 open and based on domain name Lighttp selectively forwards requests to the right server. This is all fine and dandy and been working well for a while now.

Problem is that Foris and Luci are also served. That I want to stop for security reasons (clearly)and restrict access to Foris and Luci only from the LAN and from specified IPs in the WAN (so I can get to to it from my office for example). I do this already for port 22 using the firewall and port 5900 for VNC access to machines in the LAN (that is, these ports are only open to the LAN and my office IP).

The only way I can think of to keep Foris and Luci out of public service is to move them to another port, 81 is a common choice for such things (admin interfaces). Then in the firewall I can configure port 81 so it’s only open from the LAN and from my office IP much as I do for 22 and 5900.

But I’m not sure what the easiest way to configure Foris and Luci to serve only on port 81 is. Problem is I don’t really want to edit files in /etc/lighttpd/conf.d that are parts of the Foris and Luci packages. To wit I think perhaps the best way is to selectively load the confs, replacing include "/etc/lighttpd/conf.d/*.conf" with explicit loads of the various confs. I can and have done that but post here, wondering if anyone has any tips here. Anyone has tried to do same.

It can’t be a first surely? I want foris and luci, but I don’t want them exposed to the world. I do want to serve other web pages from behind my Omnia though so I do selective reverse proxying based on SNI in the lightttpd confs.

In my opinion you should have lighttpd (the one which decides based on domain) in virtual container and forward all 80,443 from WAN to your public IP to this virtual space.
From LAN to LAN then you can still access foris 80,443. To access your domains from LAN on public IP you need to set hairpin NAT or use intranet addresses.

So:
WAN -> router WAN IP: forward 80,443 to LXC container
LAN -> router LAN IP: keep as is to access foris
LAN -> router WAN IP: hairpin NAT to LXC container

Sounds a little more complex than I’d like. Running a LXC container and by inference two instances of lighttp one on the Omnia, the other in an LXC container seems like slight overkill to me. Easier to server Luci and Foris on port 81, and keep them separate from port 80 traffic methinks.

Also given how much I have behind that gateway, including a full blown web server, I have a good few instances of lighttpd running on different machines that have different roles (a web server, a file server, a cloud server, a mail server) and could just as soon us the webserver in place of the LXC container.

Still not sure I understand you summary and how it helps, I think I can rewrite it as:

WAN -> router WAN IP: forward 80, 443 to another lighttpd which reverse proxies based on SNI
LAN -> router WAN IP: forward 80, 443 to another lighttpd which reverse proxies based on SNI
LAN -> router LAN IP: accept 80, 443 on the Omnia

This leaves Foris and Luci accessible on LAN yes, by delegating all WAN IP bound traffic to another lighttpod instance (my webserver say, or in an LXC container in your suggestion) and keeping LAN IP bound traffic on the Omnia.

But I’d also kind of like to say:

WAN source IP=… -> keep on Omnia to serve Foris and Luci.

That is, what I do for ssh now for example, I accept port 22 only from LAN and from WAN from specif source IPs (namely my workplace IP). And I use an openvpn as well, to access it when I’m on the road with no certain IP.

What is your question then?
If anybody else changed port 80 to another but by any other method than editing lighttpd .conf files - directly or indirectly (include option)?

It seems like this might get you started on what you need.

@blbeczech82 my question is “has anyone else done this: run web services behind an Omnia or OpenWRT router, wnatd Fors and Luci available but not on WAN on on LAN and specific WAN clients? And if so, how is it most elegantly done?”.

@jklaas that does look interesting. I’ve been using the firewall to check source IP. Still the open question is, given the nature of configs where to put this test. That is indeed part of the original puzzle for me. There are files in/etc/lighttpd/conf.d:

# ll /etc/lighttpd/conf.d/
-rw-r--r--    1 root     root          2139 Jul 22 21:21 LAN-servers.conf
-rw-r--r--    1 root     root           177 Jun 26 19:14 foris-config.conf
-rw-r--r--    1 root     root           421 Jun 26 19:14 foris-root.conf
-rw-r--r--    1 root     root           177 Jun 26 19:14 foris-wizard.conf
-rw-r--r--    1 root     root           150 May  4 18:34 foris-ws.conf
-rw-r--r--    1 root     root           824 Jun  6 23:09 luci.conf
-rw-------    1 root     root           514 Jan 26 09:15 ssl-enable.conf

Luci configs look nice and contained, foris configs seem unclearly spread out. But in both cases modifying these files is sub-optimal as they belong to packages and the package manager will update them from time to time, or probably not, if I modify them opkg probably leaves incoming package files next to them with a -opkg suffix in the name or such.

And so the easiest way seems to be to edit /etc/lighttpd/lighttpd.conf because I already have edits and so already have an opkg drop there:

# ll /etc/lighttpd
drwxr-xr-x    1 root     root           204 Jul 22 21:21 conf.d/
-rw-r--r--    1 root     root          2831 Jul 13 17:00 lighttpd.conf
-rw-r--r--    1 root     root          1153 May  4 18:19 lighttpd.conf-opkg
-rw-r--r--    1 root     root         21895 May  4 18:19 mime.conf
drwxr-xr-x    1 root     root           450 May 10 21:59 modules.d/
drwxr-xr-x    1 root     root           118 Sep 16  2017 ssl/

and from there, based on IP I could selectively load the conf.d files. But alas it still seems a tad messy, not least because I have yet another place to manage my safe source IP (work). But it may be it’s the easiest way.

In part I guess what I’m fishing for is a sense of how many people users or even Turris engineers have given selective access to Foris and Luci good thought and implemented solutions, which permit the Omnia to serve on 80 and 443 WAN websites for other domain names (based on SNI).

Easiest way is to create a new file, e.g. /etc/lighttpd/conf.d/deny-wan.conf and put following snippet into it:

$HTTP["remoteip"] != "192.0.2.1" {
     $HTTP["url"] !~ "/secret/url" {
	     url.access-deny = ("")
     	}
}

Of course modify remote IP and /secret/URL to match your needs.

If you create a new file it should not interfere with updates.

3 Likes

That wins a prize. Thanks pspacek. Means I can use negative logic to exclude all IPs outside of range 192.168.*. I’m guessing and will test:

$HTTP["remoteip"] !~ "^192.168." {
     $HTTP["url"] =~ "(/foris|/cgi-bin/luci)" {
	     url.access-deny = ("")
     	}
}

I’ll research it a little. But the clues are very gratefully received. Thank you muchly.

1 Like

If you want to use subnets have a look at https://redmine.lighttpd.net/boards/2/topics/1279 , there are some traps in syntax.

1 Like

That looks great. But I just tested with this:

$HTTP["remoteip"] !~ "^192.168." {
     $HTTP["url"] =~ "(/foris|/cgi-bin/luci)" {
	     url.access-deny = ("")
     }
} 

and confirmed using a proxy (so accessing from a WAN server) that both foris and luci access efforts return"

Error: The requested resource could not be loaded because the server returned an error: 403 Forbidden.

which I conclude is the result of url.access-deny = ("")

So that works. I’ll have to try and VPN in with OpenVPN and see what IP that gives me if it’s not in the 192.168.. range enable that too. Been a while since I VPNed in - I only have that on for my trips to China so I can use social media really, they’ve clamped down on commercial VPNs there something awesome ;-).

Can you please do a check with an invalid remoteip value like 92 instead if 192 and try to connect to the services?

Not sure how to do that alas. Open to tips.

instead of

$HTTP[“remoteip”] !~ “^192.168.” {
$HTTP[“url”] =~ “(/foris|/cgi-bin/luci)” {
url.access-deny = (“”)
}
}

use

$HTTP[“remoteip”] !~ “^92.168.” {
$HTTP[“url”] =~ “(/foris|/cgi-bin/luci)” {
url.access-deny = (“”)
}
}
or s.th. like that and then try to access foris or luci.

Done. If I do that I get 403 from the LAN and the WAN as expected. No foris or luci. In short, proof it works ;-).

1 Like

The deny-wan.conf file needs to start with the following line:

server.modules += ( "mod_access" )