Hi all I have a strange behaviour in pf on 5.9-stable:
A system (asterisk) behind the gateway is receiving and replying to udp streams (RTP). The connection parameters (src/dst ip/port) are set up before (STUN and SIP), so both systems "know" where to send to. The gateway does NAT (rdr-to in, nat-to out) for the system. But while incoming packets are forwarded with source and destination port unchanged, the source port on the outgoing packets is changed (to something in the >50000 range). This breaks the connection, as the external system (resp. the firewall it is behind) expects the packets to have the original dst port as src port. The same happens when the system starts a udp stream on its own - the source port gets rewritten. Also the UDP checksum appears to be wrong after the NAT. Short question: How do I prevent pf from changing the source port of outgoing natted udp packets? Long question: tcpdump: $int_if: 18:40:21.392468 $int_server_ip.10442 > $external_system.5012: [udp sum ok] udp 32 (DF) (ttl 64, id 64912, len 60) 18:40:21.396091 $external_system.5012 > $int_server_ip.10442: [bad udp cksum a9e7! -> 316d] udp 32 (ttl 115, id 9052, len 60) 18:40:21.413332 $int_server_ip.10442 > $external_system.5012: [udp sum ok] udp 32 (DF) (ttl 64, id 64916, len 60) 18:40:21.415143 $external_system.5012 > $int_server_ip.10442: [bad udp cksum a9e7! -> 7036] udp 32 (ttl 115, id 9053, len 60) ... $ext_if: 18:40:21.392510 $sext_server_ip.51049 > $external_system.5012: [bad udp cksum 528b! -> e3da] udp 32 (ttl 63, id 16487, len 60) 18:40:21.395975 $external_system.5012 > $sext_server_ip.10442: [udp sum ok] udp 32 (ttl 116, id 9052, len 60) <--This is a "new" incoming stream 18:40:21.413377 $sext_server_ip.51049 > $external_system.5012: [bad udp cksum 528b! -> 53d8] udp 32 (ttl 63, id 30449, len 60) 18:40:21.415089 $external_system.5012 > $sext_server_ip.10442: [udp sum ok] udp 32 (ttl 116, id 9053, len 60) ... The problem seems to be that the internal system tells the external one about the source port (10442) it should connect to (via SIP), and as last step sends a packet from that port (plus in-protocol info, I assume). But pf changes that source port on that outgoing packet (to 51049), and keeps doing so for all following packets, while the external system sticks to the protocol and sends its traffic to 10442. So it looks like pf can't distinguish between what it sees as "follow up" packets to the first outgoing packet (18:40:21.392468) and the reply packets to the "incoming" stream. The connection breaks because the firewall the $external_system is behind expects replies to the packets send to 10442 to come back from that port. All of this wouldn't happen if the source port hadn't been changed to 51049. So: is there any way of preventing this behaviour? I didn't find anything in pf.conf(5) or elsewhere ... Thx for any insight, folks /markus PS: These are the rules in question: match in from any to $ext_server_ip rdr-to $int_server_ip match out from $int_server_ip to any nat-to $ext_server_ip pass log quick on { $ext_if, $int_if } inet proto udp from any to $int_server_ip port { 9999 >< 11001 } label "RTP IN -- ACCEPT " pass log quick on { $ext_if, $int_if } inet proto udp from $int_server_ip to any port { >= 1024 } label "UDP HIGH OUT -- ACCEPT "