mirror of
https://github.com/zeek/zeek.git
synced 2025-10-06 08:38:20 +00:00
Merge branch 'topic/robin/tunnels-merge'
* topic/robin/tunnels-merge: (51 commits) Updating baselines and NEWS. Remove &synchronized from Tunnel::active table. Refactor of interal tunnel analysis code. Add state management of NetSessions's IP tunnel map. Add "encap_hdr_size" option back in. Script-layer tunnel interface cleanup. Fix performance problem checking packet encapsulation. (addresses #830) Adding a SOCKS test case. Updating DataSeries baselines. Moving my todos over to the tracker ticket. Extend weird names that occur in core packet processing during decapsulation. Add Teredo analysis option to reduce false positive decapsulation. Just some cleanup/documentation of new tunnel-handling code. Memory leak fixes Add a config.h definition for IPPROTO_IPV4. Add AYIYA tunnel decapsulation unit test. Add Teredo-specific events. Refactor some of the NetSessions routines that recurse on IP packets. Add independent options to toggle the different decapsulation methods Add more sanity checks before recursing on encapsulated IP packets. ... Conflicts: src/event.bif
This commit is contained in:
commit
b096168318
93 changed files with 2638 additions and 236 deletions
|
@ -149,3 +149,46 @@ signature dpd_ssl_client {
|
|||
payload /^(\x16\x03[\x00\x01\x02]..\x01...\x03[\x00\x01\x02]|...?\x01[\x00\x01\x02][\x02\x03]).*/
|
||||
tcp-state originator
|
||||
}
|
||||
|
||||
signature dpd_ayiya {
|
||||
ip-proto = udp
|
||||
payload /^..\x11\x29/
|
||||
enable "ayiya"
|
||||
}
|
||||
|
||||
signature dpd_teredo {
|
||||
ip-proto = udp
|
||||
payload /^(\x00\x00)|(\x00\x01)|([\x60-\x6f])/
|
||||
enable "teredo"
|
||||
}
|
||||
|
||||
signature dpd_socks_client {
|
||||
ip-proto == tcp
|
||||
# '32' is a rather arbitrary max length for the user name.
|
||||
payload /^\x04[\x01\x02].{0,32}\x00/
|
||||
tcp-state originator
|
||||
}
|
||||
|
||||
signature dpd_socks_server {
|
||||
ip-proto == tcp
|
||||
requires-reverse-signature dpd_socks_client
|
||||
payload /^\x00[\x5a\x5b\x5c\x5d]/
|
||||
tcp-state responder
|
||||
enable "socks"
|
||||
}
|
||||
|
||||
signature dpd_socks_reverse_client {
|
||||
ip-proto == tcp
|
||||
# '32' is a rather arbitrary max length for the user name.
|
||||
payload /^\x04[\x01\x02].{0,32}\x00/
|
||||
tcp-state responder
|
||||
}
|
||||
|
||||
signature dpd_socks_reverse_server {
|
||||
ip-proto == tcp
|
||||
requires-reverse-signature dpd_socks_client
|
||||
payload /^\x00[\x5a\x5b\x5c\x5d]/
|
||||
tcp-state originator
|
||||
enable "socks"
|
||||
}
|
||||
|
||||
|
|
1
scripts/base/frameworks/tunnels/__load__.bro
Normal file
1
scripts/base/frameworks/tunnels/__load__.bro
Normal file
|
@ -0,0 +1 @@
|
|||
@load ./main
|
145
scripts/base/frameworks/tunnels/main.bro
Normal file
145
scripts/base/frameworks/tunnels/main.bro
Normal file
|
@ -0,0 +1,145 @@
|
|||
##! This script handles the tracking/logging of tunnels (e.g. Teredo,
|
||||
##! AYIYA, or IP-in-IP such as 6to4 where "IP" is either IPv4 or IPv6).
|
||||
##!
|
||||
##! For any connection that occurs over a tunnel, information about its
|
||||
##! encapsulating tunnels is also found in the *tunnel* field of
|
||||
##! :bro:type:`connection`.
|
||||
|
||||
module Tunnel;
|
||||
|
||||
export {
|
||||
## The tunnel logging stream identifier.
|
||||
redef enum Log::ID += { LOG };
|
||||
|
||||
## Types of interesting activity that can occur with a tunnel.
|
||||
type Action: enum {
|
||||
## A new tunnel (encapsulating "connection") has been seen.
|
||||
DISCOVER,
|
||||
## A tunnel connection has closed.
|
||||
CLOSE,
|
||||
## No new connections over a tunnel happened in the amount of
|
||||
## time indicated by :bro:see:`Tunnel::expiration_interval`.
|
||||
EXPIRE,
|
||||
};
|
||||
|
||||
## The record type which contains column fields of the tunnel log.
|
||||
type Info: record {
|
||||
## Time at which some tunnel activity occurred.
|
||||
ts: time &log;
|
||||
## The unique identifier for the tunnel, which may correspond
|
||||
## to a :bro:type:`connection`'s *uid* field for non-IP-in-IP tunnels.
|
||||
uid: string &log;
|
||||
## The tunnel "connection" 4-tuple of endpoint addresses/ports.
|
||||
## For an IP tunnel, the ports will be 0.
|
||||
id: conn_id &log;
|
||||
## The type of activity that occurred.
|
||||
action: Action &log;
|
||||
## The type of tunnel.
|
||||
tunnel_type: Tunnel::Type &log;
|
||||
};
|
||||
|
||||
## Logs all tunnels in an ecapsulation chain with action
|
||||
## :bro:see:`Tunnel::DISCOVER` that aren't already in the
|
||||
## :bro:id:`Tunnel::active` table and adds them if not.
|
||||
global register_all: function(ecv: EncapsulatingConnVector);
|
||||
|
||||
## Logs a single tunnel "connection" with action
|
||||
## :bro:see:`Tunnel::DISCOVER` if it's not already in the
|
||||
## :bro:id:`Tunnel::active` table and adds it if not.
|
||||
global register: function(ec: EncapsulatingConn);
|
||||
|
||||
## Logs a single tunnel "connection" with action
|
||||
## :bro:see:`Tunnel::EXPIRE` and removes it from the
|
||||
## :bro:id:`Tunnel::active` table.
|
||||
##
|
||||
## t: A table of tunnels.
|
||||
##
|
||||
## idx: The index of the tunnel table corresponding to the tunnel to expire.
|
||||
##
|
||||
## Returns: 0secs, which when this function is used as an
|
||||
## :bro:attr:`&expire_func`, indicates to remove the element at
|
||||
## *idx* immediately.
|
||||
global expire: function(t: table[conn_id] of Info, idx: conn_id): interval;
|
||||
|
||||
## Removes a single tunnel from the :bro:id:`Tunnel::active` table
|
||||
## and logs the closing/expiration of the tunnel.
|
||||
##
|
||||
## tunnel: The tunnel which has closed or expired.
|
||||
##
|
||||
## action: The specific reason for the tunnel ending.
|
||||
global close: function(tunnel: Info, action: Action);
|
||||
|
||||
## The amount of time a tunnel is not used in establishment of new
|
||||
## connections before it is considered inactive/expired.
|
||||
const expiration_interval = 24hrs &redef;
|
||||
|
||||
## Currently active tunnels. That is, tunnels for which new, encapsulated
|
||||
## connections have been seen in the interval indicated by
|
||||
## :bro:see:`Tunnel::expiration_interval`.
|
||||
global active: table[conn_id] of Info = table() &read_expire=expiration_interval &expire_func=expire;
|
||||
}
|
||||
|
||||
const ayiya_ports = { 5072/udp };
|
||||
redef dpd_config += { [ANALYZER_AYIYA] = [$ports = ayiya_ports] };
|
||||
|
||||
const teredo_ports = { 3544/udp };
|
||||
redef dpd_config += { [ANALYZER_TEREDO] = [$ports = teredo_ports] };
|
||||
|
||||
redef likely_server_ports += { ayiya_ports, teredo_ports };
|
||||
|
||||
event bro_init() &priority=5
|
||||
{
|
||||
Log::create_stream(Tunnel::LOG, [$columns=Info]);
|
||||
}
|
||||
|
||||
function register_all(ecv: EncapsulatingConnVector)
|
||||
{
|
||||
for ( i in ecv )
|
||||
register(ecv[i]);
|
||||
}
|
||||
|
||||
function register(ec: EncapsulatingConn)
|
||||
{
|
||||
if ( ec$cid !in active )
|
||||
{
|
||||
local tunnel: Info;
|
||||
tunnel$ts = network_time();
|
||||
tunnel$uid = ec$uid;
|
||||
tunnel$id = ec$cid;
|
||||
tunnel$action = DISCOVER;
|
||||
tunnel$tunnel_type = ec$tunnel_type;
|
||||
active[ec$cid] = tunnel;
|
||||
Log::write(LOG, tunnel);
|
||||
}
|
||||
}
|
||||
|
||||
function close(tunnel: Info, action: Action)
|
||||
{
|
||||
tunnel$action = action;
|
||||
tunnel$ts = network_time();
|
||||
Log::write(LOG, tunnel);
|
||||
delete active[tunnel$id];
|
||||
}
|
||||
|
||||
function expire(t: table[conn_id] of Info, idx: conn_id): interval
|
||||
{
|
||||
close(t[idx], EXPIRE);
|
||||
return 0secs;
|
||||
}
|
||||
|
||||
event new_connection(c: connection) &priority=5
|
||||
{
|
||||
if ( c?$tunnel )
|
||||
register_all(c$tunnel);
|
||||
}
|
||||
|
||||
event tunnel_changed(c: connection, e: EncapsulatingConnVector) &priority=5
|
||||
{
|
||||
register_all(e);
|
||||
}
|
||||
|
||||
event connection_state_remove(c: connection) &priority=-5
|
||||
{
|
||||
if ( c$id in active )
|
||||
close(active[c$id], CLOSE);
|
||||
}
|
|
@ -178,6 +178,32 @@ type endpoint_stats: record {
|
|||
## use ``count``. That should be changed.
|
||||
type AnalyzerID: count;
|
||||
|
||||
module Tunnel;
|
||||
export {
|
||||
## Records the identity of an encapsulating parent of a tunneled connection.
|
||||
type EncapsulatingConn: record {
|
||||
## The 4-tuple of the encapsulating "connection". In case of an IP-in-IP
|
||||
## tunnel the ports will be set to 0. The direction (i.e., orig and
|
||||
## resp) are set according to the first tunneled packet seen
|
||||
## and not according to the side that established the tunnel.
|
||||
cid: conn_id;
|
||||
## The type of tunnel.
|
||||
tunnel_type: Tunnel::Type;
|
||||
## A globally unique identifier that, for non-IP-in-IP tunnels,
|
||||
## cross-references the *uid* field of :bro:type:`connection`.
|
||||
uid: string;
|
||||
} &log;
|
||||
} # end export
|
||||
module GLOBAL;
|
||||
|
||||
## A type alias for a vector of encapsulating "connections", i.e for when
|
||||
## there are tunnels within tunnels.
|
||||
##
|
||||
## .. todo:: We need this type definition only for declaring builtin functions
|
||||
## via ``bifcl``. We should extend ``bifcl`` to understand composite types
|
||||
## directly and then remove this alias.
|
||||
type EncapsulatingConnVector: vector of Tunnel::EncapsulatingConn;
|
||||
|
||||
## Statistics about a :bro:type:`connection` endpoint.
|
||||
##
|
||||
## .. bro:see:: connection
|
||||
|
@ -199,10 +225,10 @@ type endpoint: record {
|
|||
flow_label: count;
|
||||
};
|
||||
|
||||
# A connection. This is Bro's basic connection type describing IP- and
|
||||
# transport-layer information about the conversation. Note that Bro uses a
|
||||
# liberal interpreation of "connection" and associates instances of this type
|
||||
# also with UDP and ICMP flows.
|
||||
## A connection. This is Bro's basic connection type describing IP- and
|
||||
## transport-layer information about the conversation. Note that Bro uses a
|
||||
## liberal interpreation of "connection" and associates instances of this type
|
||||
## also with UDP and ICMP flows.
|
||||
type connection: record {
|
||||
id: conn_id; ##< The connection's identifying 4-tuple.
|
||||
orig: endpoint; ##< Statistics about originator side.
|
||||
|
@ -227,6 +253,12 @@ type connection: record {
|
|||
## that is very likely unique across independent Bro runs. These IDs can thus be
|
||||
## used to tag and locate information associated with that connection.
|
||||
uid: string;
|
||||
## If the connection is tunneled, this field contains information about
|
||||
## the encapsulating "connection(s)" with the outermost one starting
|
||||
## at index zero. It's also always the first such enapsulation seen
|
||||
## for the connection unless the :bro:id:`tunnel_changed` event is handled
|
||||
## and re-assigns this field to the new encapsulation.
|
||||
tunnel: EncapsulatingConnVector &optional;
|
||||
};
|
||||
|
||||
## Fields of a SYN packet.
|
||||
|
@ -884,18 +916,9 @@ const frag_timeout = 0.0 sec &redef;
|
|||
const packet_sort_window = 0 usecs &redef;
|
||||
|
||||
## If positive, indicates the encapsulation header size that should
|
||||
## be skipped. This either applies to all packets, or if
|
||||
## :bro:see:`tunnel_port` is set, only to packets on that port.
|
||||
##
|
||||
## .. :bro:see:: tunnel_port
|
||||
## be skipped. This applies to all packets.
|
||||
const encap_hdr_size = 0 &redef;
|
||||
|
||||
## A UDP port that specifies which connections to apply :bro:see:`encap_hdr_size`
|
||||
## to.
|
||||
##
|
||||
## .. :bro:see:: encap_hdr_size
|
||||
const tunnel_port = 0/udp &redef;
|
||||
|
||||
## Whether to use the ``ConnSize`` analyzer to count the number of packets and
|
||||
## IP-level bytes transfered by each endpoint. If true, these values are returned
|
||||
## in the connection's :bro:see:`endpoint` record value.
|
||||
|
@ -1250,7 +1273,7 @@ type ip6_ext_hdr: record {
|
|||
mobility: ip6_mobility_hdr &optional;
|
||||
};
|
||||
|
||||
## A type alias for a vector of IPv6 extension headers
|
||||
## A type alias for a vector of IPv6 extension headers.
|
||||
type ip6_ext_hdr_chain: vector of ip6_ext_hdr;
|
||||
|
||||
## Values extracted from an IPv6 header.
|
||||
|
@ -1336,6 +1359,42 @@ type pkt_hdr: record {
|
|||
icmp: icmp_hdr &optional; ##< The ICMP header if an ICMP packet.
|
||||
};
|
||||
|
||||
## A Teredo origin indication header. See :rfc:`4380` for more information
|
||||
## about the Teredo protocol.
|
||||
##
|
||||
## .. bro:see:: teredo_bubble teredo_origin_indication teredo_authentication
|
||||
## teredo_hdr
|
||||
type teredo_auth: record {
|
||||
id: string; ##< Teredo client identifier.
|
||||
value: string; ##< HMAC-SHA1 over shared secret key between client and
|
||||
##< server, nonce, confirmation byte, origin indication
|
||||
##< (if present), and the IPv6 packet.
|
||||
nonce: count; ##< Nonce chosen by Teredo client to be repeated by
|
||||
##< Teredo server.
|
||||
confirm: count; ##< Confirmation byte to be set to 0 by Teredo client
|
||||
##< and non-zero by server if client needs new key.
|
||||
};
|
||||
|
||||
## A Teredo authentication header. See :rfc:`4380` for more information
|
||||
## about the Teredo protocol.
|
||||
##
|
||||
## .. bro:see:: teredo_bubble teredo_origin_indication teredo_authentication
|
||||
## teredo_hdr
|
||||
type teredo_origin: record {
|
||||
p: port; ##< Unobfuscated UDP port of Teredo client.
|
||||
a: addr; ##< Unobfuscated IPv4 address of Teredo client.
|
||||
};
|
||||
|
||||
## A Teredo packet header. See :rfc:`4380` for more information about the
|
||||
## Teredo protocol.
|
||||
##
|
||||
## .. bro:see:: teredo_bubble teredo_origin_indication teredo_authentication
|
||||
type teredo_hdr: record {
|
||||
auth: teredo_auth &optional; ##< Teredo authentication header.
|
||||
origin: teredo_origin &optional; ##< Teredo origin indication header.
|
||||
hdr: pkt_hdr; ##< IPv6 and transport protocol headers.
|
||||
};
|
||||
|
||||
## Definition of "secondary filters". A secondary filter is a BPF filter given as
|
||||
## index in this table. For each such filter, the corresponding event is raised for
|
||||
## all matching packets.
|
||||
|
@ -2636,11 +2695,33 @@ const record_all_packets = F &redef;
|
|||
## .. bro:see:: conn_stats
|
||||
const ignore_keep_alive_rexmit = F &redef;
|
||||
|
||||
## Whether the analysis engine parses IP packets encapsulated in
|
||||
## UDP tunnels.
|
||||
##
|
||||
## .. bro:see:: tunnel_port
|
||||
const parse_udp_tunnels = F &redef;
|
||||
module Tunnel;
|
||||
export {
|
||||
## The maximum depth of a tunnel to decapsulate until giving up.
|
||||
## Setting this to zero will disable all types of tunnel decapsulation.
|
||||
const max_depth: count = 2 &redef;
|
||||
|
||||
## Toggle whether to do IPv{4,6}-in-IPv{4,6} decapsulation.
|
||||
const enable_ip = T &redef;
|
||||
|
||||
## Toggle whether to do IPv{4,6}-in-AYIYA decapsulation.
|
||||
const enable_ayiya = T &redef;
|
||||
|
||||
## Toggle whether to do IPv6-in-Teredo decapsulation.
|
||||
const enable_teredo = T &redef;
|
||||
|
||||
## With this option set, the Teredo analysis will first check to see if
|
||||
## other protocol analyzers have confirmed that they think they're
|
||||
## parsing the right protocol and only continue with Teredo tunnel
|
||||
## decapsulation if nothing else has yet confirmed. This can help
|
||||
## reduce false positives of UDP traffic (e.g. DNS) that also happens
|
||||
## to have a valid Teredo encapsulation.
|
||||
const yielding_teredo_decapsulation = T &redef;
|
||||
|
||||
## How often to cleanup internal state for inactive IP tunnels.
|
||||
const ip_tunnel_timeout = 24hrs &redef;
|
||||
} # end export
|
||||
module GLOBAL;
|
||||
|
||||
## Number of bytes per packet to capture from live interfaces.
|
||||
const snaplen = 8192 &redef;
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
@load base/frameworks/metrics
|
||||
@load base/frameworks/intel
|
||||
@load base/frameworks/reporter
|
||||
@load base/frameworks/tunnels
|
||||
|
||||
@load base/protocols/conn
|
||||
@load base/protocols/dns
|
||||
|
@ -36,6 +37,7 @@
|
|||
@load base/protocols/http
|
||||
@load base/protocols/irc
|
||||
@load base/protocols/smtp
|
||||
@load base/protocols/socks
|
||||
@load base/protocols/ssh
|
||||
@load base/protocols/ssl
|
||||
@load base/protocols/syslog
|
||||
|
|
|
@ -101,6 +101,10 @@ export {
|
|||
resp_pkts: count &log &optional;
|
||||
## Number IP level bytes the responder sent. See ``orig_pkts``.
|
||||
resp_ip_bytes: count &log &optional;
|
||||
## If this connection was over a tunnel, indicate the
|
||||
## *uid* values for any encapsulating parent connections
|
||||
## used over the lifetime of this inner connection.
|
||||
tunnel_parents: set[string] &log;
|
||||
};
|
||||
|
||||
## Event that can be handled to access the :bro:type:`Conn::Info`
|
||||
|
@ -190,6 +194,8 @@ function set_conn(c: connection, eoc: bool)
|
|||
c$conn$ts=c$start_time;
|
||||
c$conn$uid=c$uid;
|
||||
c$conn$id=c$id;
|
||||
if ( c?$tunnel && |c$tunnel| > 0 )
|
||||
add c$conn$tunnel_parents[c$tunnel[|c$tunnel|-1]$uid];
|
||||
c$conn$proto=get_port_transport_proto(c$id$resp_p);
|
||||
if( |Site::local_nets| > 0 )
|
||||
c$conn$local_orig=Site::is_local_addr(c$id$orig_h);
|
||||
|
@ -227,6 +233,14 @@ event content_gap(c: connection, is_orig: bool, seq: count, length: count) &prio
|
|||
|
||||
c$conn$missed_bytes = c$conn$missed_bytes + length;
|
||||
}
|
||||
|
||||
event tunnel_changed(c: connection, e: EncapsulatingConnVector) &priority=5
|
||||
{
|
||||
set_conn(c, F);
|
||||
if ( |e| > 0 )
|
||||
add c$conn$tunnel_parents[e[|e|-1]$uid];
|
||||
c$tunnel = e;
|
||||
}
|
||||
|
||||
event connection_state_remove(c: connection) &priority=5
|
||||
{
|
||||
|
|
1
scripts/base/protocols/socks/__load__.bro
Normal file
1
scripts/base/protocols/socks/__load__.bro
Normal file
|
@ -0,0 +1 @@
|
|||
@load ./main
|
15
scripts/base/protocols/socks/main.bro
Normal file
15
scripts/base/protocols/socks/main.bro
Normal file
|
@ -0,0 +1,15 @@
|
|||
@load base/frameworks/tunnels
|
||||
|
||||
module SOCKS;
|
||||
|
||||
export {
|
||||
type RequestType: enum {
|
||||
CONNECTION = 1,
|
||||
PORT = 2,
|
||||
};
|
||||
}
|
||||
|
||||
event socks_request(c: connection, request_type: count, dstaddr: addr, dstname: string, p: port, user: string)
|
||||
{
|
||||
Tunnel::register([$cid=c$id, $tunnel_type=Tunnel::SOCKS, $uid=c$uid]);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue