mirror of
https://github.com/zeek/zeek.git
synced 2025-10-04 07:38:19 +00:00
Adding support to de-capsulate tunnels.
Checkpoint. Decapsulation happens after IP Defragmentation. The "identity" of the enclosing tunnel (the "parent") is added to the connection record of the child (tunneled) connection as an optional field $tunnel_parent.
This commit is contained in:
parent
6c806b0bce
commit
9c388a1809
10 changed files with 183 additions and 17 deletions
|
@ -81,6 +81,11 @@ type endpoint_stats: record {
|
||||||
|
|
||||||
type AnalyzerID: count;
|
type AnalyzerID: count;
|
||||||
|
|
||||||
|
type tunnel_parent_t: record {
|
||||||
|
cid: conn_id;
|
||||||
|
tunnel_type: tunneltype_t;
|
||||||
|
};
|
||||||
|
|
||||||
type connection: record {
|
type connection: record {
|
||||||
id: conn_id;
|
id: conn_id;
|
||||||
orig: endpoint;
|
orig: endpoint;
|
||||||
|
@ -92,6 +97,7 @@ type connection: record {
|
||||||
hot: count; # how hot; 0 = don't know or not hot
|
hot: count; # how hot; 0 = don't know or not hot
|
||||||
history: string;
|
history: string;
|
||||||
uid: string;
|
uid: string;
|
||||||
|
tunnel_parent: tunnel_parent_t &optional;
|
||||||
};
|
};
|
||||||
|
|
||||||
type SYN_packet: record {
|
type SYN_packet: record {
|
||||||
|
|
|
@ -388,6 +388,7 @@ set(bro_SRCS
|
||||||
Timer.cc
|
Timer.cc
|
||||||
Traverse.cc
|
Traverse.cc
|
||||||
Trigger.cc
|
Trigger.cc
|
||||||
|
TunnelHandler.cc
|
||||||
Type.cc
|
Type.cc
|
||||||
UDP.cc
|
UDP.cc
|
||||||
Val.cc
|
Val.cc
|
||||||
|
|
|
@ -139,7 +139,7 @@ unsigned int Connection::external_connections = 0;
|
||||||
|
|
||||||
IMPLEMENT_SERIAL(Connection, SER_CONNECTION);
|
IMPLEMENT_SERIAL(Connection, SER_CONNECTION);
|
||||||
|
|
||||||
Connection::Connection(NetSessions* s, HashKey* k, double t, const ConnID* id)
|
Connection::Connection(NetSessions* s, HashKey* k, double t, const ConnID* id, RecordVal *arg_tunnel_parent)
|
||||||
{
|
{
|
||||||
sessions = s;
|
sessions = s;
|
||||||
key = k;
|
key = k;
|
||||||
|
@ -183,6 +183,8 @@ Connection::Connection(NetSessions* s, HashKey* k, double t, const ConnID* id)
|
||||||
|
|
||||||
uid = 0; // Will set later.
|
uid = 0; // Will set later.
|
||||||
|
|
||||||
|
tunnel_parent = arg_tunnel_parent;
|
||||||
|
|
||||||
if ( conn_timer_mgr )
|
if ( conn_timer_mgr )
|
||||||
{
|
{
|
||||||
++external_connections;
|
++external_connections;
|
||||||
|
@ -370,6 +372,7 @@ RecordVal* Connection::BuildConnVal()
|
||||||
|
|
||||||
char tmp[20];
|
char tmp[20];
|
||||||
conn_val->Assign(9, new StringVal(uitoa_n(uid, tmp, sizeof(tmp), 62)));
|
conn_val->Assign(9, new StringVal(uitoa_n(uid, tmp, sizeof(tmp), 62)));
|
||||||
|
conn_val->Assign(10, tunnel_parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( root_analyzer )
|
if ( root_analyzer )
|
||||||
|
|
|
@ -86,7 +86,7 @@ class Analyzer;
|
||||||
|
|
||||||
class Connection : public BroObj {
|
class Connection : public BroObj {
|
||||||
public:
|
public:
|
||||||
Connection(NetSessions* s, HashKey* k, double t, const ConnID* id);
|
Connection(NetSessions* s, HashKey* k, double t, const ConnID* id, RecordVal *arg_tunnel_parent);
|
||||||
virtual ~Connection();
|
virtual ~Connection();
|
||||||
|
|
||||||
// Invoked when connection is about to be removed. Use Ref(this)
|
// Invoked when connection is about to be removed. Use Ref(this)
|
||||||
|
@ -335,6 +335,7 @@ protected:
|
||||||
double inactivity_timeout;
|
double inactivity_timeout;
|
||||||
RecordVal* conn_val;
|
RecordVal* conn_val;
|
||||||
LoginConn* login_conn; // either nil, or this
|
LoginConn* login_conn; // either nil, or this
|
||||||
|
RecordVal* tunnel_parent; // nil if not tunneled
|
||||||
int suppress_event; // suppress certain events to once per conn.
|
int suppress_event; // suppress certain events to once per conn.
|
||||||
|
|
||||||
unsigned int installed_status_timer:1;
|
unsigned int installed_status_timer:1;
|
||||||
|
|
|
@ -521,7 +521,7 @@ Connection* ConnCompressor::Instantiate(HashKey* key, PendingConn* pending)
|
||||||
// Fake the first packet.
|
// Fake the first packet.
|
||||||
const IP_Hdr* faked_pkt = PendingConnToPacket(pending);
|
const IP_Hdr* faked_pkt = PendingConnToPacket(pending);
|
||||||
Connection* new_conn = sessions->NewConn(key, pending->time, &conn_id,
|
Connection* new_conn = sessions->NewConn(key, pending->time, &conn_id,
|
||||||
faked_pkt->Payload(), IPPROTO_TCP);
|
faked_pkt->Payload(), IPPROTO_TCP, 0);
|
||||||
|
|
||||||
if ( ! new_conn )
|
if ( ! new_conn )
|
||||||
{
|
{
|
||||||
|
@ -574,7 +574,7 @@ Connection* ConnCompressor::Instantiate(double t, HashKey* key,
|
||||||
conn_id.dst_port = tp->th_dport;
|
conn_id.dst_port = tp->th_dport;
|
||||||
|
|
||||||
Connection* new_conn =
|
Connection* new_conn =
|
||||||
sessions->NewConn(key, t, &conn_id, ip->Payload(), IPPROTO_TCP);
|
sessions->NewConn(key, t, &conn_id, ip->Payload(), IPPROTO_TCP, 0);
|
||||||
|
|
||||||
if ( ! new_conn )
|
if ( ! new_conn )
|
||||||
{
|
{
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include "DPM.h"
|
#include "DPM.h"
|
||||||
|
|
||||||
#include "PacketSort.h"
|
#include "PacketSort.h"
|
||||||
|
#include "TunnelHandler.h"
|
||||||
|
|
||||||
// These represent NetBIOS services on ephemeral ports. They're numbered
|
// These represent NetBIOS services on ephemeral ports. They're numbered
|
||||||
// so that we can use a single int to hold either an actual TCP/UDP server
|
// so that we can use a single int to hold either an actual TCP/UDP server
|
||||||
|
@ -128,6 +129,12 @@ NetSessions::NetSessions()
|
||||||
arp_analyzer = new ARP_Analyzer();
|
arp_analyzer = new ARP_Analyzer();
|
||||||
else
|
else
|
||||||
arp_analyzer = 0;
|
arp_analyzer = 0;
|
||||||
|
|
||||||
|
|
||||||
|
if ( 1 )
|
||||||
|
tunnel_handler = new TunnelHandler(this);
|
||||||
|
else
|
||||||
|
tunnel_handler = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetSessions::~NetSessions()
|
NetSessions::~NetSessions()
|
||||||
|
@ -433,14 +440,6 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr,
|
||||||
if ( discarder && discarder->NextPacket(ip_hdr, len, caplen) )
|
if ( discarder && discarder->NextPacket(ip_hdr, len, caplen) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int proto = ip_hdr->NextProto();
|
|
||||||
if ( proto != IPPROTO_TCP && proto != IPPROTO_UDP &&
|
|
||||||
proto != IPPROTO_ICMP )
|
|
||||||
{
|
|
||||||
dump_this_packet = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
FragReassembler* f = 0;
|
FragReassembler* f = 0;
|
||||||
uint32 frag_field = ip_hdr->FragField();
|
uint32 frag_field = ip_hdr->FragField();
|
||||||
|
|
||||||
|
@ -474,6 +473,23 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TunnelInfo *tunnel_info = tunnel_handler->DecapsulateTunnel(ip_hdr, len, caplen, hdr, pkt);
|
||||||
|
if (tunnel_info)
|
||||||
|
{
|
||||||
|
ip4 = tunnel_info->child->IP4_Hdr();
|
||||||
|
ip_hdr = tunnel_info->child;
|
||||||
|
len -= tunnel_info->hdr_len;
|
||||||
|
caplen -= tunnel_info->hdr_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int proto = ip_hdr->NextProto();
|
||||||
|
if ( proto != IPPROTO_TCP && proto != IPPROTO_UDP &&
|
||||||
|
proto != IPPROTO_ICMP )
|
||||||
|
{
|
||||||
|
dump_this_packet = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
len -= ip_hdr_len; // remove IP header
|
len -= ip_hdr_len; // remove IP header
|
||||||
caplen -= ip_hdr_len;
|
caplen -= ip_hdr_len;
|
||||||
|
|
||||||
|
@ -561,7 +577,7 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr,
|
||||||
conn = (Connection*) d->Lookup(h);
|
conn = (Connection*) d->Lookup(h);
|
||||||
if ( ! conn )
|
if ( ! conn )
|
||||||
{
|
{
|
||||||
conn = NewConn(h, t, &id, data, proto);
|
conn = NewConn(h, t, &id, data, proto, tunnel_info);
|
||||||
if ( conn )
|
if ( conn )
|
||||||
d->Insert(h, conn);
|
d->Insert(h, conn);
|
||||||
}
|
}
|
||||||
|
@ -581,7 +597,7 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr,
|
||||||
conn->Event(connection_reused, 0);
|
conn->Event(connection_reused, 0);
|
||||||
|
|
||||||
Remove(conn);
|
Remove(conn);
|
||||||
conn = NewConn(h, t, &id, data, proto);
|
conn = NewConn(h, t, &id, data, proto, tunnel_info);
|
||||||
if ( conn )
|
if ( conn )
|
||||||
d->Insert(h, conn);
|
d->Insert(h, conn);
|
||||||
}
|
}
|
||||||
|
@ -609,6 +625,8 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr,
|
||||||
record_packet, record_content,
|
record_packet, record_content,
|
||||||
hdr, pkt, hdr_size);
|
hdr, pkt, hdr_size);
|
||||||
|
|
||||||
|
if ( tunnel_info )
|
||||||
|
delete tunnel_info;
|
||||||
if ( f )
|
if ( f )
|
||||||
{
|
{
|
||||||
// Above we already recorded the fragment in its entirety.
|
// Above we already recorded the fragment in its entirety.
|
||||||
|
@ -1045,13 +1063,17 @@ void NetSessions::GetStats(SessionStats& s) const
|
||||||
}
|
}
|
||||||
|
|
||||||
Connection* NetSessions::NewConn(HashKey* k, double t, const ConnID* id,
|
Connection* NetSessions::NewConn(HashKey* k, double t, const ConnID* id,
|
||||||
const u_char* data, int proto)
|
const u_char* data, int proto, TunnelInfo* tunnel_info)
|
||||||
{
|
{
|
||||||
// FIXME: This should be cleaned up a bit, it's too protocol-specific.
|
// FIXME: This should be cleaned up a bit, it's too protocol-specific.
|
||||||
// But I'm not yet sure what the right abstraction for these things is.
|
// But I'm not yet sure what the right abstraction for these things is.
|
||||||
int src_h = ntohs(id->src_port);
|
int src_h = ntohs(id->src_port);
|
||||||
int dst_h = ntohs(id->dst_port);
|
int dst_h = ntohs(id->dst_port);
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
|
RecordVal *tunnel_parent = 0;
|
||||||
|
|
||||||
|
if ( tunnel_info )
|
||||||
|
tunnel_parent = tunnel_info->GetRecordVal();
|
||||||
|
|
||||||
// Hmm... This is not great.
|
// Hmm... This is not great.
|
||||||
TransportProto tproto;
|
TransportProto tproto;
|
||||||
|
@ -1098,7 +1120,7 @@ Connection* NetSessions::NewConn(HashKey* k, double t, const ConnID* id,
|
||||||
id = &flip_id;
|
id = &flip_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
Connection* conn = new Connection(this, k, t, id);
|
Connection* conn = new Connection(this, k, t, id, tunnel_parent);
|
||||||
conn->SetTransport(tproto);
|
conn->SetTransport(tproto);
|
||||||
dpm->BuildInitialAnalyzerTree(tproto, conn, data);
|
dpm->BuildInitialAnalyzerTree(tproto, conn, data);
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,9 @@ class Discarder;
|
||||||
class SteppingStoneManager;
|
class SteppingStoneManager;
|
||||||
class PacketFilter;
|
class PacketFilter;
|
||||||
|
|
||||||
|
class TunnelHandler;
|
||||||
|
class TunnelInfo;
|
||||||
|
|
||||||
class PacketSortElement;
|
class PacketSortElement;
|
||||||
|
|
||||||
struct SessionStats {
|
struct SessionStats {
|
||||||
|
@ -144,7 +147,7 @@ protected:
|
||||||
friend class TimerMgrExpireTimer;
|
friend class TimerMgrExpireTimer;
|
||||||
|
|
||||||
Connection* NewConn(HashKey* k, double t, const ConnID* id,
|
Connection* NewConn(HashKey* k, double t, const ConnID* id,
|
||||||
const u_char* data, int proto);
|
const u_char* data, int proto, TunnelInfo *tunnel_info);
|
||||||
|
|
||||||
// Check whether the tag of the current packet is consistent with
|
// Check whether the tag of the current packet is consistent with
|
||||||
// the given connection. Returns:
|
// the given connection. Returns:
|
||||||
|
@ -214,6 +217,8 @@ protected:
|
||||||
int num_packets_processed;
|
int num_packets_processed;
|
||||||
PacketProfiler* pkt_profiler;
|
PacketProfiler* pkt_profiler;
|
||||||
|
|
||||||
|
TunnelHandler *tunnel_handler;
|
||||||
|
|
||||||
// We may use independent timer managers for different sets of related
|
// We may use independent timer managers for different sets of related
|
||||||
// activity. The managers are identified by an unique tag.
|
// activity. The managers are identified by an unique tag.
|
||||||
typedef std::map<TimerMgr::Tag, TimerMgr*> TimerMgrMap;
|
typedef std::map<TimerMgr::Tag, TimerMgr*> TimerMgrMap;
|
||||||
|
|
48
src/TunnelHandler.cc
Normal file
48
src/TunnelHandler.cc
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
// $Id: Sessions.cc 7075 2010-09-13 02:39:38Z vern $
|
||||||
|
//
|
||||||
|
// See the file "COPYING" in the main distribution directory for copyright.
|
||||||
|
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "TunnelHandler.h"
|
||||||
|
#include "Conn.h"
|
||||||
|
#include "Sessions.h"
|
||||||
|
|
||||||
|
|
||||||
|
TunnelHandler::TunnelHandler(NetSessions *arg_s)
|
||||||
|
{
|
||||||
|
s = arg_s;
|
||||||
|
}
|
||||||
|
|
||||||
|
TunnelInfo* TunnelHandler::DecapsulateTunnel(const IP_Hdr *ip_hdr, int len, int caplen,
|
||||||
|
const struct pcap_pkthdr* hdr, const u_char* const pkt)
|
||||||
|
{
|
||||||
|
TunnelInfo *tunnel_info = 0;
|
||||||
|
switch (ip_hdr->NextProto()) {
|
||||||
|
#ifdef BROv6
|
||||||
|
case IPPROTO_IPV6: /* 6in4 and 6to4 */
|
||||||
|
if (len < (int)sizeof(struct ip6_hdr) || caplen < (int)sizeof(struct ip6_hdr))
|
||||||
|
{
|
||||||
|
s->Weird("truncated_header", hdr, pkt);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// TODO: check if IP6 header makes sense
|
||||||
|
tunnel_info = new TunnelInfo();
|
||||||
|
tunnel_info->child = new IP_Hdr((const struct ip6_hdr*)ip_hdr->Payload());
|
||||||
|
tunnel_info->tunneltype = BifEnum::IP6inIP;
|
||||||
|
tunnel_info->hdr_len = ip_hdr->HdrLen();
|
||||||
|
tunnel_info->SetParentIPs(ip_hdr);
|
||||||
|
return tunnel_info;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
} /* end switch */
|
||||||
|
return 0;
|
||||||
|
}
|
73
src/TunnelHandler.h
Normal file
73
src/TunnelHandler.h
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
// See the file "COPYING" in the main distribution directory for copyright.
|
||||||
|
|
||||||
|
#ifndef tunnelhandler_h
|
||||||
|
#define tunnelhandler_h
|
||||||
|
|
||||||
|
#include "IP.h"
|
||||||
|
#include "Conn.h"
|
||||||
|
#include "Sessions.h"
|
||||||
|
#include "Val.h"
|
||||||
|
|
||||||
|
|
||||||
|
class TunnelInfo {
|
||||||
|
public:
|
||||||
|
TunnelInfo()
|
||||||
|
{
|
||||||
|
child = 0;
|
||||||
|
tunneltype = BifEnum::NONE;
|
||||||
|
hdr_len = 0;
|
||||||
|
parent.src_addr = parent.dst_addr = 0;
|
||||||
|
parent.src_port = parent.dst_port = 0;
|
||||||
|
parent.is_one_way = 0;
|
||||||
|
}
|
||||||
|
~TunnelInfo()
|
||||||
|
{
|
||||||
|
if (child) delete child;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetParentIPs(const IP_Hdr *ip_hdr)
|
||||||
|
{
|
||||||
|
parent.src_addr = ip_hdr->SrcAddr();
|
||||||
|
parent.dst_addr = ip_hdr->DstAddr();
|
||||||
|
}
|
||||||
|
void SetParentPorts(uint32 src_port, uint32 dst_port)
|
||||||
|
{
|
||||||
|
parent.src_port = src_port;
|
||||||
|
parent.dst_port = dst_port;
|
||||||
|
}
|
||||||
|
|
||||||
|
RecordVal* GetRecordVal() const
|
||||||
|
{
|
||||||
|
RecordVal *rv = new RecordVal(BifType::Record::tunnel_parent_t);
|
||||||
|
|
||||||
|
RecordVal* id_val = new RecordVal(conn_id);
|
||||||
|
id_val->Assign(0, new AddrVal(parent.src_addr));
|
||||||
|
id_val->Assign(1, new PortVal(ntohs(parent.src_port), TRANSPORT_UNKNOWN));
|
||||||
|
id_val->Assign(2, new AddrVal(parent.dst_addr));
|
||||||
|
id_val->Assign(3, new PortVal(ntohs(parent.dst_port), TRANSPORT_UNKNOWN));
|
||||||
|
rv->Assign(0, id_val);
|
||||||
|
rv->Assign(1, new EnumVal(tunneltype, BifType::Enum::tunneltype_t));
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
IP_Hdr *child;
|
||||||
|
ConnID parent;
|
||||||
|
int hdr_len;
|
||||||
|
BifEnum::tunneltype_t tunneltype;
|
||||||
|
};
|
||||||
|
|
||||||
|
class TunnelHandler {
|
||||||
|
public:
|
||||||
|
TunnelHandler(NetSessions *arg_s);
|
||||||
|
~TunnelHandler();
|
||||||
|
|
||||||
|
TunnelInfo* DecapsulateTunnel(const IP_Hdr* ip_hdr, int len, int caplen,
|
||||||
|
/* need those for passing them back to NetSessions::Weird() */
|
||||||
|
const struct pcap_pkthdr* hdr, const u_char* const pkt);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
NetSessions *s;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -167,3 +167,10 @@ enum ID %{
|
||||||
%}
|
%}
|
||||||
|
|
||||||
module GLOBAL;
|
module GLOBAL;
|
||||||
|
|
||||||
|
enum tunneltype_t %{
|
||||||
|
NONE,
|
||||||
|
IP6inIP,
|
||||||
|
%}
|
||||||
|
|
||||||
|
type tunnel_parent_t: record;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue