Browse code

Exclude ping and control packets from activity

Problem: using --ping and --inactive together partially defeats the
point of using --inactive as periodic ping packets are counted as
activity. Here is the original discussion:

http://article.gmane.org/gmane.network.openvpn.devel/3676

It turns out that "activity" is detected and recorded in two places
in the code, both in forward.c: in process_outgoing_tun() for received
packets, after they've been decrypted and sent to the TUN device; and
in process_outgoing_link(), after they've been encrypted and written
to the network socket.

In the first case we can be sure that packets that get so far are
really due to user activity, whereas in the second case there can be
non-user packets (like OpenVPN's internal ping packets, and TLS control
packets), and those should not be counted as activity as they are not
coming from the user.

So a need arises to detect those control packets and not count them as
activity for the purposes of --inactive. Unfortunately, at that stage
packets are already compressed and encrypted, so it's not possible to
look into them to see what they are. However, there seems to be a
convention in the code that packets whose buffer length in the context_2
structure is 0 should be ignored for certain purposes. TLS control
packets follow that convention already, so this patch makes a small
change in the code that generates the ping packets to set their buffer
length to 0 as well.
Finally, the call to register_activity() in process_outgoing_link() is
made conditional to the buffer length being > 0.

According to my tests, now --inactive behaves correctly according to
the configured parameters (time or time+bytes) even when --ping is
being used.

forward.c:
Call register_activity() in process_outgoing_link() only if the
packet is not a ping or TLS control packet.

openvpn.8:
Updated the description of --inactive to describe the new semantics.

ping.c:
Set c->c2.buf.len = 0 after the ping packet has been generated and
encrypted.

Test routine is described here:
<https://community.openvpn.net/openvpn/wiki/PingInactivePatch?version=6>

Signed-off-by: Davide Brini <dave_br@gmx.com>
Acked-by: David Sommerseth <dazo@users.sourceforge.net>
Signed-off-by: David Sommerseth <dazo@users.sourceforge.net>

Davide Brini authored on 2010/05/02 18:07:38
Showing 3 changed files
... ...
@@ -1168,8 +1168,9 @@ process_outgoing_link (struct context *c)
1168 1168
 		 size);
1169 1169
 	}
1170 1170
 
1171
-      /* indicate activity regarding --inactive parameter */
1172
-      register_activity (c, size);
1171
+      /* if not a ping/control message, indicate activity regarding --inactive parameter */
1172
+      if (c->c2.buf.len > 0 )
1173
+        register_activity (c, size);
1173 1174
     }
1174 1175
   else
1175 1176
     {
... ...
@@ -1366,15 +1366,25 @@ to be between 100 bytes/sec and 100 Mbytes/sec.
1366 1366
 .B \-\-inactive n [bytes]
1367 1367
 Causes OpenVPN to exit after
1368 1368
 .B n
1369
-seconds of inactivity on the TUN/TAP device.  The time length
1370
-of inactivity is measured since the last incoming tunnel packet.
1369
+seconds of inactivity on the TUN/TAP device. The time length of
1370
+inactivity is measured since the last incoming or outgoing tunnel
1371
+packet.
1371 1372
 
1372 1373
 If the optional
1373 1374
 .B bytes
1374 1375
 parameter is included,
1375
-exit after n seconds of activity on tun/tap device
1376
-produces a combined in/out byte count that is less than
1377
-.B bytes.
1376
+exit if less than
1377
+.B bytes
1378
+of combined in/out traffic are produced on the tun/tap device
1379
+in
1380
+.B n
1381
+seconds.
1382
+
1383
+In any case, OpenVPN's internal ping packets (which are just
1384
+keepalives) and TLS control packets are not considered
1385
+"activity", nor are they counted as traffic, as they are used
1386
+internally by OpenVPN and are not an indication of actual user
1387
+activity.
1378 1388
 .\"*********************************************************
1379 1389
 .TP
1380 1390
 .B \-\-ping n
... ...
@@ -86,5 +86,7 @@ check_ping_send_dowork (struct context *c)
86 86
    * encrypt, sign, etc.
87 87
    */
88 88
   encrypt_sign (c, true);
89
+  /* Set length to 0, so it won't be counted as activity */
90
+  c->c2.buf.len = 0;
89 91
   dmsg (D_PING, "SENT PING");
90 92
 }