[p2p-hackers] Official IETF behavior recommendations for
NATrelevant to P2P
David Barrett
dbarrett at quinthar.com
Fri May 20 01:05:38 UTC 2005
Hi Bryan, I think your work in this area is simply the best, and I entirely
agree with your judgment here.
I'm a P2P developer working in the VoIP space, and I can't stress enough the
annoyance of address-restricted NATs. Were I working in a "closed" space
(ala Skype) it'd be merely a nuisance. However, due to the limitations of
open standards (notably SIP and RTP), working in the presence of NATs is
quite challenging. I would enthusiastically welcome more standardized
behavior in terms of how to "punch holes" and how long I can count on these
holes remaining open. Let me explain by way of example:
First, as you well know, before anyone can hope to contact me behind a NAT,
I must first figure out what the global (NAT'd) address is for each of my
local ports. I do this with the help of some central server, such as with
STUN. Once the hole has been "punched" I have no idea how long it will stay
open, so I need to send a "keep-alive" to my central server. The net result
is that there is a very high cost to open even one UDP port behind a NAT,
and an ongoing cost to keep it open.
So even with a full-cone NAT, there is an up-front and ongoing cost to
opening a UDP port on which I intend to receive data. However, with a
full-cone NAT, the cost is purely spent by my client -- I needn't involve
anyone else (excepting the central server) in preparing to receive data than
my own instance of my own application.
In the case of an address-restricted NAT, however, not only must I pay the
cost of being behind a NAT (and pay not once, but again for each client who
communicates with me), everyone else who wishes to communicate with me must
pay as well.
For the full-cone NAT, once I know my global (NAT'd) IP/port, I can use that
as my own -- anybody can contact me via that address, without special
behavior to account for me being behind a NAT. This means NAT-ignorant
protocols (such as RTP, for example) can be received from behind NATs,
without any special programming on the part of the sender.
However, for address-restricted NATs, this is not the case. Imagine you
want to send me an RTP stream, and I am behind a NAT. With a full-cone NAT,
I could send you my global IP/port (via SIP and SDP), and you could open an
RTP stream direct back to me. But with an address-restricted NAT, this is
not enough. The reason is a bit involved, but please bear with me.
First you need to send me the SIP INVITE via my proxy server. SIP allows
the proxy server to either redirect you to contact me directly, or forward
on my request. If I'm behind a full-cone NAT, either works fine. If I'm
behind an address-restricted NAT, I can only hope that the proxy forwards
your request on to me, because I have no way of punching a hole to receive
your direct SIP request. Furthermore, I have no way of indicating to the
SIP proxy that I need it to forward to me. So right off the bat, receiving
SIP INVITE requests behind an address-restricted NAT is more complicated
than from behind a full-cone NAT.
Assuming I'm lucky and the SIP proxy forwards the request to me (via the
hole I've already punched for it), I can receive and respond to the INVITE
request indicating the port to which you should broadcast your RTP.
However, I have a complication that shared by all NATs, and that is getting
a port that complies with RTP. The RTP standard indicates RTP ports should
be even-numbered, and the next port (odd-numbered) is implied to be open to
receive RTCP. Unfortunately, I as a client have absolutely no control over
which ports my NAT assigns me, so it's very difficult for me to receive RTP
in a fully compliant fashion. So for all NATs I must put in extra effort to
communicate the real RTP/RTCP ports I wish to receive on, possibly by
bending the RTP spec. But a further complication of address-restricted NATs
is that I also need to somehow figure out the exact address you intend to
broadcast from, even though I would otherwise not care. This means I must
bend the SIP/RTP framework even more (or dig into the details more than I
might otherwise) just to support address-restricted NATs.
In the meantime, while I am playing these extra games to punch holes to
receive your data, you have already begun to broadcast. For full-cone NATs,
this is fine and expected. But for address-restricted NATs, I can't receive
data despite having told you the correct IP/port to which you should
broadcast, because I haven't punched a hole for you. While I'm playing
games trying to punch the hole, you're broadcasting data that I'm not
receiving. Depending on the codec, that might be very important header
data. Naturally UDP is an unreliable transport mechanism and thus there are
fallbacks if the occasional packet is lost, but there's a big difference
between "some packets might be lost" and "an unknown number of initial
packets *will* be lost". More work must be put into supporting the
address-restricted case, and more deviation from the "mainstream" SIP/RTP
best practices.
Furthermore, just punching the holes themselves involve violating standards,
hopefully in benign fashion. In the case of unidirectional RTP, there is
nowhere in the standard that I as a listener should send to your RTP
broadcast port -- thus there is no fully-compliant way to punch a hole to
receive your data. (Yes I can send to your RTCP port, but that's a separate
port.) The best I can do is send a malformed packet your way and hope it
doesn't cause you harm. With full-cone NATs, I have no such problem.
And finally, every hole I punch requires some maintenance. The less holes,
the better. Generally, with full-cone, the number of holes I need punch is
proportional to the number of services I wish to offer (and the same holes
are used for all users). But with address-restricted, it's proportional to
the product of the number of services, and the number of simultaneous users.
This means I have a much higher overhead to working with address-restricted
NATs. But more importantly, I have so many more things that can go wrong.
This breeds the absolute worst kind of "partial failure" bug such as:
- Why can I hear Bob, but not Alice?
- Why can I hear Bob, but he can't hear me?
- Why can I receive Bob's RTP, but not Bob's RTCP?
- And so on...
And if I walk across the room and pick a different wi-fi hub, thus changing
IP addresses, with active sessions? Oye, it's a ton of work to re-establish
all of these crazy holes and sessions in a bidirectional manner. A ton of
work that I needn't do with full-cone NATs.
So, to make a long story short, NAT traversal is a hard problem, and it's
made especially hard by address-restricted NATs. If I could count on
full-cone NAT behavior, my life as a programmer would be easier, and the
applications I produce would function better, faster, and more reliably.
In other words, I fully endorse Bryan's recommendation, and hope to see it
included in the final draft.
-david
> -----Original Message-----
> From: p2p-hackers-bounces at zgp.org [mailto:p2p-hackers-bounces at zgp.org] On
> Behalf Of Bryan Ford
> Sent: Wednesday, May 18, 2005 11:59 AM
> To: p2p-hackers at zgp.org
> Subject: [p2p-hackers] Official IETF behavior recommendations for
> NATrelevant to P2P
>
> Dear p2p-hackers,
>
> A discussion is currently taking place on the IETF BEHAVE working group
> mailing list (see http://www1.ietf.org/html.charters/behave-charter.html)
> that is highly relevant to P2P application writers. For those of you not
> already familiar with it, this IETF working group is defining standards
> for
> how NATs should behave so as to better support applications including P2P
> apps. The chair has made a "Last Call" for comments on the current draft
> document specifying NAT behavior for UDP, so this may be the last chance
> we
> have for a while to influence how well the next generation of NATs support
> UDP-based P2P applications.
>
> ** Address-Restricted vs Full Cone NAT **
>
> There's one issue in particular on which I personally fear the working
> group
> is currently headed in the wrong direction, and over which you folks on
> this
> list could perhaps exert considerable influence if you're willing to take
> a
> little time and make your voice heard on the BEHAVE list. The current UDP
> draft, draft-ietf-behave-nat-udp-01.txt, recommends that NATs implement
> "Endpoint address-dependent filtering behavior", otherwise known as
> "Address-Restricted Cone NAT". In other words, once a NATted UDP
> application
> opens a UDP session through a NAT to some external host, giving the
> application a public (NATted) port number, the NAT only accepts and
> forwards
> subsequent incoming UDP packets at that public port if they come from a
> source IP address that the application has previously sent UDP packets to.
> In other words, the NAT must see outgoing UDP traffic to a remote host
> before
> it will accept incoming traffic from that host on the application's public
> port. In the proposed alternative, "Endpoint-independent filtering" or
> "Full
> Cone NAT", the NAT forwards any incoming traffic to the correct public
> port
> regardless of source IP address or port number.
>
> Address-Restricted Cone NAT is moderately "P2P-friendly" in that it at
> least
> allows NATted applications to "hole punch" P2P connections with the help
> of a
> well-known (non-NATted) rendezvous server. Address-Restricted Cone NAT
> still
> does not, however, allow the application to have a full "first-class"
> Internet presence (i.e., public IP address and UDP port number) at which
> it
> can be contacted proactively by any other Internet-connected host. A P2P
> application behind an Address-Restricted Cone NAT is still forever
> dependent
> on other public (first-class) rendezvous servers to help establish each
> P2P
> communication session it needs. A P2P app behind a Full Cone NAT, in
> contrast, is a full "first-class" network citizen itself, and can even
> _be_ a
> public rendezvous server for other less fortunate hosts once it learns its
> own public IP address and UDP port number. This is an important benefit
> to
> applications, especially P2P applications that are trying to be highly
> decentralized.
>
> The main argument for Restricted Cone NAT, of course, is security. Until
> recently I believed this argument myself, but after further and more
> careful
> analysis I have come to the conclusion that Restricted filtering provides
> a
> very week security benefit in comparison with the fundamental loss in
> first-class application connectivity it entails. My current proposal on
> the
> BEHAVE list does NOT mandate Full Cone NAT, but it does specify that NATs
> should at least be Full Cone in their default, "out of the box"
> configuration
> as provided by NAT vendors, and recommends that NATs implement Restricted
> Cone NAT as an administrator-configurable security option. The current
> proposed text reads as follows:
>
> REQ-7: NATs MUST implement Endpoint-Independent
> Filtering in their default configuration.
> NATs SHOULD be configurable to support
> Address-Specific Filtering or Endpoint-Specific Filtering
> at the option of the system administrator.
>
> If you have thoughts or opinions on this topic, I would greatly appreciate
> hearing them (and having other participants hear them) on the BEHAVE list.
>
> ** Why the Security Benefit of Restricted Cone NAT is Minimal **
>
> Restrictive filtering ostensibly has the benefit of protecting
> applications on
> an internal host from traffic the internal host is not expecting, i.e.,
> from
> traffic from previously unknown external hosts or endpoints. This
> behavior
> can only possibly benefit the application if the application only ever
> initiates outgoing sessions from its internal port, and is obviously a
> curse
> if the application ever wants to accept incoming sessions from external
> hosts. The NAT has no way of knowing which is the case. But suppose the
> application is one that only initiates outgoing connections (i.e., a
> "traditional client/server app"), and thus might "potentially" benefit
> from a
> NAT's restrictive filtering behavior. Consider TCP and UDP separately:
>
> ** TCP: When a client/server app makes an outgoing TCP connection,
> it
> typically does a "connect()" call to the host OS's sockets API without
> bothering to bind() the socket, and the OS's TCP stack allocates a local
> TCP
> port exclusively for the use of that connection. Any TCP packets the host
> OS
> subsequently received on that port from endpoints other than the one it
> connect()ed to will be summarily rejected with TCP RSTs by the host OS,
> and
> the application never even sees any hint that they ever arrived. Even if
> the
> application does a bind() before its connect() in order to use a specific
> source port (e.g., a <1024 "privileged" port), it still almost always
> obtains
> exclusive use of that port. An application indeed has to work really
> bloody
> hard to set things up so that it can accept incoming TCP connections on
> the
> same port it is using for an outgoing connection, using SO_REUSEADDR and
> multiple sockets. No traditional client/server application is going to go
> to
> all this effort just in order to create a security hole. :) In other
> words,
> for TCP, restrictive filtering in practice provides absolutely zero
> protection from the _application_: the only entity that the restrictive
> filtering even affects is the host OS's protocol stack. Restrictive
> filtering might for example benefit a host OS with a TCP stack that is so
> broken that it fails to check the source IP address and port number on
> incoming TCP packets at all, but if the host OS is _that_ broken then it
> undoubtedly has many other problems that the NAT can't possibly guard
> against.
>
> ** UDP: When a client/server UDP app uses a UDP port for
> communication
> with just one remote host, for convenience it typically does a connect()
> to
> the appropriate remote UDP endpoint, so that it can just send messages
> with
> send() or write() without having to specify a destination address for each
> datagram, and so that it can receive messages with read() or recv()
> without
> having to check the source address and port number in each message
> received.
> In this case, the host OS effectively provides the external endpoint
> filtering functionality as for TCP, and any restrictive filtering
> implemented
> by the NAT again provides no security benefit at all to the application.
> A
> UDP application that uses a single UDP port for communication with
> multiple
> remote hosts, in contrast, must generally check the source IP addresses
> and
> port numbers in the datagrams it receives just in order to distinguish
> between the multiple communication sessions it is involved in, and hence
> it
> will inherently provide its own external endpoint filtering. It's
> conceivable that some abysmally buggy UDP applications might benefit from
> the
> NAT's external filtering - e.g., a UDP application that only talks to one
> external endpoint but doesn't use connect() and doesn't check the source
> endpoint on incoming datagrams - but an application that is so seriously
> broken probably has many other security vulnerabilities that can be
> exploited
> despite the NAT's external filtering behavior, e.g., by finding out or
> guessing the public server the application is talking to (which is easy in
> many cases such as commercial games or services where there are only a few
> well-known servers) and sending packets with spoofed source IP address and
> UDP port numbers. Besides, many, perhaps the majority, of UDP
> applications
> use UDP _because_ they need P2P-style communication, and so external
> filtering by the NAT provides no practical security benefit and only
> causes
> interference with the application.
>
> Another common argument for Restricted Cone NAT (Address-dependent
> filtering)
> is that it protects the resources on the internal network from being
> consumed
> forwarding bogus packets even if the eventual end application will
> correctly
> discard them. This argument is also weak, however:
>
> ** Even with more permissive Full Cone NAT (endpoint-independent
> filtering),
> the NAT will still in practice filter out the vast majority of bogus
> traffic
> that reaches it, because most of the NAT's ports are typically not in
> active
> use by applications behind the NAT. The only bogus traffic a Full Cone
> NAT
> will let through is bogus traffic that happens to hit the _specific_
> external
> port numbers that correspond to active port bindings. These port numbers
> are
> assigned more-or-less randomly (i.e., unpredictably) by the NAT, and they
> only
> ever appear in the high, non-well-known port number space, so most of the
> Internet "background noise" caused by viruses or other attacks on well-
> known
> ports will never get through in any case, and purely random "port
> guessing"
> attacks would have to send packets to a great many NAT ports in order to
> get
> a few packets through. Thus, the incremental benefit of restrictive
> filtering over Full Cone NAT with regards to general bogus Internet
> traffic
> is very small.
>
> ** An attacker might deliberately send bogus packets to a bound NAT
> port
> known to be in use. But if the attacker can find out which NAT port the
> application is using, then the attacker probably also knows (or can easily
> find out or guess) the address and port number of the _remote_ host that
> the
> application is talking to and just spoof that source IP address and port
> number in its attack packets, getting around Restricted filtering as well.
> In fact the remote host's endpoint is in practice likely to be much easier
> for the attacker to find out or guess than the application's public NAT
> port,
> because of the overwhelming prevalence of well-known servers and ports on
> the
> Internet in comparison to the randomness and relative obscurity of
> temporary
> NAT-assigned public ports. So the practical benefit that Restricted
> filtering provides even against directed attacks is still minimal.
>
> ** Finally, the goal of "protecting the resources on the internal
> network
> from being consumed forwarding bogus packets" is really only a
> consideration
> on large corporate or ISP networks with substantial internal traffic load,
> and if this minimization of resource use is a concern then the network
> administrator can certainly be expected to know how to configure the
> company's NAT to enable Restricted filtering. As I pointed out above,
> under
> my proposal a NAT can use Restricted filtering and still be BEHAVE-
> compliant
> as long as it is the administrator (not the NAT vendor) that enables this
> firewall behavior.
>
> ** For home NATs, in contrast, minimizing resource load on the
> internal
> network due to bogus traffic is completely a non-issue because the home
> network (Ethernet or 802.11 or whatever) is typically so much faster than
> the
> Internet uplink anyway. In this case it's much more important that NATs
> consistently support applications well, which my proposal ensures by
> requiring that the NAT's "out of the box" configuration is
> Endpoint-independent Filtering. Joe Clueless who buys a home NAT router
> probably doesn't have any idea what NAT actually is, but he wants his
> applications to work.
>
> ** Conclusion **
>
> In summary, restrictive filtering in the NAT interferes with applications
> substantially and provides very little real security benefit in
> practice, considering the way application communication and NAT port
> assignment actually works. As such, especially considering the purpose of
> the BEHAVE working group is to increase the predictability and
> compatibility
> of NATs with applications and not to specify standards for firewall
> functionality, it seems highly inappropriate for the WG's documents to
> recommend firewall functionality that interferes with applications while
> providing dubious security benefits. On the contrary, I think the WG
> should
> at least recommend, if not mandate, that NATs provide Endpoint-Independent
> Filtering (Full Cone NAT) by default. NAT vendors or system
> administrators
> that are particularly paranoid about security and perceive the security
> benefits to be worth the interference it causes with applications can
> still
> enable more restrictive filtering policies, but that's a firewall
> deployment
> issue, not a NAT functionality issue. We need to steer clear from
> recommending firewall functionality.
>
> Thanks very much for your attention. Please direct followups to the
> BEHAVE
> working group list, "ietf-behave at list.sipfoundry.org". Thanks!
>
> Bryan
> _______________________________________________
> p2p-hackers mailing list
> p2p-hackers at zgp.org
> http://zgp.org/mailman/listinfo/p2p-hackers
> _______________________________________________
> Here is a web page listing P2P Conferences:
> http://www.neurogrid.net/twiki/bin/view/Main/PeerToPeerConferences
More information about the P2p-hackers
mailing list