Overcoming client firewall restrictions with port sharingA number of organisations use java applets to do online business with customers, undertaking activities such as online chat with sales staff or real-time auctioning. Whilst this can often work well, any user who is sitting the wrong side of a restrictive outgoing firewall (perhaps only allowing HTTP connections through) will find themselves out of luck when trying to use the service. ZXTM can extend access to this otherwise unreachable user base by allowing multiple protocols to share the same port on the same server. Here we show how to configure ZXTM to allow a Java applet to be downloaded over SSL on the standard port, and have it make a request to a custom daemon running on the same host / port. The problem: You have too few available portsFor every service you want to provide, you will typically need a dedicated port. These services may provide things such as overall control, data lookups, or image serving -- an advanced application may make use of a number of these. A typical client security policy will allow an applet to connect only to the server from where it was downloaded; this causes a problem when a client firewall allows connections to only a small number of ports. In this section, we demonstrate our applet connecting to a dedicated port, as would be the case in such a deployment. Here is a web page containing an applet which retrieves a string from the server. Enclosing web page<HTML> <HEAD><TITLE>Simple connection applet</TITLE></HEAD> <BODY> <APPLET WIDTH=300 HEIGHT=100 CODE="ServerString.class"> <PARAM NAME="host" VALUE="myserver.mydomain.tld" /> <PARAM NAME="port" VALUE="12345" /> </APPLET> </BODY> </HTML> The Applet
// ServerString.java
//
// This basic applet connects to the server and asks it for the current
// time. It them displays this to the user.
import java.applet.*;
import java.awt.*;
import java.io.*;
import java.net.*;
public class ServerString extends Applet {
public void init() {
setBackground( Color.blue );
}
public void paint( Graphics gg ) {
gg.setColor( Color.green );
gg.drawString( "Contacting server...", 50, 30 );
Socket sock = null;
PrintStream out = null;
BufferedReader in = null;
String host = getParameter( "host" );
int port = Integer.parseInt(getParameter( "port" ));
try {
sock = new Socket( host, port );
out= new PrintStream( sock.getOutputStream() );
in = new BufferedReader (new InputStreamReader( sock.getInputStream() ));
out.println( "SERVERSTRING: WHAT TIME IS IT?" );
gg.drawString( in.readLine(), 50, 50 );
out.close();
in.close();
sock.close();
} catch (IOException ee) {
System.out.println( ee );
}
gg.drawString( "done.", 50, 70 );
}
}
DaemonFor this example, we will use as our backend a basic shell command which returns the date to any connecting process and then exits (this requires netcat to be installed): $ date | nc -l -p 12345 Putting it togetherThese pieces fit together as they would in a real deployment: you should serve the page and applet from a HTTPS web server pool, and the proprietary protocol from a dedicated pool. You will need two Virtual Servers for this, one listening on each port. Visiting this web page will then show the applet connecting to the daemon and retrieving the output from the As it stands, this requires have two open ports on the server: the port used to download the applet, and the port that it uses to transfer the data. The solution: Using ZXTM as a protocol splicerIf the applet were able to use port 443 instead of port 12345 for its data, then the client firewall would pose no problem. To do this, we will need to create a Virtual Server listening on port 443, using the "Generic Client-First" protocol. We can use the following TrafficScript request rule to examine an incoming request and determine whether it's intended for our daemon, or as HTTPS, thus allowing both protocols to use the same port.
# TrafficScript rule to switch on incoming protocol type
#
# We must check protocols with shortest headers first
if( request.getLength() == 0 ) {
log.warn( "server first protocol detected, aborting" );
connection.discard();
}
########
# Deal with incoming SSL connection
if( request.getLength() < 3 ) {
log.warn( "insufficient data from client (< 3 bytes), aborting" );
connection.discard();
}
$data = request.Get( 3 );
if( string.regexmatch( $data,
"(?xs)^(\\26\\03[\\0\\01\\02])# TLS / SSLv3 \
|([\\200-\\377].\\01) # SSLv2 \
|([\\0-\\177]2.) # SSLv2 \
" )) {
log.info( "SSL connection detected" );
pool.use( "ssl_backends" );
# Could use loopback here to decode SSL and process HTTP if desired
}
########
# Deal with my applet
if( request.getLength() < 12 ) {
log.warn( "insufficient data from client (< 12 bytes), aborting" );
connection.discard();
}
$data = request.Get( 12 );
if( $data == "SERVERSTRING" ) {
log.info( "ServerString applet connection detected" );
pool.use( "serverstring_backends" );
}
log.warn( "Unrecognised protocol detected" );
# Unrecognised protocol: use default pool
# (presumably discard)
A simple modification to the web page (or Java applet) to change the server port to 443 is now all that's needed to ensure that client firewalls no longer interfere with your customer communications. Which protocols can be spliced?To be able to distinguish which protocol is in use on a connection, ZXTM needs to see enough of the request to make a decision before a server response is required. Each protocol must therefore be client-first (ie the first message is sent from the client to the server). How many protocols may be served from one port?So long as disambiguation is achieved before the server sends a result, then there is no limit to the number of different protocols which can be served on a single port. What ports can be used?Any port which is not blocked by the client's firewall will do -- typically it would be reasonable to use port 80 or 443. You could even run a virtual server on both of these port, each splicing out HTTP, HTTPS and your application data!
Brian Cowe
[Zeus Systems Engineering] 20 October 2006
|
Recent Articles
Other Resources
|


