The washer-dryer talks to its maker's cloud and to nothing else. That much every owner knows. What we did not know, and could not find written anywhere, was how it talks: which server, which protocol, whether the conversation could be kept inside the flat. So on a Saturday with a full drum we listened to the whole cycle, three hours and twelve minutes of it, from the first packet after power-on to the last one after the door unlocked.
The machine that washes the clothes also talks to a server on another continent, in a protocol it will not discuss with anyone else. We wanted to know exactly what it says. This required a router with a packet sniffer, a Saturday, a full drum, and a certain amount of humility at the end.
How to listen without a laptop in the laundry room
The router can mirror traffic. Its packet sniffer streams frames over UDP to any host, and a sixty-line Python receiver on the home server turns that stream into a standard capture file. Filter on the machine's hardware address and the firehose (four megabytes a second for the whole flat) becomes a trickle: 5,900 frames for an entire wash. The receiver, the router control and the flow classifier were written and rehearsed weeks earlier on synthetic traffic, because the machine only connects when somebody is home to start it.
Two things bit us anyway. Frames towards the machine arrived with a VLAN tag, so a
parser that assumed plain Ethernet saw one direction only and confidently reported that DNS
answers never came back (they did; the server answered on the same segment, past the router).
And the router's sniffer stops streaming after about 100 kilobytes while still reporting
running: true; a watchdog that restarts it whenever the capture file stops growing
saved the day, at the cost of a few lost seconds per restart.
What the machine actually does
At power-on it asks our own DNS resolver (not a hard-coded public one, which was the first thing we checked and the best news of the day), resolves three names, and opens exactly two kinds of connection. Three short HTTPS sessions to a provisioning host in the first minute, then nothing more from that host all day.
And one long MQTT-over-TLS session to the manufacturer's message broker, which lives on a large cloud provider's IoT service, held open for the entire cycle: about five small records a minute from the machine, a hundred and thirty kilobytes up, twenty-eight down, a modest burst when the door unlocks. NTP once an hour. That is the whole vocabulary.
The wall, precisely measured
Reassembling the TLS handshakes by sequence number told us what the summary could not. The broker presents a certificate from the cloud provider's IoT service and then sends a CertificateRequest; the machine answers with its own certificate and a signature. The certificate's common name is the appliance's identifier, the same string the cloud integration uses. So this is mutual TLS with a per-device key that lives inside the machine. Both channels do it. Nothing is in the clear, nothing is guessable, and there is no local port to speak of.
What follows from that is exact. Pointing the broker's hostname at a local server is trivial, since the machine trusts our resolver. Getting the machine to accept that server is the question, because it will check the server's certificate against the cloud provider's root, and ours cannot be signed by that.
The test is cheap: a self-signed certificate with the right name, a probe that requests the client certificate but never rejects it, and the router redirecting the machine's port 8883 to the probe. The expected result is a TLS alert, "unknown CA", and the end of the road.
The test that failed for a different reason
We ran it, and the machine's display said the Wi-Fi connection had failed. That was not the alert we were waiting for. The capture showed the machine associating normally, finishing its HTTPS provisioning, and then sending SYNs to five different broker addresses in turn, with no reply to any of them. The redirect rule had matched all twenty-one packets. The probe had accepted zero connections.
The reason is old and well documented, and we walked into it anyway: the machine and the home server sit on the same subnet. The router rewrote the destination and forwarded the packet to the server, but the server's reply went straight back to the machine over the same wire, never passing the router, never being un-rewritten.
The machine received an answer from an address it had never contacted and discarded it. A destination NAT between two hosts on one segment needs a source NAT as well, so that the reply is forced back through the box that did the rewriting. We knew this. We had simply never needed it at home.
Rolling back took one command and the machine reconnected to its real broker within seconds; the rest of the wash ran on the cloud as usual. The corrected version, with the masquerade and a probe that does not exit after twenty connections, is staged for the next load. We still expect the "unknown CA" alert. But now we will get to see it.
We now know precisely how the washer talks to its maker and precisely why we cannot join the conversation. It is a strange kind of satisfaction, but it is satisfaction.