Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

FlashForge cross-VLAN discovery and connection on OPNsense

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:

  1. The printer never appears in FlashForge Studio's device list, no matter what mDNS/Bonjour reflector you install.
  2. 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.


TL;DR

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.


Why mDNS is a dead end

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-repeater and Avahi are bound to the mDNS group 224.0.0.251:5353. This traffic is on 225.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.

Part 1 — the discovery relay

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 start

Configure 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.9

Firewall rules

Usually 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.

Part 2 — making Studio actually connect

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.

Verifying

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 | strings

A 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.

Security notes

Worth knowing before you decide how much access to grant this device:

  • The access code is sent in cleartext. POST /detail is 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-streamer with 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.

Caveats

  • flashforge_relay is 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.

Author

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.

License

MIT © 2026 Adam Feind — see LICENSE.

All IP addresses, serials, and access codes in this repository are examples. Substitute your own.

About

FlashForge mDNS and printer connection LAN solution - cross-VLAN discovery and FlashForge Studio connectivity on OPNsense

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages