I am trying to classify network protocols over network traffic . Now my task is SSH protocol. I read the RFC and know SSH starts with protocol exchange message from both client and server .

Format is : SSH-protoversion-softwareversion SP comments CR LF

Also I found an open source project called "ndpi" which already implemented this

if (flow->l4.tcp.ssh_stage == 0) {
    if (packet->payload_packet_len > 7 && packet->payload_packet_len < 100
        && memcmp(packet->payload, "SSH-", 4) == 0) {
        flow->l4.tcp.ssh_stage = 1 + packet->packet_direction;
} else if (flow->l4.tcp.ssh_stage == (2 - packet->packet_direction)) {
    if (packet->payload_packet_len > 7 && packet->payload_packet_len < 100
        && memcmp(packet->payload, "SSH-", 4) == 0) {
        ndpi_int_ssh_add_connection(ndpi_struct, flow);

It is checking if payload contains "ssh-" string . But I can't understand connection with "packet_direction" . I think simply checking if 2 payloads in a flow contains "ssh-" string would be enough. I want to ask if I should take packet_direction into consideration and if yes why?

1 Answer 1


The piece of code you show is doing exactly that: it is checking that there is a packet (of size 8 to 99 bytes, beginning with "SSH-") in both directions. Since client and server are supposed to talk somewhat simultaneously, the detection engine cannot assume that it will see the packet from the client or the packet from the server first; and knowing which side of the connection is the "client" might be difficult anyway in the context of packet-by-packet processing.

So the code you show uses a flag called packet_direction which has value 0 or 1, for the two possible directions. I will thereafter call direction 0 "AtoB" and direction 1 "BtoA" (it does not really matter whether A or B is the client at the TCP level). The code also uses an internal flag ssh_stage, initially at 0. When a first packet which matches the conditions (size 8 to 99 bytes, begins with "SSH-") is detected, the first half of the code is used (since ssh_stage is 0 at that point), and ssh_stage is set to 1 if this first packet is in the "AtoB" direction, 2 if it is in the "BtoA" direction.

When a second matching packet arrives, packet_direction is now set to the direction of that second packet. If that second packet is in the same direction as the first packet, then the current value of ssh_stage will not match the expression 2 - packet->packet_direction; however, it will match it if the second packet comes from the other direction (e.g. the second packet is in "BtoA" while the first packet was in "AtoB").

To sum up, the code checks that there are indeed two "SSH-looking" packets in opposite directions, as opposed to two successive packets in the same flow direction.

What you should do depends on how reliable you want your engine to be. If you only require two SSH-looking packets without considering direction, you might get some false positives, in case a non-SSH client happens to send two such packets to a non-SSH server. Requiring that the two packets flow in opposite directions will trigger fewer false positives. Note that the ndpi code is already not 100% reliable.

Indeed, if you look at RFC 4253:

  • The initial strings sent by both client and server may have length up to 255 characters, not 99.
  • After the exchange of the version strings, the connection setup dialog continues with some extra data from the client, which the client is allowed to send immediately, possibly in the same packet as its version string, so the client payload length might be way above 255 bytes.
  • The server is allowed to send some extra lines of characters before its version string, so the server packet payload length may also exceed 255, and it does not necessarily begin with "SSH-".

So the ndpi code may miss some perfectly standard SSH connections. It is up to you to decide whether you want to miss more or fewer such connections. Of course, the more reliable you want your code to be, the more work you will have to do...


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .