How to Establish a Multi-Hop Mosh Tunnel via SSH Proxy for Firewall Bypass


13 views

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:

  1. Setup autossh on the DMZ host to maintain reverse tunnels
  2. 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:

  1. Initial TCP handshake (via SSH)
  2. UDP port negotiation
  3. 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 with journalctl -u mosh-relay -f
  • Test basic connectivity with nc -u between hops
  • Consider using autossh for maintaining SSH tunnels