跳到正文
认知
返回认知精选
认知精选科技大约 20 小时前1
单一来源当前只有一个可用来源,尚未完成多源交叉核验

逆向工程科迈空气净化器以摆脱云端依赖

The year is 2017. A string of annual wildfires rocks the West Coast. The sky looks like this in the daytime:

My home, like many in the Bay Area, has no insulation and isn’t really air sealed. To avoid choking on soot, a lot of people started buying air purifiers like this one:

It’s an overpriced box fan with a HEPA filter and an air quality sensor. It has some controls for the fan speed, and it can also automatically ramp up if the air quality is bad. It’s ugly, but they’re so ubiquitous around here that I feel like no one even notices them anymore. Also, FWIW, the device works. It really does improve air quality.

This device became a staple item in our household when my wife eventually started cranking up the fan at night for white noise (a dual purpose!). Over time, I have become accustomed to it and now also require it to sleep.

The Good Night button#

Our home also has smart lighting, and it’s all integrated with Apple Home. At night, I always press the “Good Night” button, which shuts off all the lights. I really wanted to tie the fan into that. I’d press Good Night, the lights would shut off, and the fan would crank up to my wife’s preferred white noise volume.

The old Airmega didn’t have Wi-Fi, so there was no easy way to integrate it with Apple Home. When it eventually broke, I bought the now-discontinued Coway Airmega IconS (for non-discontinued Wi-Fi models, check out the Airmega 250S or Airmega MightyS). It’s still just a box fan with a HEPA filter, but it’s considerably more expensive, aims to look like a piece of fancy mid-century furniture, and most importantly, can be controlled over Wi-Fi (sort of).

The existing Home Assistant integration#

Coway’s iPhone app is an absolutely classic IoT affair. It takes forever to load, and it asks me to change my password nearly every time I launch it. Thankfully, a brave soul reverse-engineered the app and wrote an integration for Home Assistant. The integration more or less pretends to be the phone app. It polls the Coway cloud service for status updates and sends commands through it to control the fan. Home Assistant bridges that to Apple Home and… voilà!

Why ditch the cloud?#

The downside of this approach is that you’re still at the mercy (or lack thereof) of the Coway cloud service. It seems like at least once or twice a year, it breaks.

Here are some of the reasons I have seen it break:

· Coway didn’t like the integration hammering their servers and banned it. After a protracted argument with the community, they eventually settled on allowing it.

· Coway rewrote their phone app and rebranded it from IoCare to IoCare+, so the integration had to be rewritten as well.

· Coway made minor changes to the layout of the HTML that the integration scrapes, which broke it.

· Coway’s servers were periodically offline, which prevented any remote control of the device.

· Coway banned my account at one point for running an old version of the integration. I couldn’t control the fan remotely for weeks while I waited for their support team to reverse the ban.

On top of this, it seems unlikely that Coway will maintain this service forever. I suspect that eventually, like all IoT manufacturers, they’ll either charge for this service or discontinue it. My fan model is already discontinued (though there are other Wi-Fi enabled models, so… who knows).

A way in#

I admit, I have been lazy. For years, I put off trying to figure out a way to ditch the Coway cloud, because if the device was really locked down, it would be pretty tough. Presumably, when the fan starts up, it connects to coway.com (or whatever) and checks that the server’s SSL certificate is valid. Most likely, I wouldn’t be able to make a fake certificate that passes that check, so the fan wouldn’t connect to my server.

Also, setting up a man-in-the-middle (MitM) environment is just a pain in the neck. The fan would have to connect to an isolated Wi-Fi network that routes all its traffic through my own server on the way out to the internet. To do that, you have to configure a bunch of routing and firewall rules to redirect traffic. None of this is impossible (I’ve done it before), but it’s a hassle to set up, and it’s always finicky to get right. And once you have it set up, that’s just step one.

All that said, two major things have changed.

First, there was a recent security incident (October 2026) where someone discovered that eMudhra, one of the trusted internet certificate authorities, had used a very weak parameter for some of its private keys.

