Flaw in ICMP holepunching? - nat

How is ICMP NAT traversal supposed to work if the NAT device in question rewrites outbound ICMP packets?
Diagram
=========================================================================================
| CLIENT | <---> | NAT-C | <---> { internet } <---> | NAT-S | <---> | SERVER |
=========================================================================================
19.19.19.19 (external addresses) 72.72.72.72
192.168.0.2 192.168.0.1 (internal addresses) 172.16.0.1 172.16.0.2
Mechanics
A quick overview of ICMP holepunching as described in pwnat:
SERVER sends ICMP Echo Request packets (pings) to some other host (e.g. 3.3.3.3) to open up a hole in NAT-S. When CLIENT wants to connect, it sends an ICMP Time Exceeded packet to NAT-S, which is supposed to get routed to SERVER. For said routing to work, CLIENT constructs the ICMP Time Exceeded packet by embedding within it the same packet (ICMP Echo to 3.3.3.3) it expects SERVER to be sending in the first place.
Problem
If CLIENT needs to embed the same (ICMP Echo Request) packet as it left NAT-S in its ICMP Time Exceeded reply, it must know the packet's query ID. But how does it know this query ID?
According to RFC 3022 Section 2.2, when NAT-S encounters the outbound ICMP Echo Request, it rewrites the packet's query ID field to a unique external query ID so that it can route future ICMP Echo Replies with the same query ID to SERVER.
Given the problem above, it would seem that the premise behind pwnat and ICMP holepunching is invalid and it's never supposed to work. Am I missing something here?
Thanks in advance :)

You're correct about the query ID.
pwnat rarely works nowdays. I happened to know this icmp punching thing years ago, and interested in this idea. I had read the source code of pwnat and re-implemented it in Go by myself. Only basic NAT devices (rfc 1631 describes) which does simple address translation may work with it, any NAPT device which has robust NAPT implementation won't do.
Besides the identifier problem, (by the way, the source code of pwnat use 0 as the identifier of original request) pwnat didn't give the right checksum of original ip header which may lead to the NAT-S dropping the TTL exceeded message(if the packet can reach there).
More serious, according to rfc 5508,
when the NAT device receives the ICMP Error packet from the Private Realm, the NAT device uses the packet embedded within the ICMP Error message (i.e., the IP packet from the client to the server) to look up the NAT Session to which the embedded packet belongs. If the NAT device does not have an active mapping for the embedded packet, the NAT SHOULD silently drop the ICMP Error packet.
It means the ICMP Time Exceeded packet from the client wouldn't pass through the NAT-C. This paper does mention this scenario and recommends other solutions.

Related

Why request dhcp packet is neccessary?

In DHCP protocol we have 4 packets named DORA.
first of all client send a broadcast Discovery packet for detecting DHCP server.
Then server send a Offer packet contain ip, subnet and many options and waiting for client.
If client find Offer packet suitable, send a broadcast Request and get ACK or NAK.
But why ?
Why we can't ignore Request packet and replace this way to sending 3 packets.
Discovery, Offer and ACK.
client -> Discovery
server -> Offer
client -> ACK
Why this way is not secure or suitable ?
When the client broadcasts the Discover packet, it may get Offer packets from multiple DHCP servers. The purpose of the Request packet is to say to one of the servers, "I want to use the IP address that you offered to me". If that wasn't sent:
the server whose offered IP the client is going to use wouldn't know not to offer that IP to a different client, and
the other servers wouldn't know that they can offer their IPs to other clients.
Then the final Acknowledge packet tells the client that the server has gotten the Request, and that the client now has the "lease" on the IP address.
This is intended to ensure that:
IP addresses are not wasted because a server thinks the client is using the Offered IP, when the client is actually using a different server's Offered IP.
The same IP is not accidentally leased to two clients at the same ... which causes chaos.
In the variation that you proposed, suppose that the ACK packet from the client to the server is lost. Now the server won't realize that the client is going to use the Offered IP address. A few minutes later, it could then Offer the same IP address to a different client and ... chaos ensues.
Please don't imagine that the people who design internet protocols are dullards. They have thought these things through carefully before they write the RFCs. And many other (equally smart) people have gone over the pre-approved RFCs carefully looking for problems. So ... if there is something about a standard protocol that you think is wrong ... it is probably you, and not the protocol designer who is mistaken.

