Use plain old PACKET for TCP packets sent directly to a neighbor.
authorEtienne Dechamps <etienne@edechamps.fr>
Sun, 12 Oct 2014 11:14:46 +0000 (12:14 +0100)
committerGuus Sliepen <guus@tinc-vpn.org>
Thu, 25 Dec 2014 16:59:38 +0000 (17:59 +0100)
Currently, when sending packets over TCP where the final recipient is
a node we have a direct metaconnection to, tinc first establishes a
SPTPS handshake between the two neighbors.

It turns out this SPTPS tunnel is not actually useful, because the
packet is only being sent over one metaconnection with no intermediate
nodes, and the metaconnection itself is already secured using a separate
SPTPS handshake.

Therefore it seems simpler and more efficient to simply send these
packets directly over the metaconnection itself without any additional
layer. This commits implements this solution without any changes to the
metaprotocol, since the appropriate message already exists: it's the
good old "plaintext" PACKET message.

This change brings two significant benefits:

- Packets to neighbors can be sent immediately - there is no initial
  delay and packet loss previously caused by the SPTPS handshake;

- Performance of sending packets to neighbors over TCP is greatly
  improved since the data only goes through one round of encryption
  instead of two.

Conflicts:
src/net_packet.c

src/net_packet.c

index 16dac43..c146109 100644 (file)
@@ -514,6 +514,11 @@ static bool try_sptps(node_t *n) {
        if(n->status.validkey)
                return true;
 
+       /* If n is a TCP-only neighbor, we'll only use "cleartext" PACKET
+          messages anyway, so there's no need for SPTPS at all. */
+       if(n->connection && ((myself->options | n->options) & OPTION_TCPONLY))
+               return false;
+
        logger(DEBUG_TRAFFIC, LOG_INFO, "No valid key known yet for %s (%s)", n->name, n->hostname);
 
        if(!n->status.waitingforkey)
@@ -529,7 +534,10 @@ static bool try_sptps(node_t *n) {
 }
 
 static void send_sptps_packet(node_t *n, vpn_packet_t *origpkt) {
-       if (!try_sptps(n))
+       /* Note: condition order is as intended - even if we have a direct
+          metaconnection, we want to try SPTPS anyway as it's the only way to
+          get UDP going */
+       if(!try_sptps(n) && !n->connection)
                return;
 
        uint8_t type = 0;
@@ -562,7 +570,14 @@ static void send_sptps_packet(node_t *n, vpn_packet_t *origpkt) {
                }
        }
 
-       sptps_send_record(&n->sptps, type, DATA(origpkt) + offset, origpkt->len - offset);
+       /* If we have a direct metaconnection to n, and we can't use UDP, then
+          don't bother with SPTPS and just use a "plaintext" PACKET message.
+          We don't really care about end-to-end security since we're not
+          sending the message through any intermediate nodes. */
+       if(n->connection && origpkt->len > n->minmtu)
+               send_tcppacket(n->connection, origpkt);
+       else
+               sptps_send_record(&n->sptps, type, DATA(origpkt) + offset, origpkt->len - offset);
        return;
 }