-
Notifications
You must be signed in to change notification settings - Fork 58
NETOBSERV-2471: TLS usage tracking #815
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
db94054
ba9e3c9
b33e095
e2975f9
8a813b1
f414063
a9c6e61
5e5c51d
e9f0ab7
b26bc00
a7b3374
6820367
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,287 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /* | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| TLS tracker detects TLS packets and extracts information such as version or cipher suite. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #ifndef __TLS_TRACKER_H__ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #define __TLS_TRACKER_H__ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #include "utils.h" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #define TLSTRACKER_UNKNOWN -1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #define TLSTRACKER_NOTLS -2 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #define TLSTRACKER_MATCHED 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #define CONTENT_TYPE_CHANGE_CIPHER 0x14 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #define CONTENT_TYPE_ALERT 0x15 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #define CONTENT_TYPE_HANDSHAKE 0x16 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #define CONTENT_TYPE_APP_DATA 0x17 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #define TLSTRACKER_BF_CLIENT_HELLO 0x01 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #define TLSTRACKER_BF_SERVER_HELLO 0x02 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #define TLSTRACKER_BF_OTHER_HANDSHAKE 0x04 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #define TLSTRACKER_BF_CHANGE_CIPHER 0x08 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #define TLSTRACKER_BF_ALERT 0x10 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #define TLSTRACKER_BF_APP_DATA 0x20 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // https://www.rfc-editor.org/rfc/rfc5246 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| struct tls_record { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| u8 content_type; // handshake, alert, change cipher, app data | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| u16 version; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } __attribute__((packed)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| struct tls_handshake_header { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| u8 type; // client hello, server hello ... | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } __attribute__((packed)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| struct tls_extension_header { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| u16 type; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| u16 len; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } __attribute__((packed)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| static inline int tls_read_client_hello(struct __sk_buff *skb, u32 offset, tls_info *tls) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| u16 handshake_version; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (bpf_skb_load_bytes(skb, offset, &handshake_version, sizeof(handshake_version)) < 0) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Returning unknown because it could still be a FINISHED encrypted message | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return TLSTRACKER_UNKNOWN; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| handshake_version = bpf_ntohs(handshake_version); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| offset += 2; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Accept only 0300 (ssl v3), 0301 (tls 1.0), 0302 (tls 1.1) or 0303 (tls 1.2 or 1.3) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (handshake_version < 0x0300 || handshake_version > 0x0303) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return TLSTRACKER_UNKNOWN; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tls->type = TLSTRACKER_BF_CLIENT_HELLO; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (handshake_version == 0x0303) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Check extensions to discriminate 1.2 and 1.3 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| u8 session_len, compr_len; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| u16 cipher_len, exts_len; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| offset += 32; // skip random | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Read session | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (bpf_skb_load_bytes(skb, offset, &session_len, sizeof(session_len)) < 0) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return TLSTRACKER_UNKNOWN; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| offset += 1 + session_len; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Read cipher suites | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (bpf_skb_load_bytes(skb, offset, &cipher_len, sizeof(cipher_len)) < 0) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return TLSTRACKER_UNKNOWN; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| offset += 2 + bpf_ntohs(cipher_len); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Read compression | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (bpf_skb_load_bytes(skb, offset, &compr_len, sizeof(compr_len)) < 0) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return TLSTRACKER_UNKNOWN; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| offset += 1 + compr_len; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Read extensions | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+53
to
+73
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be good to be able to see pre TLS-1.2 connections here even if it's not expected in recent environments. That's especially useful for auditing legacy TLS usage. Something around those lines should work:
Suggested change
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Pre-1.2 should already be handled - before 1.2, the TLS version was not provided through an extension, it was in the handshake version field (read from lines 41-46 above). |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (bpf_skb_load_bytes(skb, offset, &exts_len, sizeof(exts_len)) < 0) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return TLSTRACKER_UNKNOWN; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exts_len = bpf_ntohs(exts_len); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| offset += 2; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| u16 ext_offset = 0; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Read up to 30 extensions | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (int i = 0; i < 30; i++) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (ext_offset >= exts_len) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| break; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| struct tls_extension_header ext_hdr; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (bpf_skb_load_bytes(skb, offset + ext_offset, &ext_hdr, sizeof(ext_hdr)) < 0) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return TLSTRACKER_UNKNOWN; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ext_hdr.type = bpf_ntohs(ext_hdr.type); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ext_hdr.len = bpf_ntohs(ext_hdr.len); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ext_offset += 4; // 2 bytes for type, 2 bytes for length | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (ext_hdr.type == 0x002b) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Supported Versions | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| u16 supportedversions_offset = | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 1; // skip supported versions length (u8), it's always ext_hdr.len-1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Read up to 5 versions | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (int j = 0; j < 5; j++) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (supportedversions_offset >= ext_hdr.len) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| break; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| u16 version; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (bpf_skb_load_bytes(skb, offset + ext_offset + supportedversions_offset, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| &version, sizeof(version)) < 0) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return TLSTRACKER_UNKNOWN; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| version = bpf_ntohs(version); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (version > tls->hello_version) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tls->hello_version = version; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| supportedversions_offset += 2; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Stop reading here | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return TLSTRACKER_MATCHED; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ext_offset += ext_hdr.len; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tls->hello_version = handshake_version; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return TLSTRACKER_MATCHED; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| static inline int tls_read_server_hello(struct __sk_buff *skb, u32 offset, tls_info *tls) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| u16 handshake_version; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (bpf_skb_load_bytes(skb, offset, &handshake_version, sizeof(handshake_version)) < 0) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Returning unknown because it could still be a FINISHED encrypted message | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return TLSTRACKER_UNKNOWN; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| handshake_version = bpf_ntohs(handshake_version); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| offset += 2; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Accept only 0300 (ssl v3), 0301 (tls 1.0), 0302 (tls 1.1) or 0303 (tls 1.2 or 1.3) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (handshake_version < 0x0300 || handshake_version > 0x0303) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return TLSTRACKER_UNKNOWN; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tls->type = TLSTRACKER_BF_SERVER_HELLO; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (handshake_version == 0x0303) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Check extensions to discriminate 1.2 and 1.3 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| u8 session_len; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| u16 exts_len; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| offset += 32; // skip random | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Read session | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (bpf_skb_load_bytes(skb, offset, &session_len, sizeof(session_len)) < 0) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return TLSTRACKER_UNKNOWN; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| offset += 1 + session_len; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Read cipher suites | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (bpf_skb_load_bytes(skb, offset, &tls->cipher_suite, sizeof(tls->cipher_suite)) < 0) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return TLSTRACKER_UNKNOWN; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tls->cipher_suite = bpf_ntohs(tls->cipher_suite); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| offset += 3; // Skip also compression (1B) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Read extensions | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (bpf_skb_load_bytes(skb, offset, &exts_len, sizeof(exts_len)) < 0) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return TLSTRACKER_UNKNOWN; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exts_len = bpf_ntohs(exts_len); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| offset += 2; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| u16 ext_offset = 0; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| u8 ext_read = 0; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Read up to 30 extensions | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (int i = 0; i < 30; i++) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (ext_offset >= exts_len) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| break; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| struct tls_extension_header ext_hdr; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (bpf_skb_load_bytes(skb, offset + ext_offset, &ext_hdr, sizeof(ext_hdr)) < 0) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return TLSTRACKER_UNKNOWN; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ext_hdr.type = bpf_ntohs(ext_hdr.type); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ext_hdr.len = bpf_ntohs(ext_hdr.len); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ext_offset += 4; // 2 bytes for type, 2 bytes for length | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (ext_hdr.type == 0x002b) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Supported Versions: single version expected | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| u16 version; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (bpf_skb_load_bytes(skb, offset + ext_offset, &version, sizeof(version)) < 0) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return TLSTRACKER_UNKNOWN; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tls->hello_version = bpf_ntohs(version); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ext_read++; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else if (ext_hdr.type == 0x0033) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Key Share Extension (TLS 1.3) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // The Server Hello Key Share contains: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Group (2 bytes) + Key Exchange Length (2 bytes) + Key Exchange Data | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| u16 key_share; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (bpf_skb_load_bytes(skb, offset + ext_offset, &key_share, sizeof(key_share)) < | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 0) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return TLSTRACKER_UNKNOWN; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tls->key_share = bpf_ntohs(key_share); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ext_read++; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (ext_read == 2) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Return after 0x002b and 0x0033 are read | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return TLSTRACKER_MATCHED; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Something else that would be nice to pull out of the extensions is the key share. This would tell users if the server is using classical or hybrid key exchange algorithms, which is useful for finding out which applications are PQC-ready (e.g., looking for We might need to do something like: if (ext_hdr.type == 0x002b) {
// Supported Versions: single version expected
u16 version;
if (bpf_skb_load_bytes(skb, offset + ext_offset, &version, sizeof(version)) < 0) {
return TLSTRACKER_UNKNOWN;
}
tls->version = bpf_ntohs(version);
}
else if (ext_hdr.type == 0x0033) {
// Key Share Extension (TLS 1.3)
// The Server Hello Key Share contains:
// Group (2 bytes) + Key Exchange Length (2 bytes) + Key Exchange Data
u16 selected_group;
if (bpf_skb_load_bytes(skb, offset + ext_offset, &selected_group, sizeof(selected_group)) < 0) {
// not sure what would be best to return here?
return KEYSHARE_UNKNOWN;
}
tls->key_share_group = bpf_ntohs(selected_group);
}The Thoughts?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yep, definitely, if that's useful to figure out PQC-readiness, it's something that we want here
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done here a9c6e61 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ext_offset += ext_hdr.len; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tls->hello_version = handshake_version; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return TLSTRACKER_MATCHED; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| static inline int track_tls_tcp(struct __sk_buff *skb, void *l4_hdr, tls_info *tls) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| void *data_end = (void *)(long)skb->data_end; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| struct tcphdr *tcp = (struct tcphdr *)l4_hdr; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!tcp || ((void *)tcp + sizeof(*tcp) > data_end)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return TLSTRACKER_NOTLS; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| u8 len = tcp->doff * sizeof(u32); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!len) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return TLSTRACKER_NOTLS; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| struct tls_record rec; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| u32 offset = (long)l4_hdr - (long)skb->data + len; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if ((bpf_skb_load_bytes(skb, offset, &rec, sizeof(rec))) < 0) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return TLSTRACKER_NOTLS; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Record header = 5 bytes: 1 for content type, 2 for version, 2 for following message length (which we don't need to keep) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| offset += 5; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you please put a comment to explain this ? |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| rec.version = bpf_ntohs(rec.version); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Accept only 0300, 0301, 0302 or 0303 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Note that for compatibility reasons, versions cannot be trusted here: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // TLS 1.2 or 1.3 packets can be disguised as 1.0, hence further analysis is required | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (rec.version < 0x0300 || rec.version > 0x0303) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return TLSTRACKER_NOTLS; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| switch (rec.content_type) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case CONTENT_TYPE_HANDSHAKE: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Handshakes should have the handshake header, except if it's a FINISHED msg, which is encrypted. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // In both cases, there should be sufficient data to fill tls_handshake_header; but we can't assume it's valid | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| struct tls_handshake_header handshake; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (bpf_skb_load_bytes(skb, offset, &handshake, sizeof(handshake)) < 0) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return TLSTRACKER_NOTLS; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Handshake header = 4 bytes: 1 for handshake type, 3 for following length (which we don't need to keep) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| offset += 4; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here. A comment would help. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // From now on, if we fail to read what we expect, this was either not a TLS packet, or a FINISHED message. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| switch (handshake.type) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case 0x01: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return tls_read_client_hello(skb, offset, tls); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case 0x02: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return tls_read_server_hello(skb, offset, tls); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case 0x10: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case 0x0b: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case 0x0c: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case 0x0e: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Still sounds like a valid handshake, assume it is | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tls->type = TLSTRACKER_BF_OTHER_HANDSHAKE; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return TLSTRACKER_MATCHED; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Either not TLS, or FINISHED | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return TLSTRACKER_UNKNOWN; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case CONTENT_TYPE_CHANGE_CIPHER: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tls->type = TLSTRACKER_BF_CHANGE_CIPHER; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return TLSTRACKER_MATCHED; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case CONTENT_TYPE_ALERT: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tls->type = TLSTRACKER_BF_ALERT; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return TLSTRACKER_MATCHED; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case CONTENT_TYPE_APP_DATA: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tls->type = TLSTRACKER_BF_APP_DATA; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return TLSTRACKER_MATCHED; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return TLSTRACKER_NOTLS; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Extract TLS info | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| static inline int track_tls(struct __sk_buff *skb, u8 proto, void *l4_hdr, u8 flags, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tls_info *tls) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (enable_tls_usage_tracking == 0) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return TLSTRACKER_UNKNOWN; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (proto == IPPROTO_TCP && flags & 0x10) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // TCP ACK | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return track_tls_tcp(skb, l4_hdr, tls); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // TODO: UDP/QUIC | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return TLSTRACKER_UNKNOWN; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #endif // __TLS_TRACKER_H__ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.