Auditing Exposed Ports on IoT Gateways Before They Ship to the Field
Open Source

Auditing Exposed Ports on IoT Gateways Before They Ship to the Field

Most firmware engineers know to disable root login over SSH. Fewer check whether the SSH daemon was compiled into the image at all. Fewer still verify what an attacker on the public internet sees when they point a scanner at the device’s WAN-facing address on shipping day. That gap between what the development team audited and what a field-deployed device actually exposes is where real-world compromises begin.

Audit Essentials at a Glance

  • OpenWrt and Yocto-based images frequently enable Telnet, Dropbear SSH, dnsmasq, and LuCI HTTP management by default
  • Internal audits using ss and nmap build a baseline, but only an external scan confirms the true WAN-facing surface
  • iptables rules on resource-constrained hardware must stay minimal and stateless where possible to avoid RAM exhaustion
  • PSA Certified Level 1 and the Matter specification both require documented minimization of open network services
  • Auditing at every build milestone, not only at final release, catches services added by new package dependencies

The Default Port Landscape on OpenWrt and Yocto Builds

OpenWrt ships with several services enabled out of the box. dnsmasq listens on port 53 for DNS and DHCP. Dropbear SSH opens port 22. The LuCI web interface binds to port 80. On some builds, Telnet listens on port 23 until the root password is set for the first time. None of these defaults are wrong for a developer lab. All of them are wrong for a device that will sit behind a customer’s broadband modem with no additional perimeter between it and the internet.

Yocto-based builds are more configurable from the start, but configuration flexibility is not the same as secure defaults. Custom distribution layers often pull in packages that include systemd socket-activated services, mDNS advertisers, and MQTT brokers, all of which open ports the build engineer may not have anticipated. The IMAGE_FEATURES and EXTRA_IMAGE_FEATURES variables control what makes it into the final image, but engineers working under deadline pressure sometimes leave debug features enabled longer than intended. A quick prototype option becomes a permanent resident in the release artifact.

The practical lesson here is this: you cannot trust that a service is absent just because you did not intentionally add it. Every package dependency chain is a potential source of new listeners, and the only way to know what is actually running is to ask the device directly.

Auditing from the Inside Out: What Your Device Tells You Directly

The inside-out phase is what you run while you still have shell access during development and QA. Start with ss -tlnp on the device itself. This command outputs every listening TCP socket alongside the associated PID and process name. For UDP services, add the -u flag. Cross-reference the output against your expected service list for this build. Anything that appears unexpectedly gets traced back to its originating package before you move forward.

Follow that with an nmap scan from a machine on the same LAN segment:

nmap -sS -sU -p 1-65535 --open <device-ip>

The LAN-side scan catches services that are bound to all interfaces rather than a specific one. It also surfaces services that your firewall rules have not yet touched. At this stage, you are building a complete picture of everything the kernel is willing to answer on, regardless of what iptables will block later.

Document the full port list and tie each open port to a specific service, binary path, and build dependency. This becomes your baseline manifest and your reference point for every future build comparison. Without a manifest, you have no way to tell whether a port that appears in a later build is a regression or a new intentional service.

iptables Hardening Patterns for Resource-Constrained Hardware

On a device with 64 MB of RAM and a MIPS or ARM Cortex-A7 processor, connection tracking is not free. The nf_conntrack module allocates a hash table that scales with concurrent connections. On a gateway serving a handful of IoT sensors, this is manageable. On a device with 32 MB of RAM, it can consume enough memory to trigger OOM kills under sustained load. Your iptables strategy has to account for that constraint from the start.

The practical approach starts with an explicit DROP policy on inbound and forwarded traffic:

iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

From that baseline, you add only the rules the device genuinely needs. For a gateway that accepts inbound SSH from a management VLAN but nothing else on the WAN interface:

iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -i eth1 -p tcp --dport 22 -s 192.168.100.0/24 -j ACCEPT
iptables -A INPUT -i eth0 -j DROP

Here, eth0 is the WAN interface and eth1 is the management-side interface. This pattern uses conntrack only for established sessions, which keeps the table size predictable under normal operating conditions.

