mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
629 lines
28 KiB
ReStructuredText
629 lines
28 KiB
ReStructuredText
|
|
.. _framework-netcontrol:
|
|
|
|
====================
|
|
NetControl Framework
|
|
====================
|
|
|
|
.. rst-class:: opening
|
|
|
|
Bro can connect with network devices like, for example, switches
|
|
or soft- and hardware firewalls using the NetControl framework. The
|
|
NetControl framework provides a flexible, unified interface for active
|
|
response and hides the complexity of heterogeneous network equipment
|
|
behind a simple task-oriented API, which is easily usable via Bro
|
|
scripts. This document gives an overview of how to use the NetControl
|
|
framework in different scenarios; to get a better understanding of how
|
|
it can be used in practice, it might be worthwhile to take a look at
|
|
the unit tests.
|
|
|
|
.. contents::
|
|
|
|
NetControl Architecture
|
|
=======================
|
|
|
|
.. figure:: netcontrol-architecture.png
|
|
:width: 600
|
|
:align: center
|
|
:alt: NetControl framework architecture
|
|
:target: ../_images/netcontrol-architecture.png
|
|
|
|
NetControl architecture (click to enlarge).
|
|
|
|
The basic architecture of the NetControl framework is shown in the figure above.
|
|
Conceptually, the NetControl framework sits between the user provided scripts
|
|
(which use the Bro event engine) and the network device (which can either be a
|
|
hardware or software device), that is used to implement the commands.
|
|
|
|
The NetControl framework supports a number of high-level calls, like the
|
|
:bro:see:`NetControl::drop_address` function, or a lower level rule
|
|
syntax. After a rule has been added to the NetControl framework, NetControl
|
|
sends the rule to one or several of its *backends*. Each backend is responsible
|
|
to communicate with a single hard- or software device. The NetControl framework
|
|
tracks rules throughout their entire lifecycle and reports the status (like
|
|
success, failure and timeouts) back to the user scripts.
|
|
|
|
The backends are implemented as Bro scripts using a plugin based API; an example
|
|
for this is :doc:`/scripts/base/frameworks/netcontrol/plugins/broker.bro`. This
|
|
document will show how to write plugins in
|
|
:ref:`framework-netcontrol-plugins`.
|
|
|
|
NetControl API
|
|
==============
|
|
|
|
High-level NetControl API
|
|
-------------------------
|
|
|
|
In this section, we will introduce the high level NetControl API. As mentioned
|
|
above, NetControl uses *backends* to communicate with the external devices that
|
|
will implement the rules. You will need at least one active backend before you
|
|
can use NetControl. For our examples, we will just use the debug plugin to
|
|
create a backend. This plugin outputs all actions that are taken to the standard
|
|
output.
|
|
|
|
Backends should be initialized in the :bro:see:`NetControl::init` event, calling
|
|
the :bro:see:`NetControl::activate` function after the plugin instance has been
|
|
initialized. The debug plugin can be initialized as follows:
|
|
|
|
.. code:: bro
|
|
|
|
event NetControl::init()
|
|
{
|
|
local debug_plugin = NetControl::create_debug(T);
|
|
NetControl::activate(debug_plugin, 0);
|
|
}
|
|
|
|
After at least one backend has been added to the NetControl framework, the
|
|
framework can be used and will send added rules to the added backend.
|
|
|
|
The NetControl framework contains several high level functions that allow users
|
|
to drop connections of certain addresses and networks, shunt network traffic,
|
|
etc. The following table shows and describes all of the currently available
|
|
high-level functions.
|
|
|
|
.. list-table::
|
|
:widths: 32 40
|
|
:header-rows: 1
|
|
|
|
* - Function
|
|
- Description
|
|
|
|
* - :bro:see:`NetControl::drop_address`
|
|
- Calling this function causes NetControl to block all packets involving
|
|
an IP address from being forwarded.
|
|
|
|
* - :bro:see:`NetControl::drop_connection`
|
|
- Calling this function stops all packets of a specific connection
|
|
(identified by its 5-tuple) from being forwarded.
|
|
|
|
* - :bro:see:`NetControl::drop_address_catch_release`
|
|
- Calling this function causes all packets of a specific source IP to be
|
|
blocked. This function uses catch-and-release functionality and the IP
|
|
address is only dropped for a short amount of time to conserve rule
|
|
space in the network hardware. It is immediately re-dropped when it is
|
|
seen again in traffic. See :ref:`framework-netcontrol-catchrelease` for
|
|
more information.
|
|
|
|
* - :bro:see:`NetControl::shunt_flow`
|
|
- Calling this function causes NetControl to stop forwarding a
|
|
uni-directional flow of packets to Bro. This allows Bro to conserve
|
|
resources by shunting flows that have been identified as being benign.
|
|
|
|
* - :bro:see:`NetControl::redirect_flow`
|
|
- Calling this function causes NetControl to redirect a uni-directional
|
|
flow to another port of the networking hardware.
|
|
|
|
* - :bro:see:`NetControl::quarantine_host`
|
|
- Calling this function allows Bro to quarantine a host by sending DNS
|
|
traffic to a host with a special DNS server, which resolves all queries
|
|
as pointing to itself. The quarantined host is only allowed between the
|
|
special server, which will serve a warning message detailing the next
|
|
steps for the user.
|
|
|
|
* - :bro:see:`NetControl::whitelist_address`
|
|
- Calling this function causes NetControl to push a whitelist entry for an
|
|
IP address to the networking hardware.
|
|
|
|
* - :bro:see:`NetControl::whitelist_subnet`
|
|
- Calling this function causes NetControl to push a whitelist entry for a
|
|
subnet to the networking hardware.
|
|
|
|
After adding a backend, all of these functions can immediately be used and will
|
|
start sending the rules to the added backend(s). To give a very simple example,
|
|
the following script will simply block the traffic of all connections that it
|
|
sees being established:
|
|
|
|
.. btest-include:: ${DOC_ROOT}/frameworks/netcontrol-1-drop-with-debug.bro
|
|
|
|
Running this script on a file containing one connection will cause the debug
|
|
plugin to print one line to the standard output, which contains information
|
|
about the rule that was added. It will also cause creation of `netcontrol.log`,
|
|
which contains information about all actions that are taken by NetControl:
|
|
|
|
.. btest:: netcontrol-1-drop-with-debug.bro
|
|
|
|
@TEST-EXEC: btest-rst-cmd bro -C -r ${TRACES}/tls/ecdhe.pcap ${DOC_ROOT}/frameworks/netcontrol-1-drop-with-debug.bro
|
|
@TEST-EXEC: btest-rst-cmd cat netcontrol.log
|
|
|
|
In our case, `netcontrol.log` contains several :bro:see:`NetControl::MESSAGE`
|
|
entries, which show that the debug plugin has been initialized and added.
|
|
Afterwards, there are two :bro:see:`NetControl::RULE` entries; the first shows
|
|
that the addition of a rule has been requested (state is
|
|
:bro:see:`NetControl::REQUESTED`). The following line shows that the rule was
|
|
successfully added (the state is :bro:see:`NetControl::SUCCEEDED`). The
|
|
remainder of the log line gives more information about the added rule, which in
|
|
our case applies to a specific 5-tuple.
|
|
|
|
In addition to the netcontrol.log, the drop commands also create a second,
|
|
additional log called `netcontrol_drop.log`. This log file is much more succinct and
|
|
only contains information that is specific to drops that are enacted by
|
|
NetControl:
|
|
|
|
.. btest:: netcontrol-1-drop-with-debug.bro
|
|
|
|
@TEST-EXEC: btest-rst-cmd cat netcontrol_drop.log
|
|
|
|
While this example of blocking all connections is usually not very useful, the
|
|
high-level API gives an easy way to take action, for example when a host is
|
|
identified doing some harmful activity. To give a more realistic example, the
|
|
following code automatically blocks a recognized SSH guesser:
|
|
|
|
.. btest-include:: ${DOC_ROOT}/frameworks/netcontrol-2-ssh-guesser.bro
|
|
|
|
.. btest:: netcontrol-2-ssh-guesser.bro
|
|
|
|
@TEST-EXEC: btest-rst-cmd bro -C -r ${TRACES}/ssh/sshguess.pcap ${DOC_ROOT}/frameworks/netcontrol-2-ssh-guesser.bro
|
|
@TEST-EXEC: btest-rst-cmd cat netcontrol.log
|
|
|
|
Note that in this case, instead of calling NetControl directly, we also can use
|
|
the :bro:see:`Notice::ACTION_DROP` action of the notice framework:
|
|
|
|
.. btest-include:: ${DOC_ROOT}/frameworks/netcontrol-3-ssh-guesser.bro
|
|
|
|
.. btest:: netcontrol-3-ssh-guesser.bro
|
|
|
|
@TEST-EXEC: btest-rst-cmd bro -C -r ${TRACES}/ssh/sshguess.pcap ${DOC_ROOT}/frameworks/netcontrol-3-ssh-guesser.bro
|
|
@TEST-EXEC: btest-rst-cmd cat netcontrol.log
|
|
|
|
Using the :bro:see:`Notice::ACTION_DROP` action of the notice framework also
|
|
will cause the `dropped` column in `notice.log` to be set to true each time that
|
|
the NetControl framework enacts a block:
|
|
|
|
.. btest:: netcontrol-3-ssh-guesser.bro
|
|
|
|
@TEST-EXEC: btest-rst-cmd cat notice.log
|
|
|
|
Rule API
|
|
--------
|
|
|
|
As already mentioned in the last section, in addition to the high-level API, the
|
|
NetControl framework also supports a Rule based API which allows greater
|
|
flexibility while adding rules. Actually, all the high-level functions are
|
|
implemented using this lower-level rule API; the high-level functions simply
|
|
convert their arguments into the lower-level rules and then add the rules
|
|
directly to the NetControl framework (by calling :bro:see:`NetControl::add_rule`).
|
|
|
|
The following figure shows the main components of NetControl rules:
|
|
|
|
.. figure:: netcontrol-rules.png
|
|
:width: 600
|
|
:align: center
|
|
:alt: NetControl rule overview
|
|
:target: ../_images/netcontrol-rules.png
|
|
|
|
NetControl Rule overview (click to enlarge).
|
|
|
|
The types that are used to make up a rule are defined in
|
|
:doc:`/scripts/base/frameworks/netcontrol/types.bro`.
|
|
|
|
Rules are defined as a :bro:see:`NetControl::Rule` record. Rules have a *type*,
|
|
which specifies what kind of action is taken. The possible actions are to
|
|
**drop** packets, to **modify** them, to **redirect** or to **whitelist** them.
|
|
The *target* of a rule specifies if the rule is applied in the *forward path*,
|
|
and affects packets as they are forwarded through the network, or if it affects
|
|
the *monitor path* and only affects the packets that are sent to Bro, but not
|
|
the packets that traverse the network. The *entity* specifies the address,
|
|
connection, etc. that the rule applies to. In addition, each rule has a
|
|
*timeout* (which can be left empty), a *priority* (with higher priority rules
|
|
overriding lower priority rules). Furthermore, a *location* string with more
|
|
text information about each rule can be provided.
|
|
|
|
There are a couple more fields that are only needed for some rule types. For
|
|
example, when you insert a redirect rule, you have to specify the port that
|
|
packets should be redirected to. All these fields are shown in the
|
|
:bro:see:`NetControl::Rule` documentation.
|
|
|
|
To give an example on how to construct your own rule, we are going to write
|
|
our own version of the :bro:see:`NetControl::drop_connection` function. The only
|
|
difference between our function and the one provided by NetControl is the fact
|
|
that the NetControl function has additional functionality, e.g. for logging.
|
|
|
|
Once again, we are going to test our function with a simple example that simply
|
|
drops all connections on the network:
|
|
|
|
.. btest-include:: ${DOC_ROOT}/frameworks/netcontrol-4-drop.bro
|
|
|
|
.. btest:: netcontrol-4-drop.bro
|
|
|
|
@TEST-EXEC: btest-rst-cmd bro -C -r ${TRACES}/tls/ecdhe.pcap ${DOC_ROOT}/frameworks/netcontrol-4-drop.bro
|
|
@TEST-EXEC: btest-rst-cmd cat netcontrol.log
|
|
|
|
The last example shows that :bro:see:`NetControl::add_rule` returns a string
|
|
identifier that is unique for each rule (uniqueness is not preserved across
|
|
restarts of Bro). This rule id can be used to later remove rules manually using
|
|
:bro:see:`NetControl::remove_rule`.
|
|
|
|
Similar to :bro:see:`NetControl::add_rule`, all the high-level functions also
|
|
return their rule IDs, which can be removed in the same way.
|
|
|
|
Interacting with Rules
|
|
----------------------
|
|
|
|
The NetControl framework offers a number of different ways to interact with
|
|
rules. Before a rule is applied by the framework, a number of different hooks
|
|
allow you to either modify or discard rules before they are added. Furthermore,
|
|
a number of events can be used to track the lifecycle of a rule while it is
|
|
being managed by the NetControl framework. It is also possible to query and
|
|
access the current set of active rules.
|
|
|
|
Rule Policy
|
|
***********
|
|
|
|
The hook :bro:see:`NetControl::rule_policy` provides the mechanism for modifying
|
|
or discarding a rule before it is sent onwards to the backends. Hooks can be
|
|
thought of as multi-bodied functions and using them looks very similar to
|
|
handling events. In contrast to events, they are processed immediately. Like
|
|
events, hooks can have priorities to sort the order in which they are applied.
|
|
Hooks can use the ``break`` keyword to show that processing should be aborted;
|
|
if any :bro:see:`NetControl::rule_policy` hook uses ``break``, the rule will be
|
|
discarded before further processing.
|
|
|
|
Here is a simple example which tells Bro to discard all rules for connections
|
|
originating from the 192.168.* network:
|
|
|
|
.. btest-include:: ${DOC_ROOT}/frameworks/netcontrol-5-hook.bro
|
|
|
|
.. btest:: netcontrol-5-hook.bro
|
|
|
|
@TEST-EXEC: btest-rst-cmd bro -C -r ${TRACES}/tls/ecdhe.pcap ${DOC_ROOT}/frameworks/netcontrol-5-hook.bro
|
|
|
|
NetControl Events
|
|
*****************
|
|
|
|
In addition to the hooks, the NetControl framework offers a variety of events
|
|
that are raised by the framework to allow users to track rules, as well as the
|
|
state of the framework.
|
|
|
|
We already encountered and used one event of the NetControl framework,
|
|
:bro:see:`NetControl::init`, which is used to initialize the framework. After
|
|
the framework has finished initialization and will start accepting rules, the
|
|
:bro:see:`NetControl::init_done` event will be raised.
|
|
|
|
When rules are added to the framework, the following events will be called in
|
|
this order:
|
|
|
|
.. list-table::
|
|
:widths: 20 80
|
|
:header-rows: 1
|
|
|
|
* - Event
|
|
- Description
|
|
|
|
* - :bro:see:`NetControl::rule_new`
|
|
- Signals that a new rule is created by the NetControl framework due to
|
|
:bro:see:`NetControl::add_rule`. At this point, the rule has not
|
|
yet been added to any backend.
|
|
|
|
* - :bro:see:`NetControl::rule_added`
|
|
- Signals that a new rule has successfully been added by a backend.
|
|
|
|
* - :bro:see:`NetControl::rule_exists`
|
|
- This event is raised instead of :bro:see:`NetControl::rule_added` when a
|
|
backend reports that a rule was already existing.
|
|
|
|
* - :bro:see:`NetControl::rule_timeout`
|
|
- Signals that a rule timeout was reached. If the hardware does not support
|
|
automatic timeouts, the NetControl framework will automatically call
|
|
:bro:see:`NetControl::remove_rule`.
|
|
|
|
* - :bro:see:`NetControl::rule_removed`
|
|
- Signals that a new rule has successfully been removed a backend.
|
|
|
|
* - :bro:see:`NetControl::rule_destroyed`
|
|
- This event is the pendant to :bro:see:`NetControl::rule_added`, and
|
|
reports that a rule is no longer being tracked by the NetControl framework.
|
|
This happens, for example, when a rule was removed from all backends.
|
|
|
|
* - :bro:see:`NetControl::rule_error`
|
|
- This event is raised whenever an error occurs during any rule operation.
|
|
|
|
Finding active rules
|
|
********************
|
|
|
|
The NetControl framework provides two functions for finding currently active
|
|
rules: :bro:see:`NetControl::find_rules_addr` finds all rules that affect a
|
|
certain IP address and :bro:see:`NetControl::find_rules_subnet` finds all rules
|
|
that affect a specified subnet.
|
|
|
|
Consider, for example, the case where a Bro instance monitors the traffic at the
|
|
border, before any firewall or switch rules were applied. In this case, Bro will
|
|
still be able to see connection attempts of already blocked IP addresses. In this
|
|
case, :bro:see:`NetControl::find_rules_addr` could be used to check if an
|
|
address already was blocked in the past.
|
|
|
|
Here is a simple example, which uses a trace that contains two connections from
|
|
the same IP address. After the first connection, the script recognizes that the
|
|
address is already blocked in the second connection.
|
|
|
|
.. btest-include:: ${DOC_ROOT}/frameworks/netcontrol-6-find.bro
|
|
|
|
.. btest:: netcontrol-6-find.bro
|
|
|
|
@TEST-EXEC: btest-rst-cmd bro -C -r ${TRACES}/tls/google-duplicate.trace ${DOC_ROOT}/frameworks/netcontrol-6-find.bro
|
|
|
|
Notice that the functions return vectors because it is possible that several
|
|
rules exist simultaneously that affect one IP; either there could be
|
|
rules with different priorities, or rules for the subnet that an IP address is
|
|
part of.
|
|
|
|
|
|
|
|
.. _framework-netcontrol-catchrelease:
|
|
|
|
Catch and Release
|
|
-----------------
|
|
|
|
We already mentioned earlier that in addition to the
|
|
:bro:see:`NetControl::drop_connection` and :bro:see:`NetControl::drop_address`
|
|
functions, which drop a connection or address for a specified amount of time,
|
|
NetControl also comes with a blocking function that uses an approach called
|
|
*catch and release*.
|
|
|
|
Catch and release is a blocking scheme that conserves valuable rule space in
|
|
your hardware. Instead of using long-lasting blocks, catch and release first
|
|
only installs blocks for a short amount of time (typically a few minutes). After
|
|
these minutes pass, the block is lifted, but the IP address is added to a
|
|
watchlist and the IP address will immediately be re-blocked again (for a longer
|
|
amount of time), if it is seen reappearing in any traffic, no matter if the new
|
|
traffic triggers any alert or not.
|
|
|
|
This makes catch and release blocks similar to normal, longer duration blocks,
|
|
while only requiring a small amount of space for the currently active rules. IP
|
|
addresses that only are seen once for a short time are only blocked for a few
|
|
minutes, monitored for a while and then forgotten. IP addresses that keep
|
|
appearing will get re-blocked for longer amounts of time.
|
|
|
|
In contrast to the other high-level functions that we documented so far, the
|
|
catch and release functionality is much more complex and adds a number of
|
|
different specialized functions to NetControl. The documentation for catch and
|
|
release is contained in the file
|
|
:doc:`/scripts/base/frameworks/netcontrol/catch-and-release.bro`.
|
|
|
|
Using catch and release in your scripts is easy; just use
|
|
:bro:see:`NetControl::drop_address_catch_release` like in this example:
|
|
|
|
.. btest-include:: ${DOC_ROOT}/frameworks/netcontrol-7-catch-release.bro
|
|
|
|
.. btest:: netcontrol-7-catch-release.bro
|
|
|
|
@TEST-EXEC: btest-rst-cmd bro -C -r ${TRACES}/tls/ecdhe.pcap ${DOC_ROOT}/frameworks/netcontrol-7-catch-release.bro
|
|
|
|
Note that you do not have to provide the block time for catch and release;
|
|
instead, catch and release uses the time intervals specified in
|
|
:bro:see:`NetControl::catch_release_intervals` (by default 10 minutes, 1 hour,
|
|
24 hours, 7 days). That means when an address is first blocked, it is blocked
|
|
for 10 minutes and monitored for 1 hour. If the address reappears after the
|
|
first 10 minutes, it is blocked for 1 hour and then monitored for 24 hours, etc.
|
|
|
|
Catch and release adds its own new logfile in addition to the already existing
|
|
ones (netcontrol_catch_release.log):
|
|
|
|
.. btest:: netcontrol-7-catch-release.bro
|
|
|
|
@TEST-EXEC: btest-rst-cmd cat netcontrol_catch_release.log
|
|
|
|
In addition to the blocking function, catch and release comes with the
|
|
:bro:see:`NetControl::get_catch_release_info` function to
|
|
check if an address is already blocked by catch and release (and get information
|
|
about the block). The :bro:see:`NetControl::unblock_address_catch_release`
|
|
function can be used to unblock addresses from catch and release.
|
|
|
|
.. note::
|
|
|
|
Since catch and release does its own connection tracking in addition to the
|
|
tracking used by the NetControl framework, it is not sufficient to remove
|
|
rules that were added by catch and release using :bro:see:`NetControl::remove_rule`.
|
|
You have to use :bro:see:`NetControl::unblock_address_catch_release` in this
|
|
case.
|
|
|
|
.. _framework-netcontrol-plugins:
|
|
|
|
NetControl Plugins
|
|
==================
|
|
|
|
Using the existing plugins
|
|
--------------------------
|
|
|
|
In the API part of the documentation, we exclusively used the debug plugin,
|
|
which simply outputs its actions to the screen. In addition to this debugging
|
|
plugin, Bro ships with a small number of plugins that can be used to interface
|
|
the NetControl framework with your networking hard- and software.
|
|
|
|
The plugins that currently ship with NetControl are:
|
|
|
|
.. list-table::
|
|
:widths: 15 55
|
|
:header-rows: 1
|
|
|
|
* - Plugin name
|
|
- Description
|
|
|
|
* - OpenFlow plugin
|
|
- This is the most fully featured plugin which allows the NetControl
|
|
framework to be interfaced with OpenFlow switches. The source of this
|
|
plugin is contained in :doc:`/scripts/base/frameworks/netcontrol/plugins/openflow.bro`.
|
|
|
|
* - Broker plugin
|
|
- This plugin provides a generic way to send NetControl commands using the
|
|
new Bro communication library (Broker). External programs can receive
|
|
the rules and take action; we provide an example script that calls
|
|
command-line programs triggered by NetControl. The source of this
|
|
plugin is contained in :doc:`/scripts/base/frameworks/netcontrol/plugins/broker.bro`.
|
|
|
|
* - acld plugin
|
|
- This plugin adds support for the acld daemon, which can interface with
|
|
several switches and routers. The current version of acld is available
|
|
from the `LBL ftp server <ftp://ftp.ee.lbl.gov/acld.tar.gz>`_. The source of this
|
|
plugin is contained in :doc:`/scripts/base/frameworks/netcontrol/plugins/acld.bro`.
|
|
|
|
* - PacketFilter plugin
|
|
- This plugin uses the Bro process-level packet filter (see
|
|
:bro:see:`install_src_net_filter` and
|
|
:bro:see:`install_dst_net_filter`). Since the functionality of the
|
|
PacketFilter is limited, this plugin is mostly for demonstration purposes. The source of this
|
|
plugin is contained in :doc:`/scripts/base/frameworks/netcontrol/plugins/packetfilter.bro`.
|
|
|
|
* - Debug plugin
|
|
- The debug plugin simply outputs its action to the standard output. The source of this
|
|
plugin is contained in :doc:`/scripts/base/frameworks/netcontrol/plugins/debug.bro`.
|
|
|
|
Activating plugins
|
|
******************
|
|
|
|
In the API reference part of this document, we already used the debug plugin. To
|
|
use the plugin, we first had to instantiate it by calling
|
|
:bro:see:`NetControl::create_debug` and then add it to NetControl by
|
|
calling :bro:see:`NetControl::activate`.
|
|
|
|
As we already hinted before, NetControl supports having several plugins that are
|
|
active at the same time. The second argument to the `NetControl::activate`
|
|
function is the priority of the backend that was just added. Each rule is sent
|
|
to all plugins in order, from highest priority to lowest priority. The backend
|
|
can then choose if it accepts the rule and pushes it out to the hardware that it
|
|
manages. Or, it can opt to reject the rule. In this case, the NetControl
|
|
framework will try to apply the rule to the backend with the next lower
|
|
priority. If no backend accepts a rule, the rule insertion is marked as failed.
|
|
|
|
The choice if a rule is accepted or rejected stays completely with each plugin.
|
|
The debug plugin we used so far just accepts all rules. However, for other
|
|
plugins you can specify what rules they will accept. Consider, for example, a
|
|
network with two OpenFlow switches. The first switch forwards packets from the
|
|
network to the external world, the second switch sits in front of your Bro
|
|
cluster to provide packet shunting. In this case, you can add two OpenFlow
|
|
backends to NetControl. When you create the instances using
|
|
:bro:see:`NetControl::create_openflow`, you set the `monitor` and `forward`
|
|
attributes of the configuration in :bro:see:`NetControl::OfConfig`
|
|
appropriately. Afterwards, one of the backends will only accept rules for the
|
|
monitor path; the other backend will only accept rules for the forward path.
|
|
|
|
Commonly, plugins also support predicate functions, that allow the user to
|
|
specify restrictions on the rules that they will accept. This can for example be
|
|
used if you have a network where certain switches are responsible for specified
|
|
subnets. The predicate can examine the subnet of the rule and only accept the
|
|
rule if the rule matches the subnet that the specific switch is responsible for.
|
|
|
|
To give an example, the following script adds two backends to NetControl. One
|
|
backend is the NetControl debug backend, which just outputs the rules to the
|
|
console. The second backend is an OpenFlow backend, which uses the OpenFlow
|
|
debug mode that outputs the openflow rules to openflow.log. The OpenFlow
|
|
backend uses a predicate function to only accept rules with a source address in
|
|
the 192.168.17.0/24 network; all other rules will be passed on to the debug
|
|
plugin. We manually block a few addresses in the
|
|
:bro:see:`NetControl::init_done` event to verify the correct functionality.
|
|
|
|
.. btest-include:: ${DOC_ROOT}/frameworks/netcontrol-8-multiple.bro
|
|
|
|
.. btest:: netcontrol-8-multiple.bro
|
|
|
|
@TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/frameworks/netcontrol-8-multiple.bro
|
|
|
|
As you can see, only the single block affecting the 192.168.17.0/24 network is
|
|
output to the command line. The other two lines are handled by the OpenFlow
|
|
plugin. We can verify this by looking at netcontrol.log. The plugin column shows
|
|
which plugin handled a rule and reveals that two rules were handled by OpenFlow:
|
|
|
|
.. btest:: netcontrol-8-multiple.bro
|
|
|
|
@TEST-EXEC: btest-rst-cmd cat netcontrol.log
|
|
|
|
Furthermore, openflow.log also shows the two added rules, converted to OpenFlow
|
|
flow mods:
|
|
|
|
.. btest:: netcontrol-8-multiple.bro
|
|
|
|
@TEST-EXEC: btest-rst-cmd cat openflow.log
|
|
|
|
.. note::
|
|
|
|
You might have asked yourself what happens when you add two or more with the
|
|
same priority. In this case, the rule is sent to all the backends
|
|
simultaneously. This can be useful, for example when you have redundant
|
|
switches that should keep the same rule state.
|
|
|
|
Interfacing with external hardware
|
|
**********************************
|
|
|
|
Now that we know which plugins exist, and how they can be added to NetControl,
|
|
it is time to discuss how we can interface Bro with actual hardware. The typical
|
|
way to accomplish this is to use the Bro communication library (Broker), which
|
|
can be used to exchange Bro events with external programs and scripts. The
|
|
NetControl plugins can use Broker to send events to external programs, which can
|
|
then take action depending on these events.
|
|
|
|
The following figure shows this architecture with the example of the OpenFlow
|
|
plugin. The OpenFlow plugin uses Broker to send events to an external Python
|
|
script, which uses the `Ryu SDN controller <https://osrg.github.io/ryu/>`_ to
|
|
communicate with the Switch.
|
|
|
|
.. figure:: netcontrol-openflow.png
|
|
:width: 600
|
|
:align: center
|
|
:alt: NetControl and OpenFlow architecture.
|
|
:target: ../_images/netcontrol-openflow.png
|
|
|
|
NetControl and OpenFlow architecture (click to enlarge).
|
|
|
|
The Python scripts that are used to interface with the available NetControl
|
|
plugins are contained in the `bro-netcontrol` repository (`github link <https://github.com/bro/bro-netcontrol>`_).
|
|
The repository contains scripts for the OpenFlow as well as the acld plugin.
|
|
Furthermore, it contains a script for the broker plugin which can be used to
|
|
call configureable command-line programs when used with the broker plugin.
|
|
|
|
The repository also contains documentation on how to install these connectors.
|
|
The `netcontrol` directory contains an API that allows you to write your own
|
|
connectors to the broker plugin.
|
|
|
|
.. note::
|
|
|
|
Note that the API of the Broker communication library is not finalized yet.
|
|
You might have to rewrite any scripts for use in future Bro versions.
|
|
|
|
Writing plugins
|
|
---------------
|
|
|
|
In addition to using the plugins that are part of NetControl, you can write your
|
|
own plugins to interface with hard- or software that we currently do not support
|
|
out of the box.
|
|
|
|
Creating your own plugin is easy; besides a bit of boilerplate, you only need to
|
|
create two functions: one that is called when a rule is added, and one that is
|
|
called when a rule is removed. The following script creates a minimal plugin
|
|
that just outputs a rule when it is added or removed. Note that you have to
|
|
raise the :bro:see:`NetControl::rule_added` and
|
|
:bro:see:`NetControl::rule_removed` events in your plugin to let NetControl know
|
|
when a rule was added and removed successfully.
|
|
|
|
.. btest-include:: ${DOC_ROOT}/frameworks/netcontrol-9-skeleton.bro
|
|
|
|
This example is already fully functional and we can use it with a script similar
|
|
to our very first example:
|
|
|
|
.. btest-include:: ${DOC_ROOT}/frameworks/netcontrol-10-use-skeleton.bro
|
|
|
|
.. btest:: netcontrol-9-skeleton.bro
|
|
|
|
@TEST-EXEC: btest-rst-cmd bro -C -r ${TRACES}/tls/ecdhe.pcap ${DOC_ROOT}/frameworks/netcontrol-9-skeleton.bro ${DOC_ROOT}/frameworks/netcontrol-10-use-skeleton.bro
|
|
|
|
If you want to write your own plugins, it will be worthwhile to look at the
|
|
plugins that ship with the NetControl framework to see how they define the
|
|
predicates and interact with Broker.
|