mirror of
https://github.com/zeek/zeek.git
synced 2025-10-12 11:38:20 +00:00

Also fix header truncation check for IPv6 No Next header and add an "ipv6_no_next" weird for such packets that aren't tunneled over Teredo (which it calls "bubbles" and are used to create mappings in NATs).
142 lines
4.1 KiB
Text
142 lines
4.1 KiB
Text
##! 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
|
|
##! 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 past day.
|
|
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;
|
|
user: string &log &optional;
|
|
};
|
|
|
|
## 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);
|
|
|
|
## Currently active tunnels. That is, tunnels for which new, encapsulated
|
|
## connections have been seen in the last day.
|
|
global active: table[conn_id] of Info = table() &synchronized &read_expire=24hrs &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
|
|
{
|
|
if ( c?$tunnel )
|
|
register_all(c$tunnel);
|
|
register_all(e);
|
|
}
|
|
|
|
event connection_state_remove(c: connection) &priority=-5
|
|
{
|
|
if ( c$id in active )
|
|
close(active[c$id], CLOSE);
|
|
}
|