Setup a reverse SSH tunnel to bypass NAT to Git daemon ad-hoc server

  23 Jan 2014


During project development, I need to serve my local Git repository for some working-in-progress works over the internet to my friend. (that is, with local commits that still not get rebased and don’t want to push etc.)

I have found there are at least 8 ways! that you can serve your git repo. The simplest and fastest way, though, is to use git daemon. If you and your friend sit in the same LAN, you should be fine to use git daemon

Just run this similar command git daemon --verbose --export-all --base-path=/path/to /path/to/project

Then your friend will be able to do git clone over git protocol git clone git://yourlaptop-ipaddress/project

Though, I and my friend sit on different network…

I usually sit behind NAT that I get private IP range (you might be familiar with 192.168.x.x, 10.x.x.x, 172.16-31.x.x)

If you are at home, you should be able to allow connection from the outside by setting up an appropriate port forwarding on your home NAT router to git daemon to work just like on LAN.

But, I (especially during this period) sit where my computer get private IP allocated by office or coffee shop router etc. that I don’t have an access to configure…that is life the way it is.

Then, look at other 7 possibilities I mentioned above, they seem a bit tedious and slightly overhead in order to set web server etc. to just make it work for your friends to clone your local repo. And there must be simpler way.

Luckily, we have such a powerful tool to setup a SSH tunnel \o/

Yes, you must have *nix box somewhere (these days, it is very cheap to have it DigitalOcean or EC2 for instance)

Traditionally, we do ssh -L to create a tunnel that is opened on our local port to the server.

This time, I would call it a reverse tunnel, we will use ssh -R to create a tunnel that is opened on SSH server and forward the connection to our local tunnel.

Let’s say, my laptop’s IP address (at home) is 192.168.182.251 (Unix box that your friend has to access, aka the running git server on port 9418). Your friend public IP is 171.7.199.166. (The git client that is needed to access the git server), and here is the senario (to access the dest from the src)

The problem:
                192.168.182.251   ++---++    171.7.199.166
               +-------+dest      ||   ||    src+---------+
               |  you  |<---------||NAT||-------| friend  |
               +-------+          ||   ||       +---------+
                                  ++---++
                              
The solution:          
              192.168.182.251   ++---++    171.7.199.166
             +-------+dest      ||   ||    src+---------+
             |  you  |<---------||NAT||-------| friend  |
             +-----+-+          ||   ||       +-------+-+
             127.0.0.1:9418     ++---++               |
                   ^                                  |
                   |                                  |
                   |                                  |
                   |         +------------+           |
                   |         |            |           |
                   +---------+unix server |<----------+
                             |            |:9418
                             +------------+
                               162.242.226.5
  1. Serve your git repository with git daemon as I mentioned above, run this command on 192.168.182.251 machine.

    git daemon --verbose --export-all --base-path=/path/to /path/to/project

  2. Create a remote tunnel on the unix server that is listening connection on port 9418 at the remote unix server ip 162.242.226 and redirect all transmission data to loopback interface on port 9418 where the git server is listening to.

    ssh -R 162.242.226.5:9418:127.0.0.1:9418 zdk@162.242.226.5

This should work.

  • Though, I get “Connection refused”. So, I have to configure sshd. Open /etc/ssh/sshd_config file with a text editor. Then set

    GatewayPorts yes

(Please check further details for more possible values to set for GatewayPorts)

  • Run following command to check if the service is listening on an appropriate port:

    netstat -ntl
    

If you see 0.0.0.0:9418 in local address, you will see the light :)

Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 0.0.0.0:9418            0.0.0.0:*               LISTEN     * Try to clone the project from the unix server address
  • Now your friend should be able to clone the project on 171.7.199.166 machine, git clone git://162.242.226.5/project
    If you see a message like this

      Cloning into 'project'...
      remote: Counting objects: 480, done.
      remote: Compressing objects: 100% (342/342), done.
      remote: Total 480 (delta 207), reused 259 (delta 110)
      Receiving objects: 100% (480/480), 418.77 KiB | 59.00 KiB/s, done.
      Resolving deltas: 100% (207/207), done.
      Checking connectivity... done
    

That is a paradise message. Therefore, it is now time to party!

comments powered by Disqus