Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to connect to the server behind NAT using mosh

Tags:

udp

nat

mosh

I'd like to connect to my server which is behind the NAT through mosh. I can't touch the router to set it as upnp support, but I've apply for a UDP port forward 9807->60000, and a ssh port forward of cause.

So, is there anyway to specified the server port through command line args or conf file at client and/or server side?

Note: the following not work!!

mosh -p 9807 user@my_server

Edit:

I've try to ssh to my server first, and run mosh-server -p 60000 manually, and then mosh -p 9807 my_server from another terminal. This cause an error:

Error binding to IP my_server_ip: bind: Address already in use

That said:

  1. the port forward is working.
  2. the mosh try to install the mosh-server at port 60000.

Thanks.

like image 711
Alsan Avatar asked Dec 18 '14 06:12

Alsan


People also ask

How do you SSH with mosh?

For Mosh to work, the server needs to have Mosh binaries installed. This doesn't run a daemon like sshd ; rather, it's the first command your Mosh client runs when connecting over SSH. When the connection closes, the server terminates the running Mosh server.

What is mosh terminal?

Mosh (mobile shell) is a remote terminal application that supports intermittent connectivity, allows roaming, and speculatively and safely echoes user keystrokes for better interactive response over high-latency paths.


2 Answers

The problem you're having lies in the port redirection. Your NAT forward at the router is sending incoming traffic sent to <domain>:9807 on to <internal-ip>:60000. When you start mosh with the -p option, the client connects to the server over ssh and tells the server to start, listening on the port specified. The mosh-server then communicates the open port number (in this case, the one you specified) back to the client, which closes the ssh connection and tries to connect to <domain>:<port>. The client is trying to communicate to the same port the server is listening on. The problem is that your NAT router is redirecting traffic from one port on the WAN side to a different port on the NAT'd machine. This will not work.

The best thing to do would be to get a direct translation, such as requesting the router forward port 9807 on the WAN side to your mosh-server machine at port 9807.

If that is not an option, the next best thing I can think of is to mangle the traffic on the server machine using iptables.

iptables -t nat -A PREROUTING -p udp --dport 60000 -j REDIRECT --to-port 9807

The execute your client as you describe

mosh -p 9807 user@my_server

What happens is:

  1. the mosh client on your machine opens an ssh connection (presumably forwarded to your machine through the NAT router) to your server, which executes mosh-server listening on port 9807.
  2. The mosh server exits, telling the client connected over ssh that the UDP port to connect to is 9807
  3. The mosh client closes the ssh connection and attempts to connect to the server at port 9807
  4. The NAT router sees this incoming traffic on port 9807 and sends it to your server at port 60000
  5. Your machine receives packets at port 60000 over UDP, which matches the iptables rule and get redirected to their destination (the server's IP, in this case), but at port 9807
  6. The client traffic's SRC port is unchanged by your NAT router, so mosh-server sends packets back out to your client at the port the client is listening on, which are received properly.
like image 70
MeanderingCode Avatar answered Oct 23 '22 14:10

MeanderingCode


Let me suggest the following proof-of-concept method of connecting to mosh server behind NAT. Lets say we have the following computers:

  • client_host behind NAT, from which we want to connect to mosh server
  • server_host behind another NAT, where mosh server is running. Note, that in this method client_host still need direct SSH access to server_host to start the mosh-server. ssh -R ... relay_host on the server may help.
  • relay_host which has publicly visible IP address and is controllable by us.

So we do:

  1. On relay_host install and run udprelay tool. It repeats everything it receives from one port to another and vice versa.
    relay_host> udprelay 0.0.0.0 34730 34731
    
    Port numbers mentioned above are hardcoded into the client script, but they could be easily changed. Also note, that udprelay is dramatically insecure at the moment.
  2. On server_host install mosh-nat-server.sh, just put it to any folder mentioned in PATH. Make sure that popular socat tool is also installed there.
  3. Finally, on the client, run mosh-nat-client.sh as follows
    client_host> mosh-nat-client.sh SERVER_SSH_NAME RELAY_IP
    
    This script calls server_host with ssh SERVER_SSH_NAME <mosh-nat-server.sh ARGS>, records the key and uses it to run the mosh-client. The tricky part of it is to punch a hole in server's NAT and let both sides met at udprelay.

See also a nice blog post describing a slightly different situation. In the above terms, it shows how to connect from relay_host to server_host. Author doesn't use udp relays but he still needs bulky LD_PRELOAD machinery. Surprisingly, it does it's job.

like image 34
grwlf Avatar answered Oct 23 '22 15:10

grwlf