Quickstart: Enable SSH and RDP over an IoT Hub device stream by using a C# proxy application (preview)

Microsoft Azure IoT Hub currently supports device streams as a preview feature.

IoT Hub device streams allow service and device applications to communicate in a secure and firewall-friendly manner. This quickstart guide involves two C# applications that enable client-server application traffic (such as Secure Shell [SSH] and Remote Desktop Protocol [RDP] to be sent over a device stream that's established through an IoT hub. For an overview of the setup, see Local proxy application sample for SSH or RDP.

This article first describes the setup for SSH (using port 22) and then describes how to modify the setup's port for RDP. Because device streams are application- and protocol-agnostic, the same sample can be modified to accommodate other types of application traffic. This modification usually involves only changing the communication port to the one that's used by the intended application.

How it works

The following figure illustrates how the device-local and service-local proxy applications in this sample enable end-to-end connectivity between the SSH client and SSH daemon processes. Here, we assume that the daemon is running on the same device as the device-local proxy application.

Local proxy application setup

  1. The service-local proxy application connects to the IoT hub and initiates a device stream to the target device.

  2. The device-local proxy application completes the stream initiation handshake and establishes an end-to-end streaming tunnel through the IoT hub's streaming endpoint to the service side.

  3. The device-local proxy application connects to the SSH daemon that's listening on port 22 on the device. This setting is configurable, as described in the "Run the device-local proxy application" section.

  4. The service-local proxy application waits for new SSH connections from a user by listening on a designated port, which in this case is port 2222. This setting is configurable, as described in the "Run the service-local proxy application" section. When the user connects via the SSH client, the tunnel enables SSH application traffic to be transferred between the SSH client and server application.

Note

SSH traffic that's sent over a device stream is tunneled through the IoT hub's streaming endpoint rather than sent directly between service and device. For more information, see the benefits of using Iot Hub device streams.

Use Azure Cloud Shell

Azure hosts Azure Cloud Shell, an interactive shell environment that you can use through your browser. Cloud Shell lets you use either bash or PowerShell to work with Azure services. You can use the Cloud Shell pre-installed commands to run the code in this article without having to install anything on your local environment.

To launch Azure Cloud Shell:

Option Example/Link
Select Try It in the upper-right corner of a code block. Selecting Try It doesn't automatically copy the code to Cloud Shell. Example of Try It for Azure Cloud Shell
Go to https://shell.azure.com or select the Launch Cloud Shell button to open Cloud Shell in your browser. Launch Cloud Shell in a new window
Select the Cloud Shell button on the top-right menu bar in the Azure portal. Cloud Shell button in the Azure portal

To run the code in this article in Azure Cloud Shell:

  1. Launch Cloud Shell.

  2. Select the Copy button on a code block to copy the code.

  3. Paste the code into the Cloud Shell session with Ctrl+Shift+V on Windows and Linux, or Cmd+Shift+V on macOS.

  4. Press Enter to run the code.

If you don’t have an Azure subscription, create a free account before you begin.

Prerequisites

  • The preview of device streams is currently supported only for IoT hubs that are created in the following regions:

    • Central US
    • Central US EUAP
  • The two sample applications that you run in this quickstart are written in C#. You need the .NET Core SDK 2.1.0 or later on your development machine.

    You can download the .NET Core SDK for multiple platforms from .NET.

  • Verify the current version of C# on your development machine by using the following command:

    dotnet --version
    
  • Run the following command to add the Azure IoT Extension for Azure CLI to your Cloud Shell instance. The IOT Extension adds IoT Hub, IoT Edge, and IoT Device Provisioning Service (DPS)-specific commands to the Azure CLI.

    az extension add --name azure-cli-iot-ext
    
  • Download the sample C# project, and extract the ZIP archive.

  • A valid user account and credential on the device (Windows or Linux) used to authenticate the user.

Create an IoT hub

This section describes how to create an IoT hub using the Azure portal.

  1. Sign in to the Azure portal.

  2. Choose Create a resource, and then enter IoT Hub in the Search the Marketplace field.

  3. Select IoT Hub from the search results, and then select Create.

  4. On the Basics tab, complete the fields as follows:

    • Subscription: Select the subscription to use for your hub.

    • Resource Group: Select a resource group or create a new one. To create a new one, select Create new and fill in the name you want to use. To use an existing resource group, select that resource group. For more information, see Manage Azure Resource Manager resource groups.

    • Region: Choose the region in which you want your hub to be located. Select a region that supports the IoT Hub device streams preview, either Central US or Central US EUAP.

    • IoT Hub Name: Enter a name for your hub. This name must be globally unique. If the name you enter is available, a green check mark appears.

    Creating an IoT hub in the Azure portal

    Important

    Because the IoT hub will be publicly discoverable as a DNS endpoint, be sure to avoid entering any sensitive or personally identifiable information when you name it.

  5. Select Next: Size and scale to continue creating your hub.

    Setting size and scale for a new IoT hub using the Azure portal

    In Size and scale, you can accept the default settings and select Review + create at the bottom. Consider the following options:

    • Pricing and scale tier: Your selected tier. Select one of the standard tiers (S1, S2, or S3) or F1: Free tier. This choice can also be guided by the size of your fleet and the non-streaming workloads that you expect in your hub, for example, telemetry messages. For example, the free tier is intended for testing and evaluation. It allows 500 devices to be connected to the IoT hub and up to 8,000 messages per day. Each Azure subscription can create one IoT hub in the free tier.

    • Number of IoT Hub units: The number of messages allowed per unit per day depends on your hub's pricing tier. This choice depends on non-streaming workload you expect in your hub. You can select 1 for now.

    • Advanced Settings > Device-to-cloud partitions: This property relates the device-to-cloud messages to the number of simultaneous readers of the messages. Most hubs only need four partitions.

    For more information about tier options, see Choose the right IoT hub tier.

  6. To review your choices, choose Review + create. Your results will be similar to the following:

    Information for creating the new IoT hub

  7. To create your new IoT hub, select Create. The process takes a few minutes.

Register a device

A device must be registered with your IoT hub before it can connect. In this quickstart, you use Azure Cloud Shell to register a simulated device.

  1. To create the device identity, run the following command in Cloud Shell:

    Note

    • Replace the YourIoTHubName placeholder with the name you chose for your IoT hub.
    • For the name of the device you're registering, it's recommended to use MyDevice as shown. If you choose a different name for your device, use that name throughout this article, and update the device name in the sample applications before you run them.
    az iot hub device-identity create --hub-name {YourIoTHubName} --device-id MyDevice
    
  2. To get the device connection string for the device that you just registered, run the following commands in Cloud Shell:

    Note

    Replace the YourIoTHubName placeholder with the name you chose for your IoT hub.

    az iot hub device-identity show-connection-string --hub-name {YourIoTHubName} --device-id MyDevice --output table
    

    Note the returned device connection string for later use in this quickstart. It looks like the following example:

    HostName={YourIoTHubName}.azure-devices.net;DeviceId=MyDevice;SharedAccessKey={YourSharedAccessKey}

  3. To connect to your IoT hub and establish a device stream, you also need the service connection string from your IoT hub to enable the service-side application. The following command retrieves this value for your IoT hub:

    Note

    Replace the YourIoTHubName placeholder with the name you chose for your IoT hub.

    az iot hub show-connection-string --policy-name service --name {YourIoTHubName} --output table
    

    Note the returned service connection string for later use in this quickstart. It looks like the following example:

    "HostName={YourIoTHubName}.azure-devices.net;SharedAccessKeyName=service;SharedAccessKey={YourSharedAccessKey}"

SSH to a device via device streams

In this section, you establish an end-to-end stream to tunnel SSH traffic.

Run the device-local proxy application

In a local terminal window, navigate to the device-streams-proxy/device directory in your unzipped project folder. Keep the following information handy:

Argument name Argument value
DeviceConnectionString The device connection string of the device that you created earlier.
targetServiceHostName The IP address where the SSH server listens. The address would be localhost if it were the same IP where the device-local proxy application is running.
targetServicePort The port that's used by your application protocol (for SSH, by default, this would be port 22).

Compile and run the code with the following commands:

cd ./iot-hub/Quickstarts/device-streams-proxy/device/

# Build the application
dotnet build

# Run the application
# In Linux or macOS
dotnet run ${DeviceConnectionString} localhost 22

# In Windows
dotnet run {DeviceConnectionString} localhost 22

Run the service-local proxy application

