Configuring a remote device and using IoT agent - Amazon IoT Core
Services or capabilities described in Amazon Web Services documentation might vary by Region. To see the differences applicable to the China Regions, see Getting Started with Amazon Web Services in China (PDF).

Configuring a remote device and using IoT agent

The IoT agent is used to receive the MQTT message that includes the client access token and start a local proxy on the remote device. You must install and run the IoT agent on the remote device if you want secure tunneling to deliver the client access token using MQTT. The IoT agent must subscribe to the following reserved IoT MQTT topic:


If you want to deliver the destination client access token to the remote device through methods other than subscribing to the reserved MQTT topic, you might need a destination client access token (CAT) listener and a local proxy. The CAT listener must work with your chosen client access token delivery mechanism and be able to start a local proxy in destination mode.

IoT agent snippet

The IoT agent must subscribe to the following reserved IoT MQTT topic so that it can receive the MQTT message and start the local proxy:


Where thing-name is the name of Amazon IoT thing associated with the remote device.

The following is an example MQTT message payload:

{ "clientAccessToken": "destination-client-access-token", "clientMode": "destination", "region": "aws-region", "services": ["destination-service"] }

After it receives an MQTT message, the IoT agent must start a local proxy on the remote device with the appropriate parameters.

The following Java code demonstrates how to use the Amazon IoT Device SDK and ProcessBuilder from the Java library to build a simple IoT agent to work with secure tunneling.

// Find the IoT device endpoint for your Amazon Web Services account final String endpoint = iotClient.describeEndpoint(new DescribeEndpointRequest().withEndpointType("iot:Data-ATS")).getEndpointAddress(); // Instantiate the IoT Agent with your Amazon credentials final String thingName = "RemoteDeviceA"; final String tunnelNotificationTopic = String.format("$aws/things/%s/tunnels/notify", thingName); final AWSIotMqttClient mqttClient = new AWSIotMqttClient(endpoint, thingName, "your_aws_access_key", "your_aws_secret_key"); try { mqttClient.connect(); final TunnelNotificationListener listener = new TunnelNotificationListener(tunnelNotificationTopic); mqttClient.subscribe(listener, true); } finally { mqttClient.disconnect(); } private static class TunnelNotificationListener extends AWSIotTopic { public TunnelNotificationListener(String topic) { super(topic); } @Override public void onMessage(AWSIotMessage message) { try { // Deserialize the MQTT message final JSONObject json = new JSONObject(message.getStringPayload()); final String accessToken = json.getString("clientAccessToken"); final String region = json.getString("region"); final String clientMode = json.getString("clientMode"); if (!clientMode.equals("destination")) { throw new RuntimeException("Client mode " + clientMode + " in the MQTT message is not expected"); } final JSONArray servicesArray = json.getJSONArray("services"); if (servicesArray.length() > 1) { throw new RuntimeException("Services in the MQTT message has more than 1 service"); } final String service = servicesArray.get(0).toString(); if (!service.equals("SSH")) { throw new RuntimeException("Service " + service + " is not supported"); } // Start the destination local proxy in a separate process to connect to the SSH Daemon listening port 22 final ProcessBuilder pb = new ProcessBuilder("localproxy", "-t", accessToken, "-r", region, "-d", "localhost:22"); pb.start(); } catch (Exception e) { log.error("Failed to start the local proxy", e); } } }