Ok so your using active. Which means the client sends some random Port and server will connect to your client on that port from Port 20.
The issue is, that on site B the servers source port is 20. But after it goes through NAT that port could be random. Which is why you need to setup a static port nat. In a normal nat setup you run into this – these are source ports going to say port 1028 on server from client
privateip:20 --->public:2028 (NAT router) publicIP:randomPORT ---> public:2028
Now to be honest your ftp helper on side A should allow for this and send the traffic in to your client. No matter what the source port is.
All you really should have to do is setup site B to forward 21 to your server - you could lock this down so only site A IP is allowed.
When your server comes back to site A -- your ftp helper should allow the connection back in. I don't have any problems using active pfsense from behind a nat. Now if you lock down B to only allow specific ports outbound you might have issues? What are your lan rules on site B? Do you allow all outbound ports? Even if you do not, just allow all outbound ports to site A IP from source of your ftp server private IP on your lan rules and you should be good.
What version of pfsense are you using btw. I know I have no problems with active connections to ftp server from my clients - I am using 2.1 version of pfsense. Let me make a test connection to show you.
edit: So here is active connection to server on the public internet from client behind nat
Status: Resolving address of snipped.net
Status: Connecting to 173.xx.xx.xx:21...
Status: Connection established, waiting for welcome message...
Response: 220 snipped FTP Server
Command: USER johnpoz
Response: 331 Password required for johnpoz
Command: PASS **********
Response: 230 User johnpoz logged in
Command: SYST
Response: 215 UNIX Type: L8
Command: FEAT
Response: 211-Features:
Response: MDTM
snipped for brevity
Response: REST STREAM
Response: SIZE
Response: 211 End
Command: OPTS UTF8 ON
Response: 200 UTF8 set to on
Status: Connected
Status: Retrieving directory listing...
Command: PWD
Response: 257 "/" is the current directory
Command: TYPE I
Response: 200 Type set to I
Command: PORT 192,168,1,100,98,136
Response: 200 PORT command successful
Command: MLSD
Response: 150 Opening ASCII mode data connection for MLSD
Response: 226 Transfer complete
Status: Directory listing successful
So you see there where client sent its Private IP of 192.168.1.100 on port (256x98+136 = 25224)
And pfsense helper changed that IP to my public one, and allowed the connection back into my client. Unless your blocking outbound connections on your side B. You should have no issues. And only rule you should need is forward 21 on side B, and allow the ports outbound on your Side A
So I just looked in my states after doing a few refreshes, so the PORT command changes every time you make a data connection.
192.168.1.100:25238 <- 24.13.xx.xx:25238 <- 173.xx.xx.xx:20
Notice how the public port is same as private port - that is doing a static nat. That is not always the case in a napt nat setup you could have something like this in the state
192.168.1.100:2283 <- 24.13.xx.xx:25238 <- 173.xx.xx.xx:20