NTVL – Nat Traversal Virtual LAN

Nat Traversal Virtual LAN / Virtual VPN, isa networking tool to create a public/private network on the Internet bypassing firewalls.
NTVL can also use as a layer-two peer-to-peer virtual private network (VPN) which allows users to exploit features typical of P2P applications at network instead of application level. This means that users can gain native IP visibility (e.g. two PCs belonging to the same ntvl network can ping each other) and be reachable with the same network IP address regardless of the network where they currently belong.

In a nutshell, as OpenVPN moved SSL from application (e.g. used to implement the https protocol) to network protocol, NTVL moves P2P from application to network level.

The main ntvl design features are:

  • An ntvl is an encrypted layer two private network based on a P2P protocol.
  • Encryption is performed on edge nodes using open protocols with user-defined encryption keys: you control your security without delegating it to companies as it happens with Skype or Hamachi.
  • Each ntvl user can simultaneously belong to multiple networks (a.k.a. communities).
  • Ability to cross NAT and firewalls in the reverse traffic direction (i.e. from outside to inside) so that ntvl nodes are reachable even if running on a private network. Firewalls no longer are an obstacle to direct communications at IP level.
  • NTVL networks are not meant to be self-contained, but it is possible to route traffic across ntvl and non-ntvl networks.

The natvl architecture is based on two components:

  • edge nodes: Applications installed on user PCs that allow the natvl network to be build. Practically each edge node creates a tun/tap device that is then the entry point to the ntvl network.
  • an supernode: It is used by edge nodes at startup or for reaching nodes behind symmetrical firewalls. This application is basically a directory register and a packet router for those nodes that cannot talk directly.
  • Edge nodes talk by means of virtual tap interfaces. Each tap interface is an natvl edge node. Each PC can have multiple tap interfaces, one per ntvl network, so that the same PC can belong to multiple communities

This file describes the internals of ntvl. Read this before starting to modify the code. Because coding examples may be present in this document it is licensed under the GPL rather than FDL.


Symmetric NAT is a form of firewall NAT in which an UDP packets are only passed
back to an inside host socket when the return packets originate from the outside
socket to which the initiating UDP packets were sent. This means that when an
inside host sends UDP to some outside socket; other hosts cannot piggyback on
this opening in the firewall to send data to the inside host.

When two inside hosts are both behind symmetric NAT, peer-to-peer packet
exchange is not possible via ntvl. These hosts will require the supernode to
relay packets.


ntvl makes use of the host operating system’s own ARP cache. Each edge node
allocates a random MAC address to itself. This MAC is constant for the life of
the edge process. ARP packets are passed around as broadcast ethernet packets
over ntvl and these packets cause the native ARP cache to be updated.

Edge nodes send gratuitous ARP packets on startup. See GRATUITOUS ARP below.


A and B are edge nodes with public sockets Apub and Bpub; and private network
addresses A and B respectively.  S is the supernode.

A sends {REGISTER,Amac} to S. S registers {Amac->Apub}.
B sends {REGISTER,Bmac} to S. S registers {Bmac->Bpub}.

Now ping from A to B.

A sends broadcast “arp who-has B” to S. S relays the packet to all known edge
nodes. B replies “B at Bmac” to supernode which forwards this to A. So now ping
A->B is known to be ping Amac(A)->Bmac(B).  Note: gratuitous arp also requires

In response to receiving the arp reply, Apub sends {REGISTER,Amac} to Bpub. If
Bpub receives the request it sends back {REGISTER_ACK,Amac} and also sends its
own {REGISTER,Bmac} request.

In response to receiving the “arp who-has”, Bpub sends {REGISTER,Bmac} to Apub.

Now the OS has received the arp reply and sends ICMP to Bmac(B) via the tunnel
on A. A looks up Bmac in the peers list and encapsulates the packet to Bpub or
the supernode if the MAC is not found.

We assume that between two edge nodes, if Bpub receives a packet from Apub then
Apub can receive a packet from Bpub. This is the symmetric NAT case.  Note: In
the symmetric NAT case, the public socket for a MAC address will be different
for direct contact when compared to information from the supernode.

When two edge nodes are both behind symmetric NAT they cannot establish direct

If A receives {REGISTER,Bmac} from B, A adds {Bmac->Bpub} to its peers list
knowing that Bmac is now reachable via that public socket. Similarly if B
receives {REGISTER,Amac} from A.

