forked from pnill/cartographer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnat_punch.txt
72 lines (52 loc) · 3.97 KB
/
nat_punch.txt
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
-------------------------------------------------------------------------
NAT Punchthrough Implemenation / Theory / Design
-------------------------------------------------------------------------
In theory we should pre-bind and create sockets before bind is even ever called from the game,
We control the ports which are bound to (BUT) we still need to be able to map them back to the original ones.
This is difficult, the game will directly send to the port so if we randomize it we won't know which is which.
(Is this true?, Have we bound to another socket and checked the sendto data?, I believe the game statically defines 1001/1000 actually...)
Basically we need to create a map of each port,
1000 = New Bind port
1001 = New Bind Port
1005 = New Bind Port
1006 = New Bind Port
Technicaly we don't need a map of each port on bind, the python server should be informing us of the port.
The first step is attempt to bind and if bind fails increase by 100, resulting in 1101.
We do this 3 times before simply aborting...
Every time our port binding succeeds we will attempt a hole punch via a remote server,
The way this will work is we will take the local secure addr and abEnet which have both been confirmed and talk to the Python server handling the hole punch data.
We will use this socket we've created in order to perform our hole punch on this specific socket,
The packet sent to the python server should be as follows,
int socket_original_port
char abEnet[8]
int secure_address;
The python server then makes two separate dictionaries,
Where new_port is actually the source port the client connected with (This is the hole punched in the router via NAT).
One of these dictionaries stores abEnet+original_port = new_port.
The other will store secure_address+original_port = new_port.
After storing this data the python server should send a confirmation to the client telling it has accepted the data,
If this is not received the client should abort and attempt binding on a new port... our punch through didn't work.
This process can happen at least 2-3 times so we can attempt to give the client a proper port,
I personally only want to do it twice at most.
This allows us to initiate requests to the python server by supplying original port and either abEnet or secure_address,
Then update us with the port it was communicated on from the client ( The hole punched port ).
The strict NAT setup becomes an issue here because that port we communicated with the python server on will not be able to be connected to,
from other sources which are not the python server... in this case the client should abort the attempts bind to any port and report the NAT as strict.
(
The only way to really test this is attempt a connection from a different IP - this is difficult as hell as we won't want to run multiple servers,
The solution is this, we only resolve this data for servers, so basically it only means strict servers can't host which is fine with us.
It also means people with a 'strict' NAT type will not be able to join servers which are moderate and use this NAT punching method,
the good thing being that because the way the sockets are bound any actual servers will have OPEN NAT.
And the clients will be able to translate to their real ports based on their assigned secure addresses or abEnet instead of attempting 1001.
)
In theory the above configuration should support any setup.
We then need storage locally of which ports map to what on local side.
For this we will have maps specifically in our NAT punch through
map_a(port 1000)
map_b(port 1001)
map_c(port 1005)
map_d(port 1006)
Beyond this we will leave our original network address translation in place in order to also make an attempt to support strict NAT.
The goal of all of this is two things,
1. Automatically allow multiple instances of servers and or clients on local networks - effectively telling clients which port on a server they should connect to.
2. Allow moderate NAT users to host lobbies.