diff --git a/README.md b/README.md index ef35ebe..a857009 100644 --- a/README.md +++ b/README.md @@ -8,11 +8,11 @@ The idea is to try out a sequence of well known hole punching techniques until o - [SYNI](https://www.uni-kassel.de/eecs/fileadmin/datas/fb16/Fachgebiete/UC/papers/HWW_11-SYNI.pdf) (TCP hole punching based on SYN injection), DOI: 10.1109/NCA.2011.66 - [NUTSS](https://www.cs.cornell.edu/people/francis/nutss-fdna.pdf) (TCP hole punching, the non-spoofing approach described in section 4.2.2 of the paper), DOI: 10.1145/1016707.1016715 -The assumption of those techniques is that there is a side-channel (i.e. a rendezvous server) between the two hosts. A peer that wants to be available for hole punching needs to constantly be connected (subscribed) to the rendezvous server so it can be notified by other peers about new hole punching attempts. Also it needs to provide an endpoint (public IP address and port) to other peers before those can initiate the hole punching. See the example applications for a naive rendezvous server implementation. +The assumption of those techniques is that there is a side-channel (i.e. a rendezvous server) between the two hosts. A peer that wants to be available for hole punching needs to constantly be connected to the rendezvous server so it can be notified by other peers about new hole punching attempts. Also it needs to provide an endpoint (public IP address and port) to other peers before those can initiate the hole punching. See the example applications for a naive rendezvous server implementation. # How can I use punchd? -Applications can communicate with ``punchd`` through a unix domain socket (by default ``/tmp/punchd.socket``). An application can call one of ``punchd``'s API functions to either start a hole punching attempt (``initiate``) or react to an attempt started by another peer (``respond``). After calling an API function ``punchd`` will report back a status (either ``ok``, ``progress`` or ``error``). After a successful hole punching attempt, ``punchd`` will pass a socket to the application which can be used immediately to communicate with the other peer. The full ``punchd`` API is described in section ``The punchd API``. +Applications can communicate with ``punchd`` through a unix domain socket. An application can call one of ``punchd``'s API functions to either start a hole punching attempt (``initiate``) or react to an attempt started by another peer (``respond``). After calling an API function ``punchd`` will report back a status (either ``ok``, ``progress`` or ``error``). After a successful hole punching attempt, ``punchd`` will pass a socket to the application which can be used immediately to communicate with the other peer. The full ``punchd`` API is described in section ``The punchd API``. The figure below shows the workflow of a successful hole punching attempt between two peers A (initiator) and B (responder). @@ -46,7 +46,7 @@ The figure below shows the workflow of a successful hole punching attempt betwee # Installation -No packages exist yet, so installation has to be done manually to the desired location after running ``nimble install``. Starting punchd is as simple as +No packages exist yet, so installation has to be done manually to the desired location after running ``nimble install``. Starting ``punchd`` is as simple as ``` $ sudo ./punchd @@ -54,7 +54,81 @@ $ sudo ./punchd # The punchd API -TBD +Applications can exchange messages with ``punchd`` through a unix domain socket. By default this is ``/tmp/punchd.socket``. The message format is described in the next section. After that an example message exchange is given. Finally we need to understand how to receive a successfully connected socket from ``punchd``. + + +## The message format +A ``punchd`` message is a string with a maximum length of 500 bytes followed by +a line feed character ('\n'). The string consists of fields (positional +arguments) separated by '|'. + +An application can send two types of messages (requests) to ``punchd``: +"initiate" messages (ask ``punchd`` to start a new hole punching attempt) or +"respond" messages (ask ``punchd`` to react to the hole punching attempt started +by another peer). These messages have the following formats: + +``` +initiate|ID|TECHNIQUE|IP_FROM|PORTS_FROM|IP_TO|PORTS_TO +respond|ID|TECHNIQUE|IP_FROM|PORTS_FROM|IP_TO|PORTS_TO|EXTRA_ARGS +``` + +The fields have the following semantics: + +- ``ID``: the message ID (random string) +- ``TECHNIQUE``: the hole punching technique, one out of "tcp-syni" and "tcp-nutss" +- ``IP_FROM``: the public IP address of the initiating peer +- ``PORTS_FROM``: a list of previously used source ports of the initiating peer +- ``IP_TO``: the public IP address of the responding peer +- ``PORTS_TO``: a list of previously used source ports of the responding peer +- ``EXTRA_ARGS``: technique-specific arguments + +For each request (identified by a message ID) ``punchd`` will report back a +status (containing the same message ID). The status can be "ok" (hole punching +was successful), "progress" (hole punching is in progress, the other peer has to +be notified) or "error" (the hole punching failed). These status messages have +the following formats: + +``` +ok|ID +progress|ID|TECHNIQUE|IP_FROM|PORTS_FROM|IP_TO|PORTS_TO|EXTRA_ARGS +error|ID|ERROR_MSG +``` + +The fields in the "progress" message are the same that can be found in "respond" +message described above. This is because the application is expected to forward +them to the other peer through the rendezvous server so the other peer can call +"respond" on its ``punchd`` instance. + + +## Example + +An example session between two applications AA and AB on two different peers (AA +has the endpoint 1.2.3.4:1234; AB has the endpoint 5.6.7.8:5678) and their +respective ``punchd`` instances (PA and PB) might look like this: + +``` +AA -> PA: initiate|645|tcp-syni|1.2.3.4|1234|5.6.7.8|5678,5679,5680 +AA <- PA: progress|645|tcp-syni|1.2.3.4|1234|5.6.7.8|5678,5679,5680|344567,644456,345365 + +AB -> PB: respond|538|tcp-syni|1.2.3.4|1234|5.6.7.8|5678,5679,5680|344567,644456,345365 +AB <- PB: ok|538 +AA <- PA: ok|645 +``` + + +## Receiving sockets using recvmsg +When ``punchd`` successfully has punched a hole, i.e. has a socket that is +connected to the other peer, it will report back status "ok" to the application. +The file descriptor representing that socket will be included in the status +message in a control message, a.k.a ancillary message. + +The application has to use the ``recvmsg`` system call to receive that control +message and access the file descriptor. This mechanism is described in the man +pages [unix(7)](https://linux.die.net/man/7/unix), +[cmsg(3)](https://linux.die.net/man/3/cmsg) and +[recv(2)](https://linux.die.net/man/2/recv). The example applications can be used +as a reference too. After receiving the file descriptor it can immediately be +used to send data to the other peer. # FAQ @@ -62,7 +136,7 @@ TBD A: ``punchd`` needs to pass a file descriptor to the application. On Unix systems that is only possible using the ``sendmsg`` system call with an ancillary message of type ``SCM_RIGHTS`` on a unix domain socket. See the [unix(7) man page](https://linux.die.net/man/7/unix). - **Q: Why does ``punchd`` need root permissions?** - A: Most hole punching techniques require elevated privileges because they need raw sockets (e.g. for capturing TCP sequence numbers) or they need to create firewall rules (some techniques require sending out low-TTL packets; the resulting ICMP time-exceeded responses have to be filtered out or else TCP connections will fail). On linux punchd can run as a non-root user though if ``punchd`` is started with the ``CAP_NET_RAW`` and ``CAP_NET_ADMIN`` capabilities. + A: Most hole punching techniques require elevated privileges because they need raw sockets (e.g. for capturing TCP sequence numbers) or they need to create firewall rules (some techniques require sending out low-TTL packets; the resulting ICMP time-exceeded responses have to be filtered out or else TCP connections will fail). On linux ``punchd`` can run as a non-root user though if ``punchd`` is started with the ``CAP_NET_RAW`` and ``CAP_NET_ADMIN`` capabilities. - **Q: Which one is the best hole punching technique?** A: No hole punching technique will work for all environments. In fact there are environments where no hole punching will be possible at all. The goal of this project is to find a good *sequence* of hole punching techniques to be tried one after the other. A lot of research still has to be done. See the example applications for some proposed sequences.