How do SSH tunnels to Nethserver 8 web services work?

Dear community,

I primarily use SSH for maintaining my servers. If a web GUI is unavoidable, I connect to it via an SSH tunnel whenever possible (e.g., for the GUI of various PROXMOX services or for other web configurations).

This works with numerous web GUIs, but unfortunately, it doesn’t work with Nethserver 8. I can get to the login window (i.e., the tunnel is basically up) and can log in there, but after that, it always says “Websocket disconnected.”

Do you see any way to get further with this?

It’s extremely impractical to always have to use a separate VPN for maintenance and configuration on Nethserver 8, especially if you have to disconnect your standard VPN for this. Setting up different VPN types specifically for parallel connections wouldn’t be very practical either. And exposing the Nethserver 8 web GUI to the internet is out of the question.

Since the SSH tunnels don’t work for SOGo, LAM, or Guacamole, I assume this has something to do with Nethserver 8’s traffic flow? Unfortunately, I don’t know anything about that. I use NGINX for my manually configured web proxies, and SSH tunnels work for those, or rather, all, web services configured outside of Nethserver 8.

Do you have any ideas or suggestions?

Regards, Yummiweb

Is it about local forwarding? See also SSH Tunneling: Client Command & Server Configuration

Connect to NS8 by SSH and forward local port 8443 to remote port 443:

ssh -L 127.0.0.1:8443:neth.server.ip:443 root@neth.server.ip

Cluster admin can then be reached like:

https://localhost:8443

For the apps a name is needed, so to reach for example Guacamole:

Edit the localhost in /etc/hosts on the client:

127.0.0.1 localhost guacamole.neth.tld

Browse to following address:

https://guacamole.neth.tld:8443
2 Likes

This resembles an open bug. You can find details here: Support team locked out of cluster-admin HTTP route · Issue #7436 · NethServer/dev · GitHub

As Markus noted, applications that use server name-based HTTP routes may not be reachable from a SSH-tunneled port. It is not a NS8 limitation but an application configuration choice over path-based routes with their pros and cons.

Application developers have to decide what kind of HTTP route to use. If the application is for system management a path-based route like /cluster-admin is a good choice.

You can disable public access with the Allow access from option of Traefik Proxy — NS8 documentation.

I can understand you’d like to reduce the “attack surface” exposing as few applications as possible to the public. This makes sense for apps that are for system management, like cluster-admin or LAM. Admins can connect through a SSH tunnel or management VPN to reach them.

IMO this is less interesting for apps like SOGo, that are designed for widespread access.

2 Likes

If you do want to expose less apps as possible to the public, use wireguard or openvpn to connect.

Thank you for your feedback.

My command is a bit longer (it connects via a proxy) and looks like this:

ssh -J proxyuser@proxy.mydomain.tld:56789 neth8user@neth8.mydomain.internal -p 54321 -fN -L 127.0.0.1:5550xx:neth8.mydomain.internal:443 -o ExitOnForwardFailure=yes
**And for Mac users add: open -W https://127.0.0.1:555xx**

56789 = ext. shh port (proxy)
54321 = int. ssh port (neth8)
555xx = dynamically generated, among others, by $(date "+%M")

Since the Lgin page opens, it’s probably not the command that’s causing it.

The note regarding name-based forwarding is of course correct, but the Nethserver 8 GUI does not use it.

As explained in Support team locked out of cluster-admin HTTP route · Issue #7436 · NethServer/dev · GitHub it should help to add the loopback device in the http route allow list.
Please also add another IP to access cluster-admin to not lock yourself out…

1 Like

This primarily concerns the NetServer 8 configuration. Anything that is supposed to be accessible externally, like SOGo, obviously doesn’t require an SSH tunnel.

For the cluster admin, it would, in my opinion, make more sense to simply make it accessible via other ports (even self-selected?). This gives them even more options for enforcing access rules via an (external) firewall. Blocking 443 externally would be counterproductive. Enforcing access rules (also) via a proxy (Treafik) is a nice additional option, but in my world, that’s more the job of a port-based firewall – which, of course, can also evaluate source and destination.

But a discussion about this has probably already taken place and been decided long ago.

I’ll quote myself from my inquiry:

Because this may not have been entirely clear:

Configuring via VPN isn’t a problem, but having multiple VPN connections open at the same time IS a problem (it only works to a limited extent or not at all, especially DNS resolution…).

Keep in mind: Some people have a VPN active by default to their home or company server, e.g., for open work files (SMB) or a KeePass password database. Opening one VPN for the network server configuration means closing another one – and thus losing access to the aforementioned files, for example.

Therefore, it is sometimes incredibly useful to do various things via SSH sessions or tunnels – including browser sessions to configuration interfaces.

Thanks for your suggestion anyway.

Thank you for your detailed description. But even a 127.0.01 entry in the “cluster-admin” http route doesn’t change anything.

When I look at the info page for this route, I at least find some interesting information:

http://127.0.0.1:9311

If I include this directly in my tunnel, I avoid the “/cluster-admin” path – and of course, I lose TLS (because that probably comes from traefik?), which makes the session on my side vulnerable.

But even if I try that anyway, I get the message “Websocket disconnected” after logging in.

Which somehow indicates that the problem probably has nothing to do with the traefik (because that doesn’t play a role with a direct connection?).

By the way, it’s not the browser (or its caches) either; I installed a completely new one, and it doesn’t change anything.

Got it.

Is there a firewall in front? Something which could handle several wg or openvpn (roadwarrior) connections?

My opnsense can easyly handle multiple different connections to my LAN.

You should still be protected by the SSH tunnel.

With Core 3.7.1 it should be fixed.

2 Likes

I’ve already marked this as a “solution” (after the core update to 3.7.1), but that’s only partially true:

Variant 1:
If the tunnel is routed directly to the source of the service “http://127.0.0.1:9311,” it works.

Variant 2:
If the tunnel is routed via the Traefik input of the service “https://127.0.0.1:443/cluster-admin,” the problem persists.

Both variants are encrypted through the tunnel, but variant 1 could of course be sniffed—albeit only locally. TLS variant 2 (Traefik input), on the other hand, would be protected from the browser to the Traefik input—as it should be.

One could argue that if an attacker can sniff packets locally, they could also intercept other browser inputs or even keyboard inputs in general – but there is still a difference: for variant 1, I have to allow the browser to use unencrypted connections, or I can’t generally prohibit them.

Perhaps someone can take another look at this from this perspective?

Regards, Yummiweb

After establishing the SSH tunnel using variant 1…

ssh -L 127.0.0.1:9311:ns8.server.com:9311 root@ns8.server.com

…I can’t sniff anything as it’s encrypted:

Listen on eth0 shows nothing as it’s encrypted.

tcpdump -Ai eth0 host ns8.server.com

Listen on lo shows cleartext passwords:

tcpdump -Ai lo

Using TLS in the SSH tunnel means double encryption.

1 Like

Try capturing from local Loopback…

1 Like

OK, maybe I’m making a mistake, so please correct me:

I’m setting up a tunnel locally, and my browser has to send requests to the entrance to allow them to pass through the tunnel.

If these requests aren’t TLS-encrypted by the browser, they go to the tunnel entrance unencrypted—right?

You’re right, I tried to listen on loopback again and can see a password in clear text. I corrected my previous post.
But I don’t think it’s a security issue as an attacker would need to listen on the local loopback device which needs root permissions.

Regards Yummiweb

I preferred the first version over this one because ns8.server.com is resolved to an IP with DNS on ns8 side.

Instead the following command does not rely on DNS to set up the tunnel destination, which may be unpredictable:

 ssh -L 8311:127.0.0.1:9311 root@ns8.server.com
  1. starts ssh client on your PC and make it listen on local port 8311
  2. if you connect on local port 8311 connection is tunnelled with encryption to ns8.server.com
  3. sshd on ns8 forwards the tunnelled data to 127.0.0.1:9311

Data is safely sent over the wire in a SSH encrypted tunnel. No clear text data can be intercepted.

Your browser connects to http://127.0.0.1:8311, which is a loopback address: no data is sent over the wire in clear text. It is as safe as your OS.


Edit: changed local port to 8311, to differentiate the local and remote ends of the tunnel

1 Like

As I’ve written several times now:

Loopback can also be read. If you think that’s irrelevant because an attacker would then have to be on the local machine anyway, fine.

But then I have to configure my browser to allow non-TLS connections again. I CAN do that, but then it could affect EVERY external connection. This removes an additional layer of security (or attention) - without it being necessary.

And I like to keep the browsers I use to configure servers as restrictive as possible. Don’t you?

An attacker on the local machine needs root privileges to sniff traffic on the loopback interface.

With root privileges they can steal your password straight from RAM contents, after it was decrypted from TLS, sent from the safest of browsers.

Double encryption is a waste of CPU cycles.

1 Like