Hello all,

While using SSLH ( www.rutschle.net/tech/sslh.shtml ) which tries to use function is_openvpn_protocol from the OpenVPN implementation as much as possible to detect OpenVPN connections (with only one difference), I found that I can not detect OpenVPN connections when they are established via shared secret (via option 'secret /etc/openvpn/somStaticKey.key'). The point is that for shared secret exchanges byte 3 of the initial message is ignored and hence filled by the client with rand data. This leads to randomly having connections even when using shared secrets and if being unlucky it can take up to 20 minutes of retries until I can connect.

After researching, I have the following questions to understand this behavior:

____________________________
/*
 * Given either the first 2 or 3 bytes of an initial client -> server
 * data payload, return true if the protocol is that of an OpenVPN
 * client attempting to connect with an OpenVPN server.
 */
bool
is_openvpn_protocol (const struct buffer *buf)
{
  const unsigned char *p = (const unsigned char *) BSTR (buf);
  const int len = BLEN (buf);
  if (len >= 3)
    {
      return p[0] == 0
        && p[1] >= 14
        && p[2] == (P_CONTROL_HARD_RESET_CLIENT_V2<<P_OPCODE_SHIFT);
    }
  else if (len >= 2)
    {
      return p[0] == 0 && p[1] >= 14;
    }
  else
    return true; // SSLH returns 0 at that point
}
____________________________


1. Because byte 1 + 2 define the message length, shouldn't be the following check better than 'p[0] == 0 && p[1] >= 14;'?

 int packet_len = (p[0]<<8) + (p[1]);
 if(len - 2 == packet_len) ...

This worked well in one of my tests. I only tried with shared secret but even in case of the shared secret, the packet_len is set properly.

2. Why only checking for P_CONTROL_HARD_RESET_CLIENT_V2 but not for P_CONTROL_HARD_RESET_CLIENT_V1 here as well?

3. Check 2 is only executed if the len is exactly 2. Which kind of empty OpenVPN message does set the message length field to a value that does not fit the message length?

4. The last 'else' block is only called and says "this is a OpenVPN message" if the message has a length of 0 or 1 independent of which value byte 1 has. I also did not find which kind of initial OpenVPN messages look like this.

5. Finally, I'm seeking for a good criteria to identify OpenVPN initial messages if a shared secret is used. What would be a good probe for that? Is there any other in addition to 'if(len - 2 == packet_len)' as described in point 1?

Many thanks for all input
/Kai

Reply via email to