Skip to content

Commit 2b9ecef

Browse files
authored
Merge pull request #204 from netd-tud/feature-tls-extensions
Feature tls extensions
2 parents b1eaf0e + b528335 commit 2b9ecef

File tree

6 files changed

+132
-41
lines changed

6 files changed

+132
-41
lines changed

README.md

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -288,12 +288,14 @@ List of unirec fields exported together with basic flow fields on interface by R
288288
### TLS
289289
List of unirec fields exported together with basic flow fields on interface by TLS plugin.
290290

291-
| Output field | Type | Description |
292-
|:-------------------:|:------:|:-------------------------------------------------------------:|
293-
| TLS_SNI | string | TLS server name indication field from client |
294-
| TLS_ALPN | string | TLS application protocol layer negotiation field from server |
295-
| TLS_VERSION | uint16 | TLS client protocol version |
296-
| TLS_JA3 | string | TLS client JA3 fingerprint |
291+
| Output field | Type | Description |
292+
|:------------:|:--------:|:------------------------------------------------------------:|
293+
| TLS_SNI | string | TLS server name indication field from client |
294+
| TLS_ALPN | string | TLS application protocol layer negotiation field from server |
295+
| TLS_VERSION | uint16 | TLS client protocol version |
296+
| TLS_JA3 | string | TLS client JA3 fingerprint |
297+
| TLS_EXT_TYPE | uint16\* | TLS extensions in the TLS Client Hello |
298+
| TLS_EXT_LEN | uint16\* | Length of each TLS extension |
297299

298300
### DNS
299301
List of unirec fields exported together with basic flow fields on interface by DNS plugin.

include/ipfixprobe/ipfix-elements.hpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,9 @@ namespace ipxp {
186186
#define TLS_VERSION(F) F(39499, 333, 2, nullptr)
187187
#define TLS_ALPN(F) F(39499, 337, -1, nullptr)
188188
#define TLS_JA3(F) F(39499, 357, -1, nullptr)
189+
#define TLS_EXT_TYPE(F) F(0, 291, -1, nullptr)
190+
#define TLS_EXT_LEN(F) F(0, 291, -1, nullptr)
191+
189192

190193
#define SMTP_COMMANDS(F) F(8057, 810, 4, nullptr)
191194
#define SMTP_MAIL_COUNT(F) F(8057, 811, 4, nullptr)
@@ -378,7 +381,9 @@ namespace ipxp {
378381
F(TLS_VERSION) \
379382
F(TLS_SNI) \
380383
F(TLS_ALPN) \
381-
F(TLS_JA3)
384+
F(TLS_JA3) \
385+
F(TLS_EXT_TYPE) \
386+
F(TLS_EXT_LEN)
382387

383388
#define IPFIX_NTP_TEMPLATE(F) \
384389
F(NTP_LEAP) \

process/tls.cpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
* \author Ondrej Sedlacek <[email protected]>
1010
* \author Karel Hynek <[email protected]>
1111
* \author Andrej Lukacovic [email protected]
12+
* \author Jonas Mücke <[email protected]>
1213
* \date 2018-2022
1314
*/
1415

@@ -99,7 +100,6 @@ bool TLSPlugin::obtain_tls_data(TLSData &payload, RecordExtTLS *rec, std::string
99100
std::string ecliptic_curves;
100101
std::string ec_point_formats;
101102

102-
103103
while (payload.start + sizeof(tls_ext) <= payload.end) {
104104
tls_ext *ext = (tls_ext *) payload.start;
105105
uint16_t length = ntohs(ext->length);
@@ -118,6 +118,20 @@ bool TLSPlugin::obtain_tls_data(TLSData &payload, RecordExtTLS *rec, std::string
118118
} else if (type == TLS_EXT_EC_POINT_FORMATS) {
119119
ec_point_formats = tls_parser.tls_get_ja3_ec_point_formats(payload);
120120
}
121+
122+
if (!rec->tls_ext_len_set && !rec->tls_ext_type_set) {
123+
// Store extension type
124+
if (rec->tls_ext_type_len < MAX_TLS_EXT_LEN) {
125+
rec->tls_ext_type[rec->tls_ext_type_len] = type;
126+
rec->tls_ext_type_len += 1;
127+
}
128+
129+
// Store extension type length
130+
if (rec->tls_ext_len_len < MAX_TLS_EXT_LEN) {
131+
rec->tls_ext_len[rec->tls_ext_len_len] = length;
132+
rec->tls_ext_len_len += 1;
133+
}
134+
}
121135
} else if (hs_type == TLS_HANDSHAKE_SERVER_HELLO) {
122136
rec->server_hello_parsed = true;
123137
if (type == TLS_EXT_ALPN) {
@@ -138,6 +152,12 @@ bool TLSPlugin::obtain_tls_data(TLSData &payload, RecordExtTLS *rec, std::string
138152
}
139153
}
140154
}
155+
if (rec->tls_ext_type_len > 0 ) {
156+
rec->tls_ext_type_set = true;
157+
rec->tls_ext_len_set = true;
158+
}
159+
160+
141161
if (hs_type == TLS_HANDSHAKE_SERVER_HELLO) {
142162
return false;
143163
}

process/tls.hpp

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
* \author Jiri Havranek <[email protected]>
99
* \author Karel Hynek <[email protected]>
1010
* \author Andrej Lukacovic [email protected]
11+
* \author Jonas Mücke <[email protected]>
1112
* \date 2022
1213
*/
1314

@@ -29,6 +30,7 @@
2930
#include <ipfixprobe/process.hpp>
3031
#include <ipfixprobe/flowifc.hpp>
3132
#include <ipfixprobe/packet.hpp>
33+
#include <ipfixprobe/ipfix-basiclist.hpp>
3234
#include <ipfixprobe/ipfix-elements.hpp>
3335
#include <ipfixprobe/utils.hpp>
3436
#include <process/tls_parser.hpp>
@@ -37,18 +39,23 @@
3739
#define BUFF_SIZE 255
3840

3941
namespace ipxp {
40-
#define TLS_UNIREC_TEMPLATE "TLS_SNI,TLS_JA3,TLS_ALPN,TLS_VERSION"
42+
#define TLS_UNIREC_TEMPLATE "TLS_SNI,TLS_JA3,TLS_ALPN,TLS_VERSION,TLS_EXT_TYPE,TLS_EXT_LEN"
4143

4244
UR_FIELDS(
4345
string TLS_SNI,
4446
string TLS_ALPN,
4547
uint16 TLS_VERSION,
46-
bytes TLS_JA3
48+
bytes TLS_JA3,
49+
uint16* TLS_EXT_TYPE,
50+
uint16* TLS_EXT_LEN
4751
)
4852

4953
/**
5054
* \brief Flow record extension header for storing parsed HTTPS packets.
5155
*/
56+
// TODO fix IEs
57+
#define TLS_EXT_TYPE_FIELD_ID 802
58+
#define TLS_EXT_LEN_FIELD_ID 803
5259
struct RecordExtTLS : public RecordExt {
5360
static int REGISTERED_ID;
5461

@@ -60,6 +67,14 @@ struct RecordExtTLS : public RecordExt {
6067
std::string ja3;
6168
bool server_hello_parsed;
6269

70+
uint16_t tls_ext_type[MAX_TLS_EXT_LEN];
71+
uint16_t tls_ext_type_len;
72+
bool tls_ext_type_set;
73+
74+
uint16_t tls_ext_len[MAX_TLS_EXT_LEN];
75+
uint8_t tls_ext_len_len;
76+
bool tls_ext_len_set;
77+
6378
/**
6479
* \brief Constructor.
6580
*/
@@ -69,6 +84,14 @@ struct RecordExtTLS : public RecordExt {
6984
sni[0] = 0;
7085
ja3_hash[0] = 0;
7186
server_hello_parsed = false;
87+
88+
memset(tls_ext_type, 0, sizeof(tls_ext_type));
89+
tls_ext_type_len = 0;
90+
tls_ext_type_set = false;
91+
92+
memset(tls_ext_len, 0, sizeof(tls_ext_len));
93+
tls_ext_len_len = 0;
94+
tls_ext_len_set = false;
7295
}
7396

7497
#ifdef WITH_NEMEA
@@ -78,6 +101,14 @@ struct RecordExtTLS : public RecordExt {
78101
ur_set_string(tmplt, record, F_TLS_SNI, sni);
79102
ur_set_string(tmplt, record, F_TLS_ALPN, alpn);
80103
ur_set_var(tmplt, record, F_TLS_JA3, ja3_hash_bin, 16);
104+
ur_array_allocate(tmplt, record, F_QUIC_TLS_EXT_TYPE, tls_ext_type_len);
105+
for (int i = 0; i < tls_ext_type_len; i++) {
106+
ur_array_set(tmplt, record, F_TLS_EXT_TYPE, i, tls_ext_type[i]);
107+
}
108+
ur_array_allocate(tmplt, record, F_TLS_EXT_LEN, tls_ext_len_len);
109+
for (int i = 0; i < tls_ext_len_len; i++) {
110+
ur_array_set(tmplt, record, F_TLS_EXT_LEN, i, tls_ext_len[i]);
111+
}
81112
}
82113

83114
const char *get_unirec_tmplt() const
@@ -89,11 +120,18 @@ struct RecordExtTLS : public RecordExt {
89120

90121
virtual int fill_ipfix(uint8_t *buffer, int size)
91122
{
123+
IpfixBasicList basiclist;
124+
basiclist.hdrEnterpriseNum = IpfixBasicList::CesnetPEM;
125+
92126
uint16_t sni_len = strlen(sni);
93127
uint16_t alpn_len = strlen(alpn);
94128

95129
uint32_t pos = 0;
96-
uint32_t req_buff_len = (sni_len + 3) + (alpn_len + 3) + (2) + (16 + 3); // (SNI) + (ALPN) + (VERSION) + (JA3)
130+
131+
uint16_t len_tls_ext_type = sizeof(tls_ext_type[0]) * (tls_ext_type_len) + basiclist.HeaderSize();
132+
uint16_t len_tls_len = sizeof(tls_ext_len[0]) * (tls_ext_len_len) + basiclist.HeaderSize();
133+
134+
uint32_t req_buff_len = (sni_len + 3) + (alpn_len + 3) + (2) + (16 + 3) + len_tls_ext_type + len_tls_len; // (SNI) + (ALPN) + (VERSION) + (JA3)
97135

98136
if (req_buff_len > (uint32_t) size) {
99137
return -1;
@@ -108,7 +146,16 @@ struct RecordExtTLS : public RecordExt {
108146
buffer[pos++] = 16;
109147
memcpy(buffer + pos, ja3_hash_bin, 16);
110148
pos += 16;
111-
149+
pos += basiclist.FillBuffer(
150+
buffer + pos,
151+
tls_ext_type,
152+
(uint16_t) tls_ext_type_len,
153+
(uint16_t) TLS_EXT_TYPE_FIELD_ID);
154+
pos += basiclist.FillBuffer(
155+
buffer + pos,
156+
tls_ext_len,
157+
(uint16_t) tls_ext_len_len,
158+
(uint16_t) TLS_EXT_LEN_FIELD_ID);
112159
return pos;
113160
}
114161

@@ -133,6 +180,22 @@ struct RecordExtTLS : public RecordExt {
133180
for (int i = 0; i < 16; i++) {
134181
out << std::hex << std::setw(2) << std::setfill('0') << (unsigned) ja3_hash_bin[i];
135182
}
183+
out << ",tlsexttype=(";
184+
for (int i = 0; i < tls_ext_type_len; i++) {
185+
out << std::dec << (uint16_t) tls_ext_type[i];
186+
if (i != tls_ext_type_len - 1) {
187+
out << ",";
188+
}
189+
}
190+
out << "),tlsextlen=(";
191+
for (int i = 0; i < tls_ext_len_len; i++) {
192+
out << std::dec << (uint16_t) tls_ext_len[i];
193+
if (i != tls_ext_len_len - 1) {
194+
out << ",";
195+
}
196+
}
197+
out << ")";
198+
136199
return out.str();
137200
}
138201
};

process/tls_parser.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
// draf-02 az draft-12 have this value defined as 0x26 == 38
2727
#define TLS_EXT_QUIC_TRANSPORT_PARAMETERS_V2 0x26
2828
#define TLS_EXT_GOOGLE_USER_AGENT 0x3129
29+
#define MAX_TLS_EXT_LEN 30
2930

3031

3132
namespace ipxp {

0 commit comments

Comments
 (0)