@cryptotaxi247 / netdata-1 / commits / 31a1faf7a

new feature: added data collection for SYNPROXY - netfilter TCP anti-DDoS protection; renamed the conntrack and nfacct charts to group them under netfilter; updated the dashboard for netfilter;

Costa Tsaousis (ktsaou) committed Apr 9, 2016 at 00:19 UTC 31a1faf7ad89b66a68b0ac548f1c9a9dfc3c37af
7 files changed +183 -17
src/Makefile.am
+1
@@ -50,6 +50,7 @@ netdata_SOURCES = \
50 proc_net_snmp.c \
51 proc_net_snmp6.c \
52 proc_net_stat_conntrack.c \
53 + proc_net_stat_synproxy.c \
54 proc_stat.c \
55 proc_sys_kernel_random_entropy_avail.c \
56 proc_vmstat.c \
src/plugin_nfacct.c
+4 -4
@@ -168,9 +168,9 @@ void *nfacct_main(void *ptr) {
168 if(nfacct_list && nfacct_list->len) {
169 int i;
170
171 - st = rrdset_find_bytype("nfacct", "packets");
171 + st = rrdset_find_bytype("netfilter", "nfacct_packets");
172 if(!st) {
173 - st = rrdset_create("nfacct", "packets", NULL, "netfilter", NULL, "Netfilter Accounting Packets", "packets/s", 1006, rrd_update_every, RRDSET_TYPE_STACKED);
173 + st = rrdset_create("netfilter", "nfacct_packets", NULL, "nfacct", NULL, "Netfilter Accounting Packets", "packets/s", 1006, rrd_update_every, RRDSET_TYPE_STACKED);
174
175 for(i = 0; i < nfacct_list->len ; i++)
176 rrddim_add(st, nfacct_list->data[i].name, NULL, 1, rrd_update_every, RRDDIM_INCREMENTAL);
@@ -188,9 +188,9 @@ void *nfacct_main(void *ptr) {
188
189 // ----------------------------------------------------------------
190
191 - st = rrdset_find_bytype("nfacct", "bytes");
191 + st = rrdset_find_bytype("netfilter", "nfacct_bytes");
192 if(!st) {
193 - st = rrdset_create("nfacct", "bytes", NULL, "netfilter", NULL, "Netfilter Accounting Bandwidth", "kilobytes/s", 1007, rrd_update_every, RRDSET_TYPE_STACKED);
193 + st = rrdset_create("netfilter", "nfacct_bytes", NULL, "nfacct", NULL, "Netfilter Accounting Bandwidth", "kilobytes/s", 1007, rrd_update_every, RRDSET_TYPE_STACKED);
194
195 for(i = 0; i < nfacct_list->len ; i++)
196 rrddim_add(st, nfacct_list->data[i].name, NULL, 1, 1000 * rrd_update_every, RRDDIM_INCREMENTAL);
src/plugin_proc.c
+10
@@ -47,6 +47,7 @@ void *proc_main(void *ptr)
47 int vdo_proc_net_netstat = !config_get_boolean("plugin:proc", "/proc/net/netstat", 1);
48 int vdo_proc_net_stat_conntrack = !config_get_boolean("plugin:proc", "/proc/net/stat/conntrack", 1);
49 int vdo_proc_net_ip_vs_stats = !config_get_boolean("plugin:proc", "/proc/net/ip_vs/stats", 1);
50 + int vdo_proc_net_stat_synproxy = !config_get_boolean("plugin:proc", "/proc/net/stat/synproxy", 1);
51 int vdo_proc_stat = !config_get_boolean("plugin:proc", "/proc/stat", 1);
52 int vdo_proc_meminfo = !config_get_boolean("plugin:proc", "/proc/meminfo", 1);
53 int vdo_proc_vmstat = !config_get_boolean("plugin:proc", "/proc/vmstat", 1);
@@ -66,6 +67,7 @@ void *proc_main(void *ptr)
67 unsigned long long sutime_proc_net_netstat = 0ULL;
68 unsigned long long sutime_proc_net_stat_conntrack = 0ULL;
69 unsigned long long sutime_proc_net_ip_vs_stats = 0ULL;
70 + unsigned long long sutime_proc_net_stat_synproxy = 0ULL;
71 unsigned long long sutime_proc_stat = 0ULL;
72 unsigned long long sutime_proc_meminfo = 0ULL;
73 unsigned long long sutime_proc_vmstat = 0ULL;
@@ -194,6 +196,14 @@ void *proc_main(void *ptr)
196 }
197 if(unlikely(netdata_exit)) break;
198
199 + if(!vdo_proc_net_stat_synproxy) {
200 + debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_net_stat_synproxy().");
201 + sunow = sutime();
202 + vdo_proc_net_stat_synproxy = do_proc_net_stat_synproxy(rrd_update_every, (sutime_proc_net_stat_synproxy > 0)?sunow - sutime_proc_net_stat_synproxy:0ULL);
203 + sutime_proc_net_stat_synproxy = sunow;
204 + }
205 + if(unlikely(netdata_exit)) break;
206 +
207 if(!vdo_proc_stat) {
208 debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_stat().");
209 sunow = sutime();
src/plugin_proc.h
+1
@@ -19,5 +19,6 @@ extern int do_proc_interrupts(int update_every, unsigned long long dt);
19 extern int do_proc_softirqs(int update_every, unsigned long long dt);
20 extern int do_sys_kernel_mm_ksm(int update_every, unsigned long long dt);
21 extern int do_proc_loadavg(int update_every, unsigned long long dt);
22 +extern int do_proc_net_stat_synproxy(int update_every, unsigned long long dt);
23
24 #endif /* NETDATA_PLUGIN_PROC_H */
src/proc_net_stat_conntrack.c
+14 -13
@@ -12,7 +12,8 @@
12 #include "rrd.h"
13 #include "plugin_proc.h"
14
15 -#define RRD_TYPE_NET_STAT_CONNTRACK "netfilter"
15 +#define RRD_TYPE_NET_STAT_NETFILTER "netfilter"
16 +#define RRD_TYPE_NET_STAT_CONNTRACK "conntrack"
17 #define RRD_TYPE_NET_STAT_CONNTRACK_LEN strlen(RRD_TYPE_NET_STAT_CONNTRACK)
18
19 int do_proc_net_stat_conntrack(int update_every, unsigned long long dt) {
@@ -97,9 +98,9 @@ int do_proc_net_stat_conntrack(int update_every, unsigned long long dt) {
98 // --------------------------------------------------------------------
99
100 if(do_sockets) {
100 - st = rrdset_find(RRD_TYPE_NET_STAT_CONNTRACK ".sockets");
101 + st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_sockets");
102 if(!st) {
102 - st = rrdset_create(RRD_TYPE_NET_STAT_CONNTRACK, "sockets", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Netfilter Connections", "active connections", 1000, update_every, RRDSET_TYPE_LINE);
103 + st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_sockets", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Connections", "active connections", 1000, update_every, RRDSET_TYPE_LINE);
104
105 rrddim_add(st, "connections", NULL, 1, 1, RRDDIM_ABSOLUTE);
106 }
@@ -112,9 +113,9 @@ int do_proc_net_stat_conntrack(int update_every, unsigned long long dt) {
113 // --------------------------------------------------------------------
114
115 if(do_new) {
115 - st = rrdset_find(RRD_TYPE_NET_STAT_CONNTRACK ".new");
116 + st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_new");
117 if(!st) {
117 - st = rrdset_create(RRD_TYPE_NET_STAT_CONNTRACK, "new", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Netfilter New Connections", "connections/s", 1001, update_every, RRDSET_TYPE_LINE);
118 + st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_new", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker New Connections", "connections/s", 1001, update_every, RRDSET_TYPE_LINE);
119
120 rrddim_add(st, "new", NULL, 1, 1, RRDDIM_INCREMENTAL);
121 rrddim_add(st, "ignore", NULL, -1, 1, RRDDIM_INCREMENTAL);
@@ -131,9 +132,9 @@ int do_proc_net_stat_conntrack(int update_every, unsigned long long dt) {
132 // --------------------------------------------------------------------
133
134 if(do_changes) {
134 - st = rrdset_find(RRD_TYPE_NET_STAT_CONNTRACK ".changes");
135 + st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_changes");
136 if(!st) {
136 - st = rrdset_create(RRD_TYPE_NET_STAT_CONNTRACK, "changes", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Netfilter Connection Changes", "changes/s", 1002, update_every, RRDSET_TYPE_LINE);
137 + st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_changes", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Changes", "changes/s", 1002, update_every, RRDSET_TYPE_LINE);
138 st->isdetail = 1;
139
140 rrddim_add(st, "inserted", NULL, 1, 1, RRDDIM_INCREMENTAL);
@@ -151,9 +152,9 @@ int do_proc_net_stat_conntrack(int update_every, unsigned long long dt) {
152 // --------------------------------------------------------------------
153
154 if(do_expect) {
154 - st = rrdset_find(RRD_TYPE_NET_STAT_CONNTRACK ".expect");
155 + st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_expect");
156 if(!st) {
156 - st = rrdset_create(RRD_TYPE_NET_STAT_CONNTRACK, "expect", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Netfilter Connection Expectations", "expectations/s", 1003, update_every, RRDSET_TYPE_LINE);
157 + st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_expect", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Expectations", "expectations/s", 1003, update_every, RRDSET_TYPE_LINE);
158 st->isdetail = 1;
159
160 rrddim_add(st, "created", NULL, 1, 1, RRDDIM_INCREMENTAL);
@@ -171,9 +172,9 @@ int do_proc_net_stat_conntrack(int update_every, unsigned long long dt) {
172 // --------------------------------------------------------------------
173
174 if(do_search) {
174 - st = rrdset_find(RRD_TYPE_NET_STAT_CONNTRACK ".search");
175 + st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_search");
176 if(!st) {
176 - st = rrdset_create(RRD_TYPE_NET_STAT_CONNTRACK, "search", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Netfilter Connection Searches", "searches/s", 1010, update_every, RRDSET_TYPE_LINE);
177 + st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_search", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Searches", "searches/s", 1010, update_every, RRDSET_TYPE_LINE);
178 st->isdetail = 1;
179
180 rrddim_add(st, "searched", NULL, 1, 1, RRDDIM_INCREMENTAL);
@@ -191,9 +192,9 @@ int do_proc_net_stat_conntrack(int update_every, unsigned long long dt) {
192 // --------------------------------------------------------------------
193
194 if(do_errors) {
194 - st = rrdset_find(RRD_TYPE_NET_STAT_CONNTRACK ".errors");
195 + st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_errors");
196 if(!st) {
196 - st = rrdset_create(RRD_TYPE_NET_STAT_CONNTRACK, "errors", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Netfilter Errors", "events/s", 1005, update_every, RRDSET_TYPE_LINE);
197 + st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_errors", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Errors", "events/s", 1005, update_every, RRDSET_TYPE_LINE);
198 st->isdetail = 1;
199
200 rrddim_add(st, "icmp_error", NULL, 1, 1, RRDDIM_INCREMENTAL);
src/proc_net_stat_synproxy.c new
+138
@@ -0,0 +1,138 @@
1 +#ifdef HAVE_CONFIG_H
2 +#include <config.h>
3 +#endif
4 +#include <stdio.h>
5 +#include <stdlib.h>
6 +
7 +#include "common.h"
8 +#include "appconfig.h"
9 +#include "procfile.h"
10 +#include "rrd.h"
11 +#include "plugin_proc.h"
12 +#include "log.h"
13 +
14 +#define RRD_TYPE_NET_STAT_NETFILTER "netfilter"
15 +#define RRD_TYPE_NET_STAT_SYNPROXY "synproxy"
16 +#define RRD_TYPE_NET_STAT_SYNPROXY_LEN strlen(RRD_TYPE_NET_STAT_SYNPROXY)
17 +
18 +int do_proc_net_stat_synproxy(int update_every, unsigned long long dt) {
19 + static int do_entries = -1, do_cookies = -1, do_syns = -1, do_reopened = -1;
20 + static procfile *ff = NULL;
21 +
22 + if(do_entries == -1) do_entries = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY entries", CONFIG_ONDEMAND_ONDEMAND);
23 + if(do_cookies == -1) do_cookies = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY cookies", CONFIG_ONDEMAND_ONDEMAND);
24 + if(do_syns == -1) do_syns = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY SYN received", CONFIG_ONDEMAND_ONDEMAND);
25 + if(do_reopened == -1) do_reopened = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY connections reopened", CONFIG_ONDEMAND_ONDEMAND);
26 +
27 + if(dt) {};
28 +
29 + if(!ff) {
30 + char filename[FILENAME_MAX + 1];
31 + snprintf(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/net/stat/synproxy");
32 + ff = procfile_open(config_get("plugin:proc:/proc/net/stat/synproxy", "filename to monitor", filename), " \t,:|", PROCFILE_FLAG_DEFAULT);
33 + }
34 + if(!ff) return 1;
35 +
36 + ff = procfile_readall(ff);
37 + if(!ff) return 0; // we return 0, so that we will retry to open it next time
38 +
39 + // make sure we have 3 lines
40 + unsigned long lines = procfile_lines(ff), l;
41 + if(lines < 2) {
42 + error("/proc/net/stat/synproxy has %d lines, expected no less than 2. Disabling it.", lines);
43 + return 1;
44 + }
45 +
46 + unsigned long long entries = 0, syn_received = 0, cookie_invalid = 0, cookie_valid = 0, cookie_retrans = 0, conn_reopened = 0;
47 +
48 + // synproxy gives its values per CPU
49 + for(l = 1; l < lines ;l++) {
50 + int words = procfile_linewords(ff, l);
51 + if(words < 6) continue;
52 +
53 + entries += strtoull(procfile_lineword(ff, l, 0), NULL, 16);
54 + syn_received += strtoull(procfile_lineword(ff, l, 1), NULL, 16);
55 + cookie_invalid += strtoull(procfile_lineword(ff, l, 2), NULL, 16);
56 + cookie_valid += strtoull(procfile_lineword(ff, l, 3), NULL, 16);
57 + cookie_retrans += strtoull(procfile_lineword(ff, l, 4), NULL, 16);
58 + conn_reopened += strtoull(procfile_lineword(ff, l, 5), NULL, 16);
59 + }
60 +
61 + unsigned long long events = entries + syn_received + cookie_invalid + cookie_valid + cookie_retrans + conn_reopened;
62 +
63 + RRDSET *st;
64 +
65 + // --------------------------------------------------------------------
66 +
67 + if((do_entries == CONFIG_ONDEMAND_ONDEMAND && events) || do_entries == CONFIG_ONDEMAND_YES) {
68 + do_entries = CONFIG_ONDEMAND_YES;
69 +
70 + st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_SYNPROXY "_entries");
71 + if(!st) {
72 + st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_SYNPROXY "_entries", NULL, RRD_TYPE_NET_STAT_SYNPROXY, NULL, "SYNPROXY Entries Used", "entries", 1004, update_every, RRDSET_TYPE_LINE);
73 +
74 + rrddim_add(st, "entries", NULL, 1, 1, RRDDIM_ABSOLUTE);
75 + }
76 + else rrdset_next(st);
77 +
78 + rrddim_set(st, "entries", entries);
79 + rrdset_done(st);
80 + }
81 +
82 + // --------------------------------------------------------------------
83 +
84 + if((do_syns == CONFIG_ONDEMAND_ONDEMAND && events) || do_syns == CONFIG_ONDEMAND_YES) {
85 + do_syns = CONFIG_ONDEMAND_YES;
86 +
87 + st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_SYNPROXY "_syn_received");
88 + if(!st) {
89 + st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_SYNPROXY "_syn_received", NULL, RRD_TYPE_NET_STAT_SYNPROXY, NULL, "SYNPROXY SYN Packets received", "SYN/s", 1001, update_every, RRDSET_TYPE_LINE);
90 +
91 + rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
92 + }
93 + else rrdset_next(st);
94 +
95 + rrddim_set(st, "received", syn_received);
96 + rrdset_done(st);
97 + }
98 +
99 + // --------------------------------------------------------------------
100 +
101 + if((do_reopened == CONFIG_ONDEMAND_ONDEMAND && events) || do_reopened == CONFIG_ONDEMAND_YES) {
102 + do_reopened = CONFIG_ONDEMAND_YES;
103 +
104 + st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_SYNPROXY "_conn_reopened");
105 + if(!st) {
106 + st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_SYNPROXY "_conn_reopened", NULL, RRD_TYPE_NET_STAT_SYNPROXY, NULL, "SYNPROXY Connections Reopened", "connections/s", 1003, update_every, RRDSET_TYPE_LINE);
107 +
108 + rrddim_add(st, "reopened", NULL, 1, 1, RRDDIM_INCREMENTAL);
109 + }
110 + else rrdset_next(st);
111 +
112 + rrddim_set(st, "reopened", conn_reopened);
113 + rrdset_done(st);
114 + }
115 +
116 + // --------------------------------------------------------------------
117 +
118 + if((do_cookies == CONFIG_ONDEMAND_ONDEMAND && events) || do_cookies == CONFIG_ONDEMAND_YES) {
119 + do_cookies = CONFIG_ONDEMAND_YES;
120 +
121 + st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_SYNPROXY "_cookies");
122 + if(!st) {
123 + st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_SYNPROXY "_cookies", NULL, RRD_TYPE_NET_STAT_SYNPROXY, NULL, "SYNPROXY TCP Cookies", "cookies/s", 1002, update_every, RRDSET_TYPE_LINE);
124 +
125 + rrddim_add(st, "valid", NULL, 1, 1, RRDDIM_INCREMENTAL);
126 + rrddim_add(st, "invalid", NULL, -1, 1, RRDDIM_INCREMENTAL);
127 + rrddim_add(st, "retransmits", NULL, 1, 1, RRDDIM_INCREMENTAL);
128 + }
129 + else rrdset_next(st);
130 +
131 + rrddim_set(st, "valid", cookie_valid);
132 + rrddim_set(st, "invalid", cookie_invalid);
133 + rrddim_set(st, "retransmits", cookie_retrans);
134 + rrdset_done(st);
135 + }
136 +
137 + return 0;
138 +}
web/index.html
+15
@@ -966,6 +966,21 @@ var submenuData = {
966 'mem.ksm': {
967 title: 'Memory Deduper',
968 info: 'Kernel Same-page Merging (KSM) is the kernel memory de-duper.'
969 + },
970 +
971 + 'netfilter.conntrack': {
972 + title: 'Connection Tracker',
973 + info: 'The following information is taken from <code>/proc/net/stat/nf_conntrack</code>. The connection tracker keeps track of all connections of the machine, inbound and outbound. It works by keeping a database with all open connections, tracking network and address translation and connection expectations.'
974 + },
975 +
976 + 'netfilter.nfacct': {
977 + title: 'Bandwidth Accounting',
978 + info: 'The following information is read using the <code>nfacct.plugin</code>.'
979 + },
980 +
981 + 'netfilter.synproxy': {
982 + title: 'Anti-DDoS Protection',
983 + info: 'The following information is taken from <code>/proc/net/stat/synproxy</code>. <a href="https://github.com/firehol/firehol/wiki/Working-with-SYNPROXY" target="_blank">SYNPROXY</a> is a TCP SYN packets proxy. It is used to protect any TCP server (like a web server) from SYN floods and similar DDoS attacks. It is a netfilter module, in the Linux kernel (since version 3.12). It is optimized to handle millions of packets per second utilizing all CPUs available without any concurrency locking between the connections. It can be used for any kind of TCP traffic (even encrypted), since it does not interfere with the content itself.'
984 }
985 };
986