Add a Block Creality Cloud Telemetry option - #18
Open
arlophoenix wants to merge 2 commits into
Open
Conversation
The stock telemetry agent (alchemistp) uploads printer configs and Klipper logs to *.cxswyjy.com, which the crealitycloud.com-only blocklists in circulation do not cover at all. This adds a menu option that blackholes the 16 known Creality cloud hosts in /etc/hosts and drops outbound MQTT on tcp 1883/8883 to anything off the LAN. The rules are re-applied by an init script because the K1 2025 rootfs is a volatile RAM filesystem, so /etc/hosts reverts to stock on every boot, and iptables rules never survive a reboot on any model. It is a blocklist, not a firewall: the OUTPUT policy is untouched and nothing else is filtered, so the cloud relay options the helper installs keep working. iptables is missing entirely on the K1 and Ender-3 V3 series, so the port rules are skipped there and only the hosts blocklist is applied.
Review found that both halves of this option identified their own state by matching content, so uninstall could remove things it never created. A user who had already blackholed one of these hosts by hand lost that line, and an identical MQTT rule belonging to another tool was deleted along with ours. The hosts entries now live between BEGIN and END markers and are removed as a range, and the firewall rules live in a CREALITY_CLOUDBLOCK chain that is flushed and deleted on uninstall. Both are rebuilt from scratch on every start, so a changed LAN, a hand-edited entry, or a host list that grew between versions self-heal instead of accumulating. Removing the content matching also removed the need to recompute the LAN at uninstall time, which used to strand ACCEPT rules for a subnet the printer had moved off. The chain is linked with an insert rather than an append, because an OUTPUT chain that already carries a broad ACCEPT would otherwise match before the drops and the block would silently do nothing. Rule failures are no longer swallowed: iptables calls take -w where the build supports it, a present-but-unusable iptables is now distinguished from a model that has none, and start propagates a non-zero exit so the installer stops reporting success after a partial apply. Also pins umask 022 for the same reason S56moonraker_service does, stops requiring "proto kernel" in ip route output, and keeps the guard against a hosts file with no trailing newline, without which the begin marker would join onto the last line and hide the block from the range delete.
arlophoenix
marked this pull request as draft
July 27, 2026 20:34
arlophoenix
marked this pull request as ready for review
July 27, 2026 23:40
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Creality's stock telemetry agent uploads printer configs and Klipper logs to
*.cxswyjy.com, a domain thecrealitycloud.com-only blocklists in circulation do not cover at all. This adds a Customize menu option that blackholes the 16 known Creality cloud hosts and drops outbound MQTT to anything off the LAN.The agent is
alchemistp(init scriptCS61alchemistp_service), whose config at/etc/appetc/alchemistp/config.jsondeclaresUploadFileFlag: 1over/usr/data/printer_data/config/*and/usr/data/printer_data/logs/*, pointed atc-smart.cxswyjy.comanddevdata.cxswyjy.com. It has already uploaded:upload_file_offset.jsonon a stock machine listsprinter.cfg,klippy.logand the per-daemon logs as having gone out. Captured on the wire mid-print on a K1C 2025, with a five-host.comblocklist already active:That SYN-ACK is a real AWS load balancer answering, and
/proc/net/tcpshowed the socket established a minute later. Separately,onyxpbeacons SN and MAC to the.cnsignalling hosts once per boot and got a live{"code":4,"errMsg":"Invalid Token"}reply, which likewise means a server answered rather than a blackhole.The option installs the hosts entries and an init script at
$INITD_FOLDER/S995cloudblock. The boot script is not optional bookkeeping: on the K1 2025 the rootfs is a volatile RAM filesystem, so/etc/hostsreverts to stock on every boot, and iptables rules never survive a reboot on any model.Everything the script writes is explicitly owned rather than identified by matching content, because content matching means uninstall removes state it never created. The hosts entries live between
# BEGINand# ENDmarkers and are removed as a range, so a user who had already blackholed one of these hosts by hand keeps their line. The firewall rules live in aCREALITY_CLOUDBLOCKchain that uninstall flushes and deletes, so an identical MQTT rule belonging to another tool survives, and removal does not need to know which LAN was attached at install time. Both are rebuilt from scratch on every start, so a changed subnet, a hand-edited entry, or a host list that grew between versions self-heal instead of accumulating.Two details are worth calling out because the obvious implementation gets them wrong. Loopback needs an explicit exemption ahead of the MQTT drops: with the hosts blackhole active a daemon resolves
mqtt.crealitycloud.comto0.0.0.0, the kernel routes that connect to127.0.0.1:1883, and a plain--dport 1883 -j DROPswallows it silently instead of letting it fail fast with a RST. And the chain is linked into OUTPUT with an insert rather than an append, because an OUTPUT chain that already carries a broad ACCEPT would otherwise match first and the drops would never be reached. The LAN is detected fromip routerather than hardcoded, keyed onsrcplus a CIDR rather than onproto kernelwhich not everyipimplementation prints, and the exemption is skipped entirely when detection turns up nothing, because a wrong CIDR on a headless printer is undebuggable remotely.Failures are not swallowed. iptables calls take
-wwhere the build supports it and fall back where it does not, a present-but-unusable iptables is distinguished from a model that simply has none, andstartreturns non-zero so the installer reports a partial apply instead of printing success over it.Per-model behaviour is gated on capability, not assumption. The K1 and Ender-3 V3 series ship without an iptables binary even though the kernel module is loaded, so the port rules are skipped there and the install says so; the hosts blocklist still applies.
INITD_FOLDERfrompaths.shhandles the/usr/apps/etc/init.dversus/etc/init.dsplit, and on the 2025 that path is what/bin/seed.shwalks forS??*at boot.This is a blocklist, not a firewall. The OUTPUT policy is left untouched and nothing else is filtered, so OctoEverywhere, Obico, GuppyFLO, SimplyPrint, OctoApp and Mobileraker are unaffected.
Test plan
sh -nparses the new boot script, the new option,paths.sh, and all twelve touched menu filesdashagainst a stateful fakeiptables(custom chains included) and a fakeip route: 16 entries applied, idempotent across repeated starts, the chain linked once and first in OUTPUT, and after uninstall no rules, no chain, and no residue0.0.0.0entry for a blocked host survives uninstall, another tool's identical--dport 1883 -j DROPand broad-o lo -j ACCEPTare left untouched, and a hand-edited managed line heals on the next start rather than duplicating-w, no route detected, and a subnet change between install and uninstall all behave correctly and leave nothing behind/etc/hostsrestored byte-for-byte on a newline-terminated file; on a file with no trailing newline it comes back with one synthesised newline added and is otherwise identicalsedrange delete and its unterminated-block recovery,localin ash,tail -c, theip routeparse,iptables -wand-Csupport on the 2025 and the total absence of iptables on the OG,/etc/hostsbeing a regular file on both, and thatrcKcallsstopat shutdownThe shell-level checks above use fakes for
iptablesandip route, so they verify the logic rather than the live effect. Nothing has been installed on a printer, no reboot persistence test has been run, and the per-model gating is reasoned rather than observed on four of the six models. The manual pass below is the one that matters and has not been done.Manual test pass
/etc/hostsand an executableS995cloudblockin$INITD_FOLDERnslookup devdata.cxswyjy.com; expect0.0.0.0S995cloudblock status; expect 16 entries reported and the chain listed with the loopback and LAN ACCEPT rules above both dropsiptables -L OUTPUT -v -n; expect the jump toCREALITY_CLOUDBLOCK, and the 1883 drop counter not climbing steadily (steady growth means the loopback exemption is wrong)/etc/hostsidentical to stock, noCREALITY_CLOUDBLOCKchain, and the init script goneNot addressed
/etc/hostscannot express wildcards, so any other subdomain ofcxswyjy.comorcrealitycloud.cnstays reachable, and a hardcoded IP bypasses the hosts file entirely. The port rules cover the hardcoded MQTT brokers invectorp(47.114.48.45:1883and120.55.101.240:1883), but the wildcard gap is real. Closing it properly needs a default-deny egress firewall, which breaks every cloud relay option this helper ships, so that UX problem should be solved before such a thing is offered to anyone.The LAN wait at boot is capped at five seconds. If DHCP takes longer than that on a cold wifi association, the chain is built without a LAN exemption and a local MQTT broker stays unreachable until the next start. Raising the cap would delay boot on a printer with no network at all, and a background retry felt like more machinery than this warrants, so the bound stays fixed and visible as
LAN_WAIT_SECONDS.Remove is gated on the init script existing. If someone deletes
$INITD_FOLDER/S995cloudblockby hand, the hosts entries and the chain stay live with no menu path to clear them; recovery is to install again and then remove. On the K1 2025 a reboot clears both anyway, since the rootfs and the ruleset are volatile.Disabling the stock daemons outright is deliberately separate. The two are complementary rather than alternatives: disabling removes the processes that want to talk, blocking removes the ability, and the block is what still protects a user after a firmware OTA or a helper reinstall puts the daemons back.
IPv6 is not filtered. The 2025 has no IPv6 address and no v6 default route, so v6 egress is currently impossible, and its kernel has no ip6
filtertable at all, so if SLAAC were ever enabled there would be no way to filter it.The single stale broker IP
47.253.214.226that older blocklist scripts pin is deliberately not included. It appears in none of the seven stock binaries; it was a runtime DNS answer formqtt.crealitycloud.comon one particular day and pinning it achieves nothing the hosts entry does not.