Getting a FlashForge 3D printer to work from a different VLAN than the one it sits on — discovery, FlashForge Studio, and Home Assistant.
If you segment your network and your printer lives on an isolated VLAN, you have probably hit one or both of these:
- The printer never appears in FlashForge Studio's device list, no matter what mDNS/Bonjour reflector you install.
- The printer does appear, but entering the correct access code fails to connect.
Neither problem is what it looks like. This repo explains why and provides a working fix.
Verified on OPNsense 26.7 (FreeBSD 15.1) with a FlashForge Creator 5 Pro (firmware 1.9.4). The approach should apply to other Klipper-era FlashForge models and to any pf-based firewall.
| Symptom | Real cause | Fix |
|---|---|---|
| Printer invisible across VLANs | It doesn't use mDNS at all. It uses a proprietary protocol on 225.0.0.9:19000 and subnet broadcast :48899, and the query is sent with TTL=1 |
socat relay that re-originates the query (rc.d/flashforge_relay) |
| Visible but access code "fails" | Studio takes the printer's address from the source IP of the discovery reply, ignoring the ipAddr in the payload — so it dials your firewall |
Port-forward firewall_vlan_ip:8898 and :8080 to the printer |
An mDNS reflector (Avahi, mdns-repeater) will not help. Keep it for HomeKit/AirPlay/etc.,
but it is irrelevant to this printer.
A packet capture of a laptop connecting to the printer on the same VLAN shows the printer sending zero mDNS traffic. It never advertises itself. What actually happens:
Query: CLIENT:18000 -> 225.0.0.9:19000 TTL=1 8 bytes magic "FPJ8"
Reply: PRINTER:19000 -> CLIENT:18000 TTL=64 280 bytes magic "J8FP" + model + serial
Query: CLIENT:18001 -> <subnet>.255:48899 TTL=1 8 bytes magic "FQ.."
Reply: PRINTER:48899 -> CLIENT:18001 TTL=64 280 bytes
Two independent reasons this cannot cross a router:
- TTL=1 on the query. It is decremented to zero at the first hop and discarded. Multicast
routing (
igmpproxy, PIM) does not help — those also decrement TTL. - Wrong group.
mdns-repeaterand Avahi are bound to the mDNS group224.0.0.251:5353. This traffic is on225.0.0.9, and the second channel is a directed subnet broadcast. Neither is ever touched.
The only way across is something that re-originates the query with a fresh TTL.
See docs/protocol.md for the full packet-level breakdown.
rc.d/flashforge_relay runs two socat processes on the firewall.
Each joins the relevant group/port on every client VLAN, and forwards any query it receives to
the printer, returning the printer's reply to whoever asked.
pkg install socat
install -m 755 rc.d/flashforge_relay /usr/local/etc/rc.d/flashforge_relay
install -m 644 rc.conf.d/flashforge_relay.example /etc/rc.conf.d/flashforge_relay
# edit /etc/rc.conf.d/flashforge_relay for your printer IP and VLAN addresses
service flashforge_relay startConfigure with the firewall's own IP on each client VLAN — these are the interfaces that will listen for discovery queries:
flashforge_relay_enable="YES"
flashforge_relay_printer="10.60.0.13"
flashforge_relay_ifaces="10.10.0.1 10.20.0.1 10.30.0.1"Verify the multicast joins landed:
service flashforge_relay status
ifmcstat -i <iface> | grep 225.0.0.9Usually none are needed. The relay talks to the printer from the firewall itself, and pf state carries the reply back. Notably the printer never needs to initiate anything toward your client VLANs — so you can keep the printer VLAN fully isolated from internal networks.
If your printer VLAN blocks traffic to RFC1918 destinations (a good idea — see Security below), that block does not need an exception for this to work.
With the relay running, discovery works and the printer appears in Studio. Entering the correct access code still fails. A capture on the client side shows why:
CLIENT:59982 > FIREWALL_VLAN_IP:8898 SYN, retried 3x, no response
Studio recorded the firewall as the printer's address, because that is where the discovery
reply came from. It ignores the ipAddr field inside the reply payload. The port is closed, so
the connection times out — and Studio reports it as an authentication failure, which sends you
chasing a perfectly valid access code.
Two ways to fix it. Port forwarding is recommended — it is simpler and works regardless of which address Studio picks:
rdr pass on <client_if> inet proto tcp from any to (<client_if>):8898 -> PRINTER_IP port 8898
rdr pass on <client_if> inet proto tcp from any to (<client_if>):8080 -> PRINTER_IP port 8080
In the OPNsense GUI: Firewall → NAT → Port Forward, one pair per client VLAN, destination
<VLAN>ip, target the printer. Port 8898 is control; 8080 is the camera stream.
The alternative is source-NAT on the relay's replies so they appear to come from the printer.
That is arguably more "correct" but needs a NAT rule per VLAN with static-port, and relies on
source-address rewriting. The port forward is fewer moving parts.
Probe the protocol directly without the app — from a client on a different VLAN:
printf '\x46\x50\x4a\x38\x00\x10\x30\x90' | socat -T4 - UDP4-SENDTO:225.0.0.9:19000,ip-multicast-ttl=1 | stringsA working setup returns a 280-byte reply containing the model name. docs/troubleshooting.md
has a decision tree for when it doesn't.
Confirm the control channel independently of Studio:
curl -s -X POST http://PRINTER_IP:8898/detail \
-H 'Content-Type: application/json' \
-d '{"serialNumber": "YOUR_SERIAL", "checkCode": "YOUR_ACCESS_CODE"}'{"code":0,...} means the credential and path are both fine — any remaining failure is in the
app's address handling, not your firewall.
Worth knowing before you decide how much access to grant this device:
- The access code is sent in cleartext.
POST /detailis plain HTTP with{"serialNumber": ..., "checkCode": ...}in the body, on every poll. Anyone who can observe the network — including passively over Wi-Fi — recovers full control of the printer. This is a protocol limitation; no firewall configuration fixes it. - The camera is unauthenticated. Port 8080 serves
mjpg-streamerwith no credentials. Anyone who can reach the port gets a live video feed. - Consequently: keep the printer on an isolated VLAN, make sure the WLAN it uses has a strong WPA2/WPA3 PSK, and do not expose either port to the internet.
The design here is deliberately one-directional — clients reach the printer, the printer reaches nothing. You can keep a blanket "block printer VLAN → all internal networks" rule in place.
flashforge_relayis a hand-rolled rc script, not an OPNsense plugin. It has no GUI, and a major firmware upgrade may remove it. Keep a copy off the firewall.- Tested with one model and one firmware. The 8-byte query magic may differ on other FlashForge generations — capture your own on-VLAN session to confirm (see docs/protocol.md).
- Some older models use TCP 8899 for control instead of 8898. Scan your printer to see which.
Adam Feind (@afeind)
Findings come from packet captures taken on a live OPNsense deployment. Corrections and results from other FlashForge models are welcome — please open an issue.
MIT © 2026 Adam Feind — see LICENSE.
All IP addresses, serials, and access codes in this repository are examples. Substitute your own.