While Mosh excels at maintaining connections over unstable networks, its UDP nature makes tunneling through intermediate hosts more challenging than SSH. The core issue lies in establishing end-to-end UDP connectivity when you need to traverse multiple network segments.
The traditional SSH proxy method works well because TCP is easily forwarded. Here's the standard config:
Host jump-host
HostName dmz.example.com
User admin
Host internal-server
HostName 10.0.1.5
ProxyCommand ssh -W %h:%p jump-host
For a quick solution, you can chain Mosh through SSH:
ssh -J dmz.example.com internal-server "mosh-server new -c 256 -s -l LANG=en_US.UTF-8" | \
grep "^MOSH CONNECT" | \
while read -r _ _ port key; do \
mosh-client "127.0.0.1" "$port" "$key"; \
done
For a more permanent solution, consider these components:
- Setup autossh on the DMZ host to maintain reverse tunnels
- Configure systemd to keep mosh-server running
# /etc/systemd/system/mosh-tunnel.service
[Unit]
Description=Mosh Tunnel Service
After=network.target
[Service]
User=moshuser
ExecStart=/usr/bin/mosh-server new -i 127.0.0.1 -p 60000:61000 -- daemon
Restart=always
RestartSec=60
[Install]
WantedBy=multi-user.target
For complex scenarios, socat can bridge UDP across hosts:
# On DMZ host (listens on UDP 60000, forwards to internal server)
socat UDP4-LISTEN:60000,fork UDP4:internal-server:60000
# Local client connects to DMZ host
mosh-client dmz.example.com 60000
- Always use SSH encryption for the initial connection
- Restrict mosh-server ports with iptables
- Consider VPN alternatives for high-security environments
For better performance over proxy chains:
mosh --predict=always --ssh="ssh -J dmz.example.com" internal-server
When working with networks that have DMZ configurations, establishing reliable terminal connections often requires creative tunneling solutions. While SSH has well-documented proxy capabilities through ProxyCommand
and -J
(JumpHost) options, Mosh presents unique challenges due to its UDP-based architecture and connection handshake requirements.
Unlike SSH's TCP connections, Mosh operates over UDP with these distinct phases:
- Initial TCP handshake (via SSH)
- UDP port negotiation
- Persistent UDP connection with state synchronization
Method | Pros | Cons |
---|---|---|
SSH ProxyCommand | Simple configuration | Only works for SSH phase |
SSH-to-Mosh Bridge | Partial Mosh benefits | Not true end-to-end Mosh |
Mosh Relay | Full Mosh functionality | Requires persistent server |
For true end-to-end Mosh connectivity through a DMZ host, we need a persistent relay. Here's how to implement it:
# On DMZ server (server-in-dmz)
# Create a systemd service to keep mosh-server running
cat > /etc/systemd/system/mosh-relay.service <
Combine SSH port forwarding with Mosh connection:
# Local SSH config (~/.ssh/config)
Host server-behind-firewall
ProxyCommand ssh -W %h:%p server-in-dmz
# Connection command
mosh --ssh="ssh -J server-in-dmz" server-behind-firewall
For networks requiring strict UDP forwarding:
# On DMZ server
socat UDP4-LISTEN:60001,fork UDP4:server-behind-firewall:60000 &
# On local machine
mosh --client=60000 --server=60001 user@server-in-dmz
- Verify UDP ports (60000-61000) are open
- Check
mosh-server
logs withjournalctl -u mosh-relay -f
- Test basic connectivity with
nc -u
between hops - Consider using
autossh
for maintaining SSH tunnels