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


2 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