Fix host LRU resolution not performed in some cases

This commit is contained in:
emanuele-f 2021-03-25 11:29:40 +01:00
parent b32563c159
commit fbabe5478f
2 changed files with 98 additions and 82 deletions

View File

@ -107,7 +107,8 @@ public class ConnectionsAdapter extends RecyclerView.Adapter<ConnectionsAdapter.
if(conn.status < ConnectionDescriptor.CONN_STATUS_CLOSED)
statusInd.setTextColor(0xFF28BC36); // Open
else if(conn.status == ConnectionDescriptor.CONN_STATUS_CLOSED)
else if((conn.status == ConnectionDescriptor.CONN_STATUS_CLOSED)
|| (conn.status == ConnectionDescriptor.CONN_STATUS_RESET))
statusInd.setTextColor(0xFFAAAAAA);
else
statusInd.setTextColor(0xFFF20015); // Error

View File

@ -31,7 +31,7 @@
#define CONNECTION_DUMP_UPDATE_FREQUENCY_MS 1000
#define MAX_JAVA_DUMP_DELAY_MS 1000
#define MAX_DPI_PACKETS 12
#define MAX_HOST_LRU_SIZE 64
#define MAX_HOST_LRU_SIZE 128
#define JAVA_PCAP_BUFFER_SIZE (512*1024) // 512K
#define PERIODIC_PURGE_TIMEOUT_MS 5000
@ -323,10 +323,85 @@ const char *getProtoName(struct ndpi_detection_module_struct *mod, ndpi_protocol
/* ******************************************************* */
static void end_ndpi_detection(conn_data_t *data, vpnproxy_data_t *proxy, const zdtun_conn_t *conn_info) {
const zdtun_5tuple_t *tuple = zdtun_conn_get_5tuple(conn_info);
if(!data->ndpi_flow)
return;
if(data->l7proto.app_protocol == NDPI_PROTOCOL_UNKNOWN) {
uint8_t proto_guessed;
data->l7proto = ndpi_detection_giveup(proxy->ndpi, data->ndpi_flow, 1 /* Guess */,
&proto_guessed);
}
if(data->l7proto.master_protocol == 0)
data->l7proto.master_protocol = data->l7proto.app_protocol;
log_android(ANDROID_LOG_DEBUG, "nDPI completed[ipver=%d, proto=%d] -> l7proto: app=%d, master=%d",
tuple->ipver, tuple->ipproto, data->l7proto.app_protocol, data->l7proto.master_protocol);
switch (data->l7proto.master_protocol) {
case NDPI_PROTOCOL_DNS:
if(data->ndpi_flow->host_server_name[0]) {
u_int16_t rsp_type = data->ndpi_flow->protos.dns.rsp_type;
zdtun_ip_t rsp_addr = {0};
int ipver = 0;
if(data->info)
free(data->info);
data->info = strdup((char*)data->ndpi_flow->host_server_name);
if((rsp_type == 0x1) && (data->ndpi_flow->protos.dns.rsp_addr.ipv4 != 0)) { /* A */
rsp_addr.ip4 = data->ndpi_flow->protos.dns.rsp_addr.ipv4;
ipver = 4;
} else if((rsp_type == 0x1c)
&& ((data->ndpi_flow->protos.dns.rsp_addr.ipv6.u6_addr.u6_addr8[0] & 0xE0) == 0x20)) { /* AAAA unicast */
memcpy(&rsp_addr.ip6, &data->ndpi_flow->protos.dns.rsp_addr.ipv6.u6_addr, 16);
ipver = 6;
}
if(ipver != 0) {
char rspip[INET6_ADDRSTRLEN];
int family = (ipver == 4) ? AF_INET : AF_INET6;
inet_ntop(family, &rsp_addr, rspip, sizeof(rspip));
log_android(ANDROID_LOG_DEBUG, "Host LRU cache ADD [v%d]: %s -> %s", ipver, rspip, data->info);
ip_lru_add(proxy->ip_to_host, &rsp_addr, data->info);
}
}
break;
case NDPI_PROTOCOL_HTTP:
if(data->ndpi_flow->host_server_name[0]) {
if(data->info)
free(data->info);
data->info = strdup((char*) data->ndpi_flow->host_server_name);
}
if(data->ndpi_flow->http.url)
data->url = strdup(data->ndpi_flow->http.url);
break;
case NDPI_PROTOCOL_TLS:
if(data->ndpi_flow->protos.stun_ssl.ssl.client_requested_server_name[0]) {
if(data->info)
free(data->info);
data->info = strdup(data->ndpi_flow->protos.stun_ssl.ssl.client_requested_server_name);
}
break;
}
free_ndpi(data);
}
/* ******************************************************* */
static void process_ndpi_packet(conn_data_t *data, vpnproxy_data_t *proxy, const zdtun_conn_t *conn_info,
const char *packet, int size, uint8_t from_tun) {
bool giveup = ((data->sent_pkts + data->rcvd_pkts) >= MAX_DPI_PACKETS);
const zdtun_5tuple_t *tuple = zdtun_conn_get_5tuple(conn_info);
data->l7proto = ndpi_detection_process_packet(proxy->ndpi, data->ndpi_flow, (const u_char *)packet,
size, data->last_seen,
@ -334,82 +409,8 @@ static void process_ndpi_packet(conn_data_t *data, vpnproxy_data_t *proxy, const
from_tun ? data->dst_id : data->src_id);
if(giveup || ((data->l7proto.app_protocol != NDPI_PROTOCOL_UNKNOWN) &&
(!ndpi_extra_dissection_possible(proxy->ndpi, data->ndpi_flow)))) {
if(data->l7proto.app_protocol == NDPI_PROTOCOL_UNKNOWN) {
uint8_t proto_guessed;
data->l7proto = ndpi_detection_giveup(proxy->ndpi, data->ndpi_flow, 1 /* Guess */,
&proto_guessed);
}
if(data->l7proto.master_protocol == 0)
data->l7proto.master_protocol = data->l7proto.app_protocol;
log_android(ANDROID_LOG_DEBUG, "nDPI completed[ipver=%d, proto=%d] -> l7proto: app=%d, master=%d",
tuple->ipver, tuple->ipproto, data->l7proto.app_protocol, data->l7proto.master_protocol);
switch (data->l7proto.master_protocol) {
case NDPI_PROTOCOL_DNS:
if(data->ndpi_flow->host_server_name[0]) {
u_int16_t rsp_type = data->ndpi_flow->protos.dns.rsp_type;
zdtun_ip_t rsp_addr = {0};
int ipver = 0;
data->info = strdup((char*)data->ndpi_flow->host_server_name);
if((rsp_type == 0x1) && (data->ndpi_flow->protos.dns.rsp_addr.ipv4 != 0)) { /* A */
rsp_addr.ip4 = data->ndpi_flow->protos.dns.rsp_addr.ipv4;
ipver = 4;
} else if((rsp_type == 0x1c)
&& ((data->ndpi_flow->protos.dns.rsp_addr.ipv6.u6_addr.u6_addr8[0] & 0xE0) == 0x20)) { /* AAAA unicast */
memcpy(&rsp_addr.ip6, &data->ndpi_flow->protos.dns.rsp_addr.ipv6.u6_addr, 16);
ipver = 6;
}
if(ipver != 0) {
char rspip[INET6_ADDRSTRLEN];
int family = (ipver == 4) ? AF_INET : AF_INET6;
inet_ntop(family, &rsp_addr, rspip, sizeof(rspip));
log_android(ANDROID_LOG_DEBUG, "Host LRU cache ADD [v%d]: %s -> %s", ipver, rspip, data->info);
ip_lru_add(proxy->ip_to_host, &rsp_addr, data->info);
}
}
break;
case NDPI_PROTOCOL_HTTP:
if(data->ndpi_flow->host_server_name[0])
data->info = strdup((char*)data->ndpi_flow->host_server_name);
if(data->ndpi_flow->http.url)
data->url = strdup(data->ndpi_flow->http.url);
break;
case NDPI_PROTOCOL_TLS:
if(data->ndpi_flow->protos.stun_ssl.ssl.client_requested_server_name[0])
data->info = strdup(data->ndpi_flow->protos.stun_ssl.ssl.client_requested_server_name);
break;
}
if(!data->info) {
// Search the LRU cache
zdtun_ip_t ip = tuple->dst_ip;
data->info = ip_lru_find(proxy->ip_to_host, &ip);
if(data->info) {
char resip[INET6_ADDRSTRLEN];
int family = (tuple->ipver == 4) ? AF_INET : AF_INET6;
inet_ntop(family, &ip, resip, sizeof(resip));
log_android(ANDROID_LOG_DEBUG, "Host LRU cache HIT: %s -> %s", resip, data->info);
}
}
if(data->info)
log_android(ANDROID_LOG_DEBUG, "info: %s", data->info);
free_ndpi(data);
}
(!ndpi_extra_dissection_possible(proxy->ndpi, data->ndpi_flow))))
end_ndpi_detection(data, proxy, conn_info);
}
/* ******************************************************* */
@ -570,6 +571,7 @@ static int resolve_uid(vpnproxy_data_t *proxy, const zdtun_5tuple_t *conn_info)
static int handle_new_connection(zdtun_t *tun, zdtun_conn_t *conn_info) {
vpnproxy_data_t *proxy = ((vpnproxy_data_t*)zdtun_userdata(tun));
const zdtun_5tuple_t *tuple = zdtun_conn_get_5tuple(conn_info);
if(!check_dns_req_allowed(proxy, conn_info)) {
// block connection
@ -603,11 +605,24 @@ static int handle_new_connection(zdtun_t *tun, zdtun_conn_t *conn_info) {
}
data->first_seen = data->last_seen = time(NULL);
data->uid = resolve_uid(proxy, zdtun_conn_get_5tuple(conn_info));
data->uid = resolve_uid(proxy, tuple);
// Try to resolve host name via the LRU cache
zdtun_ip_t ip = tuple->dst_ip;
data->info = ip_lru_find(proxy->ip_to_host, &ip);
if(data->info) {
char resip[INET6_ADDRSTRLEN];
int family = (tuple->ipver == 4) ? AF_INET : AF_INET6;
inet_ntop(family, &ip, resip, sizeof(resip));
log_android(ANDROID_LOG_DEBUG, "Host LRU cache HIT: %s -> %s", resip, data->info);
}
zdtun_conn_set_userdata(conn_info, data);
if(!shouldIgnoreConn(proxy, zdtun_conn_get_5tuple(conn_info), data)) {
if(!shouldIgnoreConn(proxy, tuple, data)) {
// Important: only set the incr_id on registered connections since
// ConnectionsRegister::connectionsUpdates does not allow gaps
data->incr_id = proxy->incr_id++;
@ -632,7 +647,7 @@ static void destroy_connection(zdtun_t *tun, const zdtun_conn_t *conn_info) {
}
/* Will free the other data in sendConnectionsDump */
free_ndpi(data);
end_ndpi_detection(data, proxy, conn_info);
data->status = zdtun_conn_get_status(conn_info);
if(!data->pending_notification && !shouldIgnoreConn(proxy, zdtun_conn_get_5tuple(conn_info), data)) {