[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Still stumped

On Tue, Feb 08, 2005 at 11:30:22AM -0700, Tim Pushor wrote:
> I have tried everything I can think of, and am stumped. Any help is 
> greatly appreciated..
I think you're running into a state key conflict.
You're not using 'keep state' on your pass rules, but connections
involving 'nat' or 'rdr' always create state.
The first packet passes in on the internal interface. It matches the
'pass' rule without 'keep state', and just passes, not creating state.
> 01:21:03.093418 IP > UDP, 
Next, it is filtered outgoing on the external interface. It matches the
nat rule, gets its source address replaced, then matches a 'pass' rule
and passes.
> 01:21:42.041081 IP > UDP, 
Because the connection involves translation (nat), a state is
automatically translated:
  lan                   gwy                  ext
Next, the external peer replies. The reply arrives in on your external
> 01:21:42.109673 IP > UDP, 
Oddly, the peer is not replying to the source port you used (51881), but
to fixed port 5060. For pf, this packet does not match the state created
above, and is not part of the same connection.
Hence, filter rules are evaluated. The packet matches your rdr rule. The
destination address is replaced (from to, a
pass rule matches, the packet is passed. Since this second connection
involves translation (rdr), a state is created automatically:
  lan                   gwy                  ext
But pf can't insert this second state, as it collides with the first
one. Each state entry must have both a unique lan/ext and a unique
ext/gwy pair. While the ext/gwy pairs are different in the two states,
the lan/ext pairs are the same (,
Imagine there was no such restriction on key uniqueness, and the second
state could be inserted. The next packet is filtered outgoing on the
external interface with
  src                 dst
Which of the two state entries should this packet match? It would match
both. But pf must pick one state to determine what source address
translation to apply. Picking the first state would replace the source
with, but picking the second state would replace it
with Instead of relying on any imperfect strategy to
choose, pf simply refuses to insert a state entry which would lead to
such a conflict.
But there is probably no need for a second state entry, or even a rdr
rule at all. Probably both peers consider all packets in this case to be
part of a single connection. The problem is that the external peer is
replying to fixed port 5060 instead of the random proxy port chosen by
the nat translation. So, don't use a random proxy port, but tell nat to
leave the port as it is, 5060, using 'static-port', i.e.
  nat on $ext_if from port 5060 to any port 5060 \
	-> $ext_if static-port
  nat on $ext_if from to any -> $ext_if
As a side note, when using tcpdump on pflog0, use the flags shown by the
pflog(4) man page, i.e.
  tcpdump -nettti pflog0
so the output will include the additional values from pf (like the
reason why a packet was logged, what rule it matched, etc.), otherwise
the output is much less useful for debugging.
Also, if you enable debug logging with pfctl -xm, you'll get additional
output in /var/log/messages. In this particular case, they'd have told
you immediately that the state insertions failed.