Hack 97. Run Two Services on a Single TCP Port


Reuse your precious ports simultaneously.

It is a well-known trick to use the HTTP CONNECT method to politely ask a web proxy to open a specific port on a specific machine on the Internet. This is how many people manage to connect back to their SSH server at home. SSH clients such as PuTTY know how to go through web proxies using this technique.

However, your company security administrator may have configured the proxy to only allow port 443[8] for outgoing CONNECT requests. Well, you can easily set up your SSH server so that it listens on both 22 and 443 ports:

[8] The standard port for HTTPS.

# sshd_config file Port 22 Port 443

What if you also run a HTTPS server on this machine? There is no way for you to contact it outside port 443 (due to the security policy) and besides, everyone else using the service at https://home.example.com/ uses port 443.

You have one port and two services. Do you really have to abandon one of them?

The Hack

You need some kind of proxy, or rather, reverse-proxy sitting on port 443 at home.example.com that can tell the difference between a SSL connection and a SSH connection.

Using a tool such as Ethereal, it's quite easy to notice the differences between the two protocols by looking at the first few packets of data exchanged. The SSH server packets look something like:

SSH-2.0-OpenSSH_3.9p1

while the client resembles:

SSH-2.0-OpenSSH_4.2p1 Debian-5

Then they both negotiate the cyphering protocol and everything else. HTTP over SSL looks different. A common session might be:

Client: ....s...o......$.@]w#.U!..F.(.h..^.#y....D....[/.x.=...."..w.4.. Server: ....J...F..C.B.....y..cY.}s......h\\.qo.......9..8.i.|..7..

Here it's unreadable garbage from the beginningbut did you notice the difference?

When using a protocol like SSH, the server always speaks first, and sends a banner to the client. When using HTTP over SSL, it's the client that speaks first.

Now you have a way to discriminate between the two services: once a client has connected to the reverse-proxy's port 443, if it immediately sends data then it's an SSL client; if it does nothing and waits for data to be sent by the server, then it's a SSH client. The reverse proxy can wait for a short timeout before deciding which of the two services to contact. With the connection established, it can start its proxy work and send data back and forth between client and server.

In 2003, Philippe "BooK" Bruhat wrote a 160-line script that did just that. Nowadays, all the necessary logic to write a network proxy is in a module aptly named Net::Proxy. Creating a reverse proxy to serve both HTTPS and SSH on port 443 of your home machine is now a handful of lines of code away:

#!/usr/bin/perl use strict; use warnings; use Net::Proxy; # show some information on STDERR Net::Proxy->set_verbosity(1); # run this on the server that should listen on port 443 my $proxy = Net::Proxy->new(     {   in =>         {             type         => 'dual',             host         => '0.0.0.0',             port         => 443,             client_first =>             {                 type => 'tcp',                 port => 444,     # move the https server to another port             },             server_first =>             {                 type => 'tcp',                 port => 22,      # good old SSH             },             # wait during a 2 second timeout             timeout      => 2,         },         out => { type => 'dummy' },     } ); $proxy->register( ); Net::Proxy->mainloop( );

Depending on your operating system, you may need to run the program with some administrative privileges to listen on a port below 1024.

Running the Hack

Run the program on your server. From your workstation, connect as usual. The only limitation of dual is that you have to find a pair of services with these special characteristics. HTTP and HTTPS are protocols where the client speaks first. The server speaks first with SSH, POP3, and SMTP.

Hacking the Hack

Net::Proxy is how BooK hacked the sslh hack (the 160-line Perl script). This module introduces the concept of connectors: in connectors accept incoming (client) connections and forward them toward servers via out connectors.

There is a tcp connector that handles standard TCP inbound and outbound connections, a connect connector that implements the CONNECT trick mentioned earlier, and a dummy connector that does nothing. BooK plans to add new connectors over time.

The dual connector used in this example uses the timeout trick to decide which connector (server_first or client_first) will contact the remote service. So the usual out parameter is just a dummy connector.

You can also use Net::Proxy to proxy an outgoing SSH connection through the corporate proxy:

#!/usr/bin/perl use strict; use warnings; use Net::Proxy; # show some information on STDERR Net::Proxy->set_verbosity(1); # run this on your workstation my $proxy = Net::Proxy->new(     {   in =>         {             # local port for local SSH client             port => 2222,             type => 'tcp',         },         out =>         {             host        => 'home.example.com',             port        => 443,             proxy_host  => 'proxy.company.com',             proxy_port  => 8080,             proxy_user  => 'id23494',             proxy_pass  => 's3kr3t',             proxy_agent => 'Mozilla/4.0 (compatible; MSIE 6.0; Windows XP)',         },     } ); $proxy->register( ); Net::Proxy->mainloop( );

To reach the https server, use your browser as usualyou've already configured it to use the corporate proxy!

Two scripts included in the Net::Proxy distribution support both of these uses. sslh lets you run two services on a single port on the server side and connect-tunnel helps you get through the corporate proxy on the client side.



Perl Hacks
Perl Hacks: Tips & Tools for Programming, Debugging, and Surviving
ISBN: 0596526741
EAN: 2147483647
Year: 2004
Pages: 141

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net