Mosh through your own relay
Mosh (mobile shell) is the remote terminal for people who close the lid.
Your session survives sleep, a change of wifi, a train tunnel, and a laggy
link, because instead of one long TCP connection it sends small encrypted
UDP datagrams and lets either end roam. If you have used it once you do not
go back to a plain ssh session on a laptop.
It also does not work through tunnel products, and never has. Those products forward TCP: ngrok offers no UDP endpoint at all, and Cloudflare Tunnel carries UDP only to a device running its own client. Mosh through them connects, prints nothing, and hangs. Tailscale is the exception, because Tailscale is a network rather than a tunnel, and UDP simply routes.
As of today 1lan carries mosh, with nothing but the OpenSSH tunnel each machine already holds.
What we did
Mosh has two phases. The first is plain SSH: connect, start mosh-server,
read back a port and a key. That already worked through 1lan, because
ssh fred.example.com already worked. The second phase is the point: the
client drops SSH and sends its own encrypted datagrams straight to that port,
from whatever address it has at the moment. OpenSSH reverse forwards carry
TCP only, so those datagrams had nowhere to go.
So a small daemon on the relay listens on a block of public UDP ports that
belong to one machine, frames each datagram, and writes it down one TCP
connection into that machine’s tunnel. A matching agent on the machine
unframes them onto 127.0.0.1, where mosh-server is listening. Replies
go back to whichever address last spoke on that port, which is what makes
roaming work.
Two details made it small. The registry already allocates each machine its own loopback address on the relay, and pins the machine’s key to it, so the carrier connection needed no new authorization: it lands on an address the machine already owns. And the same port number is used on both ends, so nothing has to parse or rewrite mosh’s connect line. The user runs:
mosh --experimental-remote-ip=local -p 61000 you@fred.example.com
The one flag tells mosh to send to what the name resolves to, the relay, rather than to the loopback address the far sshd reports. A shell alias hides it.
What we tell you plainly
The lossy leg gets real UDP. Between your laptop and the relay, where the wifi is bad and the address changes, the datagrams are native, and mosh does everything it is famous for. Between the relay and your machine they ride the SSH tunnel, which is TCP, so heavy loss on that leg would stall them in order. That leg is the colo uplink, the most stable hop in the path, and in our own use you cannot tell. But it is a difference, and a product page that hid it would be a product page you should not trust.
The relay still cannot read your session. Mosh encrypts its datagrams end to end, and both the relay and the tunnel forward ciphertext. The property we lead with survives.
And one nuisance we accepted rather than solved: the relay updates a port’s reply address on any inbound datagram, because it holds no keys and cannot tell you from someone spoofing your port. They read nothing and inject nothing, and your next packet takes the path back. Sustained spraying is a denial of service against one session, the same class of thing as flooding the port. It is written in the design notes, where you can check it.
What it cost
One day. Two daemons of about a hundred lines each, a registry field, a
generator, a test that runs both halves in one process and proves a machine
cannot answer on a port it does not own, and a rehearsal on a throwaway
relay with a real mosh-client and mosh-server on two hosts before it
touched the production relay. The whole thing is in the 1lan repository
under docs/mosh.md, caveats first.