-
Notifications
You must be signed in to change notification settings - Fork 0
/
HACKING
259 lines (191 loc) · 10.4 KB
/
HACKING
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
file: HACKING
Last updated: 2010-01-01 09:55 UTC
--------
(C) 2008-2010 - Richard Andrews
This program and document is free software; you can redistribute
it and/or modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not see see <http://www.gnu.org/licenses/>
--------
This file describes the internals of n2n. 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
-------------
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 n2n. These hosts will require the supernode to
relay packets.
ARP CACHE
---------
n2n 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 n2n and these packets cause the native ARP cache to be updated.
Edge nodes send gratuitous ARP packets on startup. See GRATUITOUS ARP below.
REGISTRATION AND PEER-TO-PEER COMMUNICATION SETUP
-------------------------------------------------
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
discussion.
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
communication.
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").
EDGE REGISTRATION DESIGN AMMENDMENTS (starting from 2008-04-10)
------------------------------------
* 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
entry.
peer = find_by_src_mac( hdr, known_peers ); /* return NULL or entry */
if ( peer )
{
peer_last_seen = time(NULL);
}
else
{
if ( ! is_broadcast( hdr ) ) /* ignore broadcasts */
{
if ( IS_REGISTER_ACK( hdr ) )
{
/* move from pending to known_peers */
set_peer_operational( hdr );
}
else
{
/* add to pending and send REGISTER - ignore if in pending. */
try_send_register( hdr )
}
}
}
(Notes):
* 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.
GRATUITOUS ARP
--------------
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.
MAN PAGES
---------
Look at a non-installed man page like this (linux/UNIX):
nroff -man edge.8 | less
common header FORMAT
--------------------
All message encoding and decoding is contained in wire.c.
0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Version=2 ! TTL ! Flags ! PktType !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4 ! Community :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
8 ! ... Community ... :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
12 ! ... Community ... :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16 ! ... Community ... !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
PACKET message FORMAT
---------------------
The PACKET message is of main concern as it is the most frequently transferred
as it contains encapsulated ethernet packets. For these, PktFormat is set to
n2n_packet and it goes on as follows:
If the N2N_FLAGS_SOCKET-Flag is set, the socket of the original sender of the
packet is encoded next. IPv4 or IPv6 is determined by the Socket Flags.
Socket encoding for IPv4 takes 8 bytes and looks as follows:
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
0 ! Socket Flags (v=IPv4) ! Destination UDP Port !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4 ! Destination IPv4 Address !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
For IPv6 it takes 20 bytes:
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
0 ! Socket Flags (v=IPv6) ! Destination UDP Port !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4 ! Destination IPv6 Address :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
8 : :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
12 : :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16 : !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
After that, if the N2N_FLAGS_LOCAL_SOCKET-Flag is set, yet another socket
(using the same format as above) will follow (used for bypassing the
behind-same-nat problem)
Finally, the last part of the packet looks like this:
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
40 ! Transform ID ! Payload ... :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
44 : ... Payload ... :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
48 : ... Payload ...
-------
January 2010 - Richard Andrews <andrews@ntop.org>