I'm in the process of converting our proxy server to 3261 compliance, and
I've run into a situation where I'm not sure what the correct thing is to
do, algorithmically.

Specifically, I'm not sure when a proxy should forward an ACK message that's
not associated with any transaction, and when it should just drop it.

An ACK message which doesn't match an existing INVITE transaction, and which
isn't addressed to a resource the proxy's responsible for, is presumably, if
the sender is RFC-compliant, an end-to-end ACK.  According to my reading of
RFC 3261 section 16.5, it should just be forwarded, presumably statelessly
since no responses are expected.

However, my concern is that the sender might *not* be RFC-compliant; in
particular, it might be hostile, and trying to use our proxy server to
perform ACK-flood denial-of-service on some third party, or something.  So
I'd like some way to be sure that ACKs we forward are associated with INVITE
transactions we actually accepted and forwarded in the past.

For a UAS, associating an end-to-end ACK with its corresponding INVITE is
reasonably straightforward.  You find the dialog matching the ACK's dialog
ID, and then within that dialog find the INVITE transaction whose CSeq
matches the CSeq of the ACK.  But this doesn't work for a proxy server,
which might be stateless.  (It also doesn't uniquely identify a proxy
transaction if there's a spiral, but that doesn't matter for this purpose.)

We need to consider: why would we, legitimately, receive the end-to-end ACK
at a proxy server?  There are two potential reasons.  First of all, the
proxy could have Record-Route'd.  In this case, associating the ACK with the
initial transaction is straightforward, in principle: the proxy can insert a
transaction hash in a parameter of the Record-Route URI, so it'll be in the
Route header it receives (or the request-URI if the upstream is a strict
router).  If this transaction hash is valid, it forwards the ACK; otherwise,
it drops it.  This should be correct even in the presence of Record-Route'd
request spirals.

Secondly, however, we could have a UAC using the proxy as an outbound proxy.
In this case, it's possible that we don't insert a Record-Route header, not
anticipating that we'll be doing anything that requires us to stay on the
dialog path, but the UAC could send us the ACK anyway.

If the initial INVITE was destined for a foreign location -- i.e., the UAC
is using us as a true outbound proxy -- our proxy's current relay-denying
policy is that it 407s the request and insists that the UAC provide
credentials before it'll forward the request.  In this case, 3261 says that
the ensuing end-to-end ACK should carry the same credentials as the INVITE,
so we can verify that, even if we can't necessarily associate the ACK with a
specific INVITE transaction, we know that forwarding it statelessly is
valid.

However, it's also possible that a UAC is using us as an outbound proxy, but
is also calling a local user.  With our proxy, if a request's Request-URI
points at a resource we handle, we don't normally challenge the INVITE
(unless the target has an always-authenticate policy).  However, the
following flow can occur (assume the local domain is cs.columbia.edu):

UAC -> Proxy         INVITE sip:[EMAIL PROTECTED] SIP/2.0
Proxy -> downstream  INVITE sip:[EMAIL PROTECTED] SIP/2.0
...
downstream -> Proxy  200 OK / Contact: <sip:device.somewhere.example>
Proxy -> UAC         200 OK / Contact: <sip:device.somewhere.example>
UAC -> Proxy         ACK sip:device.somewhere.example SIP/2.0

What do we do with this ACK?  It's not transactionally associated with the
initial INVITE transaction, it's not directed at a URI we handle locally, it
doesn't have any Route headers, and it doesn't carry any credentials.  You
can't respond to an ACK, so we can't send a 407 to get credentials.  Yet
clearly, from a big-picture point of view, we have to forward the ACK.

So, I'm not sure what to do here.  Unfortunately, there doesn't seem to be
any way for a proxy to put a piece of information into a forwarded INVITE
that it gets back in an end-to-end ACK, other than by Record-Routing or
performing an authentication challenge.

We can't trust either the From: address, or the source IP, of the ACK, since
either one could be forged.

We could just say in our documentation "if your proxy server is going to be
used as an outbound proxy, you must enable Record-Route for all
transactions".  But that doesn't seem like a good idea.

We could just not worry about it, and always statelessly proxy ACK messages,
since there's no message traffic amplification (it's one message in -> one
out), and no local state accumulation, so the use for denial-of-service is
limited.  But I'm nervous about this.

So, any thoughts?

-- 
Jonathan Lennox
[EMAIL PROTECTED]
_______________________________________________
Sip-implementors mailing list
[EMAIL PROTECTED]
http://lists.cs.columbia.edu/mailman/listinfo/sip-implementors

Reply via email to