Permalink
Browse files

af-packet: IPS and TAP feature

This patch adds a new feature to AF_PACKET capture mode. It is now
possible to use AF_PACKET in IPS and TAP mode: all traffic received
on a interface will be forwarded (at the Ethernet level) to an other
interface. To do so, Suricata create a raw socket and sends the receive
packets to a interface designed in the configuration file.

This patch adds two variables to the configuration of af-packet
interface:
 copy-mode: ips or tap
 copy-iface: eth1 #the interface where packet are copied
If copy-mode is set to ips then the packet wth action DROP are not
copied to the destination interface. If copy-mode is set to tap,
all packets are copied to the destination interface.
Any other value of copy-mode results in the feature to be unused.
There is no default interface for copy-iface and the variable has
to be set for the ids or tap mode to work.

For now, this feature depends of the release data system. This
implies you need to activate the ring mode and zero copy. Basically
use-mmap has to be set to yes.

This patch adds a peering of AF_PACKET sockets from the thread on
one interface to the threads on another interface. Peering is
necessary as if we use an other socket the capture socket receives
all emitted packets. This is made using a new AFPPeer structure to
avoid direct interaction between AFPTreadVars.

There is currently a bug in Linux kernel (prior to 3.6) and it is
not possible to use multiple threads.

You need to setup two interfaces with equality on the threads
variable. copy-mode variable must be set on the two interfaces
and use-mmap must be set to activated.

A valid configuration for an IPS using eth0 and vboxnet1 interfaces
will look like:

af-packet:
  - interface: eth0
    threads: 1
    defrag: yes
    cluster-type: cluster_flow
    cluster-id: 98
    copy-mode: ips
    copy-iface: vboxnet1
    buffer-size: 64535
    use-mmap: yes
  - interface: vboxnet1
    threads: 1
    cluster-id: 97
    defrag: yes
    cluster-type: cluster_flow
    copy-mode: ips
    copy-iface: eth0
    buffer-size: 64535
    use-mmap: yes
  • Loading branch information...
regit authored and inliniac committed Jul 19, 2012
1 parent 2011a3f commit 662dccd8a5180807e3749842508b80e2e2183051
Showing with 346 additions and 21 deletions.
  1. +85 −8 src/runmode-af-packet.c
  2. +225 −11 src/source-af-packet.c
  3. +27 −2 src/source-af-packet.h
  4. +2 −0 src/suricata.c
  5. +7 −0 suricata.yaml.in
View
@@ -109,9 +109,11 @@ void *ParseAFPConfig(const char *iface)
AFPIfaceConfig *aconf = SCMalloc(sizeof(*aconf));
char *tmpclusterid;
char *tmpctype;
char *copymodestr;
intmax_t value;
int boolval;
char *bpf_filter = NULL;
char *out_iface = NULL;
if (aconf == NULL) {
return NULL;
@@ -134,6 +136,7 @@ void *ParseAFPConfig(const char *iface)
aconf->DerefFunc = AFPDerefConfig;
aconf->flags = 0;
aconf->bpf_filter = NULL;
aconf->out_iface = NULL;
if (ConfGet("bpf-filter", &bpf_filter) == 1) {
if (strlen(bpf_filter) > 0) {
@@ -169,6 +172,44 @@ void *ParseAFPConfig(const char *iface)
aconf->threads = 1;
}
if (ConfGetChildValue(if_root, "copy-iface", &out_iface) == 1) {
if (strlen(out_iface) > 0) {
aconf->out_iface = out_iface;
}
}
(void)ConfGetChildValueBool(if_root, "use-mmap", (int *)&boolval);
if (boolval) {
SCLogInfo("Enabling mmaped capture on iface %s",
aconf->iface);
aconf->flags |= AFP_RING_MODE;
}
aconf->copy_mode = AFP_COPY_MODE_NONE;
if (ConfGetChildValue(if_root, "copy-mode", &copymodestr) == 1) {
if (aconf->out_iface == NULL) {
SCLogInfo("Copy mode activated but no destination"
" iface. Disabling feature");
} else if (!(aconf->flags & AFP_RING_MODE)) {
SCLogInfo("Copy mode activated but use-mmap "
"set to no. Disabling feature");
} else if (strlen(copymodestr) <= 0) {
aconf->out_iface = NULL;
} else if (strcmp(copymodestr, "ips") == 0) {
SCLogInfo("AF_PACKET IPS mode activated %s->%s",
iface,
aconf->out_iface);
aconf->copy_mode = AFP_COPY_MODE_IPS;
} else if (strcmp(copymodestr, "tap") == 0) {
SCLogInfo("AF_PACKET TAP mode activated %s->%s",
iface,
aconf->out_iface);
aconf->copy_mode = AFP_COPY_MODE_TAP;
} else {
SCLogInfo("Invalid mode (not in tap, ips)");
}
}
SC_ATOMIC_RESET(aconf->ref);
(void) SC_ATOMIC_ADD(aconf->ref, aconf->threads);
@@ -246,13 +287,6 @@ void *ParseAFPConfig(const char *iface)
aconf->iface);
aconf->promisc = 0;
}
(void)ConfGetChildValueBool(if_root, "use-mmap", (int *)&boolval);
if (boolval) {
SCLogInfo("Enabling mmaped capture on iface %s",
aconf->iface);
aconf->flags |= AFP_RING_MODE;
}
if (ConfGetChildValue(if_root, "checksum-checks", &tmpctype) == 1) {
if (strcmp(tmpctype, "auto") == 0) {
@@ -309,6 +343,11 @@ int RunModeIdsAFPAuto(DetectEngineCtx *de_ctx)
(void)ConfGet("af-packet.live-interface", &live_dev);
if (AFPPeersListInit() != TM_ECODE_OK) {
SCLogError(SC_ERR_RUNMODE, "Unable to init peers list.");
exit(EXIT_FAILURE);
}
ret = RunModeSetLiveCaptureAuto(de_ctx,
ParseAFPConfig,
AFPConfigGeThreadsCount,
@@ -320,6 +359,12 @@ int RunModeIdsAFPAuto(DetectEngineCtx *de_ctx)
exit(EXIT_FAILURE);
}
/* In IPS mode each threads must have a peer */
if (AFPPeersListCheck() != TM_ECODE_OK) {
SCLogError(SC_ERR_RUNMODE, "Some IPS capture threads did not peer.");
exit(EXIT_FAILURE);
}
SCLogInfo("RunModeIdsAFPAuto initialised");
#endif
SCReturnInt(0);
@@ -342,6 +387,11 @@ int RunModeIdsAFPAutoFp(DetectEngineCtx *de_ctx)
SCLogDebug("live_dev %s", live_dev);
if (AFPPeersListInit() != TM_ECODE_OK) {
SCLogError(SC_ERR_RUNMODE, "Unable to init peers list.");
exit(EXIT_FAILURE);
}
ret = RunModeSetLiveCaptureAutoFp(de_ctx,
ParseAFPConfig,
AFPConfigGeThreadsCount,
@@ -353,8 +403,13 @@ int RunModeIdsAFPAutoFp(DetectEngineCtx *de_ctx)
exit(EXIT_FAILURE);
}
SCLogInfo("RunModeIdsAFPAutoFp initialised");
/* In IPS mode each threads must have a peer */
if (AFPPeersListCheck() != TM_ECODE_OK) {
SCLogError(SC_ERR_RUNMODE, "Some IPS capture threads did not peer.");
exit(EXIT_FAILURE);
}
SCLogInfo("RunModeIdsAFPAutoFp initialised");
#endif /* HAVE_AF_PACKET */
SCReturnInt(0);
@@ -377,6 +432,11 @@ int RunModeIdsAFPSingle(DetectEngineCtx *de_ctx)
(void)ConfGet("af-packet.live-interface", &live_dev);
if (AFPPeersListInit() != TM_ECODE_OK) {
SCLogError(SC_ERR_RUNMODE, "Unable to init peers list.");
exit(EXIT_FAILURE);
}
ret = RunModeSetLiveCaptureSingle(de_ctx,
ParseAFPConfig,
AFPConfigGeThreadsCount,
@@ -388,6 +448,12 @@ int RunModeIdsAFPSingle(DetectEngineCtx *de_ctx)
exit(EXIT_FAILURE);
}
/* In IPS mode each threads must have a peer */
if (AFPPeersListCheck() != TM_ECODE_OK) {
SCLogError(SC_ERR_RUNMODE, "Some IPS capture threads did not peer.");
exit(EXIT_FAILURE);
}
SCLogInfo("RunModeIdsAFPSingle initialised");
#endif /* HAVE_AF_PACKET */
@@ -414,6 +480,11 @@ int RunModeIdsAFPWorkers(DetectEngineCtx *de_ctx)
(void)ConfGet("af-packet.live-interface", &live_dev);
if (AFPPeersListInit() != TM_ECODE_OK) {
SCLogError(SC_ERR_RUNMODE, "Unable to init peers list.");
exit(EXIT_FAILURE);
}
ret = RunModeSetLiveCaptureWorkers(de_ctx,
ParseAFPConfig,
AFPConfigGeThreadsCount,
@@ -425,6 +496,12 @@ int RunModeIdsAFPWorkers(DetectEngineCtx *de_ctx)
exit(EXIT_FAILURE);
}
/* In IPS mode each threads must have a peer */
if (AFPPeersListCheck() != TM_ECODE_OK) {
SCLogError(SC_ERR_RUNMODE, "Some IPS capture threads did not peer.");
exit(EXIT_FAILURE);
}
SCLogInfo("RunModeIdsAFPSingle initialised");
#endif /* HAVE_AF_PACKET */
Oops, something went wrong.

0 comments on commit 662dccd

Please sign in to comment.