Tunnelling UDP over the Service Bus – or how to get Sentinel licencing server working on Azure

Before I start, I don’t think that a licencing server is necessary for cloud applications. It just adds extra complexity and cost with no benefit. If you are in control of your code piracy shouldn’t be a concern. However, I accept that in some cases software may be licensed via third parties, or business may not want a version of their codebase with  licencing disabled.

Sentinel cannot be installed on a VM, I believe it needs a fixed MAC address, and it talks UDP which isn’t currently available in Azure. Therefore we need to keep Sentinel on premises and find a way of getting UDP traffic across the internet. Well it turns out that this is a problem shared with the Quake 3 community. The Quake server also uses UDP, and playing against people on a different network is a challenge. Their solution is ‘Tunnel’ a UDP -> TCP tunnel written in Java:

http://tunnel.mrq3.com/

Another problem is that businesses are unlikely to want to expose their licencing server on the internet, but Azure has the solution; the Service Bus. PortBridge is a ready to go application VPN, which can traverse firewalls, and connect together otherwise unconnectable endpoints:

http://vasters.com/clemensv/2009/11/18/Port+Bridge.aspx

The deployed system looks like this:

The steps to get this up and running are as follows:

  1. Configure a ServiceBus endpoint in the Azure Management Portal.
  2. Put the Java runtime in a zip file, and upload it to Blob Storage (you need to manually deploy this to the Azure Role).
  3. Create a cloud project with a Worker/Web Role, and add the PortBridge Agent and Tunnel client files to the project, set the files to copy local. This will package up these dependencies with your application.
  4. Update the PortBridge config file, so the portBridgeAgent section looks something like this:
     
    <portBridgeAgent serviceBusNamespace="YOUR_NAMESPACE" serviceBusIssuerName="owner" serviceBusIssuerSecret="YOUR_SECRET">
      <portMappings>
        <port localTcpPort="6667" targetHost="YOUR_SENTINEL_SERVER_NAME" remoteTcpPort="6667">
          <firewallRules>
            <rule source="127.0.0.1"/>
            <rule sourceRangeBegin="10.0.0.0" sourceRangeEnd="10.255.255.255"/>
          </firewallRules>
        </port>
      </portMappings>
    </portBridgeAgent>
  5. Update the client.txt of Tunnel to something like this:
     
    #Login data for the server
    username = ech
    password = password
    
    #Address of the tunnel server
    tunnel = 127.0.0.1:6667
    
    #Number of TCP connections to make (1-30)
    connections = 30
    
    redirect1 = 5093 -> 127.0.0.1:5093
  6. The Worker Role should then have a startup task, which will download Java, and unzip it. (I tend to use 7zip console to extract the files from the archive, I just wrote a quick .NET console application to download the zip for me). Add startup tasks to run the PortBridgeAgent and the Tunnel client as background processes. I used this script to start the Tunnel, which will restart the Tunnel if the connection drops:
     
    :start
    
    REM pause for 10 seconds, waiting for portbridge to start
    PING 1.1.1.1 -n 1 -w 10000 >NUL
    
    c:\applications\java\bin\java -classpath build;lib\log4j-1.2.7.jar -Dlog4j.configuration=file:.\log4j.properties com.mrq3.tunnel.Client 
    
    goto start
  7. Configure the PortBridge service config file (which will run on premises):
     
    <portBridge serviceBusNamespace="YOUR_NAMESPACE" serviceBusIssuerName="owner" serviceBusIssuerSecret="YOUR_SECRET">
      <hostMappings>
        <add targetHost="YOUR_SENTINEL_SERVER_NAME" allowedPorts="6667"/>
      </hostMappings>
    </portBridge>
  8. Configure the Tunnel sever.txt file (which will run on premises):
     
    user1 = ech
    pass1 = password
  9. Start the on premises components, deploy the Worker Role, and cross your fingers…
Advertisements