So, if the device is unpatched AND it has hardcoded root certificates AND it doesn’t pin the cloud service’s certificate, then… maybe that’s a way in. Admittedly, that’s a lot of ifs, but assuming the device doesn’t have any major security mistakes in its design, this could be the foothold needed to take control of it.

The second thing is simply AI. An LLM can set up everything you need for a MitM environment, so you can get straight to sleuthing out how the fan works. It can do this unattended, in minutes.

Once you can sit between the fan and the internet, you can see how it communicates, which should help us understand how to get the fan to talk to us instead of the cloud.

Our man in the middle#

Initially, I tried to set it up like this:

This actually didn’t work, because a Raspberry Pi uses a smallish PCB trace antenna that doesn’t get a ton of signal strength. With the Pi in the room with my router, the signal was too weak to reach the fan. I guess I could’ve moved the fan into the room with the router, but why do that when I can solve this with a convoluted technical solution?

The Raspberry Pi uses its Wi-Fi radio to run its own access point for the fan to connect to. It can’t easily do that while also connecting over Wi-Fi to the home network. So, I moved the Pi into the room with the fan and plugged its Ethernet port into my laptop, which bridges it to the home network over Wi-Fi:

Next, we need to configure the Pi.

I’m not really making a value judgment here on whether this is a fair thing to block, but Claude will not oblige the request, not even for… uhh… testing purposes.

Luckily, ChatGPT has no such compunctions.

After a few rounds of that, here are the nftables rules it ended up with:

scottjg@pi:~ $ sudo nft -a list ruleset table inet mitmproxy_ap { # handle 8 set client_interfaces { # handle 4 type ifname elements = { "wlan0" } }

chain prerouting { # handle 1 type nat hook prerouting priority dstnat; policy accept; meta nfproto ipv4 iifname @client_interfaces tcp dport { 80, 443 } counter packets 2 bytes 120 redirect to :8080 # handle 6 }

chain input { # handle 2 type filter hook input priority filter - 10; policy accept; iifname != "lo" iifname != @client_interfaces tcp dport 8080 counter packets 0 bytes 0 reject with tcp reset # handle 7 iifname @client_interfaces meta nfproto ipv6 counter packets 9 bytes 2397 drop # handle 8 iifname @client_interfaces ct state established,related accept # handle 9 iifname @client_interfaces udp dport { 53, 67 } accept # handle 11 iifname @client_interfaces tcp dport { 53, 8080 } accept # handle 13 iifname @client_interfaces ip protocol icmp accept # handle 14 iifname @client_interfaces counter packets 23 bytes 4697 reject with icmpx admin-prohibited # handle 15 }

chain forward { # handle 3 type filter hook forward priority filter - 10; policy accept; iifname @client_interfaces meta nfproto ipv6 counter packets 0 bytes 0 drop # handle 16 oifname @client_interfaces meta nfproto ipv6 counter packets 0 bytes 0 drop # handle 17 iifname @client_interfaces udp dport 443 counter packets 1 bytes 57 reject # handle 18 iifname @client_interfaces oifname != "eth0" counter packets 0 bytes 0 reject with icmpx admin-prohibited # handle 19 } } table ip nm-shared-wlan0 { # handle 12 chain nat_postrouting { # handle 1 type nat hook postrouting priority srcnat; policy accept; ip saddr 10.42.0.0/24 ip daddr != 10.42.0.0/24 masquerade # handle 2

Evidence

来源与证据

单一来源 · 1 个信源

当前仅有一个可用来源,尚未完成多源交叉核验。

发布时间
内容处理
AI 翻译 / 摘要,需结合原文核对
内容有误或来源失效?告诉我们

每天早上收到这 5 条

免注册,填邮箱即可;每封邮件都能一键退订。

提交即表示同意按隐私说明保存你的邮箱,只用于发送简报。

或用 RSS 订阅

AI 翻译、摘要和解读仅用于辅助判断;涉及重要决策时,请回到上方来源核实。