I'm running OpenBSD 6.6 operating as an inter-VLAN and border router
using pf. Recently I wanted to use a nondefault state timeout for some
UDP traffic traversing from my voip subnet to a provider off site.
Within pf, there are three rules involved. The first is for traffic
coming from the voip subnet, which gets a six minute state timeout and a
tag:
pass in quick on vlan110 proto udp from any to port = 9430 tag VOIP_UDP
keep state (udp.multiple 360)
Then there is a NAT rule:
match out on $ext_if from 10.128.0.0/16 nat-to { $ext_vip } sticky-address
And a rule giving the traffic going out to the Internet a six minute
timeout as well:
pass out quick on $ext_if proto udp tagged VOIP_UDP keep state
(udp.multiple 360)
This initially looks like it worked; after the initial connection:
bash-5.0# pfctl -v -s state | grep -A1 '110.73:9430'
all udp 198.148.6.55:9430 <- 10.128.110.73:9430 MULTIPLE:MULTIPLE
age 00:00:00, expires in 00:06:00, 7:5 pkts, 4451:2203 bytes, rule 63
all udp 96.251.22.157:55202 (10.128.110.73:9430) -> 198.148.6.55:9430
MULTIPLE:MULTIPLE
age 00:00:00, expires in 00:06:00, 7:5 pkts, 4451:2203 bytes, rule
48, source-track
There are two states, one with the internal addressing and one for the
NAT translation, both with six minute timeouts. As time goes by:
all udp 198.148.6.55:9430 <- 10.128.110.73:9430 MULTIPLE:MULTIPLE
age 00:00:08, expires in 00:05:54, 31:31 pkts, 16469:18285 bytes,
rule 63
all udp 96.251.22.157:55202 (10.128.110.73:9430) -> 198.148.6.55:9430
MULTIPLE:MULTIPLE
age 00:00:08, expires in 00:05:54, 31:31 pkts, 16469:18285 bytes,
rule 48, source-track
all udp 198.148.6.55:9430 <- 10.128.110.73:9430 MULTIPLE:MULTIPLE
age 00:00:20, expires in 00:05:42, 31:31 pkts, 16469:18285 bytes,
rule 63
all udp 96.251.22.157:55202 (10.128.110.73:9430) -> 198.148.6.55:9430
MULTIPLE:MULTIPLE
age 00:00:20, expires in 00:05:42, 31:31 pkts, 16469:18285 bytes,
rule 48, source-track
More packets are seen, resetting the timeout:
all udp 198.148.6.55:9430 <- 10.128.110.73:9430 MULTIPLE:MULTIPLE
age 00:00:23, expires in 00:05:58, 32:32 pkts, 16872:19073 bytes,
rule 63
all udp 96.251.22.157:55202 (10.128.110.73:9430) -> 198.148.6.55:9430
MULTIPLE:MULTIPLE
age 00:00:23, expires in 00:05:58, 32:32 pkts, 16872:19073 bytes,
rule 48, source-track
all udp 198.148.6.55:9430 <- 10.128.110.73:9430 MULTIPLE:MULTIPLE
age 00:00:38, expires in 00:05:43, 32:32 pkts, 16872:19073 bytes,
rule 63
all udp 96.251.22.157:55202 (10.128.110.73:9430) -> 198.148.6.55:9430
MULTIPLE:MULTIPLE
age 00:00:38, expires in 00:05:43, 32:32 pkts, 16872:19073 bytes,
rule 48, source-track
again:
all udp 198.148.6.55:9430 <- 10.128.110.73:9430 MULTIPLE:MULTIPLE
age 00:00:41, expires in 00:06:00, 33:33 pkts, 17275:19931 bytes,
rule 63
all udp 96.251.22.157:55202 (10.128.110.73:9430) -> 198.148.6.55:9430
MULTIPLE:MULTIPLE
age 00:00:41, expires in 00:06:00, 33:33 pkts, 17275:19931 bytes,
rule 48, source-track
all udp 198.148.6.55:9430 <- 10.128.110.73:9430 MULTIPLE:MULTIPLE
age 00:00:58, expires in 00:05:43, 33:33 pkts, 17275:19931 bytes,
rule 63
all udp 96.251.22.157:55202 (10.128.110.73:9430) -> 198.148.6.55:9430
MULTIPLE:MULTIPLE
age 00:00:58, expires in 00:05:43, 33:33 pkts, 17275:19931 bytes,
rule 48, source-track
etc, etc:
all udp 198.148.6.55:9430 <- 10.128.110.73:9430 MULTIPLE:MULTIPLE
age 00:02:26, expires in 00:05:52, 37:37 pkts, 18863:23594 bytes,
rule 63
all udp 96.251.22.157:55202 (10.128.110.73:9430) -> 198.148.6.55:9430
MULTIPLE:MULTIPLE
age 00:02:26, expires in 00:05:52, 37:37 pkts, 18863:23594 bytes,
rule 48, source-track
Until finally, there are no more packets for a while:
all udp 198.148.6.55:9430 <- 10.128.110.73:9430 MULTIPLE:MULTIPLE
age 00:02:36, expires in 00:05:54, 47:46 pkts, 24551:29876 bytes,
rule 63
all udp 96.251.22.157:55202 (10.128.110.73:9430) -> 198.148.6.55:9430
MULTIPLE:MULTIPLE
age 00:02:36, expires in 00:05:54, 47:46 pkts, 24551:29876 bytes,
rule 48, source-track
all udp 198.148.6.55:9430 <- 10.128.110.73:9430 MULTIPLE:MULTIPLE
age 00:03:31, expires in 00:04:59, 47:46 pkts, 24551:29876 bytes,
rule 63
all udp 96.251.22.157:55202 (10.128.110.73:9430) -> 198.148.6.55:9430
MULTIPLE:MULTIPLE
age 00:03:31, expires in 00:04:59, 47:46 pkts, 24551:29876 bytes,
rule 48, source-track
After this, the next time I look a couple seconds later, the state is
gone? It reproducibly seems to disappear a minute after the last traffic
is seen on the connection. Yet the timeout says 5 minutes are left?
Why would the state be removed when it still had five minutes left
before it expired? I know if it were a TCP state, it might go away
before the timeout expires if the connection is shut down. But this is a
UDP state. What would cause it to go away before the timeout expiration?
Is there something wrong with my initial rules?
Thanks much for any thoughts on this issue…