cvstunnel - Transparently communicate with a CVS pserver behind a firewall through an ssh(1) tunnel
For several tunnels:
ln -s cvstunnel cvs-t1 # cvs-t1 must end up in your PATH ln -s cvstunnel cvs-t2 # etc. cvs-t1 [login|checkout|update|...] cvs-t1 commit -m 'Log message' ...
or even
ln -s cvstunnel cvs-t1 # cvs-t1 must end up in your PATH ln -s cvstunnel cvs-t2 # etc. alias cvs=cvs-t1 # csh: alias cvs cvs-t1 cvs [login|checkout|update|...] cvs commit -m 'Log message'
For just one tunnel:
# no need for linking alias cvs=cvstunnel # csh: alias cvs cvstunnel cvs [login|checkout|update|...] cvs commit -m 'Log message'
cvstunnel is a wrapper around cvs(1) that tunnels all the cvs traffic through an ssh(1) tunnel.
Tunneling is required if either the local machine (where you run the CVS commands) does not allow outgoing traffic on port 2401, or if the CVS server does not allow incoming traffic from external networks -- both scenarios are typically due to somewhat paranoid firewall settings.
cvstunnel tries to be as transparent as possible, while at the same time ensuring to close down the tunnel when it is no longer needed.
In order to use cvstunnel, you need to set up some command aliases in in your ~/.cvstunnel file, see CONFIGURATION below.
To be more specific, consider the following situation: You are working on host local and want to connect to a CVS server server, but a stupid firewall keeps you from doing so directly. However, you can ssh(1) to a server gate which can access the CVS server (because it is outside your local firewall and/or behind the server's firewall; often gate will be the same as server). So the connections used by cvstunnel are
local <--ssh (port 22)--> gate <--cvs (port 2401)--> server .
If you only work with one server, you should configure the name `cvstunnel' (see section CONFIGURATION), alias cvs to cvstunnel, and use the command `cvs' (which is now in fact an alias) as you always did:
alias cvs=cvstunnel # csh: alias cvs cvstunnel cvs [login|checkout|update|...]
If, on the other hand, you need to tunnel to different servers, you can configure cvstunnel such that it tunnels to one server when called as cvs-t1 and to another when called as cvs-t2 (where cvs-t1 etc need to be configured, see section CONFIGURATION):
ln cvstunnel cvs-t1 # cvs-t1 must end up in your PATH ln cvstunnel cvs-t2 [...] cvs-t1 [login|checkout|update|...] cvs-t2 [login|checkout|update|...]
You can still alias cvs
to one of the cvs-tX
commands, but probably
you should do that just temporarily when you are working in a given
repository.
Make sure that you use the right cvs-tX
command for a given directory
because the local cvs command believes it interacts with a local server
in both cases and cannot distinguish between the two [this could probably
be overcome using different ports as supported by recent CVS clients].
You can have as many links of cvstunnel (and gateway--host combinations) as you like.
The tunnel will remain up for 30 seconds by default, and it will (most
likely) not close while there is traffic through it.
The time limitation is to minimize damage if the ssh subprocess is not
shut down when cvstunnel quits.
If 30 seconds is too short (or too long), you need to adjust the
parameter $ssh_sleep
in the Perl code.
All options are passed on to cvs.
cvstunnel tries to read configuration for connection names from /etc/cvstunnel and ~/.cvstunnel, in this order (i.e. the user configuration overrides the system-wide configuration). A sample configuration file for several CVS hosts looks like this
# .cvstunnel -*-mode: default-generic-*- # # Configuration file for cvstunnel(1). # Name cvs-t1 Gate gate1.to.circumvent.firewall Pserver cvs.server1.net
Name cvs-t2 Gate gate2.to.circumvent.firewall Pserver cvs.server2.net
Name cvs-t3 Gate gate3.to.circumvent.firewall Pserver cvs.server3.net
The Name parameter sets the name under which cvstunnel is called.
So if you call a link cvs-t2 -> cvstunnel
, the settings associated
to that name will be applied, i.e. the tunnel is opened through
gate2.to.circumvent.firewall to cvs.server2.net.
If you have just one CVS host to connect to, the configuration file reduces to
# .cvstunnel -*-mode: default-generic-*- # # Configuration file for cvstunnel(1). # Name cvstunnel Gate gate.to.circumvent.firewall Pserver cvs.server.net
cvstunnel will adapt CVSROOT to using localhost as CVS host.
E.g. a CVSROOT of :pserver:toto@remote.server.net:/path/to/repo
will
be mapped to :pserver:toto@localhost:/path/to/repo
before running
cvs.
Since this mapping is done via CVSROOT, it is overridden by cvs's -d option, so the idiom
cvs -d $CVSROOT co <module> # don't..
(in case you have a CVS/ subdirectory that overrides your current CVSROOT) will not work if CVSROOT refers to remote.server.net; you need to explicitly adapt the -d option:
cvs -d :pserver:toto@localhost:/path/to/repo co <module>
Set this variable to 1 to get debugging output.
Configuration files.
Wolfgang Dobler <Wolfgang [.] Dobler [at] kis.uni-freiburg.de>
cvs(1), ssh(1), perl(1).
Running cvs commit
through cvstunnel is quite a challenge if you
have to type the log comment in vi.
This is because cvstunnel captures the output from cvs and thus vi
only gets the keyboard input when you press enter.
If you are an experienced vi user, you can fare OK by not looking at
the screen while typing the log comment.
If you are not, you should rather use
cvs commit -m <log message>
and type the log message at the
command line.
[I currently do not know (and am too lazy to check) how well this works with a graphical CVSEDITOR; maybe the problem disappears altogether, maybe it will just not work at all.]
.. on the other hand, you cannot use single quotes in log messages with the -m switch.
If two users are using cvstunnel at the same time (or if a tunnel should fail to get closed), one of them will not get anywhere because the process listening on port 2401 is owned by the other.
There ought to be (but currently is not) an option that allows the user to choose the port for the connection from A to B, which would allow circumventing this problem. This is however not as trivial as it may seem, since the port number gets stored in CVS/Root.
If both cvs and ssh ask for a password, you are in trouble, as they will compete for your keyboard input. Try setting up passwordless ssh, (or use ssh's recent ControlMaster feature), or using cvstunnel will be no fun anyway.
If you cannot avoid this situation, you can adapt a valid ~.cvspass
entry for the server by replacing the host name by `localhost', and then
manually add this line to your local ~/.cvspass file to avoid
running cvs login
at all.
The timeout is currently hard-coded in the Perl code, so to change it
users have to edit the source, which is bad, and also makes the time-out
the same for all connections.
It would be way better to have a (global or per-name) Timeout
parameteri
in the configuration file.
You must be kidding... Anyway, please send bug reports to <Wolfgang [.] Dobler [at] kis.uni-freiburg.de>.