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:
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:
The deployed system looks like this:
The steps to get this up and running are as follows:
- Configure a ServiceBus endpoint in the Azure Management Portal.
- Put the Java runtime in a zip file, and upload it to Blob Storage (you need to manually deploy this to the Azure Role).
- 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.
- 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>
- 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
- 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 126.96.36.199 -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
- 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>
- Configure the Tunnel sever.txt file (which will run on premises):
user1 = ech pass1 = password
- Start the on premises components, deploy the Worker Role, and cross your fingers…