mirror of
https://github.com/M66B/NetGuard.git
synced 2024-12-21 23:33:21 +00:00
Added SNI decoding
This commit is contained in:
parent
27cfbe8aba
commit
78a0feb5a6
4 changed files with 202 additions and 0 deletions
|
@ -9,6 +9,7 @@ add_library( netguard
|
||||||
src/main/jni/netguard/tcp.c
|
src/main/jni/netguard/tcp.c
|
||||||
src/main/jni/netguard/udp.c
|
src/main/jni/netguard/udp.c
|
||||||
src/main/jni/netguard/icmp.c
|
src/main/jni/netguard/icmp.c
|
||||||
|
src/main/jni/netguard/tls.c
|
||||||
src/main/jni/netguard/dns.c
|
src/main/jni/netguard/dns.c
|
||||||
src/main/jni/netguard/dhcp.c
|
src/main/jni/netguard/dhcp.c
|
||||||
src/main/jni/netguard/pcap.c
|
src/main/jni/netguard/pcap.c
|
||||||
|
|
|
@ -292,6 +292,20 @@ void handle_ip(const struct arguments *args,
|
||||||
uid = get_uid_q(args, version, protocol, source, sport, dest, dport);
|
uid = get_uid_q(args, version, protocol, source, sport, dest, dport);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get server name
|
||||||
|
if (protocol == IPPROTO_TCP) {
|
||||||
|
const struct tcphdr *tcphdr = (struct tcphdr *) payload;
|
||||||
|
const uint8_t tcpoptlen = (uint8_t) ((tcphdr->doff - 5) * 4);
|
||||||
|
const uint8_t *data = payload + sizeof(struct tcphdr) + tcpoptlen;
|
||||||
|
const uint16_t datalen = (const uint16_t) (length - (data - pkt));
|
||||||
|
|
||||||
|
char server_name[TLS_SNI_LENGTH + 1];
|
||||||
|
if (get_sni(data, datalen, server_name)) {
|
||||||
|
log_android(ANDROID_LOG_INFO, "TLS server name: %s", server_name);
|
||||||
|
dns_resolved(args, server_name, server_name, dest, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
log_android(ANDROID_LOG_DEBUG,
|
log_android(ANDROID_LOG_DEBUG,
|
||||||
"Packet v%d %s/%u > %s/%u proto %d flags %s uid %d",
|
"Packet v%d %s/%u > %s/%u proto %d flags %s uid %d",
|
||||||
version, source, sport, dest, dport, protocol, flags, uid);
|
version, source, sport, dest, dport, protocol, flags, uid);
|
||||||
|
|
|
@ -253,6 +253,18 @@ typedef struct pcaprec_hdr_s {
|
||||||
|
|
||||||
#define LINKTYPE_RAW 101
|
#define LINKTYPE_RAW 101
|
||||||
|
|
||||||
|
// TLS
|
||||||
|
|
||||||
|
#define TLS_SNI_LENGTH 255
|
||||||
|
#define TLS_HANDSHAKE_RECORD 22
|
||||||
|
#define TLS_MESSAGE_CLIENTHELLO 1
|
||||||
|
#define TLS_EXTENSION_TYPE_SERVER_NAME 0
|
||||||
|
|
||||||
|
int get_sni(
|
||||||
|
const uint8_t *data,
|
||||||
|
const uint16_t datalen,
|
||||||
|
char *server_name);
|
||||||
|
|
||||||
// DNS
|
// DNS
|
||||||
|
|
||||||
#define DNS_QCLASS_IN 1
|
#define DNS_QCLASS_IN 1
|
||||||
|
|
175
app/src/main/jni/netguard/tls.c
Normal file
175
app/src/main/jni/netguard/tls.c
Normal file
|
@ -0,0 +1,175 @@
|
||||||
|
/*
|
||||||
|
This file is part of NetGuard.
|
||||||
|
|
||||||
|
NetGuard is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
NetGuard is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with NetGuard. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Copyright 2015-2019 by Marcel Bokhorst (M66B)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "netguard.h"
|
||||||
|
|
||||||
|
int get_sni(
|
||||||
|
const uint8_t *data,
|
||||||
|
const uint16_t datalen,
|
||||||
|
char *server_name) {
|
||||||
|
if (datalen < 6) {
|
||||||
|
log_android(ANDROID_LOG_DEBUG, "TLS header too short");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t content_type = (uint8_t) data[0];
|
||||||
|
uint8_t major_version = (uint8_t) data[1];
|
||||||
|
uint8_t minor_version = (uint8_t) data[2];
|
||||||
|
uint16_t content_length = ((uint16_t) data[3] << 8) | data[4];
|
||||||
|
uint8_t message_type = (uint8_t) data[5];
|
||||||
|
|
||||||
|
// https://www.rfc-editor.org/rfc/rfc5246#section-7.4.1.2
|
||||||
|
if (content_type != TLS_HANDSHAKE_RECORD ||
|
||||||
|
major_version < 0x03 ||
|
||||||
|
5 + content_length != datalen ||
|
||||||
|
message_type != TLS_MESSAGE_CLIENTHELLO) {
|
||||||
|
log_android(ANDROID_LOG_DEBUG, "TLS content %d version %d length %d/%d type %d",
|
||||||
|
content_type, major_version, 5 + content_length, datalen, message_type);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_android(ANDROID_LOG_DEBUG, "TLS client hello version %d.%d",
|
||||||
|
major_version, minor_version);
|
||||||
|
|
||||||
|
uint8_t index = 6 + // header above
|
||||||
|
3 + // client hello length
|
||||||
|
2 + // client hello protocol version
|
||||||
|
32; // random value
|
||||||
|
|
||||||
|
// Session ID
|
||||||
|
if (index >= datalen) {
|
||||||
|
log_android(ANDROID_LOG_WARN, "TLS session ID %d/%d", index, datalen);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_android(ANDROID_LOG_DEBUG, "TLS hello version %d.%d",
|
||||||
|
data[9], data[10]);
|
||||||
|
|
||||||
|
uint8_t session_len = data[index];
|
||||||
|
index += 1 + session_len;
|
||||||
|
|
||||||
|
// Cipher suites
|
||||||
|
if (index + 1 >= datalen) {
|
||||||
|
log_android(ANDROID_LOG_WARN, "TLS cipher suites %d/%d", index + 1, datalen);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint16_t suites_len = ((uint16_t) data[index] << 8) | data[index + 1];
|
||||||
|
index += 2 + suites_len;
|
||||||
|
|
||||||
|
// Compression method
|
||||||
|
if (index >= datalen) {
|
||||||
|
log_android(ANDROID_LOG_WARN, "TLS compression %d/%d", index, datalen);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint8_t compression_len = data[index];
|
||||||
|
index += 1 + compression_len;
|
||||||
|
|
||||||
|
// Extensions length
|
||||||
|
if (index + 1 >= datalen) {
|
||||||
|
log_android(ANDROID_LOG_WARN, "TLS extensions %d/%d", index + 1, datalen);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint16_t edatalen = ((uint16_t) data[index] << 8) | data[index + 1];
|
||||||
|
index += 2;
|
||||||
|
|
||||||
|
if (edatalen == 0 || index + edatalen != datalen) {
|
||||||
|
log_android(ANDROID_LOG_WARN, "TLS extensions(2) len=%d %d/%d",
|
||||||
|
edatalen, index + edatalen, datalen);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t eindex = 0;
|
||||||
|
const uint8_t *edata = data + index;
|
||||||
|
while (eindex < edatalen) {
|
||||||
|
if (eindex + 1 >= edatalen) {
|
||||||
|
log_android(ANDROID_LOG_WARN, "TLS ext_type %d/%d", eindex + 1, edatalen);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint16_t ext_type = ((uint16_t) edata[eindex] << 8) | edata[eindex + 1];
|
||||||
|
eindex += 2;
|
||||||
|
log_android(ANDROID_LOG_DEBUG, "TLS ext_type=%d", ext_type);
|
||||||
|
|
||||||
|
if (eindex + 1 >= edatalen) {
|
||||||
|
log_android(ANDROID_LOG_WARN, "TLS ext_len %d/%d", eindex + 1, edatalen);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint16_t ext_len = ((uint16_t) edata[eindex] << 8) | edata[eindex + 1];
|
||||||
|
eindex += 2;
|
||||||
|
|
||||||
|
if (eindex + ext_len > edatalen) {
|
||||||
|
log_android(ANDROID_LOG_WARN, "TLS ext_len(2) %d/%d", eindex + ext_len, edatalen);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://datatracker.ietf.org/doc/html/rfc6066
|
||||||
|
if (ext_type == TLS_EXTENSION_TYPE_SERVER_NAME) {
|
||||||
|
if (eindex + 1 >= edatalen) {
|
||||||
|
log_android(ANDROID_LOG_WARN, "TLS sni_len %d/%d", eindex + 1, edatalen);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint16_t sni_len = ((uint16_t) edata[eindex] << 8) | edata[eindex + 1];
|
||||||
|
eindex += 2;
|
||||||
|
log_android(ANDROID_LOG_DEBUG, "TLS sni_len=%d", sni_len);
|
||||||
|
|
||||||
|
|
||||||
|
if (eindex + sni_len >= edatalen) {
|
||||||
|
log_android(ANDROID_LOG_WARN, "TLS sni_len(2) len=%d %d/%d",
|
||||||
|
sni_len, eindex + sni_len, edatalen);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eindex >= edatalen) {
|
||||||
|
log_android(ANDROID_LOG_WARN, "TLS sni_type %d/%d", eindex, edatalen);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint8_t sni_type = edata[eindex++];
|
||||||
|
if (sni_type != 0) {
|
||||||
|
log_android(ANDROID_LOG_WARN, "TLS sni_type=%d", sni_type);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eindex + 1 >= edatalen) {
|
||||||
|
log_android(ANDROID_LOG_WARN, "TLS name_len %d/%d", eindex + 1, edatalen);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint16_t name_len = ((uint16_t) edata[eindex] << 8) | edata[eindex + 1];
|
||||||
|
eindex += 2;
|
||||||
|
|
||||||
|
if (eindex + name_len >= edatalen) {
|
||||||
|
log_android(ANDROID_LOG_WARN, "TLS name_len(2) len=%d %d/%d",
|
||||||
|
name_len, eindex + name_len, edatalen);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (name_len >= TLS_SNI_LENGTH) {
|
||||||
|
log_android(ANDROID_LOG_WARN, "TLS name_len(3) %d/%d",
|
||||||
|
name_len, TLS_SNI_LENGTH);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(server_name, edata + eindex, name_len);
|
||||||
|
server_name[name_len] = 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
eindex += ext_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in a new issue