# MQTT Service Detection and Version Identification

- **URL:** https://hackindex.io/services/mqtt/enumeration/mqtt-service-detection-and-version-identification
- **Path:** MQTT > Enumeration
- **Up:** [Enumeration](https://hackindex.io/services/mqtt/enumeration.md)
- **Published:** 2026-03-16
- **Updated:** 2026-03-16

MQTT brokers listen on TCP 1883 for plaintext and TCP 8883 for TLS. Neither port is universally standard: embedded devices and IoT deployments frequently use non-standard ports or run brokers on [localhost](http://localhost) only. The first step is confirming the service is present, that it speaks MQTT, and what implementation is running.

## Nmap Service Detection

```bash
nmap -sV -p 1883,8883 $TARGET_IP
# PORT     STATE SERVICE  VERSION
# 1883/tcp open  mqtt     Mosquitto mqttd 1.6.9
# 8883/tcp open  ssl/mqtt Mosquitto mqttd 1.6.9
```

Nmap's service detection recognises MQTT by the CONNECT/CONNACK handshake. A version string in the output identifies the broker software. Common implementations you will encounter:

- Mosquitto: most common on Linux targets
- HiveMQ: enterprise Java broker, community and commercial editions
- EMQX: Erlang-based, common in large-scale IoT deployments
- VerneMQ: Erlang-based, clustered deployments
- RabbitMQ with MQTT plugin: general-purpose message broker with MQTT support

Scan common alternative ports:

```bash
nmap -sV -p 1883,8883,1884,8884,11883 $TARGET_IP
```

## Confirm with Mosquitto Client

The `mosquitto_sub` client attempts a CONNECT and reports the broker's CONNACK response code, which tells you immediately whether anonymous access is permitted:

```bash
mosquitto_sub -h $TARGET_IP -p 1883 -t '#' --retained-only -C 1 -v 2>&1 | head -5
# Client mosqsub|12345-kali sending CONNECT
# Client mosqsub|12345-kali received CONNACK (0)
```

CONNACK return code 0 means connection accepted. Any non-zero code means the connection was refused: the reason tells you more:

| Code | Meaning |
| --- | --- |
| 0 | Accepted |
| 1 | Unacceptable protocol version |
| 2 | Identifier rejected |
| 3 | Server unavailable |
| 4 | Bad username or password |
| 5 | Not authorised |

Code 4 or 5 confirms authentication is required. Code 0 without supplying credentials confirms anonymous access: a vulnerability finding covered in [MQTT Unauthenticated Access](https://hackindex.io/services/mqtt/vulnerability-discovery/mqtt-unauthenticated-access).

## Confirm TLS on 8883

Check whether 8883 enforces TLS and note the certificate details:

```bash
openssl s_client -connect $TARGET_IP:8883 -quiet 2>/dev/null | head -10
# depth=0 CN=mosquitto
# verify error:num=18:self-signed certificate
# Certificate chain...
```

A self-signed certificate is common on embedded deployments. Note the CN and expiry: they sometimes reveal hostnames or internal domain names.

Connect over TLS without verifying the certificate:

```bash
mosquitto_sub -h $TARGET_IP -p 8883 --insecure -t '#' --retained-only -C 1 -v 2>&1 | head -5
```

`--insecure` skips certificate validation, which is required for self-signed certs.

## Identify Protocol Version

MQTT has versions 3.1, 3.1.1, and 5.0. The version affects available features and how the broker handles malformed packets. Force a specific version to test support:

```bash
mosquitto_sub -h $TARGET_IP -p 1883 -t '#' -C 1 -V mqttv311 2>&1 | head -3
mosquitto_sub -h $TARGET_IP -p 1883 -t '#' -C 1 -V mqttv5 2>&1 | head -3
```

If version 5 is rejected (CONNACK code 1) but 3.1.1 is accepted, note this: version 5 has better authentication controls and its absence is relevant for the security posture.

## References

- [Mosquitto: mosquitto_sub man page](https://mosquitto.org/man/mosquitto_sub-1.html) - Full reference for connection flags, version selection, and CONNACK code interpretation
- [Nmap NSE: mqtt-subscribe](https://nmap.org/nsedoc/scripts/mqtt-subscribe.html) - NSE script for MQTT topic subscription and broker fingerprinting
