Created Sunday 1/2/2004
▨ Todo: Needs textile formatting
▨ Note: CVS examples for accessing port 2401 from behing a firewall in cvs.
It's possible to forward ports on the local machine to ports on a remote server using ssh(1). The -L command of ssh allows for a target port on the remote server to be mapped to a different port on that same server.
This has obvious implications for client pc's that have ssh access to a particular server that run's services that are of interest. Examples of these include accessing a Perforce repository, running X11 applications and accessing database serices.
It is possib;e to access a perforce server running on a remote machine called perforce.com, by making an ssh tunnel from the client PC and requesting that the ssh daemon at the other end perform port fowarding of a given port to the perforce port.
If the server is listening for perforce requests on the standard port 1666, then we might ask that server to forward 4000 to 1666 on the localhost, by executing the command:
ssh -L 4000:localhost:1666 user@perforce.com
Any other ssh options such the userid and any special ports required to access the ssh daemon must also be given. After the ssh connection is established, the client simply sets the perforce server and port to localhost:4000.
Any request send to the localhost's port 4000 is picked up by ssh and dispatched off to the ssh daemon listening at the other end's port 4000, who then redirects these requests onto the normal perforce port 1666.
For neatness, it's possible to get the ssh client to not actually login and create a shell by asking it to perform some arbitraryily long command like sleep(1). This can be done with:
ssh -L 4000:localhost:1666 user@perforce.com -c "sleep 9999999&"
Another interesting part of ssh forwarding is the use of the -X switch, which tells ssh to foward all X11 requests back to the client. If the client is running an X-server, then it's possible to run an application under X on the remote machine and have it display on the client.
By default, X11 forwarding is done via port 6000 on the X display server (the client PC). The ssh client then connects to the remote machine and sets up the port forwarding there. The same process also sets the DISPLAY variable to point back to the forwarded port on the remote machine. To do this, use ssh's -X option, such as:
ssh -X foo@server.com
After login, the DISPLAY variable will be something like DISPLAY=localhost:14. X11 requests received on the localhost (which is the remote machine) will be forwarded back to the X display server (the client pc) on port 6000 by default. The client PC must be running an instance of X (via xinit or gdm or other).
Cygwin's X server works fine in this way too. Simply start a cygwin shell, run X via xinit (by executing "startx"), start another shell and login to the remote server with X11 forwarding, using the -X option and bob is your uncle.
It's possible to setup an ssh tunnel to avoid the hassle of having to go through a restricted ssh port on a machine that allows connections only from a specific host (assumeing of course access is available from the ssh client machine to this specific host). E.g., assume host transmission only allows ssh connections over port 2222 from host bund. In this case, a client 'gillian can access transmission'' directly by setting up the following tunnels:
▨ Note: This section assumes access to port 22 is available.
The cvs remote repository normally works over port 2401. If this is blocked, but 22 is open on the localhost and you have ssh access to a machine that has 2401 open, then the cvs remote commands and work via hopping over the blocked ports using the ssh tunnels, like this:
For example, the cvs repository for enlightenment is hosted on 2401 at cvs.sourceforge.net. To access this repository from blockedhost, do the following:
blockedhost $ ssh -L 2401:localhost:2401 user@openhost openhost $ ssh -L 2401:cvs.sourceforge.net:2401 user@localhost
Then operations on the cvs repository on "blockedhost" are directed at localhost, thus:
blockedhost $ cvs -d:pserver:anonymous@localhost:/cvsroot/enlightenment login blockedhost $ cvs -z3 -d:pserver:anonymous@localhost:/cvsroot/enlightenment co module
This should checkout the files in module from cvs.sourceforge.net using the several ssh portforwarded tunnels.
Many of the p2p chat programs use http tunnels to establish the communication socket on which to talk. However, some programs don't and go directly over the msn chat port (1863). If this port is blocked, or the http tunnel method of amsn doesn't work, then port forward the msn port 1863 to a host that does allow access over the msn port. The hostname to link the final phase of the redirect is 207.46.107.113 (which is baym-cs313.msgr.hotmail.com) and not messenger.hotmail.com. E.g.,:
on blockedhost: bash $ ssh -L 1863:localhost:1863 user@openhost
on openhost: bash $ ssh -L 1863:207.46.107.113:1863 user@localhost
or: bash $ ssh -L 1863:baym-cs313.msgr.hotmail.com:1863 user@localhost
Then in GAIM/AMSN configuration: set the connection method to direct so that it uses port 1863 (this option is available in amsn on the tools->preferences->connection tab. I think GAIM uses this port by default and so probably doesn't require an explicit configuation setting). Then specify the connect server as localhost:1863 (within AMSN, this is on the tools->preferences->advanced tab)
▨ Assumption: port 22 and 80 outbound are open on the blockedhost and we can ssh to a host that has the public port range open. In the following steps blockehost refers to the host with only 22 and 80 open and openhost refers to the host with the public port range open.
▨ Todo: Add sub-sections for the A,B,C sections and textile markup and to general cleanup
The gnutella network uses port 6346 by default, but the Gwebcaches open redirect to many other ports (7504, 4191, 6350, etc.). The easiest way to get arround the situation where outbound ports are blocked is to do the following:
▨ Note: The output in the following sections uses > for the mutella prompt and $ for the shell prompt. The shell prompt is prefixed by an example name where required.
Set up an ssh tunnel over the gnutella port 6346 on the blockedhost the same port on the openhost . In ssh terms, this requires forwarding the port from the host behind the firewall (the blockedhost) to the host outside the firewall (the openhost) using the unblocked ssh port 22. E.g.,
blockedhost $ ssh -L 6346:localhost:6346 user@openhost
▨ Note: This step requires mutella, download from mutella.sourceforge.net
In selecting a gnutella host, it is best to choose one with a high efficency. The best way to determine this is to use mutella on the host outside the firewall (i.e., on openhost). The mutella command info conn will list the active connections, displaying data about the connected hosts. From the displayed list, locate an entry that has a high efficiency and has a non-zero I/O Rate and a reasonable Horizon.
> info conn gnutella network connections: ----------------------------- no.| address:port | rate i:o | horizon | eff. | uptime 1) 81.241.61.34:7504 1.25K:5 2/128M 100% 2h25m 2) 68.13.81.226:6346 0:0 0/0K 0% 11s
From this, we see that the first (#1) entry is a good candidate. we remember this host ip and port
After selecting a host with high efficiency host, an ssh tunnel must be established by using the ssh port forwarding option. The tunnel will connect the the openhost to the IP and port selected in step #7.B, previously.
openhost $ ssh -L 6346:81.241.61.34:7504 user@localhost
On blockedhost, edit the hosts.save file, located in the $HOME/.mutella directory. Add the single entry localhost:6346
▨ Todo: Describe why this is necessary
The Web Cache entries on the blockedhost must be edited so that XXXX. This is done by editing the Gwebcache entries in the xx on blockedhost. These entries are in the $HOME/.mutella/webcaches.save file. Remove all entries that do not use the standard http port 80. E.g., an entry like http://goeg.dk/Gnutella/gcache.php is ok as it uses the default http port (80), but entries such as http://cache.kicks-ass.net:8000 (where the specified port is anything other than 80) should be removed.
Start the mutella app on blockedhost by running whatever startup script is appropriate. Typically this is done by simply running the command:
blockedhost $ mutella
A connection to localhost must be created. This is done using mutella's open command, which assumes port 6346 by default. Again, the > is the mutella prompt.
> open localhost
We have now forwarded port to 6346 on the blockedhost to the same port on openhost. The openhost port 6346 is then itself forwarded to (e.g.,) port 7504 on the host with IP address 81.241.61.34 (this is the host we determined as having high efficency in step #7B). This now means that we should see an active connection to a host in the gnutella network. We can determine if this is the case by excuting a connection information request by issuing info conn within mutella on the blockedhost. The list should contain one active entry that matches the stats of the gnutella host we selected in step #7C. The list will also contain a bunch of dead entries, which correspond to standard gnutella discovery (pointing to hosts and ports that we cannot reach as we did not forward to them):
> info conn gnutella network connections: ----------------------------- no. | address:port | rate i:o | horizon | eff. | uptime 1) 127.0.0.1:6346 389:1 51/3.19G 100% 2h43m 2) 68.90.79.91:6349 0:0 0/0K 0% 6s 3) 213.46.199.20:6346 0:0 0/0K 0% 6s etc.
After completing the preceeding steps, it should now be possible to access hosts on the gnutella network on a blockedhost, a host beind a firewall which has the gnutella ports (6436, 7504 etc.) blocked. As a test, perform a find on the gnutella network. For example,
> find 2pac
> list
Searches in progress, matching your criteria
1) `2pac'
no size filter HITS:256
count: 2
It's possible to forward udp ports over tcp using netcat, nc(1), Here's an example excerpt from from nc(1):
▨ Todo: Need citation as for why for tunnelling UDP over TCP is not good
Tunneling UDP over TCP is generally considered a bad idea netcat may be of use here? Something like this may work (warning: not tried and certainly not tested):
outside-firewall$ nc -l 2345 | nc -u localhost 1234 inside-firewall$ nc -l 1234 -u | nc outside 2345
Which should (in theory) connect UDP port 1234 on inside to UDP port 1234 on the outside, tunneling via TCP on port 2345. So instead of connecting directly to outside:1234 you can connect to localhost:1234.
▨ Assumption #1: The localhost has IP address 83.31.205.217
Services on hosts in the CU Polksa DMZ such as bumerang can be accessed by setting up several ssh tunnels. If the host that the tunnels are being created from is in the same geographic region (i.e, in Poland), then accessing services such as Perforce over these ssh tunnels is actually much faster than using the vpn the end-points of the service tunnel are connecting hosts that are a few hops away from each other. For the vpn, traffic must travel from poland to melbournce then up to poland then back again.
To setup the ssh tunnel, use the ssh(1) port forward (-L) and reverse forwarding options (-R). The script ssh-portfw(1U) does the port forwarding so long as reverse tunnel as been previously setup. The ssh-portfw uses the port specified in the variable ssh_tunnel_port as the port where the reverse tunnel has been created. The following interaction shows how to hop over specific ports on a firewall. The configuration in this example is typical of many commerical environments, where a user is allowed to login to a host, but is typically restricted to port 80 (http) and similar (imap and a few others).
▨ Assumption #2: All ports a blocked inbound including ssh 22 inbound. The user is already on blockedhost (i.e., on the internal network).
In this sequence, an ssh connection to bumerang, a host in the CUP DMZ is established. This is done by connecting to the Fluency GW, which is only possible if the connection is comming from one of a few well-known hosts, such as bund.com.au, from the Fluency GW, a connection to the CUP DMZ is possible via the Fluency-CUP VPN. The DMZ is located behind a CUP Firewall which is pretty much all inbound ports blocked but allows ssh outbound over port 22. We make use of ssh outbound over port 22 to create a reverse tunnel over port 2225, which is then used as the connect-to (inbound) port for setting up port forwarding for ports like Perforce (1666), Bugzero (8080), Oracle (1521) and etc. The forwarded ports are setup using the ssh-portfw script, which requires the existence of a reverse ssh tunnel. The ssh-portfw script uses the variable ssh_tunnel_port as the reverse tunnelling port, which has a default value of 2225. Be sure to specify a different value for this variable if the reverse tunnel is created on a different port.
somehost $ ssh foo@bund.com.au bund $ ssh -p 2222 foo@mel-gw.fluencyfinancial.com mel-gw $ ssh foo@bumerang bumerang $ ssh -R 2225:localhost:22 foo@83.31.205.217 somehost $ ssh_tunnel_port=2225 ssh-portfw
Other foonix™ documentation relating to port forwarding:
Stuart Moorfoot © 1 Feb 2004 foo@bund.com.au