From: David Limbeck Date: Thu, 13 Dec 2018 12:08:51 +0000 (+0100) Subject: add conntrack logging via libnetfilter_conntrack X-Git-Url: https://git.proxmox.com/?p=pve-firewall.git;a=commitdiff_plain;h=fdf943fe82bf37f381248d2a6260019c8088c391 add conntrack logging via libnetfilter_conntrack add conntrack logging to pvefw-logger including timestamps (requires /proc/sys/net/netfilter/nf_conntrack_timestamp to be 1). this allows the tracking of sessions (start, end timestamps with nf_conntrack_timestamp on [DESTROY] messages). commit includes Build-Depends inclusion of libnetfilter-conntrack-dev and libnetfilter_conntrack library in the Makefile. Signed-off-by: David Limbeck --- diff --git a/debian/control b/debian/control index a68a81c..2a92b16 100644 --- a/debian/control +++ b/debian/control @@ -5,6 +5,7 @@ Maintainer: Proxmox Support Team Build-Depends: debhelper (>= 7.0.50~), dh-systemd, libglib2.0-dev, + libnetfilter-conntrack-dev, libnetfilter-log-dev, libpve-common-perl, pve-cluster, diff --git a/src/Makefile b/src/Makefile index ed74393..a35e53d 100644 --- a/src/Makefile +++ b/src/Makefile @@ -25,7 +25,7 @@ LDFLAGS:=$(shell dpkg-buildflags --get LDFLAGS) pvefw-logger: pvefw-logger.c gcc -Wall -Werror pvefw-logger.c -o pvefw-logger -std=gnu99 \ $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) \ - $(shell pkg-config libnetfilter_log glib-2.0 --libs --cflags) + $(shell pkg-config libnetfilter_log libnetfilter_conntrack glib-2.0 --libs --cflags) .PHONY: install install: pve-firewall pve-firewall.8 pve-firewall.bash-completion pvefw-logger diff --git a/src/pvefw-logger.c b/src/pvefw-logger.c index 2bd869c..506568c 100644 --- a/src/pvefw-logger.c +++ b/src/pvefw-logger.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -53,10 +54,12 @@ static struct nflog_handle *logh = NULL; static struct nlif_handle *nlifh = NULL; +static struct nfct_handle *nfcth = NULL; GMainLoop *main_loop; gboolean foreground = FALSE; gboolean debug = FALSE; +gboolean conntrack = FALSE; /* @@ -76,6 +79,7 @@ Example: #define LOCKFILE "/var/lock/pvefw-logger.lck" #define PIDFILE "/var/run/pvefw-logger.pid" +#define LOG_CONNTRACK_FILE "/var/lib/pve-firewall/log_nf_conntrack" #define LQ_LEN 512 #define LE_MAX (512 - 4) // try to fit into 512 bytes @@ -917,6 +921,42 @@ signal_read_cb(GIOChannel *source, return TRUE; } +static int +nfct_cb(const struct nlmsghdr *nlh, + enum nf_conntrack_msg_type type, + struct nf_conntrack *ct, + void *data) +{ + struct log_entry *le = g_new0(struct log_entry, 1); + int len = nfct_snprintf(&le->buf[le->len], LE_MAX - le->len, + ct, type, NFCT_O_DEFAULT, + NFCT_OF_SHOW_LAYER3|NFCT_OF_TIMESTAMP); + le->len += len; + + if (le->len == LE_MAX) { + le->buf[le->len-1] = '\n'; + } else { // le->len < LE_MAX + le->buf[le->len++] = '\n'; + } + + queue_log_entry(le); + + return NFCT_CB_STOP; +} + +static gboolean +nfct_read_cb(GIOChannel *source, + GIOCondition condition, + gpointer data) +{ + int res; + if ((res = nfct_catch(nfcth)) < 0) { + log_status_message(3, "error catching nfct"); + return FALSE; + } + return TRUE; +} + int main(int argc, char *argv[]) { @@ -932,6 +972,7 @@ main(int argc, char *argv[]) GOptionEntry entries[] = { { "debug", 'd', 0, G_OPTION_ARG_NONE, &debug, "Turn on debug messages", NULL }, { "foreground", 'f', 0, G_OPTION_ARG_NONE, &foreground, "Do not daemonize server", NULL }, + { "conntrack", 0, 0, G_OPTION_ARG_NONE, &conntrack, "Add conntrack logging", NULL }, { NULL }, }; @@ -954,6 +995,23 @@ main(int argc, char *argv[]) g_option_context_free(context); + if (!conntrack) { + int log_nf_conntrackfd = open(LOG_CONNTRACK_FILE, O_RDONLY); + if (log_nf_conntrackfd == -1) { + if (errno != ENOENT) { + fprintf(stderr, "error: failed to open "LOG_CONNTRACK_FILE": %s\n", strerror(errno)); + } + } else { + char c = '0'; + ssize_t bytes = read(log_nf_conntrackfd, &c, sizeof(c)); + if (bytes < 0) { + fprintf(stderr, "error: failed to read value in log_nf_conntrack: %s\n", strerror(errno)); + } else { + conntrack = (c == '1'); + } + } + } + if (debug) foreground = TRUE; if ((lockfd = open(LOCKFILE, O_RDWR|O_CREAT|O_APPEND, 0644)) == -1) { @@ -1017,6 +1075,13 @@ main(int argc, char *argv[]) exit(-1); } + if (conntrack) { + if ((nfcth = nfct_open(CONNTRACK, NF_NETLINK_CONNTRACK_NEW|NF_NETLINK_CONNTRACK_DESTROY)) == NULL) { + fprintf(stderr, "unable to open netfilter conntrack\n"); + exit(-1); + } + } + sigset_t mask; sigemptyset(&mask); sigaddset(&mask, SIGINT); @@ -1076,6 +1141,13 @@ main(int argc, char *argv[]) g_io_add_watch(nflog_ch, G_IO_IN, nflog_read_cb, NULL); + if (conntrack) { + nfct_callback_register2(nfcth, NFCT_T_NEW|NFCT_T_DESTROY, &nfct_cb, NULL); + int nfctfd = nfct_fd(nfcth); + GIOChannel *nfct_ch = g_io_channel_unix_new(nfctfd); + g_io_add_watch(nfct_ch, G_IO_IN, nfct_read_cb, NULL); + } + GIOChannel *sig_ch = g_io_channel_unix_new(sigfd); if (!g_io_add_watch(sig_ch, G_IO_IN, signal_read_cb, NULL)) { exit(-1); @@ -1093,6 +1165,11 @@ main(int argc, char *argv[]) close(outfd); + if (conntrack) { + nfct_callback_unregister2(nfcth); + nfct_close(nfcth); + } + nflog_close(logh); if (wrote_pidfile)