So, I run a web server. I do not pay for hosting. Maybe one day when I’m rich and famous I’ll have the need to offload my computing and security needs to a third party, but for now it’s the joy of having full control over the hardware that both feeds and permits my curiosity of technology. Hey, the title of this post was not misleading. If you’re actually reading this, then you must share some of these interests.
With all web-accessible content comes the need for access control. Normally I handle this through the operating system’s administration panel, but a need arose in which this wasn’t as practical as I had hoped. Here’s why:
- No one can ever remember their login credentials
- The web GUI is processor-intensive, and therefore slow (especially on mobile devices), leading to user impatience
- the web GUI doesn’t play nice with mobile OSes in general
- Mounting network shares is a lot of trouble for a single file (also: see the first bullet)
- Access control management is a pain, especially when it’s a new user who doesn’t necessarily need access to the server for anything else
- The files were meant to be shared with anyone on the LAN, who presumably would already have been authenticated by me or else they wouldn’t be on my LAN in the first place
- When a file needs to be downloaded, and the client doesn’t need to upload anything, few methods are easier and more universal than good ol’ HTTP
Based on these limitations and my needs, I determined the best solution was to create a file repository that was devoid of separate access control, restricted to the local LAN. Only people on my LAN could access the files, and any people on my LAN by default would have de facto permission to access them (and not those on the guest subnet).
Fortunately from experience, once I identified these needs, I knew of the solution, though it did take a little research. Any web server has individual configuration files which can be applied at the directory level:
- IIS has “web.config”
- NGINX has “nginx.conf”
- Apache has “.htaccess”
Natrually I would never be caught dead using IIS, although I was forced to use it for a prior job. But my server, Linux-based of course, leverages NGINX with an Apache backend. I had a working familiarity of Apache, and I had already dabbled with .htaccess and .htpasswd files before, as well as modifying the Apache config files to allow their overrides, so this seemed like the best option.
Still with me? Okay good. I created a new directory “/public_LAN/” and with the server’s own text editor, created the directory’s own .htaccess file. And my god why do OSes have to be so difficult with non-standard file extensions? I know why: some idiot will mess with a critical config file or open malware, but why can’t I turn it off? I used to be able to edit any file type I wanted with older Apple OSes, but it seems that now it’s forbidden completely. So no, I couldn’t just open my HTML editor and save a text file as .htaccess because that’s an usupported extension. Whatever.
Into this file I placed:
Options +Indexes
ErrorDocument 403 “<h1>403 Forbidden</h1><p>This page is restricted to internal LAN access only:<br><a href=’http://192.168.0.106/public_LAN/’>192.168.0.106/public_LAN/</a></p>”
order deny,allow
allow from 192.168.0.
allow from 10.8.0.
deny from all
BAM! Okay, triumphant interjection aside, what does this mean? I will explain, else I risk bastardizing the value of this post:
Options+Indexes : This command enables directory browsing. Web servers always have this off by default for security reasons, but since I was going to use the directory for the very purpose of browsing files within, I needed to turn it on. This is how you do it.
ErrorDocument 403 “<h1>403 Forbidden</h1><p>This page is restricted to internal LAN access only:<br><a href=’http://192.168.0.106/public_LAN/’>192.168.0.106/public_LAN/</a></p>” : This is optional, but it adds a custom 403 error page (for this directory only). In short, mine says that if it’s triggered, the user isn’t inside the LAN and therefore can’t go there. Attentive readers will notice that I neither link to a TLS connection, nor use the domain name. More on this later.
order deny,allow : This sets the precedent that all access will be denied by default first, then checked for conditions under which access is allowed.
allow from 192.168.0. : This line is the condition under which access will be granted. It is the first 3 blocks of the main LAN IP address. This includes any client IP address that begins with these 3 blocks–which will be anything on my LAN (excluding the guest network).
allow from 10.8.0. : This is the second set of LAN IP addresses to allow. In my case, this is the subnet for anything connected to the LAN via VPN. I wanted this available to VPN clients too as the VPN is handling the authentication and encryption parts already for any remote access.
deny from all : Finally, any client that doesn’t meet the above conditions will be denied access.
Okay, now the two elephants in the room, and all the technical babble. First is the lack of encryption. Ultimately I determined that this wasn’t necessary, as any file access would be strictly over the LAN. If there are untrusted devices on my primary network, then I have bigger problems to deal with. Also, I can’t service HTTPS without a domain name being used for the connection, since no Certificate Authority will issue a valid TLS certificate to a private IP address, so I’d have to use a certificate that won’t pass a browser’s domain name validation–in itself not a problem, but then it warns the client of a potential security risk, which the client may not understand, thus inciting panic and undermining the entire point of this project–seamless ease of use. Also, as mentioned before, any remote access will be tunneled through a VPN, so any data that makes it to the outside web will be encrypted anyway. Second, domain name validation isn’t possible for the above reason, but also because I can’t access this directory via the domain name anyway (okay, I can, but only by local IP–VPN clients still perform a DNS lookup for the host IP, making the client appear to the server that it’s outside the LAN), or the server will see the request coming from the WAN IP, and not the LAN IP. Therefore, it will block the request. I could add the WAN IP to the whitelist, but it’s not static and if it ever changes I’ll have to update the .htaccess file again. Also the authentication side of domain name validation is moot while accessing via LAN IP, as it won’t be feasibly faked unless some rogue device is attempting ARP spoofing–again something which, if happening, means I have bigger problems to deal with. Whew, done.
Obviously this isn’t high-end security, but it’s reasonably effective. I wouldn’t use this method to conduct crime, but if I need to say, give a somewhat sensitive file to a guest and it’s too big to email, and I don’t want that file publicly accessible, then this is a pretty good solution. Keep your data safe!
–Simon