2

I know how to use a remote CVS repository where access to the remote server is through SSH.

Here's my problem: the remote CVS server, call it "A" is accessible by SSH only from computers within the same subnet. There is one computer "B" on the subnet that has SSH open to the world. (Don't ask why; I'm not the administrator.) I can SSH into "B", and then from there SSH into "A" where the CVS repository is.

My home PC is not on the same subnet as "A" and "B". Is it possible to access the CVS repository on "A" through my SSH connections between my home PC and "B" and between "B" and "A"?

  • Without hosting another CVS repository on "B".
  • And without checking out on "B" and synchronizing my home PC with that check out.

3 Answers 3

3

Quack's answer is a good start, but it has two problems. Thus I'll try it too:

You first have to create a tunnel from your local workstation to the SSH port of machine A. This is easily done from the command line:

ssh -L 127.0.0.1:2200:A:22 B

(ssh to B and create a tunnel from the localport 127.0.0.1:2200 to the remote port A:22)

Because CVS doesn't allow you to specify ports when using the :ext protocol, this simple command line will not be good enough. What you need to do instead is create or modify your ~/.ssh/config file:

Host B
   LocalForward 127.0.0.1:2200 A:22

Host tunnel2a
   Port 2200
   HostName 127.0.0.1

These are two entries. The first one tells ssh to create a tunnel whenever you ssh to B. The second one defines the new 'hostname' tunnel2a that you can use for cvs.

First, open the tunnel by ssh'ing to B:

ssh B

CVS should now work like that:

cvs -d :ext:username@tunnel2a:/cvsroot/ checkout someModule
2
  • 1
    terrific, manni, thx for the corrections. personally i wouldn't include that host entry for "B"; i'd name it "Btunnel" maybe and point it to "HostName B". that way i'd only get the tunnel on ssh Btunnel and not on every ssh B. otherwise +1. Nov 25, 2009 at 15:46
  • Cool. I didn't know about automatically setting up tunnels through the config file. Thanks. Nov 25, 2009 at 17:39
1

You should be able to do this through SSH tunnelling. I don't have 3 machines to test with, but if I understand the process right, you want 2 terminal windows.

In the first, SSH to "B" with this option: -L 1234:A:22. This will add a tunnel between the localhost, at port 1234, through machine "B", to machine "A", at port 22 (the SSH port).

The CVS command I originally wrote doesn't work, since CVS doesn't support ports in the :ext: format as I had written. If using a GUI IDE or CVS client, it may allow you to input an alternate port directly. If doing this with the commandline client, you'll need another route -- adding a host alias to your ~/.ssh/config file with the correct port. Manni's answer gives a great example for how that's done, so I won't reproduce that here.

By aiming at port 1234 on localhost, you'll hit the SSH tunnel and get routed to the SSH port on A.

You might want to check the answers to some related questions about SSH tunnelling. Thanks Manni for helping me beat these instructions into shape.

In the second terminal, run your CVS checkout command, but substitute localhost:1234 for A:

cvs -d :ext:username@localhost:1234:/cvs checkout test
# instead of
# cvs -d :ext:username@A:/cvs checkout test

6
  • Awesome! Thank you. I had a hunch that tunneling was part of the answer. I don't know if your cvs command is right, but I setup the tunneling and then pointed the CVS client in the Eclipse IDE to use extssh connection to localhost port 1234, and the repositories on "A" showed up. Smooth as butter! Nov 25, 2009 at 7:28
  • 1
    This is almost right, but not quite. You don't want the new port on B where it would be accessible to the whole word. You want the port on your local workstation's localhost. ssh -L will do exactly that and thus you need to change the cvs command line because cvs needs to connect to localhost and not to B.
    – innaM
    Nov 25, 2009 at 7:36
  • 1
    Oh. And additionally, CVS doesn't allow ports to be specified when using SSH. Duh.
    – innaM
    Nov 25, 2009 at 11:01
  • fair points. i'd assume the B->A tunnel wouldn't bypass standard SSH security measures, so it's not horrible. but i said it wrong; my instructions do create the port on the localhost, so B:1234 really should be localhost:1234. oops. (i'll have to take your word for CVS-not-allowing-ports, since I don't use it.) Nov 25, 2009 at 15:33
  • tho i did find lots of messages around the net that mention the same trouble and same solution (cvs-over-ssh via alternate port): see for example lists.freebsd.org/pipermail/freebsd-questions/2006-April/… Nov 25, 2009 at 15:41
0

Having had trouble with innaM's answer, even though it is spot on, and not repeated here, perhaps some additional information could help the odd user having trouble implementing the answer.

  • In the case of difficulty, be sure to experiment with the ssh and cvs commands on the command-line before going to the point of adding the configuration for the LocalForward in the config file. Editing the config file early can be discouraging if anything about a particular setup is slightly different than the answerer's environment.

  • One of the first problems one can encounter is rare, but crucial. It is of paramount importance to know the correct location of the config file. In most cases, the correct location is ~/.ssh/config / ${HOME}/.ssh/config, but, sometimes it is not. The correct config file location is required to solve this problem even when experimenting from a command-line. See also: ssh is no longer using ~/.ssh/config

  • There is also the potential of running afoul of permissions issues. It is usually safe during troubleshooting to set both the .ssh folder and the config file read-only for the user (i.e. chmod 600) though it is not necessarily required that the permissions are quite this tight. In any event, the folder and file should not be writable by other users.

  • There is also the matter of setting CVS_RSH properly. Even if the ssh environment is set up properly, the final cvs command will fail with a very unhelpful message if CVS_RSH is not properly prepared.

    CVS_RSH=ssh; export CVS_RSH
    

    Without CVS_RSH, the cvs command is likely to return:

    -l: bad option(s)
    cvs [... aborted]: end of file from server (consult above messages if any)
    
  • It is not necessary to have two shells open to work with the tunnel. innaM's answer says to set up the tunnel with:

    ssh B
    

    This leaves you with a shell open on B, and not on the local workstation. It is not necessary to have a shell open on B. One can work entirely within a single shell by setting up the tunnel with:

    ssh -fN B
    

    This command leaves you at the local system prompt rather than at a B prompt. The caveat is that in the case of ssh B it is possible to tear down the forwarding by simply logging off of B, whereas in the case of ssh -fN B the ssh process is in the background and must be killed by other means to tear down the forwarder.

  • When multiple systems require alternate port numbers, adding a Port option to the applicable config Host section is viable.

  • Bear in mind that the config file may specify User in Host sections when user names vary from system to system.

    Another potential pitfall may occur in cases where user names are improperly specified. While it is often correct and proper to specify system user names as user@hostname, DO NOT use this notation in the config file or in the ssh -L parameter. For example, this will go horribly wrong and may be very difficult to unravel:

    ssh -L 2200:Auser@A:22 Buser@B
    

    (This is never necessary CVS usage since Auser@ is specified with cvs -d :ext:Auser@A:/path/to/repository.)

    While is it perfectly acceptable to specify Buser@B, Auser@ must not be specified this way on either a command-line or in the config file. A cvs command issue with an incorrect command like this may return something like:

    ssh_exchange_identification: read: Connection reset by peer
    cvs [checkout aborted]: end of file from server (consult above messages if any)
    

    Debugging can be difficult, and can result in other inexplicable messages like:

    SSH Tunnel: channel 3: open failed: administratively prohibited
    

    The problem is that when used with -L or LocalForward, Auser@ becomes part of the host name (or IP address) so it does not resolve to the expected IP address.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .