nfq: implement "fail-open" support.

On linux >= 3.6, you can use the fail-open option on a NFQ queue
to have the kernel accept the packet if userspace is not able to keep
pace.

Please note that the kernel will not trigger an error if the feature is activated
in userspace libraries but not available in kernel.

This patch implements the option for suricata by adding a nfq.fail-open
configuration variable which is desactivated by default.
pull/15/merge
Eric Leblond 14 years ago committed by Victor Julien
parent 9e54819121
commit 2c57275921

@ -553,6 +553,7 @@ AC_INIT(configure.ac)
AC_CHECK_LIB(netfilter_queue, nfq_open,, NFQ="no",) AC_CHECK_LIB(netfilter_queue, nfq_open,, NFQ="no",)
AC_CHECK_LIB([netfilter_queue], [nfq_set_queue_maxlen],AC_DEFINE_UNQUOTED([HAVE_NFQ_MAXLEN],[1],[Found queue max length support in netfilter_queue]) ,,[-lnfnetlink]) AC_CHECK_LIB([netfilter_queue], [nfq_set_queue_maxlen],AC_DEFINE_UNQUOTED([HAVE_NFQ_MAXLEN],[1],[Found queue max length support in netfilter_queue]) ,,[-lnfnetlink])
AC_CHECK_LIB([netfilter_queue], [nfq_set_verdict2],AC_DEFINE_UNQUOTED([HAVE_NFQ_SET_VERDICT2],[1],[Found nfq_set_verdict2 function in netfilter_queue]) ,,[-lnfnetlink]) AC_CHECK_LIB([netfilter_queue], [nfq_set_verdict2],AC_DEFINE_UNQUOTED([HAVE_NFQ_SET_VERDICT2],[1],[Found nfq_set_verdict2 function in netfilter_queue]) ,,[-lnfnetlink])
AC_CHECK_LIB([netfilter_queue], [nfq_set_queue_flags],AC_DEFINE_UNQUOTED([HAVE_NFQ_SET_QUEUE_FLAGS],[1],[Found nfq_set_queue_flags function in netfilter_queue]) ,,[-lnfnetlink])
# check if the argument to nfq_get_payload is signed or unsigned # check if the argument to nfq_get_payload is signed or unsigned
AC_MSG_CHECKING([for signed nfq_get_payload payload argument]) AC_MSG_CHECKING([for signed nfq_get_payload payload argument])

@ -156,11 +156,14 @@ typedef enum NFQMode_ {
NFQ_ROUTE_MODE, NFQ_ROUTE_MODE,
} NFQMode; } NFQMode;
#define NFQ_FLAG_FAIL_OPEN (1 << 0)
typedef struct NFQCnf_ { typedef struct NFQCnf_ {
NFQMode mode; NFQMode mode;
uint32_t mark; uint32_t mark;
uint32_t mask; uint32_t mask;
uint32_t next_queue; uint32_t next_queue;
uint32_t flags;
} NFQCnf; } NFQCnf;
NFQCnf nfq_config; NFQCnf nfq_config;
@ -208,6 +211,7 @@ void NFQInitConfig(char quiet)
{ {
intmax_t value = 0; intmax_t value = 0;
char* nfq_mode = NULL; char* nfq_mode = NULL;
int boolval;
SCLogDebug("Initializing NFQ"); SCLogDebug("Initializing NFQ");
@ -228,6 +232,17 @@ void NFQInitConfig(char quiet)
} }
} }
(void)ConfGetBool("nfq.fail-open", (int *)&boolval);
if (boolval) {
#ifdef HAVE_NFQ_SET_QUEUE_FLAGS
SCLogInfo("Enabling fail-open on queue");
nfq_config.flags |= NFQ_FLAG_FAIL_OPEN;
#else
SCLogError(SC_ERR_NFQ_NOSUPPORT,
"nfq.fail-open set but NFQ library has no support for it.");
#endif
}
if ((ConfGetInt("nfq.repeat-mark", &value)) == 1) { if ((ConfGetInt("nfq.repeat-mark", &value)) == 1) {
nfq_config.mark = (uint32_t)value; nfq_config.mark = (uint32_t)value;
} }
@ -497,6 +512,21 @@ TmEcode NFQInitThread(NFQThreadVars *nfq_t, uint32_t queue_maxlen)
setsockopt(nfq_q->fd, SOL_NETLINK, NETLINK_NO_ENOBUFS, &opt, sizeof(int)); setsockopt(nfq_q->fd, SOL_NETLINK, NETLINK_NO_ENOBUFS, &opt, sizeof(int));
#endif #endif
#ifdef HAVE_NFQ_SET_QUEUE_FLAGS
if (nfq_config.flags & NFQ_FLAG_FAIL_OPEN) {
uint32_t flags = NFQA_CFG_F_FAIL_OPEN;
uint32_t mask = NFQA_CFG_F_FAIL_OPEN;
int r = nfq_set_queue_flags(nfq_q->qh, mask, flags);
if (r == -1) {
SCLogWarning(SC_ERR_NFQ_SET_MODE, "can't set fail-open mode: %s",
strerror(errno));
} else {
SCLogInfo("fail-open mode should be set on queue");
}
}
#endif
/* set a timeout to the socket so we can check for a signal /* set a timeout to the socket so we can check for a signal
* in case we don't get packets for a longer period. */ * in case we don't get packets for a longer period. */
tv.tv_sec = 1; tv.tv_sec = 1;

@ -189,11 +189,14 @@ magic-file: @e_magic_file@
# this mode, you need to set mode to 'repeat' # this mode, you need to set mode to 'repeat'
# If you want packet to be sent to another queue after an ACCEPT decision # If you want packet to be sent to another queue after an ACCEPT decision
# set mode to 'route' and set next-queue value. # set mode to 'route' and set next-queue value.
# On linux >= 3.6, you can set the fail-open option to yes to have the kernel
# accept the packet if suricata is not able to keep pace.
nfq: nfq:
# mode: accept # mode: accept
# repeat-mark: 1 # repeat-mark: 1
# repeat-mask: 1 # repeat-mask: 1
# route-queue: 2 # route-queue: 2
# fail-open: yes
# af-packet support # af-packet support
# Set threads to > 1 to use PACKET_FANOUT support # Set threads to > 1 to use PACKET_FANOUT support

Loading…
Cancel
Save