Add Geneve packet analyzer, disable old analyzer

This commit is contained in:
Tim Wojtulewicz 2021-08-26 12:15:00 -07:00
parent 7e40094f2c
commit cbb0bcd49c
19 changed files with 218 additions and 24 deletions

View file

@ -23,3 +23,4 @@ add_subdirectory(vntag)
add_subdirectory(gre)
add_subdirectory(iptunnel)
add_subdirectory(ayiya)
add_subdirectory(geneve)

View file

@ -0,0 +1,6 @@
include(ZeekPlugin)
zeek_plugin_begin(Zeek Geneve)
zeek_plugin_cc(Geneve.cc Plugin.cc)
zeek_plugin_bif(events.bif)
zeek_plugin_end()

View file

@ -0,0 +1,90 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/packet_analysis/protocol/geneve/Geneve.h"
#include "zeek/packet_analysis/protocol/geneve/events.bif.h"
#include "zeek/packet_analysis/protocol/iptunnel/IPTunnel.h"
using namespace zeek::packet_analysis::Geneve;
GeneveAnalyzer::GeneveAnalyzer() : zeek::packet_analysis::Analyzer("Geneve") { }
bool GeneveAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
{
if ( packet->encap && packet->encap->Depth() >= BifConst::Tunnel::max_depth )
{
Weird("exceeded_tunnel_max_depth", packet);
return false;
}
// This will be expanded based on the length of the options in the header,
// but it will be at least this long.
uint16_t hdr_size = 8;
if ( hdr_size > len )
{
AnalyzerViolation("Geneve header truncation", packet->session,
reinterpret_cast<const char*>(data), len);
return false;
}
// Validate that the version number is correct. According to the RFC, this
// should always be zero, and anything else should be treated as an error.
auto version = data[0] >> 6;
if ( version != 0 )
{
Weird("geneve_invalid_version", packet, util::fmt("%d", version));
return false;
}
// Option length is the number of bytes for options, expressed in 4-byte multiples.
uint8_t opt_len = (data[0] & 0x3F) * 4;
hdr_size += opt_len;
// Double-check this one now that we know the actual full length of the header.
if ( hdr_size > len )
{
AnalyzerViolation("Geneve option header truncation", packet->session,
reinterpret_cast<const char*>(data), len);
return false;
}
// Get the next header. This will probably be Ethernet (0x6558), but get it
// anyways so that the forwarding can do its thing.
auto next_header = (data[2] << 8) + data[3];
// Grab the VNI out of the data before advancing the data pointer
auto vni = (data[4] << 16) + (data[5] << 8) + data[6];
len -= hdr_size;
data += hdr_size;
int encap_index = 0;
auto inner_packet = packet_analysis::IPTunnel::build_inner_packet(
packet, &encap_index, nullptr, len, data, DLT_RAW, BifEnum::Tunnel::GENEVE,
GetAnalyzerTag());
// Skip the header and pass on to the next analyzer. It's possible for Geneve to
// just be a header and nothing after it, so check for that case.
bool fwd_ret_val = true;
if ( len > hdr_size )
fwd_ret_val = ForwardPacket(len, data, inner_packet.get(), next_header);
if ( fwd_ret_val )
{
AnalyzerConfirmation(packet->session);
if ( geneve_packet && packet->session )
{
EncapsulatingConn* ec = inner_packet->encap->At(encap_index);
if ( ec && ec->ip_hdr )
inner_packet->session->EnqueueEvent(geneve_packet, nullptr,
packet->session->GetVal(),
ec->ip_hdr->ToPktHdrVal(), val_mgr->Count(vni));
}
}
else
AnalyzerViolation("Geneve invalid inner packet", packet->session);
return fwd_ret_val;
}

View file

@ -0,0 +1,25 @@
// See the file "COPYING" in the main distribution directory for copyright.
#pragma once
#include "zeek/packet_analysis/Analyzer.h"
#include "zeek/packet_analysis/Component.h"
namespace zeek::packet_analysis::Geneve
{
class GeneveAnalyzer : public zeek::packet_analysis::Analyzer
{
public:
GeneveAnalyzer();
~GeneveAnalyzer() override = default;
bool AnalyzePacket(size_t len, const uint8_t* data, Packet* packet) override;
static zeek::packet_analysis::AnalyzerPtr Instantiate()
{
return std::make_shared<GeneveAnalyzer>();
}
};
}

View file

@ -0,0 +1,27 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/plugin/Plugin.h"
#include "zeek/packet_analysis/Component.h"
#include "zeek/packet_analysis/protocol/geneve/Geneve.h"
namespace zeek::plugin::Zeek_Geneve
{
class Plugin : public zeek::plugin::Plugin
{
public:
zeek::plugin::Configuration Configure()
{
AddComponent(new zeek::packet_analysis::Component(
"Geneve", zeek::packet_analysis::Geneve::GeneveAnalyzer::Instantiate));
zeek::plugin::Configuration config;
config.name = "Zeek::Geneve";
config.description = "Geneve packet analyzer";
return config;
}
} plugin;
}

View file

@ -0,0 +1,12 @@
## Generated for any packet encapsulated in a Geneve tunnel.
## See :rfc:`8926` for more information about the Geneve protocol.
##
## outer: The Geneve tunnel connection.
##
## inner: The Geneve-encapsulated Ethernet packet header and transport header.
##
## vni: Geneve Network Identifier.
##
## .. note:: Since this event may be raised on a per-packet basis, handling
## it may become particularly expensive for real-time analysis.
event geneve_packet%(outer: connection, inner: pkt_hdr, vni: count%);