Many additions and modifications for support of capture via Netfilter Queue.
This commit is contained in:
+2
-2
@@ -242,8 +242,8 @@ AM_CONDITIONAL([UDP_SERVER], [test "$want_udp_server" = yes])
|
||||
dnl Decide whether or not to enable UDP server mode (no libpcap dependency)
|
||||
dnl
|
||||
want_nfq_capture=no
|
||||
AC_ARG_ENABLE([nfq-server],
|
||||
[AS_HELP_STRING([--enable-nfq-server],
|
||||
AC_ARG_ENABLE([nfq-capture],
|
||||
[AS_HELP_STRING([--enable-nfq-capture],
|
||||
[Enable NF_QUEUE server mode for no libpcap dependency @<:@default is to disable@:>@])],
|
||||
[want_nfq_capture=$enableval],
|
||||
[])
|
||||
|
||||
+2
-2
@@ -30,7 +30,7 @@ if WANT_C_UNIT_TESTS
|
||||
fwknopd_utests_LDFLAGS = -lcunit $(GPGME_LIBS)
|
||||
|
||||
if NFQ_CAPTURE
|
||||
fwknop_utests_LDFLAGS += -lnetfilter_queue
|
||||
fwknopd_utests_LDFLAGS += -lnetfilter_queue
|
||||
else
|
||||
if !UDP_SERVER
|
||||
fwknopd_utests_LDFLAGS += -lpcap
|
||||
@@ -40,7 +40,7 @@ endif
|
||||
endif
|
||||
|
||||
if NFQ_CAPTURE
|
||||
fwknop_LDADD += -lnetfilter_queue
|
||||
fwknopd_LDADD += -lnetfilter_queue
|
||||
else
|
||||
if !UDP_SERVER
|
||||
fwknopd_LDADD += -lpcap
|
||||
|
||||
@@ -62,6 +62,15 @@ static char *config_map[NUMBER_OF_CONFIG_ENTRIES] = {
|
||||
"ENABLE_UDP_SERVER",
|
||||
"UDPSERV_PORT",
|
||||
"UDPSERV_SELECT_TIMEOUT",
|
||||
#if USE_LIBNETFILTER_QUEUE
|
||||
"ENABLE_NFQ_CAPTURE",
|
||||
"NFQ_INTERFACE",
|
||||
"NFQ_PORT",
|
||||
"NFQ_TABLE",
|
||||
"NFQ_CHAIN",
|
||||
"NFQ_QUEUE_NUMBER",
|
||||
"NFQ_LOOP_SLEEP",
|
||||
#endif
|
||||
"LOCALE",
|
||||
"SYSLOG_IDENTITY",
|
||||
"SYSLOG_FACILITY",
|
||||
|
||||
@@ -901,6 +901,51 @@ validate_options(fko_srv_options_t *opts)
|
||||
if(opts->config[CONF_TCPSERV_PORT] == NULL)
|
||||
set_config_entry(opts, CONF_TCPSERV_PORT, DEF_TCPSERV_PORT);
|
||||
|
||||
#if USE_LIBNETFILTER_QUEUE
|
||||
/* Enable NFQ Capture
|
||||
*/
|
||||
if(opts->config[CONF_ENABLE_NFQ_CAPTURE] == NULL)
|
||||
{
|
||||
if((strncasecmp(DEF_ENABLE_NFQ_CAPTURE, "Y", 1) == 0) &&
|
||||
!opts->enable_nfq_capture)
|
||||
{
|
||||
opts->enable_nfq_capture = 1;
|
||||
}
|
||||
set_config_entry(opts, CONF_ENABLE_NFQ_CAPTURE, DEF_ENABLE_NFQ_CAPTURE);
|
||||
}
|
||||
|
||||
/* NFQ Interface
|
||||
*/
|
||||
if(opts->config[CONF_NFQ_INTERFACE] == NULL)
|
||||
set_config_entry(opts, CONF_NFQ_INTERFACE, DEF_NFQ_INTERFACE);
|
||||
|
||||
/* NFQ port.
|
||||
*/
|
||||
if(opts->config[CONF_NFQ_PORT] == NULL)
|
||||
set_config_entry(opts, CONF_NFQ_PORT, DEF_NFQ_PORT);
|
||||
|
||||
/* NFQ Queue Number
|
||||
*/
|
||||
if(opts->config[CONF_NFQ_QUEUE_NUMBER] == NULL)
|
||||
set_config_entry(opts, CONF_NFQ_QUEUE_NUMBER,
|
||||
DEF_NFQ_QUEUE_NUMBER);
|
||||
|
||||
/* NFQ Chain
|
||||
*/
|
||||
if(opts->config[CONF_NFQ_CHAIN] == NULL)
|
||||
set_config_entry(opts, CONF_NFQ_CHAIN, DEF_NFQ_CHAIN);
|
||||
|
||||
/* NFQ Table
|
||||
*/
|
||||
if(opts->config[CONF_NFQ_TABLE] == NULL)
|
||||
set_config_entry(opts, CONF_NFQ_TABLE, DEF_NFQ_TABLE);
|
||||
|
||||
/* NFQ loop delay
|
||||
*/
|
||||
if(opts->config[CONF_NFQ_LOOP_SLEEP] == NULL)
|
||||
set_config_entry(opts, CONF_NFQ_LOOP_SLEEP, DEF_CONF_NFQ_LOOP_SLEEP);
|
||||
#endif
|
||||
|
||||
/* Enable UDP server.
|
||||
*/
|
||||
if(opts->config[CONF_ENABLE_UDP_SERVER] == NULL)
|
||||
@@ -1409,6 +1454,10 @@ usage(void)
|
||||
" -K, --kill - Kill the currently running fwknopd.\n"
|
||||
" -l, --locale - Provide a locale setting other than the system\n"
|
||||
" default.\n"
|
||||
#if USE_LIBNETFILTER_QUEUE
|
||||
" -n, --nfq-capture - Capture packets using libnetfilter_queue (falls\n"
|
||||
" back to UDP server mode if not used).\n"
|
||||
#endif
|
||||
" -O, --override-config - Specify a file with configuration entries that will\n"
|
||||
" overide those in fwknopd.conf\n"
|
||||
" -p, --pid-file - Specify an alternate fwknopd.pid file.\n"
|
||||
|
||||
+45
-23
@@ -711,11 +711,12 @@ delete_all_chains(const fko_srv_options_t * const opts)
|
||||
*/
|
||||
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_DEL_RULE_ARGS,
|
||||
fwc.fw_command,
|
||||
NFQ_TABLE,
|
||||
opts->config[CONF_NFQ_TABLE],
|
||||
"INPUT",
|
||||
1
|
||||
);
|
||||
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, 0);
|
||||
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, WANT_STDERR,
|
||||
NO_TIMEOUT, &pid_status, opts);
|
||||
|
||||
if (opts->verbose)
|
||||
log_msg(LOG_INFO, "delete_all_chains() CMD: '%s' (res: %d, err: %s)",
|
||||
@@ -731,10 +732,11 @@ delete_all_chains(const fko_srv_options_t * const opts)
|
||||
*/
|
||||
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_FLUSH_CHAIN_ARGS,
|
||||
fwc.fw_command,
|
||||
NFQ_TABLE,
|
||||
NFQ_CHAIN
|
||||
opts->config[CONF_NFQ_TABLE],
|
||||
opts->config[CONF_NFQ_CHAIN]
|
||||
);
|
||||
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, 0);
|
||||
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, WANT_STDERR,
|
||||
NO_TIMEOUT, &pid_status, opts);
|
||||
|
||||
if (opts->verbose)
|
||||
log_msg(LOG_INFO, "delete_all_chains() CMD: '%s' (res: %d, err: %s)",
|
||||
@@ -746,14 +748,15 @@ delete_all_chains(const fko_srv_options_t * const opts)
|
||||
|
||||
zero_cmd_buffers();
|
||||
|
||||
/* Create the NF_QUEUE chains and rules
|
||||
/* Delete the NF_QUEUE chains and rules
|
||||
*/
|
||||
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_DEL_CHAIN_ARGS,
|
||||
fwc.fw_command,
|
||||
NFQ_TABLE,
|
||||
NFQ_CHAIN
|
||||
opts->config[CONF_NFQ_TABLE],
|
||||
opts->config[CONF_NFQ_CHAIN]
|
||||
);
|
||||
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, 0);
|
||||
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, WANT_STDERR,
|
||||
NO_TIMEOUT, &pid_status, opts);
|
||||
|
||||
if (opts->verbose)
|
||||
log_msg(LOG_INFO, "delete_all_chains() CMD: '%s' (res: %d, err: %s)",
|
||||
@@ -841,10 +844,11 @@ create_fw_chains(const fko_srv_options_t * const opts)
|
||||
*/
|
||||
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_NEW_CHAIN_ARGS,
|
||||
fwc.fw_command,
|
||||
NFQ_TABLE,
|
||||
NFQ_CHAIN
|
||||
opts->config[CONF_NFQ_TABLE],
|
||||
opts->config[CONF_NFQ_CHAIN]
|
||||
);
|
||||
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, 0);
|
||||
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, WANT_STDERR,
|
||||
NO_TIMEOUT, &pid_status, opts);
|
||||
|
||||
if (opts->verbose)
|
||||
log_msg(LOG_INFO, "create_fw_chains() CMD: '%s' (res: %d, err: %s)",
|
||||
@@ -863,12 +867,13 @@ create_fw_chains(const fko_srv_options_t * const opts)
|
||||
*/
|
||||
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_ADD_JUMP_RULE_ARGS,
|
||||
fwc.fw_command,
|
||||
NFQ_TABLE,
|
||||
opts->config[CONF_NFQ_TABLE],
|
||||
"INPUT",
|
||||
1,
|
||||
NFQ_CHAIN
|
||||
opts->config[CONF_NFQ_CHAIN]
|
||||
);
|
||||
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, 0);
|
||||
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, WANT_STDERR,
|
||||
NO_TIMEOUT, &pid_status, opts);
|
||||
|
||||
if (opts->verbose)
|
||||
log_msg(LOG_INFO, "create_fw_chains() CMD: '%s' (res: %d, err: %s)",
|
||||
@@ -884,15 +889,32 @@ create_fw_chains(const fko_srv_options_t * const opts)
|
||||
zero_cmd_buffers();
|
||||
|
||||
/* Create the rule to direct SPA packets to the queue.
|
||||
* If an interface is specified use the "_WITH_IF" version
|
||||
* of the command.
|
||||
*/
|
||||
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " FIREWD_NFQ_ADD_ARGS,
|
||||
fwc.fw_command,
|
||||
NFQ_TABLE,
|
||||
NFQ_CHAIN,
|
||||
NFQ_PORT,
|
||||
NFQ_QUEUE_NUM
|
||||
);
|
||||
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, 0);
|
||||
if(strlen(opts->config[CONF_NFQ_INTERFACE]) > 0)
|
||||
{
|
||||
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " FIREWD_NFQ_ADD_ARGS_WITH_IF,
|
||||
fwc.fw_command,
|
||||
opts->config[CONF_NFQ_TABLE],
|
||||
opts->config[CONF_NFQ_CHAIN],
|
||||
opts->config[CONF_NFQ_INTERFACE],
|
||||
opts->config[CONF_NFQ_PORT],
|
||||
opts->config[CONF_NFQ_QUEUE_NUMBER]
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " FIREWD_NFQ_ADD_ARGS,
|
||||
fwc.fw_command,
|
||||
opts->config[CONF_NFQ_TABLE],
|
||||
opts->config[CONF_NFQ_CHAIN],
|
||||
opts->config[CONF_NFQ_PORT],
|
||||
opts->config[CONF_NFQ_QUEUE_NUMBER]
|
||||
);
|
||||
}
|
||||
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, WANT_STDERR,
|
||||
NO_TIMEOUT, &pid_status, opts);
|
||||
|
||||
if (opts->verbose)
|
||||
log_msg(LOG_INFO, "create_fw_chains() CMD: '%s' (res: %d, err: %s)",
|
||||
|
||||
@@ -69,8 +69,9 @@
|
||||
#define FIREWD_ANY_IP "0.0.0.0/0"
|
||||
|
||||
#if USE_LIBNETFILTER_QUEUE
|
||||
#define FIREWD_NFQ_ADD_ARGS "-t %s -A %s -p udp -m udp --dport %i -j NFQUEUE --queue-num %i"
|
||||
#define FIREWD_NFQ_DEL_ARGS "-t %s -D %s -p udp -m udp --dport %i -j NFQUEUE --queue-num %i"
|
||||
#define FIREWD_NFQ_ADD_ARGS "-t %s -A %s -p udp -m udp --dport %s -j NFQUEUE --queue-num %s"
|
||||
#define FIREWD_NFQ_ADD_ARGS_WITH_IF "-t %s -A %s -i %s -p udp -m udp --dport %s -j NFQUEUE --queue-num %s"
|
||||
#define FIREWD_NFQ_DEL_ARGS "-t %s -D %s -p udp -m udp --dport %s -j NFQUEUE --queue-num %s"
|
||||
#endif
|
||||
|
||||
int validate_firewd_chain_conf(const char * const chain_str);
|
||||
|
||||
+49
-23
@@ -705,11 +705,12 @@ delete_all_chains(const fko_srv_options_t * const opts)
|
||||
*/
|
||||
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_DEL_RULE_ARGS,
|
||||
fwc.fw_command,
|
||||
NFQ_TABLE,
|
||||
opts->config[CONF_NFQ_TABLE],
|
||||
"INPUT",
|
||||
1
|
||||
);
|
||||
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, 0);
|
||||
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, WANT_STDERR,
|
||||
NO_TIMEOUT, &pid_status, opts);
|
||||
|
||||
if (opts->verbose)
|
||||
log_msg(LOG_INFO, "delete_all_chains() CMD: '%s' (res: %d, err: %s)",
|
||||
@@ -725,10 +726,11 @@ delete_all_chains(const fko_srv_options_t * const opts)
|
||||
*/
|
||||
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_FLUSH_CHAIN_ARGS,
|
||||
fwc.fw_command,
|
||||
NFQ_TABLE,
|
||||
NFQ_CHAIN
|
||||
opts->config[CONF_NFQ_TABLE],
|
||||
opts->config[CONF_NFQ_CHAIN]
|
||||
);
|
||||
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, 0);
|
||||
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, WANT_STDERR,
|
||||
NO_TIMEOUT, &pid_status, opts);
|
||||
|
||||
if (opts->verbose)
|
||||
log_msg(LOG_INFO, "delete_all_chains() CMD: '%s' (res: %d, err: %s)",
|
||||
@@ -740,14 +742,15 @@ delete_all_chains(const fko_srv_options_t * const opts)
|
||||
|
||||
zero_cmd_buffers();
|
||||
|
||||
/* Create the NF_QUEUE chains and rules
|
||||
/* Delete the NF_QUEUE chains and rules
|
||||
*/
|
||||
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_DEL_CHAIN_ARGS,
|
||||
fwc.fw_command,
|
||||
NFQ_TABLE,
|
||||
NFQ_CHAIN
|
||||
opts->config[CONF_NFQ_TABLE],
|
||||
opts->config[CONF_NFQ_CHAIN]
|
||||
);
|
||||
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, 0);
|
||||
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, WANT_STDERR,
|
||||
NO_TIMEOUT, &pid_status, opts);
|
||||
|
||||
if (opts->verbose)
|
||||
log_msg(LOG_INFO, "delete_all_chains() CMD: '%s' (res: %d, err: %s)",
|
||||
@@ -817,6 +820,9 @@ static int
|
||||
create_fw_chains(const fko_srv_options_t * const opts)
|
||||
{
|
||||
int i, got_err = 0;
|
||||
#if USE_LIBNETFILTER_QUEUE
|
||||
int res = 0;
|
||||
#endif
|
||||
|
||||
for(i=0; i < NUM_FWKNOP_ACCESS_TYPES; i++)
|
||||
{
|
||||
@@ -835,10 +841,11 @@ create_fw_chains(const fko_srv_options_t * const opts)
|
||||
*/
|
||||
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_NEW_CHAIN_ARGS,
|
||||
fwc.fw_command,
|
||||
NFQ_TABLE,
|
||||
NFQ_CHAIN
|
||||
opts->config[CONF_NFQ_TABLE],
|
||||
opts->config[CONF_NFQ_CHAIN]
|
||||
);
|
||||
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, 0);
|
||||
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, WANT_STDERR,
|
||||
NO_TIMEOUT, &pid_status, opts);
|
||||
|
||||
if (opts->verbose)
|
||||
log_msg(LOG_INFO, "create_fw_chains() CMD: '%s' (res: %d, err: %s)",
|
||||
@@ -857,12 +864,13 @@ create_fw_chains(const fko_srv_options_t * const opts)
|
||||
*/
|
||||
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_ADD_JUMP_RULE_ARGS,
|
||||
fwc.fw_command,
|
||||
NFQ_TABLE,
|
||||
opts->config[CONF_NFQ_TABLE],
|
||||
"INPUT",
|
||||
1,
|
||||
NFQ_CHAIN
|
||||
opts->config[CONF_NFQ_CHAIN]
|
||||
);
|
||||
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, 0);
|
||||
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, WANT_STDERR,
|
||||
NO_TIMEOUT, &pid_status, opts);
|
||||
|
||||
if (opts->verbose)
|
||||
log_msg(LOG_INFO, "create_fw_chains() CMD: '%s' (res: %d, err: %s)",
|
||||
@@ -878,15 +886,33 @@ create_fw_chains(const fko_srv_options_t * const opts)
|
||||
zero_cmd_buffers();
|
||||
|
||||
/* Create the rule to direct SPA packets to the queue.
|
||||
* If an interface is specified use the "_WITH_IF" version
|
||||
* of the command.
|
||||
*/
|
||||
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_NFQ_ADD_ARGS,
|
||||
fwc.fw_command,
|
||||
NFQ_TABLE,
|
||||
NFQ_CHAIN,
|
||||
NFQ_PORT,
|
||||
NFQ_QUEUE_NUM
|
||||
);
|
||||
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, 0);
|
||||
if(strlen(opts->config[CONF_NFQ_INTERFACE]) > 0)
|
||||
{
|
||||
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_NFQ_ADD_ARGS_WITH_IF,
|
||||
fwc.fw_command,
|
||||
opts->config[CONF_NFQ_TABLE],
|
||||
opts->config[CONF_NFQ_CHAIN],
|
||||
opts->config[CONF_NFQ_INTERFACE],
|
||||
opts->config[CONF_NFQ_PORT],
|
||||
opts->config[CONF_NFQ_QUEUE_NUMBER]
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_NFQ_ADD_ARGS,
|
||||
fwc.fw_command,
|
||||
opts->config[CONF_NFQ_TABLE],
|
||||
opts->config[CONF_NFQ_CHAIN],
|
||||
opts->config[CONF_NFQ_PORT],
|
||||
opts->config[CONF_NFQ_QUEUE_NUMBER]
|
||||
);
|
||||
}
|
||||
|
||||
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, WANT_STDERR,
|
||||
NO_TIMEOUT, &pid_status, opts);
|
||||
|
||||
if (opts->verbose)
|
||||
log_msg(LOG_INFO, "create_fw_chains() CMD: '%s' (res: %d, err: %s)",
|
||||
|
||||
@@ -66,8 +66,8 @@
|
||||
#define IPT_ANY_IP "0.0.0.0/0"
|
||||
|
||||
#if USE_LIBNETFILTER_QUEUE
|
||||
#define IPT_NFQ_ADD_ARGS "-t %s -A %s -p udp -m udp --dport %i -j NFQUEUE --queue-num %i"
|
||||
#define IPT_NFQ_DEL_ARGS "-t %s -D %s -p udp -m udp --dport %i -j NFQUEUE --queue-num %i"
|
||||
#define IPT_NFQ_ADD_ARGS "-t %s -A %s -p udp -m udp --dport %s -j NFQUEUE --queue-num %s"
|
||||
#define IPT_NFQ_ADD_ARGS_WITH_IF "-t %s -A %s -i %s -p udp -m udp --dport %s -j NFQUEUE --queue-num %s"
|
||||
#endif
|
||||
|
||||
int validate_ipt_chain_conf(const char * const chain_str);
|
||||
|
||||
+2
-3
@@ -255,9 +255,8 @@ main(int argc, char **argv)
|
||||
#if USE_LIBPCAP
|
||||
/* Intiate pcap capture mode...
|
||||
*/
|
||||
if(!opts.enable_udp_server && !opts.enable_nfq_server
|
||||
&& strncasecmp(opts.config[CONF_ENABLE_UDP_SERVER], "N", 1) == 0
|
||||
&& strncasecmp(opts.config[CONF_ENABLE_NFQ_SERVER], "N", 1) == 0)
|
||||
if(!opts.enable_udp_server
|
||||
&& strncasecmp(opts.config[CONF_ENABLE_UDP_SERVER], "N", 1) == 0)
|
||||
{
|
||||
pcap_capture(&opts);
|
||||
}
|
||||
|
||||
@@ -52,6 +52,41 @@
|
||||
#
|
||||
#PCAP_FILTER udp port 62201;
|
||||
|
||||
### Netfilter Queue (NFQ) Parameters ###
|
||||
#
|
||||
# These settings apply only if fwknopd was compiled with libnetfilter_queue
|
||||
# support (configure with --enable-libnetfilter_queue). If this was not
|
||||
# enabled, leave these commented out.
|
||||
#
|
||||
# Uncomment and set to "Y" to capture via libnetfilter_queue. This is the
|
||||
# only option that must be set in order for NFQ capture. The remaining
|
||||
# options have reasonable default values.
|
||||
#
|
||||
#ENABLE_NFQ_CAPTURE Y;
|
||||
|
||||
# If you want to limit capture to a specific network interface, specify it
|
||||
# here. If NFQ is enabled and this is left commented out, SPA packets will
|
||||
# be captured on any/all network interfaces (which is the default).
|
||||
#
|
||||
#NFQ_INTERFACE eth0;
|
||||
|
||||
# Specify the UDP port for incoming SPA packets (default is 62201).
|
||||
#
|
||||
#NFQ_PORT 62201;
|
||||
|
||||
# Specify the iptable table for NFQ use (should stay the default of "mangle").
|
||||
#
|
||||
#NFQ_TABLE mangle;
|
||||
|
||||
# The name for the chain we will use for NFQ (default is "FWKNOP_NFQ").
|
||||
#NFQ_CHAIN
|
||||
|
||||
# Specify the NFQ queue number. The default is "1".
|
||||
#
|
||||
#NFQ_QUEUE_NUMBER 1;
|
||||
#
|
||||
### End of Netfilter Queue (NFQ) Options ###
|
||||
|
||||
# This instructs fwknopd to not honor SPA packets that have an old time
|
||||
# stamp. The value for "old" is defined by the MAX_SPA_PACKET_AGE variable.
|
||||
# If ENABLE_SPA_PACKET_AGING is set to "N", fwknopd will not use the client
|
||||
|
||||
+20
-7
@@ -113,6 +113,16 @@
|
||||
#else
|
||||
#define DEF_ENABLE_UDP_SERVER "Y"
|
||||
#endif
|
||||
#if USE_LIBNETFILTER_QUEUE
|
||||
#define DEF_ENABLE_NFQ_CAPTURE "N"
|
||||
#define DEF_NFQ_INTERFACE ""
|
||||
#define DEF_NFQ_PORT "62201"
|
||||
#define DEF_NFQ_TABLE "mangle"
|
||||
#define DEF_NFQ_CHAIN "FWKNOP_NFQ"
|
||||
#define DEF_NFQ_QUEUE_NUMBER "1"
|
||||
#define DEF_CONF_NFQ_LOOP_SLEEP "500000" /* half a second (in microseconds) */
|
||||
|
||||
#endif
|
||||
#define DEF_UDPSERV_PORT "62201"
|
||||
#define DEF_UDPSERV_SELECT_TIMEOUT "500000" /* half a second (in microseconds) */
|
||||
#define DEF_SYSLOG_IDENTITY MY_NAME
|
||||
@@ -250,6 +260,15 @@ enum {
|
||||
CONF_ENABLE_UDP_SERVER,
|
||||
CONF_UDPSERV_PORT,
|
||||
CONF_UDPSERV_SELECT_TIMEOUT,
|
||||
#if USE_LIBNETFILTER_QUEUE
|
||||
CONF_ENABLE_NFQ_CAPTURE,
|
||||
CONF_NFQ_INTERFACE,
|
||||
CONF_NFQ_PORT,
|
||||
CONF_NFQ_TABLE,
|
||||
CONF_NFQ_CHAIN,
|
||||
CONF_NFQ_QUEUE_NUMBER,
|
||||
CONF_NFQ_LOOP_SLEEP,
|
||||
#endif
|
||||
CONF_LOCALE,
|
||||
CONF_SYSLOG_IDENTITY,
|
||||
CONF_SYSLOG_FACILITY,
|
||||
@@ -437,13 +456,6 @@ typedef struct cmd_cycle_list
|
||||
struct cmd_cycle_list *next;
|
||||
} cmd_cycle_list_t;
|
||||
|
||||
#if USE_LIBNETFILTER_QUEUE
|
||||
#define NFQ_TABLE "mangle"
|
||||
#define NFQ_CHAIN "FWKNOP_NFQ"
|
||||
#define NFQ_QUEUE_NUM 1
|
||||
#define NFQ_PORT 62201
|
||||
#endif
|
||||
|
||||
/* Firewall-related data and types. */
|
||||
|
||||
#if FIREWALL_FIREWALLD
|
||||
@@ -633,6 +645,7 @@ typedef struct fko_srv_options
|
||||
unsigned char afl_fuzzing; /* SPA pkts from stdin for AFL fuzzing */
|
||||
unsigned char verbose; /* Verbose mode flag */
|
||||
unsigned char enable_udp_server; /* Enable UDP server mode */
|
||||
unsigned char enable_nfq_capture; /* Enable Netfilter Queue capture mode */
|
||||
unsigned char enable_fw; /* Command modes by themselves don't
|
||||
need firewall support. */
|
||||
|
||||
|
||||
Executable
+291
@@ -0,0 +1,291 @@
|
||||
/*
|
||||
*****************************************************************************
|
||||
*
|
||||
* File: nfq_capture.c
|
||||
*
|
||||
* Purpose: Capture routine for fwknopd that uses libnetfilter_queue.
|
||||
*
|
||||
* Fwknop is developed primarily by the people listed in the file 'AUTHORS'.
|
||||
* Copyright (C) 2009-2014 fwknop developers and contributors. For a full
|
||||
* list of contributors, see the file 'CREDITS'.
|
||||
*
|
||||
* License (GNU General Public License):
|
||||
*
|
||||
* This program 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 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA
|
||||
*
|
||||
*****************************************************************************
|
||||
*/
|
||||
#include "fwknopd_common.h"
|
||||
#include "nfq_capture.h"
|
||||
#include "process_packet.h"
|
||||
#include "sig_handler.h"
|
||||
#include "fw_util.h"
|
||||
#include "log_msg.h"
|
||||
#include "fwknopd_errors.h"
|
||||
#include "sig_handler.h"
|
||||
#include "tcp_server.h"
|
||||
#include <fcntl.h>
|
||||
#if HAVE_SYS_WAIT_H
|
||||
#include <sys/wait.h>
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
#include <linux/netfilter_ipv4.h>
|
||||
#include <libnetfilter_queue/libnetfilter_queue.h>
|
||||
|
||||
static int process_nfq_packet(struct nfq_q_handle *qh,
|
||||
struct nfgenmsg *nfmsg,
|
||||
struct nfq_data *nfa,
|
||||
void *data)
|
||||
{
|
||||
struct nfqnl_msg_packet_hdr *ph;
|
||||
int pkt_len = 0;
|
||||
int verdict;
|
||||
unsigned char *full_packet;
|
||||
fko_srv_options_t *opts = (fko_srv_options_t *)data;
|
||||
|
||||
ph = nfq_get_msg_packet_hdr(nfa);
|
||||
if (ph) {
|
||||
|
||||
/* --DSS for ref
|
||||
id = ntohl(ph->packet_id);
|
||||
hook = ph->hook;
|
||||
hw_proto = ph->protocol;
|
||||
*/
|
||||
|
||||
/* Retrieve packet payload
|
||||
*/
|
||||
pkt_len = nfq_get_payload(nfa, &full_packet);
|
||||
|
||||
process_packet(opts, pkt_len, full_packet);
|
||||
|
||||
/* Verdict on what to do with the packet. If it is coming from
|
||||
* the INPUT chain (NF_IP_LOCAL_IN), then it is assumed to be
|
||||
* a spa packet and can be dropped. Otherwise, let it through.
|
||||
*/
|
||||
verdict = (ph->hook == NF_IP_LOCAL_IN) ? NF_DROP : NF_ACCEPT;
|
||||
nfq_set_verdict(qh, ph->packet_id, verdict, 0, NULL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* The nfq capture routine.
|
||||
*/
|
||||
int
|
||||
nfq_capture(fko_srv_options_t *opts)
|
||||
{
|
||||
int res, child_pid, fd_flags;
|
||||
int nfq_errcnt = 0;
|
||||
int pending_break = 0;
|
||||
int status;
|
||||
char nfq_buf[1500];
|
||||
int chk_rm_all = 0;
|
||||
|
||||
/* Netfilter-related handles
|
||||
*/
|
||||
int nfq_fd;
|
||||
struct nfq_handle *nfq_h;
|
||||
struct nfq_q_handle *nfq_qh;
|
||||
struct nfnl_handle *nfq_nh;
|
||||
|
||||
nfq_h = nfq_open();
|
||||
if (!nfq_h) {
|
||||
log_msg(LOG_ERR, "[*] nfq_open error\n");
|
||||
clean_exit(opts, FW_CLEANUP, EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Unbind existing nf_queue handler for AF_INET (if any)
|
||||
*/
|
||||
res = nfq_unbind_pf(nfq_h, AF_INET);
|
||||
if (res < 0) {
|
||||
log_msg(LOG_WARNING, "[*] Error during nfq_unbind_pf() error: %d\n", res);
|
||||
}
|
||||
|
||||
/* Bind the given queue connection handle to process packets.
|
||||
*/
|
||||
res = nfq_bind_pf(nfq_h, AF_INET);
|
||||
if ( res < 0) {
|
||||
log_msg(LOG_ERR, "Error during nfq_bind_pf(), error: %d\n", res);
|
||||
clean_exit(opts, FW_CLEANUP, EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Create queue
|
||||
*/
|
||||
nfq_qh = nfq_create_queue(nfq_h, atoi(opts->config[CONF_NFQ_QUEUE_NUMBER]), &process_nfq_packet, opts);
|
||||
if (!nfq_qh) {
|
||||
log_msg(LOG_ERR, "Error during nfq_create_queue()\n");
|
||||
clean_exit(opts, FW_CLEANUP, EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Set the amount of data to be copied to userspace for each packet
|
||||
* queued to the given queue.
|
||||
*/
|
||||
if (nfq_set_mode(nfq_qh, NFQNL_COPY_PACKET, 0xffff) < 0) {
|
||||
log_msg(LOG_ERR, "Can't set packet_copy mode\n");
|
||||
clean_exit(opts, FW_CLEANUP, EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Get the netlink handle associated with the given queue connection
|
||||
* handle. Then use it to get the file descriptor we will use for
|
||||
* receiving the queued packets
|
||||
*/
|
||||
nfq_nh = nfq_nfnlh(nfq_h);
|
||||
nfq_fd = nfnl_fd(nfq_nh);
|
||||
|
||||
/* Set our nfq handle nonblocking mode.
|
||||
*
|
||||
*/
|
||||
if((fd_flags = fcntl(nfq_fd, F_GETFL, 0)) < 0)
|
||||
{
|
||||
log_msg(LOG_ERR, "nfq_capture: fcntl F_GETFL error: %s",
|
||||
strerror(errno));
|
||||
clean_exit(opts, FW_CLEANUP, EXIT_FAILURE);
|
||||
}
|
||||
|
||||
fd_flags |= O_NONBLOCK;
|
||||
|
||||
if(fcntl(nfq_fd, F_SETFL, fd_flags) < 0)
|
||||
{
|
||||
log_msg(LOG_ERR, "nfq_capture: fcntl F_SETFL error setting O_NONBLOCK: %s",
|
||||
strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Initialize our signal handlers. You can check the return value for
|
||||
* the number of signals that were *not* set. Those that were not set
|
||||
* will be listed in the log/stderr output.
|
||||
*/
|
||||
if(set_sig_handlers() > 0)
|
||||
log_msg(LOG_ERR, "Errors encountered when setting signal handlers.");
|
||||
|
||||
log_msg(LOG_INFO, "Starting fwknopd main event loop.");
|
||||
|
||||
/* Jump into our home-grown packet cature loop.
|
||||
*/
|
||||
while(1)
|
||||
{
|
||||
/* If we got a SIGCHLD and it was the tcp server, then handle it here.
|
||||
** XXX: --DSS Do we need this here? I'm guessing we would not be using
|
||||
** the TCP server in NF_QUEUE capture mode.
|
||||
*/
|
||||
if(got_sigchld)
|
||||
{
|
||||
if(opts->tcp_server_pid > 0)
|
||||
{
|
||||
child_pid = waitpid(0, &status, WNOHANG);
|
||||
|
||||
if(child_pid == opts->tcp_server_pid)
|
||||
{
|
||||
if(WIFSIGNALED(status))
|
||||
log_msg(LOG_WARNING, "TCP server got signal: %i", WTERMSIG(status));
|
||||
|
||||
log_msg(LOG_WARNING,
|
||||
"TCP server exited with status of %i. Attempting restart.",
|
||||
WEXITSTATUS(status)
|
||||
);
|
||||
|
||||
opts->tcp_server_pid = 0;
|
||||
|
||||
/* Attempt to restart tcp server ? */
|
||||
usleep(1000000);
|
||||
run_tcp_server(opts);
|
||||
}
|
||||
}
|
||||
|
||||
got_sigchld = 0;
|
||||
}
|
||||
|
||||
/* Any signal except USR1, USR2, and SIGCHLD mean break the loop.
|
||||
*/
|
||||
if(got_signal != 0)
|
||||
{
|
||||
if(got_sigint || got_sigterm || got_sighup)
|
||||
{
|
||||
pending_break = 1;
|
||||
}
|
||||
else if(got_sigusr1 || got_sigusr2)
|
||||
{
|
||||
/* Not doing anything with these yet.
|
||||
*/
|
||||
got_sigusr1 = got_sigusr2 = 0;
|
||||
got_signal = 0;
|
||||
}
|
||||
else
|
||||
got_signal = 0;
|
||||
}
|
||||
|
||||
res = recv(nfq_fd, nfq_buf, sizeof(nfq_buf), 0);
|
||||
|
||||
/* Count processed packets
|
||||
*/
|
||||
if(res > 0)
|
||||
{
|
||||
nfq_handle_packet(nfq_h, nfq_buf, res);
|
||||
|
||||
/* Count the set of processed packets (nfq_dispatch() return
|
||||
* value) - we use this as a comparison for --packet-limit regardless
|
||||
* of SPA packet validity at this point.
|
||||
*/
|
||||
opts->packet_ctr += res;
|
||||
if (opts->packet_ctr_limit && opts->packet_ctr >= opts->packet_ctr_limit)
|
||||
{
|
||||
log_msg(LOG_WARNING,
|
||||
"* Incoming packet count limit of %i reached",
|
||||
opts->packet_ctr_limit
|
||||
);
|
||||
|
||||
pending_break = 1;
|
||||
}
|
||||
}
|
||||
/* If there was an error, complain and go on (to an extent before
|
||||
* giving up).
|
||||
*/
|
||||
else if(res < 0 && errno != EAGAIN)
|
||||
{
|
||||
|
||||
log_msg(LOG_ERR, "[*] Error reading from nfq descriptor: %s", strerror);
|
||||
|
||||
if(nfq_errcnt++ > MAX_NFQ_ERRORS_BEFORE_BAIL)
|
||||
{
|
||||
log_msg(LOG_ERR, "[*] %i consecutive nfq errors. Giving up",
|
||||
nfq_errcnt
|
||||
);
|
||||
clean_exit(opts, FW_CLEANUP, EXIT_FAILURE);
|
||||
}
|
||||
|
||||
}
|
||||
else if(pending_break == 1 || res == -2)
|
||||
{
|
||||
log_msg(LOG_INFO, "Gracefully leaving the fwknopd event loop.");
|
||||
break;
|
||||
}
|
||||
else
|
||||
nfq_errcnt = 0;
|
||||
|
||||
/* Check for any expired firewall rules and deal with them.
|
||||
*/
|
||||
check_firewall_rules(opts, chk_rm_all);
|
||||
|
||||
usleep(atoi(opts->config[CONF_NFQ_LOOP_SLEEP]));
|
||||
}
|
||||
|
||||
nfq_destroy_queue(nfq_qh);
|
||||
nfq_close(nfq_h);
|
||||
|
||||
return(0);
|
||||
}
|
||||
/***EOF***/
|
||||
Executable
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
*****************************************************************************
|
||||
*
|
||||
* File: nfq_capture.h
|
||||
*
|
||||
* Purpose: Header file for nfq_capture.c.
|
||||
*
|
||||
* Fwknop is developed primarily by the people listed in the file 'AUTHORS'.
|
||||
* Copyright (C) 2009-2014 fwknop developers and contributors. For a full
|
||||
* list of contributors, see the file 'CREDITS'.
|
||||
*
|
||||
* License (GNU General Public License):
|
||||
*
|
||||
* This program 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 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA
|
||||
*
|
||||
*****************************************************************************
|
||||
*/
|
||||
#ifndef NFQ_CAPTURE_H
|
||||
#define NFQ_CAPTURE_H
|
||||
|
||||
/* How many consecutive capture errors will we allow
|
||||
* before giving up and bailing out.
|
||||
*/
|
||||
#define MAX_NFQ_ERRORS_BEFORE_BAIL 100
|
||||
|
||||
/* Prototypes
|
||||
*/
|
||||
int nfq_capture(fko_srv_options_t *opts);
|
||||
|
||||
#endif /* NFQ_CAPTURE_H */
|
||||
+19
-17
@@ -32,10 +32,6 @@
|
||||
*****************************************************************************
|
||||
*/
|
||||
|
||||
#if USE_LIBPCAP
|
||||
#include <pcap.h>
|
||||
#endif
|
||||
|
||||
#include "fwknopd_common.h"
|
||||
#include "netinet_common.h"
|
||||
#include "process_packet.h"
|
||||
@@ -43,11 +39,10 @@
|
||||
#include "utils.h"
|
||||
#include "log_msg.h"
|
||||
|
||||
#if USE_LIBPCAP
|
||||
|
||||
void
|
||||
process_packet(unsigned char *args, const struct pcap_pkthdr *packet_header,
|
||||
const unsigned char *packet)
|
||||
process_packet(PROCESS_PKT_ARGS_TYPE *args, PACKET_HEADER_META,
|
||||
const unsigned char *packet)
|
||||
{
|
||||
struct ether_header *eth_p;
|
||||
struct iphdr *iph_p;
|
||||
@@ -75,8 +70,25 @@ process_packet(unsigned char *args, const struct pcap_pkthdr *packet_header,
|
||||
|
||||
int offset = opts->data_link_offset;
|
||||
|
||||
#if USE_LIBPCAP
|
||||
unsigned short pkt_len = packet_header->len;
|
||||
|
||||
/* Gotta have a complete ethernet header.
|
||||
*/
|
||||
if (packet_header->caplen < ETHER_HDR_LEN)
|
||||
return;
|
||||
|
||||
/* Determine packet end.
|
||||
*/
|
||||
fr_end = (unsigned char *) packet + packet_header->caplen;
|
||||
#else
|
||||
/* This is coming from NFQ and we get the packet lentgh as an arg.
|
||||
*/
|
||||
if (pkt_len < ETHER_HDR_LEN)
|
||||
return;
|
||||
fr_end = (unsigned char *) packet + pkt_len;
|
||||
#endif
|
||||
|
||||
/* This is a hack to determine if we are using the linux cooked
|
||||
* interface. We base it on the offset being 16 which is the
|
||||
* value it would be if the datalink is DLT_LINUX_SLL. I don't
|
||||
@@ -84,19 +96,10 @@ process_packet(unsigned char *args, const struct pcap_pkthdr *packet_header,
|
||||
*/
|
||||
unsigned char assume_cooked = (offset == 16 ? 1 : 0);
|
||||
|
||||
/* Determine packet end.
|
||||
*/
|
||||
fr_end = (unsigned char *) packet + packet_header->caplen;
|
||||
|
||||
/* The ethernet header.
|
||||
*/
|
||||
eth_p = (struct ether_header*) packet;
|
||||
|
||||
/* Gotta have a complete ethernet header.
|
||||
*/
|
||||
if (packet_header->caplen < ETHER_HDR_LEN)
|
||||
return;
|
||||
|
||||
eth_type = ntohs(*((unsigned short*)ð_p->ether_type));
|
||||
|
||||
if(eth_type == 0x8100) /* 802.1q encapsulated */
|
||||
@@ -229,6 +232,5 @@ process_packet(unsigned char *args, const struct pcap_pkthdr *packet_header,
|
||||
return;
|
||||
}
|
||||
|
||||
#endif /* USE_LIBPCAP */
|
||||
|
||||
/***EOF***/
|
||||
|
||||
+11
-4
@@ -31,6 +31,15 @@
|
||||
#ifndef PROCESS_PACKET_H
|
||||
#define PROCESS_PACKET_H
|
||||
|
||||
#if USE_LIBPCAP
|
||||
#include <pcap.h>
|
||||
#define PACKET_HEADER_META const struct pcap_pkthdr *packet_header
|
||||
#define PROCESS_PKT_ARGS_TYPE unsigned char
|
||||
#else
|
||||
#define PACKET_HEADER_META unsigned short pkt_len
|
||||
#define PROCESS_PKT_ARGS_TYPE fko_srv_options_t
|
||||
#endif
|
||||
|
||||
#define IPV4_VER_MASK 0x15
|
||||
#define MIN_IPV4_WORDS 0x05
|
||||
|
||||
@@ -45,9 +54,7 @@
|
||||
|
||||
/* Prototypes
|
||||
*/
|
||||
#if USE_LIBPCAP
|
||||
void process_packet(unsigned char *args,
|
||||
const struct pcap_pkthdr *packet_header, const unsigned char *packet);
|
||||
#endif
|
||||
void process_packet(PROCESS_PKT_ARGS_TYPE *opts, PACKET_HEADER_META,
|
||||
const unsigned char *packet);
|
||||
|
||||
#endif /* PROCESS_PACKET_H */
|
||||
|
||||
Reference in New Issue
Block a user