Hello,
I'm facing a specific issue with FTP (plain FTP, port 21) when using OPNsense, which does not occur on pfSense or MikroTik, and I'd like to know if anyone has seen something similar.
Scenario
Firewall: OPNsense (current version)
WAN: Single WAN
Client host: 172.16.10.250
FTP client: FileZilla (also tested via CLI)
Server: External FTP server in the cloud
Protocol: Plain FTP (no TLS)
Problem
FTP connection works
Login works
Initial commands work
On LIST / LS, the server immediately returns:
501 server cannot accept argument
This happens right after PASV, before any data connection is established (so it's not a timeout or blocked port).
Tests already done
Firewall rules allowing all traffic
Outbound NAT (auto, hybrid, manual)
MTU changes
Disable scrub / normalization (GUI + tunables)
Disable reply-to
IDS/IPS disabled
Single WAN
Active/passive mode tests
EPSV disabled
➡️ Issue persists only on OPNsense.
Comparison
pfSense: works
MikroTik: works
OPNsense: fails with 501 on LIST
Packet capture findings
PASV → server replies 227 Entering Passive Mode
Immediately after, server sends 501
Indicates command rejection, not blocked data channel
Payload is logically the same, but TCP segmentation/reassembly differs
FTP server appears not tolerant to normalized/fragmented commands
FTP Proxy plugin
Tested os-ftp-proxy, but:
It is not a transparent FTP helper
Requires changing client port/endpoint
Does not behave like the old FTP ALG
Not suitable without modifying clients
Question
Is this a known incompatibility between OPNsense PF TCP normalization and some FTP servers?
Is there any way to:
Fully disable TCP normalization for FTP?
Pass FTP traffic completely untouched?
Any known regression or workaround?
Thanks in advance for any insight.
I wonder if configuring MTU or MSS clamping could help avoid TCP fragmentation and keep LIST/LS running smoothly. In my experience, these small changes sometimes resolve 501 errors without needing to fix the client.
Granny Game (https://grannygame.org/)
Your packet capture findings are actually the most important clue here. A 501 server cannot accept argument immediately after PASV, before any data channel is negotiated, almost certainly means the FTP server is rejecting the control-channel command itself rather than anything related to firewalling or blocked ports. On OPNsense, PF's TCP normalization and reassembly can still behave differently from pfSense or MikroTik, even when scrub rules appear disabled in the GUI. Subtle differences in how TCP segments are split or reassembled can cause commands like LIST to arrive in a format that very strict or legacy FTP servers simply refuse to accept. This would also explain why the payload looks logically identical while still triggering a server-side rejection.
A few non-obvious things worth checking or testing:
Explicitly disable MSS clamping on the WAN interface, even if MTU seems correct.
Inspect the active PF ruleset directly (pfctl -sr) to confirm no implicit scrub rules remain.
Test with a lower MTU on the client host only (e.g. 1400) to see if segmentation behavior changes.
Compare raw FTP CLI output with command echoing enabled to verify command boundaries .It's a bit like using an Albert Heijn Bonuskaart (https://bonuskaartonline.nl/).If feasible, try routing FTP traffic through a minimally processed interface or VLAN.
OPNsense currently does not provide a true "pass completely untouched" equivalent to old-style FTP ALG behavior, so some servers that are intolerant to normalization quirks can still fail in exactly this way.