Webmin is installed on the server that hosts this site and for the longest time I’ve been accessing it remotely through its default port at
https://tech-otaku.com:10000. Despite connections being encrypted through SSL and having two-factor authentication enabled in Webmin this still presents a security risk.
Remote Access to Webmin
Figure 1 shows applications on a local computer – client – sending requests to a remote host – server – and the appropriate applications on the server handling those requests and sending data back to the client applications. The server’s firewall blocks all incoming requests except to those ports that have been explicitly opened.
On the server, ufw will show which ports are open:
sudo ufw status
To Action From -- ------ ---- 10000/tcp ALLOW Anywhere 80/tcp ALLOW Anywhere 22/tcp LIMIT Anywhere 10000/tcp (v6) ALLOW Anywhere (v6) 80/tcp (v6) ALLOW Anywhere (v6) 22/tcp (v6) LIMIT Anywhere (v6)
The Webmin server – Miniserv – is listening for requests on port 10000. As port 10000 is open in the server’s firewall, any client requests on port 10000 will reach and be handled by the Webmin server rendering the Webmin login page accessible to anyone with Internet access.
Blocking Access to Webmin
The first step in securing access to Webmin is to close the port in the server firewall that the Webmin server listens on for client requests. We do this with
ufw by deleting the rule that explicitly opens port 10000:
sudo ufw delete allow 10000
Rule deleted Rule deleted (v6)
Figure 2 shows the client browser still sending requests on port 10000 to the Webmin server and the Webmin server still listening for requests on that same port. However, as port 10000 is no longer open in the server firewall, the Webmin server will never receive the client requests.
Webmin is – for now – inaccessible to everyone.
Accessing Webmin Through an SSH Tunnel
I’m going to provide access to Webmin by routing browser requests for it through an encrypted SSH connection between the client and the server and have these requests forwarded to Webmin. Figure 3 demonstrates this process:
The client establishes an encrypted SSH connection to the server on port 22…
…simultaneously opening local port 10005 on the client.
The browser no longer sends requests directly to Webmin on the server, but to local port 10005 instead.
All requests received on local port 10005 are then forwarded or tunnelled through the encrypted SSH connection to the server.
The server forwards the requests onward to the Webmin server on port 10000.
The advantage of this approach is the ability to limit Webmin access to only those users who can connect to the server via SSH. In addition, SSH provides an encrypted connection. Any plain text data being tunneled through it will benefit from that secure connection. This means that Webmin can be accessed over HTTP as the plain text data being sent to and from the Webmin server doesn’t need the encryption of TLS/SSL that HTTPS provides.
In general, on a macOS or Ubuntu Desktop client the command to establish local port forwarding through an SSH tunnel is:
ssh -p 22 user@host -L <local-port>:<remote-host>:<remote-port> -N &
More specifically, for the example in figure 3 the command is:
ssh -p 22 firstname.lastname@example.org -L 10005:127.0.0.1:10000 -N &
Please note the following:
-p 22does not need to be included in the command if the SSH server is listening on the default port 22. However, if it’s listening on say port 5522,
-p 5522would have to be part of the command.
127.0.0.1refers to a localhost on a
client, it took me a while to understand why it is being used for the
<remote-host>until I realised it’s viewed from the perspective of the server not the client.
&puts SSH into the background which is useful if you want to continue using the same Terminal window. I prefer this to the
-foption which is part of
sshas I find it easier to terminate the SSH tunnel having used the former option. On a Ubuntu Desktop client you may need to press enter to drop back to the command prompt after using
Having established the SSH tunnel and forwarded the local client port 10005 to the remote server port 10000, Webmin can be accessed from a browser using:
You may receive an error that Webmin should be accessed using
https:// instead of
http://. This is more than likely because SSL is enabled in the Webmin server configuration. You can continue by using
https://localhost:10005, but your browser will warn you that the connection is not private.
To disable SSL on the Webmin server we need to change
ssl=0 in the file
/etc/webmin/miniserv.conf on the server. To do this, on the server type:
sudo sed -i 's/^ssl=1$/ssl=0/' /etc/webmin/miniserv.conf
Then restart the Webmin server:
sudo systemctl restart webmin
Terminating the SSH Tunnel
When you’ve finished your Webmin session, it’s good practice to terminate the SSH tunnel. If you used the
& option when creating the SSH tunnel, from the same Terminal window type:
+ Running ssh -p 22 email@example.com -L 10005:127.0.0.1:10000 -N &
This will display any process running in the background each of which will start with a number in square brackets. Bring the relevant process to the foreground by typing:
ssh -p 22 firstname.lastname@example.org -L 10005:127.0.0.1:10000 -N
To end the process type
c and the SSH tunnel is no more.