I have access to server A via ssh, and from server A can access server B, which runs gitlabs and contains the repository I need access to. When I am ssh'd into server A, I can run git clone http://serverB/path/to/repo.git successfully. Using ssh:// or git:// instead of http:// does not work. (Errors are "does not appear to be a git repository" and "unable to connect to serverB," respectively.)

If I set up a tunnel like this:

ssh username@serverA -L 3333:serverB:80 -N

The following two attempts at git clones fail:

git clone http://localhost:3333/path/to/repo.git

Fails with: "fatal: repository not found"

git clone localhost:3333/path/to/repo.git

Prompts me for my password for serverB, and then fails with "fatal: 3333/path/to/repo.git does not appear to be a git repository." Of course, it isn't! My attempt at specifying localhost, port 3333, is clearly being interpreted as a relative path on serverB.

Is there a way to fix this? Is something fundamentally wrong with this approach?


Why does it not work


This fails because the URL's hostname is different (localhost vs server2), and as a result the server uses a different configuration.

All HTTP clients send the requested hostname to the server, and the server may choose from several configurations (virtual hosts) based on that name. This is how many websites (often hundreds) can share the same IP address at a hosting provider.


This fails because it's not an HTTP URL, or in fact any URL at all. (Git is not a web browser and doesn't assume http:// by default.)

Instead it's an rcp-style SSH address in the form [user@]host:path. You might have seen it earlier as git@github.com:foo/bar.git, where the ssh@ prefix is really just a SSH username.

Git treats it as equivalent to ssh://[user@]host[:port]/path URLs, except the rcp-style addresses do not have a port field at all.

What to do

curl, the HTTP client used by Git, supports SOCKS proxies as provided by ssh -D dynamic tunnel.

  1. Set up a dynamic (SOCKS) tunnel with:

    ssh username@serverA -D 1080 -N
  2. Configure Git to use it as a proxy:

    Globally (or per-repository):

    git config [--global] http.proxy socks5://localhost:1080

    For a single command:

    git -c http.proxy=socks5://localhost:1080 clone http://serverB/repo.git

The socks5 and socks4 protocols perform DNS resolution on the client side, while socks5h and socks4a pass all hostnames through SOCKS to the SSH server.

  • When I try this, I get "Could not resolve host: serverB". But, I can access this same serverB URL via a web browser, using foxyproxy and the SOCKS tunnel created in (1.) Any ideas? – Kristin Aug 25 '16 at 21:43
  • 1
    Try the socks5h:// type in that case, or maybe socks4a://. That'll let the server do the hostname resolution, instead of the client. – user1686 Aug 26 '16 at 9:36
  • socks5h:// did it! Thanks for the help and detailed explanation. – Kristin Aug 26 '16 at 16:23
  • where should command from item 1 be ran? At serverA, B or on my pc? – eri0o Mar 20 '19 at 11:46
  • @eri0o: You run this on the same computer that you'll be running the Git commands on. So usually you run it on the local computer and it connects to serverA (like regular ssh). – user1686 Mar 20 '19 at 11:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.