Merge pull request #86 from wllm-rbnt/sigs

Connection tracker live list & purge
This commit is contained in:
Alexandre Dulaunoy 2023-08-20 23:04:16 +02:00 committed by GitHub
commit 6c1aa99da8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 110 additions and 21 deletions

View file

@ -75,6 +75,7 @@
#include "record_analyze.h" #include "record_analyze.h"
#endif #endif
#include "pcap_logger.h" #include "pcap_logger.h"
#include "tcpconn.h"
#ifndef ETHERTYPE_8021Q #ifndef ETHERTYPE_8021Q
#define ETHERTYPE_8021Q 0x8100 #define ETHERTYPE_8021Q 0x8100
@ -85,7 +86,8 @@ static int pcap_if_type = DLT_NULL;
int err_exit PROTO_LIST((char *str, int num)); int err_exit PROTO_LIST((char *str, int num));
int usage PROTO_LIST((void)); int usage PROTO_LIST((void));
int print_version PROTO_LIST((void)); int print_version PROTO_LIST((void));
void sig_handler PROTO_LIST((int sig)); void sig_handler_quit PROTO_LIST((int sig));
void sig_handler_usr PROTO_LIST((int sig));
void pcap_cb PROTO_LIST((u_char * ptr, void pcap_cb PROTO_LIST((u_char * ptr,
const struct pcap_pkthdr *hdr, const struct pcap_pkthdr *hdr,
const u_char *data)); const u_char *data));
@ -102,7 +104,7 @@ logger_mod *logger = NULL;
int err_exit(char *str, int num) { int err_exit(char *str, int num) {
fprintf(stderr, "ERROR: %s\n", str); fprintf(stderr, "ERROR: %s\n", str);
sig_handler(SIGQUIT); sig_handler_quit(SIGQUIT);
exit(num); exit(num);
} }
@ -136,7 +138,7 @@ n_handler *n;
char *interface_name = 0; char *interface_name = 0;
char *file = 0; char *file = 0;
char *filter = 0; char *filter = 0;
void sig_handler(int sig) { void sig_handler_quit(int sig) {
int freed_conn = 0; int freed_conn = 0;
fflush(stdout); fflush(stdout);
if(logger) if(logger)
@ -144,7 +146,7 @@ void sig_handler(int sig) {
freed_conn = destroy_all_conn(); freed_conn = destroy_all_conn();
if(freed_conn && !(NET_print_flags & NET_PRINT_JSON)) if(freed_conn && !(NET_print_flags & NET_PRINT_JSON))
printf("Cleaned %d remaining connection(s) from connection pool\n", fprintf(stderr, "Cleaned %d remaining connection(s) from connection pool\n",
freed_conn); freed_conn);
network_handler_destroy(mod, &n); network_handler_destroy(mod, &n);
@ -161,6 +163,33 @@ void sig_handler(int sig) {
exit(sig); exit(sig);
} }
void sig_handler_usr(int sig) {
int freed_conn = 0;
if(sig == SIGUSR1) {
if(!first_conn) {
fprintf(stderr,
"Received SIGUSR1, connection pool empty, nothing to list.\n");
} else {
fprintf(
stderr,
"Received SIGUSR1, listing currently tracked connection(s) ...\n");
list_all_conn();
}
} else if(sig == SIGUSR2) {
if(!first_conn) {
fprintf(stderr,
"Received SIGUSR2, connection pool empty, nothing to purge.\n");
} else {
fprintf(stderr, "Received SIGUSR2, purging connection pool ...\n");
freed_conn = destroy_all_conn();
if(freed_conn && !(NET_print_flags & NET_PRINT_JSON))
fprintf(stderr, "Purged %d connection(s) from connection pool\n",
freed_conn);
}
}
}
void pcap_cb(u_char *ptr, const struct pcap_pkthdr *hdr, const u_char *data) { void pcap_cb(u_char *ptr, const struct pcap_pkthdr *hdr, const u_char *data) {
n_handler *n; n_handler *n;
int len; int len;
@ -186,7 +215,7 @@ void pcap_cb(u_char *ptr, const struct pcap_pkthdr *hdr, const u_char *data) {
case DLT_EN10MB: case DLT_EN10MB:
if(len < sizeof(struct ether_header)) { if(len < sizeof(struct ether_header)) {
if(!(NET_print_flags & NET_PRINT_JSON)) if(!(NET_print_flags & NET_PRINT_JSON))
printf( fprintf(stderr,
"Frame size too small to contain Ethernet header, skipping " "Frame size too small to contain Ethernet header, skipping "
"...\n"); "...\n");
return; return;
@ -291,7 +320,8 @@ void pcap_cb(u_char *ptr, const struct pcap_pkthdr *hdr, const u_char *data) {
packet_cnt = 0; packet_cnt = 0;
memcpy(&last_packet_seen_time, &hdr->ts, sizeof(struct timeval)); memcpy(&last_packet_seen_time, &hdr->ts, sizeof(struct timeval));
if((cleaned_conn = clean_old_conn()) && !(NET_print_flags & NET_PRINT_JSON)) if((cleaned_conn = clean_old_conn()) && !(NET_print_flags & NET_PRINT_JSON))
printf("%d inactive connection(s) cleaned from connection pool\n", fprintf(stderr,
"%d inactive connection(s) cleaned from connection pool\n",
cleaned_conn); cleaned_conn);
} else { } else {
packet_cnt++; packet_cnt++;
@ -330,7 +360,9 @@ int main(int argc, char **argv) {
char errbuf[PCAP_ERRBUF_SIZE]; char errbuf[PCAP_ERRBUF_SIZE];
signal(SIGINT, sig_handler); signal(SIGINT, sig_handler_quit);
signal(SIGUSR1, sig_handler_usr);
signal(SIGUSR2, sig_handler_usr);
while((c = getopt(argc, argv, "vr:F:f:S:jyTt:ai:k:l:w:p:znsAxXhHVNdqem:P")) != while((c = getopt(argc, argv, "vr:F:f:S:jyTt:ai:k:l:w:p:znsAxXhHVNdqem:P")) !=
EOF) { EOF) {
@ -442,6 +474,7 @@ int main(int argc, char **argv) {
err_exit("Aborting", -1); err_exit("Aborting", -1);
} }
} }
fprintf(stderr, "ssldump: listening on %s\n", interface_name);
if(!(p = pcap_open_live(interface_name, 65535, !no_promiscuous, 1000, if(!(p = pcap_open_live(interface_name, 65535, !no_promiscuous, 1000,
errbuf))) { errbuf))) {
fprintf(stderr, "PCAP: %s\n", errbuf); fprintf(stderr, "PCAP: %s\n", errbuf);
@ -514,7 +547,7 @@ int main(int argc, char **argv) {
freed_conn = destroy_all_conn(); freed_conn = destroy_all_conn();
if(freed_conn && !(NET_print_flags & NET_PRINT_JSON)) if(freed_conn && !(NET_print_flags & NET_PRINT_JSON))
printf("Cleaned %d remaining connection(s) from connection pool\n", fprintf(stderr, "Cleaned %d remaining connection(s) from connection pool\n",
freed_conn); freed_conn);
network_handler_destroy(mod, &n); network_handler_destroy(mod, &n);

View file

@ -47,15 +47,13 @@
#include "network.h" #include "network.h"
#include "tcpconn.h" #include "tcpconn.h"
typedef struct conn_struct_ {
tcp_conn conn;
struct conn_struct_ *next;
struct conn_struct_ *prev;
} conn_struct;
int conn_number = 1; int conn_number = 1;
static conn_struct *first_conn = 0; conn_struct *first_conn = 0;
char *state_map[] = {
"UNKNOWN", "TCP_STATE_SYN1", "TCP_STATE_SYN2",
"TCP_STATE_ACK", "TCP_STATE_ESTABLISHED", "TCP_STATE_FIN1",
"TCP_STATE_CLOSED"};
extern struct timeval last_packet_seen_time; extern struct timeval last_packet_seen_time;
extern int conn_ttl; extern int conn_ttl;
@ -179,6 +177,30 @@ int clean_old_conn(void) {
return i; return i;
} }
void list_all_conn(void) {
conn_struct *conn;
tcp_conn *tcpconn;
struct timeval dt;
long freshness;
fprintf(stderr,
"<connection #> <initiator:port> -> <responder:port> <state> "
"<freshness (in s)>\n");
conn = first_conn;
while(conn) {
tcpconn = &conn->conn;
conn = conn->next;
freshness =
(timestamp_diff(&last_packet_seen_time, &tcpconn->last_seen_time, &dt))
? 0
: dt.tv_sec;
fprintf(stderr, "Connection #%d %s:%d -> %s:%d %s %ld\n",
tcpconn->conn_number, tcpconn->i_name, tcpconn->i_port,
tcpconn->r_name, tcpconn->r_port, state_map[tcpconn->state],
freshness);
}
}
int destroy_all_conn(void) { int destroy_all_conn(void) {
int i = 0; int i = 0;
while(first_conn) { while(first_conn) {

View file

@ -62,6 +62,8 @@ typedef struct stream_data_ {
segment *oo_queue; segment *oo_queue;
} stream_data; } stream_data;
extern char *state_map[];
typedef struct tcp_conn_ { typedef struct tcp_conn_ {
int conn_number; int conn_number;
int state; int state;
@ -92,6 +94,12 @@ typedef struct tcp_conn_ {
struct conn_struct_ *backptr; struct conn_struct_ *backptr;
} tcp_conn; } tcp_conn;
typedef struct conn_struct_ {
tcp_conn conn;
struct conn_struct_ *next;
struct conn_struct_ *prev;
} conn_struct;
int tcp_find_conn PROTO_LIST((tcp_conn * *connp, int tcp_find_conn PROTO_LIST((tcp_conn * *connp,
int *directionp, int *directionp,
struct sockaddr_storage *src_addr, struct sockaddr_storage *src_addr,
@ -110,6 +118,9 @@ int free_tcp_segment_queue PROTO_LIST((segment * seg));
int copy_tcp_segment_queue PROTO_LIST((segment * *out, segment *in)); int copy_tcp_segment_queue PROTO_LIST((segment * *out, segment *in));
int clean_old_conn(void); int clean_old_conn(void);
void list_all_conn(void);
int destroy_all_conn(void); int destroy_all_conn(void);
extern conn_struct *first_conn;
#endif #endif

3
build.sh Executable file
View file

@ -0,0 +1,3 @@
#!/bin/sh
rm -Rf build && cmake -B build -G Ninja && ninja -C build

View file

@ -125,7 +125,7 @@ static int decode_ContentType_application_data(ssl_obj *ssl,
if(NET_print_flags & NET_PRINT_JSON) { if(NET_print_flags & NET_PRINT_JSON) {
json_object_object_add(jobj, "msg_data", json_object_object_add(jobj, "msg_data",
json_object_new_string_len((char *) d.data, d.len)); json_object_new_string_len((char *)d.data, d.len));
} else } else
P_(P_AD) { print_data(ssl, &d); } P_(P_AD) { print_data(ssl, &d); }
else { else {

View file

@ -534,6 +534,16 @@ and
.B \-p .B \-p
flags. flags.
.LP .LP
.SH SIGNALS
.LP
When it receives SIGUSR1,
.B ssldump
prints the list of currently tracked connection on stderr.
.LP
With SIGUSR2,
.B ssldump
purges its internal connection tracking data structures.
.LP
.SH DECRYPTION .SH DECRYPTION
.LP .LP
\fIssldump\fP can decrypt traffic between two hosts if the following two \fIssldump\fP can decrypt traffic between two hosts if the following two

View file

@ -371,6 +371,16 @@ and
**-p** **-p**
flags. flags.
<a name="signals"></a>
# Signals
When it receives SIGUSR1, _ssldump_ prints the list of currently tracked
connection on stderr.
With SIGUSR2, _ssldump_ purges its internal connection tracking data
structures.
<a name="decryption"></a> <a name="decryption"></a>