Transfer file over ICMP

I'm studying about Networking . I'm want to transfer file over ICMP protocol then capture networking traffic by wireshark to decode raw data . But I dont know how to transfer file by ICMP protocol. So my question is how can I transfer file by ICMP between host.
Thanks a lot .
If you insist on sending data using ICMP (which is reasonable in some use-cases) I suggest you read this article and that one. The first one also contains proof-of-concept C-code for client and server that use ICMP to transfer data. You can find another example written in C++ here.
The idea behind this method is using the data (payload) section of ICMP Echo (ping) requests and responses for transferring data (or files in this case). Most devices reply to ICMP Echo (ping) requests so it's a way to transfer files when other protocols (such as ssh, smb, ftp, etc.) are blocked.
If you study about TCP/IP layers, you will find that ICMP is a Internet layer protocol and its purpose is to:
The Internet Control Message Protocol (ICMP) is a supporting protocol in the Internet protocol suite. It is used by network devices, like routers, to send error messages and operational information.
So ICMP is not a data transfer protocol like HTTP or FTP etc. Technically it is not possible in any case to use ICMP as data transfer protocol, Unless you change structure and all coding of ICMP and then it will no longer be ICMP.

UDP hole punching for Server/Client communication under NAT with STUN

Problem
I'm trying to develop a communication system where:
A, B are machines under NAT, A is the server B is the client
S is the STUN server
S is running on a machine reachable on the Internet
The flow is as follows:
A hits S with an opcode saying he's the server
S registers A as server
B hits S with an opcode saying he's the client
S sends to A B's external infos (IP, PORT)
S sends to B A's external infos (IP, PORT)
A starts sending B an opcode saying he's the server every 500ms
and meanwhile listens for packets saying he's got a client
B starts sending A an opcode saying he's the client every 500ms
and meanwhile listen for packets saying he's got the server
Trouble
Here's where the troubles start, the STUN server does its job, since both ends receive correct infos about the other.
But then I do never receive the other end's message, so both ends keep listening without receiving the handshake opcode nor anything else.
NAT's Behaviour
I did examine this NAT's behaviour and seems it does like this
A is at 192.168.X.X, on port 4444
connects to the outside exposing N.N.N.N:4444
so the port number is kept as long as it's free, gets a new (random ?) one if not available.
Tests
The tests I run have seen both ends (A, B) hosted on the same machine, both bound to the machine's internal IP, tried to bind to 127.0.0.1, 0.0.0.0, nothing changed.
If while they're listening for handshakes I echo something with nc to localhost, it is received and displayed (as an unrecognised message) without any problem. The connection routed via the NAT doesn't wotk tough, every packet is discarded.
Also tried with A hosted on the machine, B on an Android phone under mobile data, with a simple app written ad-hoc. Still locks waiting for something, like the nodejs tests.
Update:
Another thing I tried to do is to open an hole with nc
On two different machines under the same NAT I ran:
echo "GREET UNKOWN PEER" | nc -u <NAT IP> 4567 -p 4568
echo "GREET UNKOWN PEER" | nc -u <NAT IP> 4568 -p 4567
Different times for each machine. From my understanding this should punch an hole in the NAT with the first packets discarded and the subsequent forwarded. But nothing happened, no end got the message.
I've also tried:
from local machine
echo "GREET UNKOWN PEER" | nc -u <PUBLIC IP> 4567 -p 4568
from public machine
echo "GREET UNKOWN PEER" | nc -u <NAT IP> 4568 -p 4567
this one works, the local machine under NAT contacts the public one and after the first discarded packet is able to receive and send on the assigned port. I wonder why this doesn't work on two machines under the same NAT (???)
Code
I didn't show any code because I think there is some kind logic flaw in this, however here's the github project for that.
index.js contains the STUN server, the tests folder contains the test cases: test.js starts the stun server, PeerClientTest.js and PeerServerTest.js are mockups of the client and server.
Run node tests/test.js to start the server on a public machine (change IPs in config.js and tests/config.js)
then node tests/PeerServerTest.js to start the server ("A") and node tests/PeerClientTest.js to start the client ("B"). Both will recognize each other via STUN, then listen for the other end's handshake opcode while sending their own handshake opcode. This never happens so they just keep sending/listening forever.
Node is not required, so if there are better solutions in other languages just tell, will be appreciated.
B's NAT is filtering A's packets and is not letting them through. NAT filters unknown packets sent to it. Your server A is sending packet to client B. But client B previously never sent a packet through NAT to A. So to B's NAT A's packets are unknown and being discarded.
You need to punch a hole in B's NAT for the NAT to allow the incoming packets. Send a packet from B to A NAT's IP:Port. After that when you send a packet from A to B, B's NAT won't discard A's packet.
This won't work if A and B's NAT has a combination like Symmetric and Symmetric/PRC NAT. In this case you will have to use a TURN relay server.

computer networking: ARP - point of the ICMP echo packets

I'm studying Address Resolution Protocol and in all my books and slides the diagrams showing an ARP take place (i.e. Host1 sends ARP request, Router checks it, redirects it, eventually gets to Host2 and then Host2 sends back an ARP Reply).
What I'm wondering is why the examples include ICMP echo replies and requests, do they serve any purpose within ARP?
Thanks
I would guess that it is to initiate the ARPs. A machine is not going to send an ARP for no reason. It will only send an ARP if it needs to send something to the IP address (and doesn't know the destination MAC address yet). Maybe the ICMP echo request is that 'something' the authors use in their examples to cause the source machine to send an ARP.
Short answer: There is no special relationship between ICMP and ARP; that's just what the authors of your book decided to use as an example.

what packet will arrive first when send request

As some one mentioned in other forum that interviewer has asked the question given below.
I dont know exact answer but I would say HTTP request ? Any suggestion and explainations
Imagine a user sitting at an Ethernet-connected PC. He has a browser open. He types "www.google.com" in the address bar and hits enter.
Now tell me what the first packet to appear on the Ethernet is .
Thanks
There's no guaranteed always-correct answer, but there are a few likely possibilities.
If the client is configured for DNS over UDP, then the first packet will be a UDP datagram containing a DNS query to resolve www.google.com to an IP address.
If the client is configured for DNS over TCP and the browser hasn't already got an established TCP connection to the DNS server, the first packet will be part of the connection handshake to DNS, and therefore the answer will be that a SYN packet is first out of the gate.
If the browser has been coded to maintain a long-lived TCP connection to the DNS server and assuming the DNS server has allowed the connection to stay alive, the first packet will be a DNS query, sent across the existing connection to that DNS server.
Finally, if the browser had recently visited www.google.com recently and is built to do some smart local caching of DNS query results then the first packet will be a SYN to establish a new connection to Google's web server.
If you want to be glib but absolutely precise about it, drop down a layer for your answer and say, "The first packet out will be an Ethernet frame containing a payload which supports whatever higher-level protocol is needed for the browser to serve up www.google.com". In fairness, the question is about the Ethernet layer...
Strictly speaking, with a completely blank slate, the first packet sent will be an ARP broadcast request ("Who has?") from the client PC attempting to discover the MAC address of its default gateway (or of its DNS server if that is on the same subnet as the client).
Interesting :) I just wiresharked it:
Client sends a SYN
Server replies with a SYN,ACK
Client sends an ACK
Client sends an HTTP GET
(like you mention in your comments the first is obviously the DNS lookup)

Resources