use flowscope::OwnedAnomaly;
use flowscope::detect::patterns::{BeaconDetector, PortScanDetector, RitaBeaconDetector};
use flowscope::detect::{DetectorRegistry, DgaDetector, HostPair, SrcHost};
use flowscope::dns::{DnsMessage, DnsUdpParser};
use flowscope::driver::{Driver, Event, SlotHandle, SlotMessage};
use flowscope::emit::EveJsonWriter;
use flowscope::extract::{FiveTuple, FiveTupleKey};
use flowscope::pcap::PcapFlowSource;
fn pump(
events: &[Event<FiveTupleKey>],
dns_slot: &mut SlotHandle<DnsMessage, FiveTupleKey>,
registry: &mut DetectorRegistry<FiveTupleKey>,
anomalies: &mut Vec<OwnedAnomaly>,
eve: &mut EveJsonWriter<std::io::StdoutLock<'static>>,
) -> std::io::Result<usize> {
anomalies.clear();
for ev in events {
registry.observe_event(ev, anomalies);
}
let mut dns_msgs: Vec<SlotMessage<DnsMessage, FiveTupleKey>> = Vec::new();
dns_slot.drain(&mut dns_msgs);
for m in &dns_msgs {
if let DnsMessage::Query(q) | DnsMessage::Unanswered(q) = &m.message
&& let Some(question) = q.questions.first()
{
registry.observe_dns(&m.key, &question.name, m.ts, anomalies);
}
}
for a in anomalies.iter() {
eve.write_owned_anomaly(a)?;
}
Ok(anomalies.len())
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let path = std::env::args()
.nth(1)
.unwrap_or_else(|| "tests/data/mixed_short.pcap".into());
let mut builder = Driver::builder(FiveTuple::bidirectional());
let mut dns_slot = builder.datagram_on_ports(DnsUdpParser::default(), [53]);
let mut driver = builder.build();
let mut registry: DetectorRegistry<FiveTupleKey> = DetectorRegistry::new();
registry
.register(BeaconDetector::<HostPair>::new())
.register(RitaBeaconDetector::<HostPair>::new())
.register(PortScanDetector::<SrcHost>::new())
.register(DgaDetector::new());
eprintln!(
"registered detectors: {:?}",
registry.kinds().collect::<Vec<_>>()
);
let mut eve = EveJsonWriter::new(std::io::stdout().lock());
let mut events: Vec<Event<FiveTupleKey>> = Vec::new();
let mut anomalies: Vec<OwnedAnomaly> = Vec::new();
let mut fired = 0usize;
for owned in PcapFlowSource::open(&path)?.views() {
let owned = owned?;
events.clear();
driver.track_into(&owned, &mut events);
fired += pump(
&events,
&mut dns_slot,
&mut registry,
&mut anomalies,
&mut eve,
)?;
}
events.clear();
driver.finish_into(&mut events);
fired += pump(
&events,
&mut dns_slot,
&mut registry,
&mut anomalies,
&mut eve,
)?;
eprintln!(
"\n{fired} anomalies emitted (EVE above); registry tracked {} keys",
registry.tracked()
);
Ok(())
}