Azure  

Expose an On-Premises WCF REST Service to an External Client Using Azure Relay

Introduction

In many enterprise scenarios, you may have a service running on-premises (behind firewalls, inside your corporate network) built using WCF. At the same time, you have cloud-based applications, partner systems, or mobile clients that need to access that service — but you don’t want to open inbound firewall ports, deploy VPNs, or expose your internal network directly.

That’s where Azure Relay steps in: it enables your on-premises WCF service to register (outbound) with a relay endpoint in Azure, and external clients to call through Azure to your service — without you having to open inbound ports on your firewall.
In this tutorial, you will learn how to:

  • Create a Relay namespace in Azure

  • Build a simple WCF REST service on-premises

  • Configure it to listen via Azure Relay

  • Build a WCF client that calls the service via the relay

  • Run the solution and verify it works

Microsoft provides a very similar tutorial under “Expose an on-premises Windows Communication Foundation (WCF) REST service to a client outside your network” in Azure Relay documentation.

Prerequisites

Before you begin, make sure you have the following:

  • An Azure subscription. (If you don’t have one, create a free account.)

  • Visual Studio (2015 or later; the examples use VS2019) and .NET Framework compatible with WCF.

  • The Azure SDK / management tools for .NET (so you can create Relay namespaces, etc.)

  • A basic understanding of WCF (contracts, endpoints, bindings) and of REST (HTTP verbs, JSON)

  • On your on-premises machine: ability to make outbound connections over HTTP(s)/TCP to Azure (no inbound ports required)

Step 1. Create a Relay Namespace in Azure

  1. Sign in to the Azure Portal.

  2. Navigate to All services → Integration → Relays (or search for “Relay service”). Click Create to add a new Relay namespace.

    • Choose a subscription

    • Select or create a resource group

    • Enter a unique namespace name (e.g., MyCompanyRelayNs)

    • Select the region/data-center

  3. After creation, obtain the Shared Access Signature (SAS) key: you’ll need a listen key (for your service) and possibly a send key (for the client).

  4. Within the namespace, create a WCF Relay (or HTTP Relay) endpoint entity (e.g., myservice/relay).

At this point, you have the Azure side prepared: a Relay namespace + relay entity + access keys.

Step 2. Define the WCF Service Contract (On-Premises)

Create a .NET Framework WCF project for the on-premises service. In Visual Studio: File → New → WCF Service Application (or Class Library + self-host).
Define a REST-style service contract, for example:

[ServiceContract]
public interface IDeviceService
{
    [OperationContract]
    [WebGet(UriTemplate = "status", ResponseFormat = WebMessageFormat.Json)]
    string GetStatus();

    [OperationContract]
    [WebInvoke(Method = "POST", UriTemplate = "upload", RequestFormat = WebMessageFormat.Json, 
               ResponseFormat = WebMessageFormat.Json)]
    UploadResult UploadData(DeviceData data);
}

Here DeviceData It is a simple POCO representing a JSON payload from the client. The REST nature is achieved by WebGet/WebInvoke attributes.

Step 3. Implement the Service and Host via Azure Relay Binding

Implement the interface as usual. Then host it using a WCF service host that uses an Azure Relay binding instead of a typical HTTP binding.

Example

string relayNamespace = "[YourRelayNamespace].servicebus.windows.net";
string entityPath     = "myservice/relay";
string sasKeyName     = "ListenPolicy";
string sasKey         = "[yourListenKey]";

var uri = ServiceBusEnvironment.CreateServiceUri("sb", relayNamespace, entityPath);

// Use the NetTcpRelayBinding or HttpRelayBinding depending on your protocol
var binding = new HttpRelayBinding(HttpRelaySecurityMode.None);

// Create the host
ServiceHost host = new ServiceHost(typeof(DeviceService));
host.AddServiceEndpoint(typeof(IDeviceService), binding, uri);

// Set the credentials
var behavior = host.Description.Behaviors.Find<ServiceBusCredentialsBehavior>();
if (behavior == null)
{
    behavior = new ServiceBusCredentialsBehavior();
    host.Description.Behaviors.Add(behavior);
}
behavior.Claims = new SendClaims(); // or ListenClaims depending on role
behavior.TokenProvider = TokenProvider.CreateSharedAccessSignatureTokenProvider(
    sasKeyName, sasKey);

host.Open();
Console.WriteLine("Listening on relay: " + uri);
Console.ReadLine();
host.Close();

In this setup:

  • The host makes an outbound connection to Azure Relay using the SAS key.

  • No inbound firewall port is needed on the on-premises machine (only outbound).

  • External clients will connect to the same relay endpoint in Azure, and Azure will forward requests to the host.

Microsoft’s tutorial covers the equivalent for a REST service via WCF Relay.

Step 4: Configure the Client to Call via the Relay

In your client (which may be a WCF client, a console app, or even another cloud-based application), configure the endpoint address to the relay namespace and entity path, and use the corresponding Send SAS key.

For instance:

string relayNamespace = "[YourRelayNamespace].servicebus.windows.net";
string entityPath     = "myservice/relay";
string sasKeyName     = "SendPolicy";
string sasKey         = "[yourSendKey]";

var uri = ServiceBusEnvironment.CreateServiceUri("sb", relayNamespace, entityPath);
var binding = new HttpRelayBinding(HttpRelaySecurityMode.None);

ChannelFactory<IDeviceService> factory = new ChannelFactory<IDeviceService>(binding, new EndpointAddress(uri));
factory.Endpoint.EndpointBehaviors.Add(new TransportClientEndpointBehavior()
{
    TokenProvider = TokenProvider.CreateSharedAccessSignatureTokenProvider(sasKeyName, sasKey)
});

IDeviceService proxy = factory.CreateChannel();
string status = proxy.GetStatus();
Console.WriteLine("Service status: " + status);

var result = proxy.UploadData(new DeviceData { DeviceId = "D1001", Timestamp = DateTime.UtcNow });
Console.WriteLine("Upload result: " + result.Message);

This makes the call through the relay endpoint in Azure, which then routes it to your host.

Step 5: Run and Verify

  1. On your on-premises machine: launch the service host. Confirm that it opens and “listening on relay: sb://…” appears.

  2. From an external client (outside the on-prem network) run the client app. It connects to the relay and invokes the service.

  3. On the host, you should see the incoming calls being processed.

  4. Test connectivity even across networks (cloud client → Azure Relay → on-prem host).

  5. Verify that firewall settings allow outbound to *.servicebus.windows.net on required ports (typically 443, 5671-5672) as described in Azure documentation. learn.microsoft.com+1

Architecture Summary

[External Client]
    |
    | (HTTPS or WCF binding via Azure Relay)
    v
[Azure Relay Namespace / Entity]
    |
    | Outbound tunnel
    v
[On-Premises WCF Host]

Key points

  • The on-prem host only opens an outbound connection to Azure Management.

  • Client uses the same relay endpoint.

  • No direct inbound firewall exceptions required (simpler security).

  • Works for WCF REST, WCF SOAP, or other WCF bindings supported by Azure Relay (NetTcpRelayBinding, HttpRelayBinding, etc).

Best Practices and Considerations

  • Use the least-privilege SAS policies: e.g., separate Listen and Send keys for hosts and clients.

  • Monitor the Azure Relay namespace usage (connections, hours, costs).

  • Ensure proper firewall/proxy rules: allow outbound to Azure Relay FQDNs.

  • Use secure bindings: consider HttpRelaySecurityMode.Transport (HTTPS) or RelayClientAuthenticationType.None with SAS or Azure AD tokens.

  • For production setups, consider high availability by hosting multiple listeners or in multiple on-prem machines.

  • Implement retry logic in client/service to handle transient connectivity.

  • If migrating from legacy WCF, note that new packages such as Microsoft.Azure.Relay may be used.

Conclusion

Using Azure Relay to expose an on-premises WCF REST service to external clients is a practical, secure, and scalable approach to bridging legacy on-premises systems with modern cloud-based apps — without the complexity of VPNs or inbound firewall openings.

By following the steps above (namespace creation, service contract, hosting with relay binding, client configuration, and verification) you can build a robust hybrid architecture.