Skip to content

Commit

Permalink
Bittorrent: improve detection of UTPv1
Browse files Browse the repository at this point in the history
* fix header length check: we must take into account optional extension
header
* it seems the check on UTPv1 header is weak only in the DATA case: wait
for multiple packets only in that case

The new attached trace has been captured with the Transmission client,
without any other kind of traffic: ideally all the flows should be
classified as Bittorrent. This is the diff of its classification with
and without this patch:

```
< DPI Packets (TCP):	2029	(7.27 pkts/flow)
< DPI Packets (UDP):	2259	(3.40 pkts/flow)
< Confidence Unknown          : 204 (flows)
< Confidence Match by port    : 394 (flows)
< Confidence DPI (partial cache): 45 (flows)
< Confidence DPI (cache)      : 15 (flows)
< Confidence DPI              : 286 (flows)
---
> DPI Packets (TCP):	2027	(7.27 pkts/flow)
> DPI Packets (UDP):	1901	(2.86 pkts/flow)
> Confidence Unknown          : 113 (flows)
> Confidence Match by port    : 11 (flows)
> Confidence DPI (partial cache): 139 (flows)
> Confidence DPI (cache)      : 16 (flows)
> Confidence DPI              : 665 (flows)

< Unknown	1528	174586	204
---
> Unknown	1301	157680	113
34c34
< BitTorrent	6177	1025172	737
---
> BitTorrent	6404	1042078	828

```
  • Loading branch information
IvanNardi committed Jan 12, 2024
1 parent dd8be1f commit 6902fb7
Show file tree
Hide file tree
Showing 5 changed files with 1,025 additions and 13 deletions.
38 changes: 32 additions & 6 deletions src/lib/protocols/bittorrent.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,24 +69,48 @@ static int search_bittorrent_again(struct ndpi_detection_module_struct *ndpi_str

/* *********************************************** */

static int get_utpv1_length(const u_int8_t *payload, u_int payload_len)
{
struct ndpi_utp_hdr *h = (struct ndpi_utp_hdr*)payload;
unsigned int off;
u_int8_t ext_type = h->next_extension;

off = sizeof(struct ndpi_utp_hdr);
while(ext_type != 0 && off + 1 < payload_len) {
ext_type = payload[off];
if(ext_type > 2)
return -1;
off += 2 + payload[off + 1];
}
if(ext_type == 0)
return off;
return -1;
}

/* *********************************************** */

static u_int8_t is_utpv1_pkt(const u_int8_t *payload, u_int payload_len) {
struct ndpi_utp_hdr *h = (struct ndpi_utp_hdr*)payload;
int h_length;

if(payload_len < sizeof(struct ndpi_utp_hdr)) return(0);
h_length = get_utpv1_length(payload, payload_len);
if(h_length == -1) return(0);
if(h->h_version != 1) return(0);
if(h->h_type > 4) return(0);
if(h->next_extension > 2) return(0);
if(h->window_size == 0) return(0);
if(h->h_type == 4 /* SYN */ && (h->tdiff_usec != 0 ||
payload_len != sizeof(struct ndpi_utp_hdr))) return(0);
payload_len != (u_int)h_length)) return(0);
if(h->h_type == 0 /* DATA */ &&
payload_len == sizeof(struct ndpi_utp_hdr)) return(0);
payload_len == (u_int)h_length) return(0);
if(h->connection_id == 0) return(0);
if(h->ts_usec == 0) return(0);

if((h->window_size == 0) && (payload_len != sizeof(struct ndpi_utp_hdr)))
if((h->window_size == 0) && (payload_len != (u_int)h_length))
return(0);

if(h->h_type == 0)
return (2); /* DATA */
return(1);
}

Expand Down Expand Up @@ -542,10 +566,12 @@ static void ndpi_search_bittorrent(struct ndpi_detection_module_struct *ndpi_str
/* Check if this is protocol v0 */
u_int8_t v0_extension = packet->payload[17];
u_int8_t v0_flags = packet->payload[18];
int rc;

if(is_utpv1_pkt(packet->payload, packet->payload_packet_len)) {
if((rc = is_utpv1_pkt(packet->payload, packet->payload_packet_len)) > 0) {
bt_proto = ndpi_strnstr((const char *)&packet->payload[20], BITTORRENT_PROTO_STRING, packet->payload_packet_len-20);
if(flow->packet_counter > 2 || bt_proto != NULL) {
/* DATA check is quite weak so in that case wait for multiple packets/confirmations */
if(rc == 1 || bt_proto != NULL || (rc == 2 && flow->packet_counter > 2)) {
goto bittorrent_found;
} else {
return;
Expand Down
Binary file not shown.
Loading

0 comments on commit 6902fb7

Please sign in to comment.