Anyone who works with Linux servers will have used SSH. It’s the stable of server management and cannot beat a GUI.The only downside with SSH is when you’re on a slow or intermittent connection, and your SSH connection keeps droppingout or locking up. It’s not fun at all…
Enter Mosh. Mosh replaces SSH and allows connections to disconnect and lag without affectingthe user. It doesn’t lock up, and tells you when you’ve lost server connection – so you know what’s going on.When it gets connection back, so do you. It runs in the local account on both sides of the connection, which meansyou don’t need an extra service running, and any user on the machine can use it. SSH is used for the initialauthentication, so all your password, keys, and port forwards will still work.
Mosh has one downside: it uses a unique UDP port for each connection, and by default expects UDP ports 60000 - 61000
to be open and ready to be used. It doesn’t reserve them, it just uses them when it needs to.From a security point of view, this isn’t good. It’s not that I think Mosh has security vulnerabilities, but if Iopen up those 1,000 ports on my server – anything else on the server can pick one and bypass my firewall…which is bad.
So, what can we do about it?
Since I use UFW as my firewall of choice on a Ubuntu server, I decided to see if I could write a script thatautomatically opens the ports that Mosh needs when it needs them, and closes them again when it’s finished.
Something like this should do the trick:
What the script does is quite simple:
- It checks what ports are open for
mosh-serv
(line 4). - Loops through each of the open port numbers (line 8).
- For each port, it checks if the port is allowed in UFW (line 10).
- If it’s not, then it allows it (line 13).
- Then it loops through each of the UFW allowed ports (line 18).
- Checks if there is a
mosh-serv
process that has it open (line 23). - If not, it closes the port through UFW (line 26).
The result is that only the active Mosh ports are open.
This could be run via cron every minute, but you’d need to get lucky when starting a Mosh connection, so it’s farbetter to run it on each user login. However, there is a problem with this… notice the sudo
commands?The user doesn’t want to type their sudo password on each login, so we need to get creative here.
Save the script somewhere global, such as /usr/local/bin/mosh-allow-ufw
, and then add a line into /etc/sudoers
:
valorin ALL=(ALL:ALL) NOPASSWD: /usr/local/bin/mosh-allow-ufw
Follow it up with an entry into your ~/.bashrc
file, which will trigger it on each login:
sudo /usr/local/bin/mosh-allow-ufw
In theory, you should now be able to Mosh into a server, and the server will automatically open the ports,and then Mosh will run. The only open ports will be those in use by Mosh.Rather than 1,000 ports open, we will only have one per connection.
Finally, to sum it all up, and because I am a big Ansible fan, we can automate the entire process.
There we have it: Mosh and UFW, without needing 1,000 ports open! 🙂
4 replies on “Mosh and UFW, without 1000 open ports”
Hi Stephen,
thanks for this blogpost – and the idea of your script. It is really a nice one!
Currently, I’m trying to get this script running on an Ubuntu 20.04 – with the `sudo /path/to/script` within /etc/profile, /etc/bash.bashrc and even ~/.bashrc for my user … but it seems they are not executed when the Mosh-Connection is created.
Where did you find the information, where to put this script? Does it still work with your setup and current Linux versions?
I didn’t get the needed information from Mosh documentation =(
Thanks for your suggestions and help =)
Best,
Martin
I haven’t used the script for a few years, so I’m not sure if it works on 20.04 or not. (I stopped using Mosh a few years ago when I changed around how I used my servers.)
I do know they’ve changed a bunch of the structural things (systemd maybe?) in Ubuntu over recent years, so it’s possible those files now operate in a different way to how they used to and it no longer is triggered correctly. Or Mosh may have changed something?
Sorry I couldn’t be more help.
i noticed that after ubuntu 14, this script stopped working for me. i thought it was maybe due to it being a non interactive login, maybe. the simple solution i used was to specify the –server command. the –server command is the command that gets executed when ssh connects, and the default is mosh-server. so i just added to that by specifying:
mosh –server=”mosh-server && sudo /usr/local/bin/mosh-allow-ufw”
i created a mosh alias in my zshrc and now so i dont have to type it anymore. add to your .bashrc (or .zshrc) on the machine you are connecting from.
alias mosh=’/usr/local/bin/mosh –server=”mosh-server && sudo /usr/local/bin/mosh-allow-ufw”‘
Thank you, Stephen, for the script. Really a must-have! And thank you Valerie for the tip about –server.
Strangely, I can’t pass tmux as command when using –server parameter (it always init a regular login shell), but I can live with it.