For devices where even conntrack overhead is a concern, restrict by interface and port combination using direct match rules. You lose some precision on asymmetric routing edge cases, but you remain within the device’s memory budget. Save the rule set with iptables-save and restore it via an init script or systemd service that runs before any network-dependent service starts. On OpenWrt, the UCI firewall subsystem handles this automatically when you configure rules through the abstraction layer rather than calling raw iptables commands directly.

Confirming What an Attacker Actually Sees from the Outside

Internal audits tell you what the device is willing to serve. They do not tell you what survives the journey through your customer’s ISP, NAT table, and any upstream infrastructure between the device and the public internet. The outside-in step closes that gap, and it is the step most development teams skip entirely.

The process is straightforward. Connect the device to a real WAN link during final validation. From a browser running on the gateway itself or on a device behind the same WAN connection, check what is my IP to confirm the public-facing address you will be scanning against. Then, from a machine outside that network entirely, run an external port scan against that address:

nmap -sS -p 1-10000 --open <wan-ip>

Compare the result against your expected surface profile. On a correctly hardened gateway, you should see zero open ports on the WAN interface unless you deliberately designed an inbound service and documented its justification. If ports appear here that did not survive your iptables review, trace them immediately. A common culprit is UPnP, which many gateway builds enable by default. UPnP can dynamically punch holes through the firewall on behalf of LAN-side devices, and it does so without generating a visible iptables rule for you to catch during internal review.

Development teams that skip this step frequently discover after deployment that their management interface was reachable from the internet, either because a NAT rule was misconfigured or because a testing exception in the firewall was accidentally committed to the production image. At that point, a patch requires an OTA update, device recall coordination, or worse.

PSA Certified and Matter’s Requirements Around Open Services

Both PSA Certified and the Matter specification treat open network services as a counted risk, not a neutral fact about how software works. PSA Certified Level 1 requires that the device security model document all communication interfaces and justify their inclusion. An open port without documented justification is a finding during certification review, and it stalls your timeline in ways that are hard to recover from under a ship schedule.

NIST’s IoT device guidance (SP 800-213) frames the same principle under device least functionality: the device should operate with only the network capabilities required for its stated purpose, those capabilities should be documented, and active controls should enforce that boundary rather than relying on passive assumptions about what is installed.

Matter’s device attestation and commissioning model assumes the device presents a minimal, predictable interface during the provisioning window. Leaving dnsmasq’s DNS port open on the WAN side, for instance, can create unexpected behavior during interoperability testing and delay your certification milestone at a point in the product cycle where delays are expensive.

A compliance-aware port audit checklist at each build milestone covers:

  • Enumerate every listening port per build and link each to a documented functional requirement
  • Record whether each port is WAN-facing, LAN-facing, or scoped to a management interface only
  • Confirm that no port is reachable on WAN without explicit design intent and security sign-off from the responsible engineer
  • Run the outside-in scan after every package update or kernel version bump, not only at release candidate stage
  • Maintain a diff of port lists between build versions so regressions surface before they reach production

This checklist is not a one-time gate. It is a recurring test that belongs in your CI pipeline alongside your unit tests and image size checks. A port that is absent in build 42 and present in build 43 is a regression that deserves a root cause, not a footnote in the release notes.

Clearing the Field-Readiness Bar, Port by Port

Shipping a connected device is a long-term commitment. Once it is in someone’s home, factory floor, or utility cabinet, every open port is a liability that belongs to the manufacturer. Regulatory pressure on IoT security is increasing across the EU, the UK, and the US, and documented negligence around attack surface management carries real consequences.

The audit pattern described here repeats cleanly at every milestone. Start with an inside-out enumeration to build a complete picture of what the kernel is serving. Apply iptables rules that enforce least-access, tuned for the memory constraints of your specific hardware target. Then step outside the network entirely and confirm that the WAN-facing surface matches your intent exactly, using the same perspective an attacker would have.

Devices that pass this sequence at every build milestone reach the field with a documented, intentional port profile. That documentation supports your PSA Certified review. It supports your Matter interoperability testing. It gives your security team a concrete artifact to point to during a customer audit. And it means that when a researcher eventually points a scanner at one of your deployed devices, the answer is silence. Silence, in this context, is exactly the right answer.

LEAVE A RESPONSE

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