Re: [BEHAVE] REQ 1 and REQ 7 of RFC5382 were supposed to be fixed years ago

ivan c <> Tue, 18 June 2013 02:21 UTC

Return-Path: <>
Received: from localhost (localhost []) by (Postfix) with ESMTP id 014A521F9CB3 for <>; Mon, 17 Jun 2013 19:21:10 -0700 (PDT)
X-Virus-Scanned: amavisd-new at
X-Spam-Flag: NO
X-Spam-Score: -2.54
X-Spam-Status: No, score=-2.54 tagged_above=-999 required=5 tests=[AWL=0.059, BAYES_00=-2.599]
Received: from ([]) by localhost ( []) (amavisd-new, port 10024) with ESMTP id aqwXTlLYZRbe for <>; Mon, 17 Jun 2013 19:21:06 -0700 (PDT)
Received: from ( []) by (Postfix) with ESMTP id C039321F9BBA for <>; Mon, 17 Jun 2013 19:21:05 -0700 (PDT)
Received: from www-data by with local (Exim 4.72) (envelope-from <>) id 1UolYR-0001MU-19 for; Tue, 18 Jun 2013 04:21:55 +0200
To: Behave <>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Date: Tue, 18 Jun 2013 04:21:55 +0200
From: ivan c <>
Organization: cacaoweb
In-Reply-To: <>
References: <> <>
Message-ID: <>
User-Agent: RoundCube Webmail/0.3.1
Subject: Re: [BEHAVE] REQ 1 and REQ 7 of RFC5382 were supposed to be fixed years ago
X-Mailman-Version: 2.1.12
Precedence: list
List-Id: mailing list of BEHAVE IETF WG <>
List-Unsubscribe: <>, <>
List-Archive: <>
List-Post: <>
List-Help: <>
List-Subscribe: <>, <>
X-List-Received-Date: Tue, 18 Jun 2013 02:21:10 -0000

Hi Simon,

You will find my explanations to your 4 questions interleaved below.

First of all, a word about the context considered in this discussion: 
We have peers, all behind NATs, attempting to connect to each other via
TCP simultaneous open (TCP simultaneous open being described in TCP RFC793
Section 3.4 Figure 8).
The first step is for these peers to discover or guess what each other's
remote external endpoint will be for the TCP connection. This step is
"remote external endpoint prediction" or informally "port prediction" (as
the hard part is to predict the external port, as created by the NAT).
external mapping have been negotiated/discovered, this information is
shared amongst the peers over some arbitrary out-of-band communication
The second step consists in performing the actual TCP simultaneous open
to the relevant endpoint.

These steps constitute the TCP Hole Punching process, it can be used for
NAT Traversal.

On Mon, 17 Jun 2013 16:54:43 +0200, Simon Perreault
<> wrote:
> I would argue that port preservation is useless for traversal.

TCP port preservation in NAT mappings allows peers to perform port
prediction trivially: the external port value of their own mapping is
the same as the local/internal port. The information of the external
endpoint can then be shared
amongst all peers over an arbitrary out-of-band 
channel. This completes the port prediction step of TCP Hole Punching.

The alternative to port preservation for the purpose of port prediction
is to use an EIM-NAT, and use
SO_REUSEADDR set on all local sockets, and use a third-party public
server. I explained this process as the
answer to your second question below. However, such technique uses
POSIX-unspecified behavior (SO_REUSEADDR is left unspecified) and is TCP
non-compliant (as it violates the TIME_WAIT state).

As a result, port preservation is desirable (and implies EIM anyway) for
TCP NAT traversal and adopted in the vast majority of NAT
implementations (in Saikat Gupta's paper, he mentions 89% of EIM NATs).
Port preservation becomes absolutely necessary in the context of fully
decentralized p2p networks. In such networks, third-party STUNT public
are generally not available, and thus a TCP Hole Punching
technique using a STUNT server is not possible.
Port Preservation alleviates the need
of a third-party STUNT server for the purpose of
performing port prediction.

See Saikat Guha (Editor of existing RFCs) paper, section 5.

> I don't see how EIM can be used for port prediction.

The single purpose of a EIM NAT for TCP is to allow an easy port
prediction with a STUNT server.

First of all, we use the term "port prediction" as a synonym for any
remote endpoint port discovery or guessing mechanism. When 2 peers behind
attempt to communicate with each other through TCP, they need to predict
other's external endpoint to perform a TCP simultaneous open.

An EIM NAT guarantees that two successive outgoing TCP connections from
the same internal endpoint are mapped to the same external endpoint on
the NAT.
This is port prediction: the first connection assists in predicting the
external endpoint that will be used by the NAT for the second connection.

Such behavior can be used for TCP Hole Punching as follows:
Let S be a server (no NAT) with a listening port Ps, let A and B be peers
behind NATs.
Port prediction works as follows:
Peer A binds a local socket on port Pa, then makes a TCP connection with
this socket to S on port Ps. Peer B does the same.
S gives the information of their respective port mapping to both peers.
Port Prediction has now been achieved: because the NAT uses
Endpoint-Independent Mapping, any subsequent connection from the same
internal endpoint will reuse the mapping.

The rest of the TCP Hole Punching process will then go as follows:
Peer A closes its local socket. Peer B does the same.
Peer A creates a new socket and binds it on the *same* port Pa. Most OS
stacks allow this as long as the SO_REUSEADDR option is set on *both*
sockets. Peer B does the same.
Then both make a connect() on this socket, to each respective endpoint.
simultaneous open is now in progress.

This is also explained in Saikat Guha's paper, in section 5.

>> REQ 7 was supposed to be fixed too, as the condition it requires is way
>> too strong as everyone can see. Port overloading for TCP is perfectly
>> acceptable when the remote endpoints are distinct.
> In your opinion, what is it about TCP that makes EDM OK?

My point is about the "TCP Port overloading" behavior and showing that
REQ 7 is too stringent.
This is orthogonal to Endpoint-Dependent Mapping (EDM) behavior.
Please explain your question.

>> Use of the SO_REUSEADDR hack violates RFC793 and should be used with
>> extra care.
> Please explain.

The SO_REUSEADDR socket option was added exclusively to bypass the TCP
TIME_WAIT state for listening servers. (which is an annoyance in
The TCP TIME_WAIT state is there to avoid the old duplicate problem. The
TIME_WAIT state lasts for 2*MSL, which is about 4 minutes.
When SO_REUSEADDR is used on sockets, an application can bind a socket
on a port that has a TIME_WAIT state pending. Bypassing the TIME_WAIT
state violates the data corruption provisions of TCP, and should only be
used by servers, in non-production
Furthermore, the behavior with
SO_REUSEADDR is intentionally left unspecified in POSIX: "SO_REUSEADDR:
Specifies that the rules
used in validating addresses supplied to bind() should allow reuse of
local addresses".

> Simon
> _______________________________________________
> Behave mailing list

Please do not hesitate to ask me for further clarification about the

_Ivan Chollet_