Tunneling git through ssh (to get past a firewall): port specification interperted as relative path?

10,642

Why does it not work

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

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.

localhost:3333/path/to/repo.git

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 [email protected]: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.

Share:
10,642

Related videos on Youtube

Kristin
Author by

Kristin

Updated on September 18, 2022

Comments

  • Kristin
    Kristin over 1 year

    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?

  • Kristin
    Kristin over 7 years
    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?
  • user1686
    user1686 over 7 years
    Try the socks5h:// type in that case, or maybe socks4a://. That'll let the server do the hostname resolution, instead of the client.
  • Kristin
    Kristin over 7 years
    socks5h:// did it! Thanks for the help and detailed explanation.
  • eri0o
    eri0o about 5 years
    where should command from item 1 be ran? At serverA, B or on my pc?
  • user1686
    user1686 about 5 years
    @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).