2
votes

I want to host a web app with node.js on a Linux virtual machine using the the HTTP module.

As the app will be visualising sensitive data I want to ensure it can only be accessed from PCs on the same LAN.

My understanding is that using the HTTP module a web server is created that's initially only accessible by other PCs on the same LAN. I've seen that either by tunnelling or portforwarding a node.js server can be exposed if desired.

Question

  1. Are there any other important considerations/ways the server could be accessed externally?

  2. Is there a particular way I can setup a node.js server to be confident that it's only accessible to local traffic?

2

2 Answers

2
votes

It really depends what you are protecting against.

For example, somebody on your LAN could port forward your service using something like ngrok. There are a few things you can check for:

  • In this case the header x-forwarded-for is set. So, to protect against this you can check for this header on the incoming request, and if set you can reject the request.
  • The host header is also set and will indicate how the client referred to your service - if it is as you expect (maybe a direct local LAN address such as 192.168.0.xxx:3000) then all is OK, if not (I ran ngrok on a local service and got something of the form xxxxxxxx.ngrok.io) then reject it.

Of course a malicious somebody could create their own server to redirect requests. The only way there is to put in usernames and passwords or similar. At least you then known who is (allegedly) accessing your service and do something about it.

However, if you are not trying to pretect against a malicious internal actor, then you should be good as you are - I can't think of any way (unless there is a security hole in your LAN) for your service to be made public without somebody actively setting that up.

My last suggestion would be to use something like express rather than the http module by itself. It really does make life a lot simpler. I use it a lot for just this kind of simple internal server.


Thought I'd add a quick example. I've tested this with ngrok and it blocks access via the public address but works find via localhost. Change the host test to whatever local address (or addresses) you want to serve this service from.

const express=require('express');

const app=express();

app.use((req,res,next)=>{
  if (req.headers.host!=='localhost:3000' || req.headers['x-forwarded-for']){
    res.status(403).send('Invalid access!');
  } else next();
});

app.get('/',(req,res)=>res.send('Hello World!'));

app.listen(3000,()=>{
  console.log('Service started.  Try it at http://localhost:3000/');
});
0
votes

I would prefer using nginx as a proxy here and rely on nginx' configuration to accept traffic from local LAN to the node.js web server. If this is not possible, a local firewall would be the best tool for the job.