The supernode never forwards REGISTER messages because the public socket seen by
the supervisor for some edge (eg. A) may be different to the socket seen by
another edge due to the actions of symmetric NAT (alocating a new public socket
for the new outbound UDP “connection”).


* Send REGISTER on rx of PACKET or REGISTER only when dest_mac == device MAC
(do not send REGISTER on Rx of broadcast packets).
* After sending REGISTER add the new peer to pending_peers list; but
* Don’t send REGISTER to a peer in pending_peers list
* Remove old entries from pending_peers at regular intervals
* On rx of REGISTER_ACK, move peer from pending_peers to known_peers for direct
comms and set last_seen=now
* On rx of any packet set last_seen=now in the known_peers entry (if it
exists); but do not add a new entry.
* If the public socket address for a known_peers entry changes, deleted it and
restart registration to the new peer.
* Peer sockets provided by the supernode are ignored unless no other entry
exists. Direct peer-to-peer sockets are always given more priority as the
supernode socket will not be usable for direct contact if the peer is behind
symmetric NAT.

The pending_peers list concept is to prevent massive registration traffic when
supernode relay is in force – this would occur if REGISTER was sent for every
incident packet sent via supernode. Periodic REGISTER attempts will still occur;
not for every received packet. In the case where the peer cannot be contacted
(eg. both peers behind symmetric NAT), then there will still be periodic
attempts. Suggest a pending timeout of about 60 sec.

A peer is only considered operational for peer-to-peer sending when a
REGISTER_ACK is returned. Once operational the peer is kept operational while
any direct packet communications are occurring. REGISTER is not required to
keep the path open through any firewalls; just some activity in one direction.

After an idle period; the peer should be deleted from the known_peers list. We
should not try to re-register when this time expires. If there is no data to
send then forget the peer. This helps scalability.

If a peer wants to be remembered it can send gratuitous ARP traffic which will
keep its entry in the known_peers list of any peers which already have the

peer = find_by_src_mac( hdr, known_peers ); /* return NULL or entry */

if ( peer )
peer_last_seen = time(NULL);
if ( ! is_broadcast( hdr ) ) /* ignore broadcasts */
if ( IS_REGISTER_ACK( hdr ) )
/* move from pending to known_peers */
set_peer_operational( hdr );
/* add to pending and send REGISTER – ignore if in pending. */
try_send_register( hdr )


* In testing it was noted that if a symmetric NAT firewall shuts down the UDP
association but the known_peers registration is still active, then the peer
becomes unreachable until the known_peers registration is deleted. Suggest two
ways to mitigate this problem:
(a) make the known_peers purge timeout a config paramter;
(b) send packets direct and via supernode if the registration is older than
eg. 60 sec.


In addition to the ARP who-has mechanism noted above, two edge nodes can become
aware of one another by gratuitous ARP. A gratuitous ARP packet is a broadcast
packet sent by a node for no other purpose than to announce its presence and
identify its MAC and IP address. Gratuitous ARP packets are to keep ARP caches
up to date so contacting the host will be faster after an long idle time.


Look at a non-installed man page like this (linux/UNIX):

nroff -man edge.8 | less


All message encoding and decoding is contained in wire.c. The PACKET message is
of main concern as it is the most frequently transferred as it contains
encapsulated ethernet packets.

Version 2

0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
! Version=2     ! TTL           ! Flags                         !
4 ! Community                                                     :
8 ! … Community …                                             :
12 ! … Community …                                             :
16 ! … Community …                                             !
20 ! Source MAC Address                                            :
24 :                               ! Destination MAC Address       :
28 :                                                               !
32 ! Socket Flags (v=IPv4)         ! Destination UDP Port          !
36 ! Destination IPv4 Address                                      !
40 ! Transform ID                  !
44 ! Payload

So each ntvl PACKET has a 44 byte overhead. For a 1500 byte ethernet packet this
is roughly 3%.

Socket flags provides support for IPv6. In this case the PACKET message ends as

32 ! Socket Flags (v=IPv6)         ! Destination UDP Port          !
36 ! Destination IPv6 Address                                      :
40 :                                                               :
44 :                                                               :
48 :                                                               !
52 ! Transform ID                  !
56 ! Encapsulated ethernet payload

Download : bambusoft-ntvl-1.0.0-RC1.tar.gz (173KB)
bambusoft-ntvl-1.0.0-RC1.tar.gz.md5  (MD5)
Find Other Version |  GIT
Read more in here : http://ntvl.bambusoft.mx/