Is it safe to use http (in nodejs) on a localhost service behind proxy_pass? [duplicate] - node.js

We have a web application which will use self signed certificates, and after installing it on the server, the browser will open at "https://localhost" (no, for argument's sake, I will state that we cannot use the actual machine name).
This will generate a browser error, because "localhost" is not the certificate's domain.
An option, is to expose the application on HTTP only on the loopback (localhost).
Our application should be encrypted whenever it is passing outside of the server, so - the question..
Are there any security concerns around allowing HTTP access to our
application on localhost (and only on localhost)? Does this expose the
application to snooping from outside of the computer?
One can assume that if someone was able to access the machine's local user sessions, then we have bigger worries, and the lack of HTTP would hence be insignificant.

There could be other process sniffing the loopback interface. It could be a service running in you PC, sniffing and sending data outside to a remote server.
You can still use https with a domain name, like https://www.myowndomain.com and in the hosts file you map this domain to 127.0.0.1

Related

How to use a secure WebSocket-Connection for a local client

I need informations about security risks and proof of concepts to work with an local client.
In my option, a user will install two components:
The game client
The client launcher
The launcher is running as an background process all the time. The launcher provides an WebSocket server.
The user will open my website to start the game (with game-server lists and other settings). The Website connects to the game launcher to handle all actions (change configuration, start the game executable)..
Problem:
How realize the communication with the website and the game launcher? Okay, Websockets, yes. But browsers forbid to connect to localhost/127.0.0.1 by security reason.
An fake-pointer as DNS or hosts-file to an subdomain like local.game.tld is bad, because SSL-Certificates can be revoked here as bad usage.
Another idea was to provide an NPAPI-Plugin for the browser. But it seems, that the NPAPI is deprecated and useless for the future.
Whats the best practice to communicate between webpages and local installed software?
But browsers forbid to connect to localhost/127.0.0.1 by security reason
This isn't true. Browsers allow you to connect to localhost / 127.0.0.1. I do it all the time on my machine.
The issue is that TLS (wss://localhost, not ws://localhost) requires a certificate and browsers forbid mixed content (you can't have an https website load non-encrypted resources).
fake-pointer as DNS or hosts-file to an subdomain like local.game.tld is bad, because SSL-Certificates can be revoked here as bad usage.
As part of your game installer you could create a hosts file entry with a certificate for mygame.localhost (possibly using a local script) and then ask the player to authorize the installation of the certificate using their password. This way your certificate won't be revoked... but you are right that this his suboptimal.
EDIT: also, please note that the domain name must be at the end, not at the beginning (i.e., game.localhost and not localhost.game).
Whats the best practice to communicate between webpages and local installed software?
Generally speaking, if your game is installed on the local machine, there's no need to encrypt the communication between the local browser and the local machine.
You can easily write your local server to accept only connections from the local machine (or, at worst, if need be, accept connections from the local area network - though this adds security risks).
Your webpage and WebSocket data can be sent "in the clear" (ws:// and http://) between the local server and the browser since they are both on the same machine - this way you don't need a browser. The local server would initiate (as a client) any encrypted connection it needs when communicating with an external service (was:// / https://).
EDIT (from the comments):
There are the only 2 solutions I know of:
Installing a self-signed certificate; or
Using http instead of https and having the server handle outside traffic as if it were a client (so all traffic going outside is encrypted).

How to create a secure internal route in the CloudFoundry environment (Swisscom AppCloud)

I would like to create a secure internal route between two applications within the same space/organization. It should never be possible to reach the Node.js application from the outside. My Java application connects via HTTP to the Node application (running on express).
I have now tried to setup the desired configuration by creating a route called example-route.apps.internal and assigned it to the Node application. As a next step, I've opened the port (I've tried 443, 80, 8080) in the network configuration of the Java application (with the destination being the Node app). I restaged both applications.
Then, I opened a Java connection to the link http://example-route.apps.internal/test123. I've also tried to use https. The result was the same. Java refused to conncet to this URL.
Now, the following questions:
How can I properly set up this communication? Should I resolve this internal DNS somehow? Which port is the correct one if I just use the port of the env variable? How should I read this port from the other application?
How secure is the communication, if HTTP is used instead of HTTPS? (I assume HTTPS is not possible internally). Is it as safe as an HTTPS connection from the outside? Which devices are between, how far out does the connection go?
Thank you!
I think you're almost there.
Then, I opened a Java connection to the link http://example-route.apps.internal/test123. I've also tried to use https. The result was the same. Java refused to conncet to this URL.
You should use http://example-route.apps.internal:8080/test123. Your app is set to listen on $PORT, which is always 8080 in current versions of CF.
Normally you don't need to worry about this because your traffic goes in through Gorouter which translates for you (maps external port 80 -> internal 8080). With internal routes, traffic is direct so there is no transformation. That's why you need to use port 8080 in your URL.
Alternatively, you could use a service discovery mechanism like Eureka or Consul, but it's not a requirement. In this case, the service would know it's listening on 8080 and register that in the registry.
As far as HTTPS, that's tricky. Your app is only listening on 80/HTTP. You would have to change it to listen on 443/HTTPS, but then you need certs and different server configuration. It's technically possible, but it's a whole can of worms.
In some newer versions, Envoy is present and accepts HTTPS traffic into a container, can make HTTPS easier but it's still not a slam dunk (at the time of writing, at least). I expect this will get better in the future.
Should I resolve this internal DNS somehow?
Internal DNS helps with locating your other apps, not the port. Otherwise you'd need to manage IP addresses, which change often, and that would require something like Eureka or Consul.
Which port is the correct one if I just use the port of the env variable?
See above.
How should I read this port from the other application?
It's always 8080 at the moment, and has been for multiple years. It's unlikely to change, so you could probably hard code or set it in a config file safely.
How secure is the communication, if HTTP is used instead of HTTPS? (I assume HTTPS is not possible internally).
Is it as safe as an HTTPS connection from the outside? Which devices are between, how far out does the connection go?
Traffic would not be accessible externally as it wouldn't leave the Cell in some cases or worst case it goes between two Cells, but traffic would be visible internally since it's not encrypted. That means you need to have more trust on your CF provider, who would have access to internal traffic.
If it were HTTPS, only someone with the key would be able to decrypt it. You would still have to trust your provider though as they could likely get the key & use it to decrypt traffic. It would just be more work for them than if traffic is unencrypted.
Hope that helps!

How tunneling services like 'Localtunnel' works without SSH?

I want to understand how my local IP address (localhost) can be exposed to Internet. For that I've read [here] a method of port forwarding using SSH. Which basically does routing from publicly available server to our localhost using SSH.
But I wonder how the service like 'LocalTunnel' works? In above article it's written as following:
There services (localtunnel for example) creates a tunnel from their server back to port 3000 on your dev box. It functions pretty much exactly like an SSH tunnel, but doesn’t require that you have a server.
I've tried reading code from it's github repository and what I understood is:
These services have a server which is publicly available, which generates different URLs, and when we hit that URL, It forward the request to localhost corresponding to that URL.
So basically it's works like a proxy server.
Is these understanding correct? If yes then what I don't understand is that how these server has access to some localhost running on my computer? How it perform request to it? What I'm missing here? Here is the code which I referred.
The Short Answer (TL;DR)
The Remote (i.e. the localtunnel software on your computer) initializes the connection to the Relay (i.e. localtunnel.me) acts as a multiplexing proxy and when Clients (i.e. web browsers) connect, the relay multiplexes the connections between remotes and clients by appending special headers with network information.
Browser <--\ /--> Device
Browser <---- M-PROXY Service ----> Device
Browser <--/ \--> Device
Video Presentation
If you prefer a video preso, I just gave a talk on this at UtahJS Conf 2018, in which I talk a little about all of the other potential solutions as well: SSH Socksv5 proxies (which you mentioned), VPN, UPnP, DHT, Relays, etc:
Access Ability: Access your Devices, Share your Stuff
Slides: http://telebit.cloud/utahjs2018
How localtunnel, ngrok, and Telebit work (Long Answer)
I'm the author of Telebit, which provides service with similar features to what ngrok, localtunnel, and libp2p provide (as well as open source code for both the remote/client and relay/server to run it yourself).
Although I don't know the exact internals of how localtunnel is implemented, I can give you an explanation of how it's generally done (and how we do it), and it's most likely nearly identical to how they do it.
The magic that you're curious about happens in two places: the remote socket and the multiplexer.
How does a remote client access the server on my localhost?
1. The Remote Socket
This is pretty simple. When you run a "remote" (telebit, ngrok, and localtunnel all work nearly the same in this regard), it's actually your computer that initiates the request.
So imagine that the relay (the localtunnel proxy in your case) uses port 7777 to receive traffic from "remotes" (like your computer) and your socket number (randomly chosen source address on your computer) is 1234:
Devices: [Your Computer] (tcp 1234:7777) [Proxy Server]
Software: [Remote] -----------------------> [Relay]
(auth & request 5678)
However, the clients (such as browsers, netcat, or other user agents) that connect to you actually also initiate requests with the relay.
Devices: [Proxy Service] (tcp 5678) [Client Computer]
Software: [Relay] <------------------------ [netcat]
If you're using tcp ports, then the relay service keeps an internal mapping, much like NAT
Internal Relay "Routing Table"
Rule:
Socket remote[src:1234] --- Captures ------> ALL_INCOMING[dst:5678]
Condition:
Incoming client[dst:5678] --- MATCHES -------> ALL_INCOMING[dst:5678]
Therefore:
Incoming client[dst:5678] --- Forwards To ---> remote[src:1234]
Both connections are "incoming" connections, but the remote connection on the "south end" is authorized to receive traffic coming from another incoming source (without some form of authorized session anyone could claim use of that port or address and hijack your traffic).
[Client Computer] (tcp 5678) [Proxy Service] (tcp 1234) [Your Computer]
[netcat] --------------> <--[Relay]--> <------------ [remote]
2. The Multiplexer
You may have noticed that there's a critical flaw in the description above. If you just route the traffic as-is, your computer (the remote) could only handle one connection at a time. If another client (browser, netcat, etc) hopped on the connection, your computer wouldn't be able to tell which packets came from where.
Browser <--\ /--> Device
Browser <---- M-PROXY Service ----> Device
Browser <--/ \--> Device
Essentially what the relay (i.e. localtunnel proxy) and the remote (i.e. your computer) do is place a header in front of all data that is to be received by the client. It needs to be something very similar to HAProxy's The PROXY Protocol, but works for non-local traffic as well. It could look like this:
<src-address>,<src-port>,<sni>,<dst-port>,<protocol-guess>,<datalen>
For example
172.2.3.4,1234,example.com,443,https,1024
That info could be sent exactly before or append to each data packet that's routed.
Likewise, when the remote responds to the relay, it has to include that information so that the relay knows which client the data packet is responding to.
See https://www.npmjs.com/package/proxy-packer for long details
Sidenote/Rant: Ports vs TLS SNI
The initial explanation I gave using tcp ports, because it's easy to understand. However, localtunnel, ngrok, and telebit all have the ability to use tls servername indicator (SNI) instead of relying on port numbers.
[Client Computer] (https 443) [Proxy Service] (wss 443) [Your Computer]
[netcat+openssl] --------------------> <--[Relay]--> <------------ [remote]
(or web browser) (sni:xyz.somerelay.com) (sni:somerelay.com)
MITM vs p2p
There are still a few different ways you can go about this (and this is where I want to give a shameless plug for telebit because if you're into decentralization and peer-to-peer, this is where we shine!)
If you only use the tls sni for routing (which is how localtunnel and ngrok both work by default last time I checked) all of the traffic is decrypted at the relay.
Anther way requires ACME/Let's Encrypt integration (i.e. Greenlock.js) so that the traffic remains encrypted, end-to-end, routing the tls traffic to the client without decrypting it. This method functions as peer-to-peer channel for all practical purposes (the relay acts as just another opaque "switch" on the network of the Internet, unaware of the contents of the traffic).
Furthermore, if https is used both for remotes (for example, via Secure WebSockets) and the clients, then the clients look just like any other type of https request and won't be hindered by poorly configured firewalls or other harsh / unfavorable network conditions.
Now, solutions built on libp2p also give you a virtualized peer connection, but it's far more indirect and requires routing through untrusted parties. I'm not a fan of that because it's typically slower and I see it as more risky. I'm a big believer than network federation will win out over anonymization (like libp2p) in the long. (for our use case we needed something that could be federated - run by independently trusted parties- which is why we built our solution the way that we did)

Is SSL necessary on localhost?

We have a web application which will use self signed certificates, and after installing it on the server, the browser will open at "https://localhost" (no, for argument's sake, I will state that we cannot use the actual machine name).
This will generate a browser error, because "localhost" is not the certificate's domain.
An option, is to expose the application on HTTP only on the loopback (localhost).
Our application should be encrypted whenever it is passing outside of the server, so - the question..
Are there any security concerns around allowing HTTP access to our
application on localhost (and only on localhost)? Does this expose the
application to snooping from outside of the computer?
One can assume that if someone was able to access the machine's local user sessions, then we have bigger worries, and the lack of HTTP would hence be insignificant.
There could be other process sniffing the loopback interface. It could be a service running in you PC, sniffing and sending data outside to a remote server.
You can still use https with a domain name, like https://www.myowndomain.com and in the hosts file you map this domain to 127.0.0.1

SSL Https, is it that simple?

I'm just setting up an SSL area of a website, and was just wondering... is it as simple as adding HTTPS on the url?
(this is presuming I have a valid certificate of the hosting company?)
Or is there something more to it?
Thanks.
You have to setup the server to allow ssl connections. That includes generating a signed server request. You send this CSR to the cert authority (Verisign etc), and they send you a cert to install on the server. If you are behind a firewall you need to open port 443.
If you don't control the server i.e. shared hosting, there is probably a page in your control panel to do it all for you using a GUI.
When you replace http: in a URL with https: you are asking your web browser to do two things:
To attempt an encrypted (SSL) connection
To change which port to use on the remote server if none is specified in the URL
Most web browsers use port 80 for unencrypted traffic and port 443 for encrypted traffic by default. So, the first thing you need is a web server that is listening on port 443. If you are using a hosting company, this is probably already the case or becomes the case when you configure SSL.
You do not have to use port 443 but that is where browsers will be looking when users do not specify a port. You could also force everybody that connects at port 80 to use SSL as well though with the right configuration. That means that ALL traffic to your site would be encrypted.
To get the encryption up and running you generally need three things: a certificate, an encryption key, and a server request (CSR).
How you configure these is extremely dependent on how you are hosting the web server. Most hosting companies have 'control panels' that you log into for configuration. Common ones are Plex and CPanel. If either of those ring a bell you can post more information to get a better answer.
If you are managing the server yourself the big question is whether you are hosting on Windows or Linux. If it is windows, you are most likely going to want to configure IIS (Internet Information Server) while if it is on Linux you are probably going to configure Apache.
If you are using IIS, this link might help:
http://www.petri.co.il/configure_ssl_on_your_website_with_iis.htm
If it is Apache, Byron gave a good link above:
http://httpd.apache.org/docs/2.0/ssl/ssl_faq.html
You can use other web servers. For example, I use nginx:
http://rubypond.com/blog/setting-up-nginx-ssl-and-virtual-hosts
So, I guess the real step one is finding out more about your server. :-)
Once your web server has the SSL cert installed, it is as easy as using HTTPS on the URLs. There are some considerations to be aware of:
Port 443 must be open between the user and web server. (obvious)
Browser caching will be reduced to in-memory session cache and not stored on disk. Also, caching proxies in between will not be able to cache anything, since everything is encrypted. This means an increase in load times and bandwidth requirements of the web server.
When using HTTPS to receive sensitive data, be sure to disallow its use over HTTP. e.g. If you have a page that accepts credit card numbers in a POST, the app should fail validation if it was not done over HTTPS. This can be done in your code or in web server configuration. This prevents a bug or malware from systematically sending sensitive data in the clear without the user knowing.

Resources