I have been reading about WebRTC and how it enables peer to peer communication. So, i did a experiment for NAT traversal.
The experiment objective was to test hole punching in NAT. I had two system both were running Ubuntu 16.04. I will refer to these systems as system A and system B.
Both systems connect to a server hosted on Amazon Web Services. System A used command nc -p 1234 -u IP_ADDRESS_OF_SERVER PORT_NUMBER_OF_SERVER and system B used command nc -p 1235 -u IP_ADDRESS_OF_SERVER PORT_NUMBER_OF_SERVER. System A and system B both were connected to the same WiFi router.
After connecting to the server, we got to know about public socket of both systems. After that, i tried to connect each other using the information of public socket we got from the server within few seconds.
System A disconnects itself from server and connects to system B by using the command nc -u -p 1234 PUBLIC_IP_OF_SYS_B PUBLIC_PORT_OF_SYS_B and system B also disconnects itself from server and connects to system A by using the command nc -u -p 1235 PUBLIC_IP_OF_SYS_A PUBLIC_PORT_OF_SYS_A.
I did this to punch a hole in our NAT. After it, system A cancel the above nc command and listen to it's port using nc -l -u -p 1234. But unfortunately, i wasn't able to receive any message typed in system B in system A.
Can anyone help me in getting this work?
So, i figure it out myself. What i was trying to do is called Hairpin Translation and hairpin translation is still much less common among existing NATs (as compared to hole punch translation).
The two systems happen to reside behind the same NAT, and are therefore located in the same private IP address realm. System A has established a UDP session with server S, to which the common NAT has assigned its own public port number(say x). System B has similarly established a session with S, to which the NAT has assigned public port number (say y).
Suppose that system A uses the hole punching technique to establish a UDP session with B, using server S as an introducer. System A sends S a message requesting a connection to B. S responds to A with B's public and private endpoints, and also forwards A's public and private endpoints to B. Both clients then attempt to send UDP datagrams to each other directly at each of these endpoints. The messages directed to the public endpoints will not reach their destination as our NAT doesn't support hairpin translation.
Anyone can read about hairpin over here.
Related
I am trying to setup peer to peer networking and am trying to understand how this works.
Normally in Client to Server connection, I will connect to the server IP and port. Behind the scenes, it will create a client socket bound to a local port at the local ip, and the packet is sent to the router. The router will then NAT the local port and the local socket, to the client public ip and a different public client socket with a destination for the server IP and port.
When the server responds, the router then DENATs the public client ip and public client port back to the local ip and local port, and the packet arrives at the computer.
In a Peer to Peer networking, I may have the peer's public IP, but it is shared by many machines and the router hasn't allowed a connection yet, so there isn't a open port I can send the data to.
There was then an option that both peers contact a server. That opens a port on the router. Then the peers send packets to each other's client port.
However, usually the router will only accept packets from the same IP the request was made to, so the two peers cannot reuse the server's connection.
How do the two peers talk to each other in this scenario ?
Peer-to-peer networking works exactly the same way as client/server networking. Only one of the peers will become a server and the other a client.
Normally in a peer-to-peer app like bittorrent all peers are also servers but of course for any individual connection one machine must take the role of the client. However a single peer may have multiple connections. So for any single peer some of the connections to it will be server sockets and some will be client sockets.
How this works with NAT is exactly the same as a client/server architecture. You must configure your router to NAT back to your peer application in order for others to connect to it. If not then your peer can only connect to other peers but other peers cannot connect to you. For example, if your bittorrent client is generally acting slow, not managing to get a lot of connections and not managing to finish downloading some torrents this often signifies that you have not configured your router's port forwarding back to your PC for your bittorrent client.
For the use-case of non-expert users (consumers) there are several ways to get around NAT automatically without requiring your users to configure their routers. The most widely used method is UPnP (Universal Plug and Play). However a lot of more expert users who can configure their own routers often disable UPnP because it is a fairly well known DDoS target. So if you do decide to use UPnP you should make it optional for more advanced users to disable it if they don't want to use it.
For cases where you need a guaranteed connection regardless of router configuration then your app cannot be 100% peer-to-peer. You'd need a relay server that acts as a server to both peers that will forward the packet form the sending client peer to the receiving client peer. Of course, the disadvantage of this is that you now have a fixed cost of maintaining a server to support your app just like traditional client/server systems but in this case you're using peer-to-peer to reduce server costs, not eliminate the server.
One example of this "hybrid" approach is cryptocurrencies like Bitcoin and Ethereum. They need a core group of servers to exist in order to work. However, for these protocols the servers run the same software as the clients - they're all just nodes. The only difference is that you don't shut down the servers whereas most people quit their bitcoin wallet once they've done using it (unless they're mining). Another example that is similar is the TOR network. There is a set of core TOR nodes that act as the "server" part of the network ensuring that the network always exist.
You said it yourself: "peers send packets to each other's client port". Therefore, the router will "accept packets from the same IP the request was made to".
Say, Alice is behind router A and Bob is behind router B.
Having learned their public endpoints from a server, Alice will send UDP packets to Bob's public IP, and Bob will send UDP packets to Alice's.
Having seen Alice talk to Bob's IP, router A will accept UDP packets from Bob.
Having seen Bob talk to Alice, router B will accept UDP packets from her as well.
That is, some initial packets might be rejected as coming from the blue, but after both parties have initiated communication on their side, routers will have no reason to block what follows.
In terms of Symmetric NAT Traversal using STUN 2003, by sending a packet to Bob, Alice is creating a door for Bob in A. On the other side, by sending a packet to Alice, Bob is creating a door for Alice in B.
The trick in UDP hole punching seems to be for the routers to reuse the same NAT tunnel for different IPs - so that the port discovered by a server is the same as the port reused for direct communication.
We can talk with different IPs from a normal UDP socket (by skipping connect and using sendto), so it's kind of logical that a tunneled socket would be able to do the same.
I have a PC A where LTTng tracing is running with live view
lttng create trace-session --live
# Traces will be output to tcp4://127.0.0.1:5342/ [data: 5343]
Another PC B is directly connected with A with a Ethernet cable. At the same time, B is connected to a local network.
Now how can I view the live trace events from a third PC C, which is in the same local network as B, for example with
babeltrace2 "net://${B_IP}/host/${B_HOSTNAME}/trace-session"
I ran the following command on PC C, to make a tunnel to PC *A.
ssh -L 5342:${A_IP}:5342 -N user_name#${B_IP}
However, it seems not to have worked. I would like to ask:
What have I done wrong here?
What is the standard way to "forward" LTTng live tracing events to be viewed by babeltrace2?
Babeltrace2 connects to lttng-relayd using the live port of the lttng-relayd process not the data and control ports.
When the command line report the following:
# Traces will be output to tcp4://127.0.0.1:5342/ [data: 5343]
It means that the lttng-sessiond and lttng-consumerd process will communicate with a lttng-relayd process listening on the 127.0.0.1:5342 for control message and 127.0.0.1:5343 for trace data exchange. A viewer, in this case Babeltrace2 can connect to the live port of a lttng-relayd process to stream live session. You can take a deeper look at the component graph here.
The default live port is 5344 and the default behavior for the lttng-relayd process is to bind on all interfaces to listen. Naturally Babeltrace2 also default on using that port if none is specified to communicate with the lttng-relayd process.
See the man page of lttng-relayd for more details.
What have I done wrong here?
In your scenario you need to tunnel the 5344 port. Note that I'm not versed in ssh tunneling so I cannot validate the ssh approach here.
ssh -L 5344:${A_IP}:5344 -N user_name#${B_IP}
What is the standard way to "forward" LTTng live tracing events to be viewed by babeltrace2?
Babeltrace2 and lttng-relayd use TCP for communication. Hence, all TCP "forwarding" methods are acceptable here. As you probably noticed, LTTng does not encrypt communication and trace data in any way. I would say that using a ssh tunnel is appropriate here if you need to move data across non-trusted network.
For two device both has public IP address, we can use socket IP and port to setup socket communication.
If both device do not has public IP but connect to sub-Lan then access public network through router (no port mapping in router), how can this two device setup socket connection?
For example in above diagram, how can machine A communicate with machine C?
Assuming that you have not set up a VPN tunnel between the two routers that connects both branches of the 192.168.1.0/24 network then the answer is: you can't.
If you set up a VPN tunnel then each side of the 192.168.1.0/24 network will be able to see the other side. Please note that the routers will need to be able to do ARP spoofing, i.e. the router for A & B will need to be able to spoof the MAC for C, i.e. intercept IP packages for C on their LAN and forward them through to the VPN to the other network half where they are delivered to C.
If you set up at least one port forwarding on one router, then you'll have other options, e.g. an SSH tunnel on C that connects to the port forward on either A & B. You can then use the -L option on C to setup port forwarding through the SSH tunnel to the other half of the network.
My current scenario is
System A is able to ping System B.
System B is not able to ping System A. [ Due to Network misconfig ]
Socket Testing :
I am running a UDP server code in System B.
Is it possible to send UDP message to System B from System A(UDP client) even though ping(B-->A) is not working.
Thanks
Balaganesh
What i require is that, I will open an UDP server listening in X port(local machine) and a machine(public IP) can send UDP packet to me. My machine doesn't have a public IP. Basically I need stun.
I am testing stuntman server/client project. I run stuntman-server in a server(public ip). Run client in my system (local ip). I asked for mapped ip/port for 9999 port.
./stunclient --mode full --protocol udp --localport 9999 stun.server.ip
Stun server returns an IP and port. What i did then, open an UDP server (using java) in my local system and start listening in 9999 port and send an UDP message from other machine (which has public IP) to mapped IP/port returned by stun server. But i can't receive any data. You can assume that my server/client code (written in java) is working fine in local network.
Flow:
My machine ->>>>>stun request for 9999 port and my ip ------> stun server
My machine <<<<<<<<<<<<<<<<<<mapped ip/port <<<<<<<<<<<<<<< stun server
My machine : Run JAVA udp server socket in 9999 port
My machine <<<<<<<<<<<<<<<<<<<UDP message to mapped ip/port<<<<<< other public machine
xxxxxxxxxxxxxxxxxxxNot workingxxxxxxxxxxxxxxxxxxxxxxxx
You didn't publish the results of your stunclient run, but I imagine it looked something like the following:
$ stunclient --mode full --localport 9999 stunserver.stunprotocol.org
Binding test: success
Local address: 192.168.1.8:9999
Mapped address: 1.2.3.4:9999
Behavior test: success
Nat behavior: Endpoint Independent Mapping
Filtering test: success
Nat filtering: Address and Port Dependent Filtering
I'm going to guess that your Behavior Test is "Endpoint Independent" and the Filtering test was "Address and Port Dependent" as those are the most common in the home and mostly matches with what you described above. (aka as "port restricted NAT").
In any case, this means you have created a port mapping between yourself and the STUN server. In the example above, my public IP address is 1.2.3.4. And is common, but not always the case, my local port (9999) is the same as the public port.
Internally, your NAT keeps a logical table such as the following:
------------------------------------------------------------------------------------
|| LOCAL IP | LOCAL PORT || EXT PORT || REMOTE IP | REMOTE PORT ||
||================================================================================||
|| 192.168.1.8 | 9999 || 9999 || 107.23.150.92 | 3478 ||
------------------------------------------------------------------------------------
Because you sent out a packet from port 9999 to the stun server (107.23.150.92), the NAT creates a port mapping entry in it's table for several minutes. When a packet arrives on the NAT/router from the Internet, it consults the table. When the response came back from the STUN server's IP:port, the NAT was able to forward it to your computer behind the NAT based on the "remote" fields in the table above.
But there is no port mapping between you and the "other public machine" that you are hoping to receive data from. Let's assume that the IP address of that other machine is 2.4.6.8 and it is attempting to send from it's local port 8888. The NAT still doesn't have anything in the table to map traffic from 2.4.6.8:8888 to a host behind the NAT. So when traffic arrive at a NAT from an a host not in the table, the NAT only knows to drop the packet on the floor. There is a NAT classification known as "Cone NAT" where this would work, but those aren't as common.
In your case, there is an easy workaround. After obtaining a port mapping from the STUN server, send another datagram from your same local port (9999) to the remote host (and remote port) that you want to receive data from. The remote host can simply ignore this datagram, but it effectively creates another port mapping entry on your NAT
------------------------------------------------------------------------------------
|| LOCAL IP | LOCAL PORT || EXT PORT || REMOTE IP | REMOTE PORT ||
||================================================================================||
|| 192.168.1.8 | 9999 || 9999 || 107.23.150.92 | 3478 ||
|| 192.168.1.8 | 9999 || 9999 || 2.4.6.8 | 8888 ||
------------------------------------------------------------------------------------
That simple 1-byte data packet to 2.4.6.8:8888 allows the NAT to forward traffic back from that address to your host behind the NAT.
In other words, using your own network flow nomenclature:
My machine:9999 ---->[STUN BINDING REQUEST]--->stun server:3478
My machine:9999 <----[STUN BINDING RESPONSE mapped IP:port]<--- stun server:3478
My machine:9999 [Open socket on port 9999]
My machine:9999 ---->[1 byte datagram] -------> 'other:8888'
My machine:9999 <---- [UDP to public IP:port obtained in step 2]<----'other:8888'
Typically, in a normal P2P flow, both endpoints work with a STUN server to discover their port mapping. And then use another service on to exchange IP:port information between each other. From what you describe, you are manually exchanging these values between your programs, which is fine for testing.
If the other machine is on the public internet, you technically do not need STUN. The first machine (behind a NAT) can just send directly to the remote IP and port to say, "send me some data". The remote side just inspects the peer address and port of this message to decide where to send back to. The port mapping has already been created. Some RTSP clients assume the server is public
My answer on the basics of socket NAT traversal is here.
I happen to know the developer of STUNTMAN. He's a reasonably nice guy, good looking, and very smart. They also say him and I look alike and have near identical spelling with our names. You can always mail him directly if you have questions about STUN and NAT traversal.