I had the exacy same problem for quite some time, and it's still not quite clear to me why it doesn't work, but this is what I found:
The port forwarding itself work just fine, the problem is when you combine this with policy routing in such a way that you need a policy route to "activate" to route the traffic out through the correct interface. Since the incoming, port-forwarded packets are placed in the state table, and thus when the computer on the inside replies to that packet, the reply is automatically accepted via the state table. Because of this, the policy routing rule is never evaluated, and thus the packet defaults to the default routing table - usually ending up exiting through your WAN, not the VPN tunnel. Since these addresses are normally in a private range, the packet will just die alone in the cold in some router out there on the internet.
In pfSense 2.1 they have made some fix to this that auto creates a "reply-to" rule when you create an incoming NAT/port forwarding. This works, and you can find it in rules.debug, but for some reason it doesn't seem to be executed correctly in all cases (not in my case atleast). What I did to correct the issue, was to make a floating rule, placed on top or near the top of the floating rules, that basicly exactly matches the auto-created interface firewall rule that the NAT/Port Forwarding rule generates. The only visible difference for me, is that this rule ends up much higher up in the rules.debug ruleset, but it makes all the difference - and suddently the portforwarding from a openVPN tunnel works perfectly.