In another local terminal window, navigate to device-streams-proxy/service in your unzipped project folder. Keep the following information handy:

Parameter name Parameter value
ServiceConnectionString The service connection string of your IoT Hub.
MyDevice The identifier of the device you created earlier.
localPortNumber A local port that your SSH client will connect to. We use port 2222 in this sample, but you could use other arbitrary numbers.

Compile and run the code with the following commands:

cd ./iot-hub/Quickstarts/device-streams-proxy/service/

# Build the application
dotnet build

# Run the application
# In Linux or macOS
dotnet run ${ServiceConnectionString} MyDevice 2222

# In Windows
dotnet run {ServiceConnectionString} MyDevice 2222

Run the SSH client

Now use your SSH client application and connect to service-local proxy application on port 2222 (instead of the SSH daemon directly).

ssh {username}@localhost -p 2222

At this point, the SSH sign-in window prompts you to enter your credentials.

Console output on the service side (the service-local proxy application listens on port 2222):

Service-local proxy application output

Console output on the device-local proxy application, which connects to the SSH daemon at IP_address:22:

Device-local proxy application output

Console output of the SSH client application. The SSH client communicates to the SSH daemon by connecting to port 22, which the service-local proxy application is listening on:

SSH client application output

RDP to a device via device streams

The setup for RDP is similar to the setup for SSH (described above). You use the RDP destination IP and port 3389 instead and use the RDP client (instead of the SSH client).

Run the device-local proxy application (RDP)

In a local terminal window, navigate to the device-streams-proxy/device directory in your unzipped project folder. Keep the following information handy:

Argument name Argument value
DeviceConnectionString The device connection string of the device that you created earlier.
targetServiceHostName The hostname or IP address where RDP server runs. The address would be localhost if it were the same IP where the device-local proxy application is running.
targetServicePort The port used by your application protocol (for RDP, by default, this would be port 3389).

Compile and run the code with the following commands:

cd ./iot-hub/Quickstarts/device-streams-proxy/device

# Run the application
# In Linux or macOS
dotnet run ${DeviceConnectionString} localhost 3389

# In Windows
dotnet run {DeviceConnectionString} localhost 3389

Run the service-local proxy application (RDP)

In another local terminal window, navigate to device-streams-proxy/service in your unzipped project folder. Keep the following information handy:

Parameter name Parameter value
ServiceConnectionString The service connection string of your IoT Hub.
MyDevice The identifier of the device you created earlier.
localPortNumber A local port that your SSH client will connect to. We use port 2222 in this sample, but you could modify this to other arbitrary numbers.

Compile and run the code with the following commands:

cd ./iot-hub/Quickstarts/device-streams-proxy/service/

# Build the application
dotnet build

# Run the application
# In Linux or macOS
dotnet run ${ServiceConnectionString} MyDevice 2222

# In Windows
dotnet run {ServiceConnectionString} MyDevice 2222

Run RDP client

Now use your RDP client application and connect to the service-local proxy application on port 2222 (this was an arbitrary available port that you chose earlier).

RDP connects to the service-local proxy application

Clean up resources

If you plan to continue to the next recommended article, you can keep and reuse the resources you've already created.

Otherwise, to avoid charges, you can delete the Azure resources that you created in this article.

Important

Deleting a resource group is irreversible. The resource group and all the resources contained in it are permanently deleted. Make sure that you don't accidentally delete the wrong resource group or resources. If you created the IoT hub inside an existing resource group that contains resources that you want to keep, delete only the IoT hub resource itself, not the resource group.

To delete a resource group by name:

  1. Sign in to the Azure portal, and then select Resource groups.

  2. In the Filter by name box, enter the name of the resource group that contains your IoT hub.

  3. In the result list, to the right of your resource group, select the ellipsis (...), and then select Delete resource group.

    The "Delete resource group" button

  4. To confirm the deletion of the resource group, reenter the resource group name, and then select Delete. After a few moments, the resource group and all its contained resources are deleted.

Next steps

In this quickstart, you set up an IoT hub, registered a device, deployed device-local and service-local proxy applications to establish a device stream through the IoT hub, and used the proxy applications to tunnel SSH or RDP traffic. The same paradigm can accommodate other client-server protocols, where the server runs on the device (for example, the SSH daemon).

To learn more about device streams, see: