Self-hosted Web Service on Windows Server 2012

When it comes to hosting web services, Microsoft Windows Server platform can do the job with or without an actual web server. In Windows Server, web server would be IIS. If IIS is installed, web service can be hosted as a website, be configured using .config files, and generally speaking all TCP/IP or SSL configuration would be done at the IIS level. This may be more convenient for people who are used to IIS or who have to have IIS up for other reasons, however in some cases you may prefer to avoid IIS and keep your attack surface to the minimum.

Self-hosting means no IIS to install and it relies on http.sys, something that is present on all Windows Server machines as part of the TCP/IP stack. Self-hosted services can be managed through netsh command line interface.

Discussion of pros and cons of self-hosted web services is outside the scope of this article but a good place to start reading up on that is on Stack Overflow.

Self-Hosted Web Service Installation

Self-hosted web service relies on something else other than IIS to open a socket and listen for inbound connections. This can be done by deploying your application as a Windows service. .NET Framework has a handy utility called InstallUtil.exe, located in C:\Windows\Microsoft.NET\Framework\v4.0.30319\ folder (.NET Framework 4.0, Windows Server 2012).

C:\Windows\Microsoft.NET\Framework\v4.0.30319\installutil.exe C:\Flexecom\Time\bin\release\Time.Sync.exe

The command above installs a Visual Studio console application as a Windows service. Right after running this command, you can launch services.msc and check for presense of this new Windows service.

For console application to install as a Windows service, you need to add Installer class to your project, which will tell InstallUtil.exe how to deploy the service:

<RunInstaller(True)> Public Class SyncWindowsServiceInstaller
     Inherits Installer
     Private process As ServiceProcessInstaller
     Private service As ServiceInstaller

     Public Sub New()
          process = New ServiceProcessInstaller
          process.Account = Service.Account.LocalSystem
          service = New ServiceInstaller
          service.ServiceName = My.Settings.WindowsServiceName
          Installers.Add(process)
          Installers.Add(service)
     End Sub
End Class

On line 10, the name of the Windows service is set to the WindowsServiceName string value from the application config file.

Configure URL Binding and SSL Certificate

For Windows service to bind successfully to a network socket, you need to configure URL access control list using netsh.exe CLI:

netsh http add urlacl url=https://www.flexecom.com:443/timesync.live sddl="D:(A;;GX;;;S-1-1-0)"

Since in this example we are using SSL (port 443, https) we also need to assign a valid certificate to the same binding:

netsh http add sslcert hostnameport=www.flexecom.com:443 certhash=certificate_hash appid={app_guid}

Now this last command is a little tricky. How do you find out certificate_hash and app_guid of your certificate and application?

Certificate hash can be obtained directly by inspecting X.509 certificate using Certificates MMC snap-in, or via certutil -store command. Find the certificate you want to use, copy its “cert hash” value (deleting all spaces) and you are set.

Getting App ID is a tad more complicated. Best way to do this is by calling it from the code using the following method:

System.Reflection.Assembly.GetExecutingAssembly.GetType().GUID.ToString

Call this method somewhere in the opening lines of your web services application and either Debug.Print the output to the console, or write it into event log, or simply break-point it and check it out in the immediate window. App ID does not change but getting it isn’t very convenient.

Verify Configuration

That’s all there is to setting up self-hosted web services on the Windows Server 2012 platform. Make sure that your Windows Firewall, if enabled, is configured to allow port 80/443 (as applicable).

At this point, start Windows service that was installed using InstallUtil.exe.

To confirm that your socket was opened successfully:

Netstat -na

To confirm configuraion of URL ACL:

netsh http show urlacl

To confirm SSL certificate binding:

netsh http show sslcert

Closing Thoughts

Ultimately, it is up to you to configure the type of network binding (http or https) and the service URL (https://www.flexecom.com:443) of your web service. There are several ways to do this, the preferred way for self-hosted web services is to set these parameters directly using .NET code within your assembly. Whatever settings you configure, they need to match the netsh configuration (specifically URLACL), otherwise your service will fail to open the socket. SSL certificate is required for HTTPS bindings. More on how to do this in another post.

Binding Multiple Web Services to the Same Socket

Is possible! All you have to do is modify the URL of the web service in your code and make sure that netsh command gets executed to add all web service URLs to the http ACL. You can have many web services running off the same base URL (https://www.flexecom.com:443) as long as what follows after / is unique. This allows you to setup a production web service as well as a dev/qa web service using the same single-name SSL certificate, the same public IP address, and the same server.

 

Leave a Reply

Your email address will not be published. Required fields are marked *