-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Import DNS from zeek/spicy-analyzers@2e5a185.
- Loading branch information
0 parents
commit 490029d
Showing
27 changed files
with
613 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
{ | ||
"parse": { | ||
"additional_commands": { | ||
"spicy_add_analyzer": { | ||
"kwargs": { | ||
"NAME": "*", | ||
"PACKAGE_NAME": "*", | ||
"SOURCES": "*", | ||
"SCRIPTS": "*" | ||
} | ||
} | ||
} | ||
}, | ||
"format": { | ||
"line_width": 100, | ||
"tab_size": 4, | ||
"separate_ctrl_name_with_space": true, | ||
"max_subgroups_hwrap": 3 | ||
}, | ||
"markup": { | ||
"enable_markup": false | ||
}, | ||
"lint": { | ||
"disabled_codes": ["C0103"] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
name: Check | ||
|
||
on: | ||
pull_request: | ||
push: | ||
branches: [main] | ||
|
||
jobs: | ||
Check: | ||
runs-on: ubuntu-latest | ||
container: zeekurity/spicy | ||
|
||
steps: | ||
- uses: actions/checkout@v2 | ||
- name: Prepare | ||
env: | ||
PATH: /usr/local/bin:/opt/cmake/bin:/opt/spicy/bin:/opt/zeek/bin:/opt/zeek/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin | ||
run: | | ||
# Clean out leftover logs for to make it easier to print "our" logs. | ||
zkg autoconfig | ||
rm -f $(zkg config state_dir)/logs/*.log | ||
zkg -vvvvv purge --force | ||
# Manually install spicy-plugin until the image contains a zkg version with a fix for https://github.com/zeek/package-manager/issues/106 (>=zkg-2.12.0). | ||
zkg -vvvvv install --force --skiptests spicy-plugin | ||
- name: Install | ||
env: | ||
PATH: /usr/local/bin:/opt/cmake/bin:/opt/spicy/bin:/opt/zeek/bin:/opt/zeek/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin | ||
run: | | ||
git clean -fd | ||
eval $(zkg env) | ||
echo Y | zkg -vvvvv install . | ||
- name: Show logs | ||
if: always() | ||
run: | | ||
tail -n 1000000 $(zkg config state_dir)/logs/*.log |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
name: pre-commit | ||
|
||
on: | ||
pull_request: | ||
push: | ||
branches: [main] | ||
|
||
jobs: | ||
pre-commit: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- uses: actions/setup-python@v2 | ||
- uses: pre-commit/[email protected] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
rules "~MD033", "~MD013", "~MD046", "~MD010" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# See https://pre-commit.com for more information | ||
# See https://pre-commit.com/hooks.html for more hooks | ||
repos: | ||
- repo: https://github.com/pre-commit/pre-commit-hooks | ||
rev: v4.0.1 | ||
hooks: | ||
- id: trailing-whitespace | ||
- id: end-of-file-fixer | ||
- id: check-yaml | ||
- id: check-added-large-files | ||
|
||
- repo: https://github.com/markdownlint/markdownlint | ||
rev: v0.11.0 | ||
hooks: | ||
- id: markdownlint | ||
|
||
- repo: https://github.com/cheshirekow/cmake-format-precommit | ||
rev: v0.6.13 | ||
hooks: | ||
- id: cmake-format | ||
- id: cmake-lint | ||
|
||
exclude: '^tests/Baseline' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
cmake_minimum_required(VERSION 3.15 FATAL_ERROR) | ||
|
||
project(Message LANGUAGES C) | ||
|
||
list(PREPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") | ||
find_package(SpicyPlugin REQUIRED) | ||
|
||
# Set mininum versions that this plugin needs. Make sure to use "x.y.z" format. | ||
spicy_require_version("1.2.0") | ||
spicy_plugin_require_version("0.99.0") | ||
zeek_require_version("3.0.0") | ||
|
||
if (NOT CMAKE_BUILD_TYPE) | ||
# Default to release build. | ||
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") | ||
endif () | ||
|
||
add_subdirectory(analyzer) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
DNS analyzer | ||
============ | ||
|
||
This repository contains a | ||
[Spicy](https://docs.zeek.org/projects/spicy/en/latest/)-based analyzer for the | ||
DNS protocol. This analyzer replaces the builtin Zeek DNS analyzer. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
spicy_add_analyzer( | ||
NAME Message | ||
PACKAGE_NAME Message | ||
SOURCES analyzer.spicy analyzer.evt zeek_analyzer.spicy | ||
SCRIPTS __load__.zeek) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
@load-sigs ./dpd.sig | ||
@load ./main.zeek |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
# Copyright (c) 2021 by the Zeek Project. See LICENSE for details. | ||
|
||
protocol analyzer spicy::DNS over UDP: | ||
parse with DNS::Message, | ||
port 53/udp, | ||
port 137/udp, | ||
port 5353/udp, | ||
port 5355/udp, | ||
replaces DNS; | ||
|
||
import Zeek_DNS; | ||
|
||
|
||
@if ZEEK_VERSION >= 30200 | ||
# Zeek >= 3.2 adds an additional parameter with the query in its original spelling. | ||
|
||
on DNS::Question if ( msg.header.flags.qr == 0 ) | ||
-> event dns_request($conn, Zeek_DNS::message(msg.header), Zeek_DNS::name(self.qname).lower(), self.qtype, self.qclass, Zeek_DNS::name(self.qname)); | ||
|
||
on DNS::Question if ( msg.header.flags.qr == 1 && ! msg.header.rejected ) | ||
-> event dns_query_reply($conn, Zeek_DNS::message(msg.header), Zeek_DNS::name(self.qname).lower(), self.qtype, self.qclass, Zeek_DNS::name(self.qname)); | ||
|
||
on DNS::Question if ( msg.header.flags.qr == 1 && msg.header.rejected ) | ||
-> event dns_rejected($conn, Zeek_DNS::message(msg.header), Zeek_DNS::name(self.qname).lower(), self.qtype, self.qclass, Zeek_DNS::name(self.qname)); | ||
|
||
on DNS::Message if ( |self.question| == 0 && ! self.header.rejected ) | ||
-> event dns_query_reply($conn, Zeek_DNS::message(self.header), b"<no query>", cast<uint64>(0), cast<uint64>(0), b"<no query>"); | ||
|
||
on DNS::Message if ( |self.question| == 0 && self.header.rejected ) | ||
-> event dns_rejected($conn, Zeek_DNS::message(self.header), b"<no query>", cast<uint64>(0), cast<uint64>(0), b"<no query>"); | ||
@else | ||
on DNS::Question if ( msg.header.flags.qr == 0 ) | ||
-> event dns_request($conn, Zeek_DNS::message(msg.header), Zeek_DNS::name(self.qname).lower(), self.qtype, self.qclass); | ||
|
||
on DNS::Question if ( msg.header.flags.qr == 1 && ! msg.header.rejected ) | ||
-> event dns_query_reply($conn, Zeek_DNS::message(msg.header), Zeek_DNS::name(self.qname).lower(), self.qtype, self.qclass); | ||
|
||
on DNS::Question if ( msg.header.flags.qr == 1 && msg.header.rejected ) | ||
-> event dns_rejected($conn, Zeek_DNS::message(msg.header), Zeek_DNS::name(self.qname).lower(), self.qtype, self.qclass); | ||
|
||
on DNS::Message if ( |self.question| == 0 && ! self.header.rejected ) | ||
-> event dns_query_reply($conn, Zeek_DNS::message(self.header), b"<no query>", cast<uint64>(0), cast<uint64>(0)); | ||
|
||
on DNS::Message if ( |self.question| == 0 && self.header.rejected ) | ||
-> event dns_rejected($conn, Zeek_DNS::message(self.header), b"<no query>", cast<uint64>(0), cast<uint64>(0)); | ||
@endif | ||
|
||
# TODO: Length of raw payload? | ||
on DNS::Message::header -> event dns_message($conn, Zeek_DNS::is_query(self.header), Zeek_DNS::message(self.header), cast<uint64>(0)); | ||
|
||
on DNS::Message | ||
-> event dns_end($conn, Zeek_DNS::message(self.header)); | ||
|
||
on DNS::ResourceRecord if ( self.ty == DNS::RDType::A ) | ||
-> event dns_A_reply($conn, Zeek_DNS::message(msg.header), Zeek_DNS::answer(self, rrtype), self.a); | ||
|
||
on DNS::ResourceRecord if ( self.ty == DNS::RDType::A6 ) | ||
-> event dns_A6_reply($conn, Zeek_DNS::message(msg.header), Zeek_DNS::answer(self, rrtype), self.a); | ||
|
||
on DNS::ResourceRecord if ( self.ty == DNS::RDType::AAAA ) | ||
-> event dns_AAAA_reply($conn, Zeek_DNS::message(msg.header), Zeek_DNS::answer(self, rrtype), self.a); | ||
|
||
on DNS::ResourceRecord if ( self.ty == DNS::RDType::NS ) | ||
-> event dns_NS_reply($conn, Zeek_DNS::message(msg.header), Zeek_DNS::answer(self, rrtype), Zeek_DNS::name(self.rname)); | ||
|
||
on DNS::ResourceRecord if ( self.ty == DNS::RDType::CNAME ) | ||
-> event dns_CNAME_reply($conn, Zeek_DNS::message(msg.header), Zeek_DNS::answer(self, rrtype), Zeek_DNS::name(self.rname)); | ||
|
||
on DNS::ResourceRecord if ( self.ty == DNS::RDType::PTR ) | ||
-> event dns_PTR_reply($conn, Zeek_DNS::message(msg.header), Zeek_DNS::answer(self, rrtype), Zeek_DNS::name(self.rname)); | ||
|
||
on DNS::ResourceRecord if ( self.ty == DNS::RDType::MX ) | ||
-> event dns_MX_reply($conn, Zeek_DNS::message(msg.header), Zeek_DNS::answer(self, rrtype), Zeek_DNS::name(self.mx.name), self.mx.preference); | ||
|
||
on DNS::ResourceRecord if ( self.ty == DNS::RDType::SOA ) | ||
-> event dns_SOA_reply($conn, Zeek_DNS::message(msg.header), Zeek_DNS::answer(self, rrtype), Zeek_DNS::soa(self.soa)); | ||
|
||
on DNS::ResourceRecord if ( self.ty == DNS::RDType::TXT ) | ||
-> event dns_TXT_reply($conn, Zeek_DNS::message(msg.header), Zeek_DNS::answer(self, rrtype), [i.data for i in self.txt]); | ||
|
||
on DNS::ResourceRecord if ( self.ty == DNS::RDType::WKS ) | ||
-> event dns_WKS_reply($conn, Zeek_DNS::message(msg.header), Zeek_DNS::answer(self, rrtype)); | ||
|
||
on DNS::ResourceRecord if ( self.ty == DNS::RDType::SRV ) | ||
-> event dns_SRV_reply($conn, Zeek_DNS::message(msg.header), Zeek_DNS::answer(self, rrtype), Zeek_DNS::name(self.srv.target), self.srv.priority_, self.srv.weight, self.srv.port_); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
# Copyright (c) 2021 by the Zeek Project. See LICENSE for details. | ||
|
||
module DNS; | ||
|
||
import spicy; | ||
|
||
type RDType = enum { | ||
A = 1, NS = 2, MD = 3, MF = 4, CNAME = 5, SOA = 6, MB = 7, MG = 8, MR = 9, | ||
NULL = 10, WKS = 11, PTR = 12, HINFO = 13, MINFO = 14, MX = 15, TXT = 16, | ||
AAAA = 28, NBS = 32, SRV= 33, A6 = 38, EDNS = 41 }; | ||
|
||
type RRType = enum { | ||
ANSWER = 1, AUTH = 2, ADDL = 3 | ||
}; | ||
|
||
public type Message = unit { | ||
%random-access; | ||
|
||
header: Header; | ||
question: (Question(self))[self.header.qdcount]; | ||
answer: (ResourceRecord(self, RRType::ANSWER))[self.header.ancount]; | ||
authority: (ResourceRecord(self, RRType::AUTH))[self.header.nscount]; | ||
additional: (ResourceRecord(self, RRType::ADDL))[self.header.arcount]; | ||
}; | ||
|
||
type Header = unit { | ||
id : uint16; | ||
flags : bitfield(16) { | ||
qr: 0; | ||
opcode: 1..4; | ||
aa: 5; | ||
tc: 6; | ||
rd: 7; | ||
ra: 8; | ||
z: 9..11; | ||
rcode: 12..15; | ||
} &bit-order = spicy::BitOrder::MSB0; | ||
|
||
qdcount: uint16; | ||
ancount: uint16; | ||
nscount: uint16; | ||
arcount: uint16; | ||
|
||
var rejected : bool; | ||
|
||
on %done { | ||
# Mimic Zeek in determining when a request has been rejected. | ||
if ( self.qdcount == 0 ) | ||
self.rejected = (self.flags.rcode != 0); # 0 == NoError; | ||
|
||
else | ||
self.rejected = (self.flags.qr == 1 && | ||
self.ancount == 0 && | ||
self.nscount == 0 && | ||
self.arcount == 0); | ||
} | ||
}; | ||
|
||
type Question = unit(msg: Message) { | ||
qname: Name(msg); | ||
qtype: uint16; | ||
qclass: uint16; | ||
}; | ||
|
||
type ResourceRecord = unit(msg: Message, rrtype: RRType) { | ||
name: Name(msg); | ||
ty: uint16 &convert=RDType($$); | ||
class: uint16; | ||
ttl: uint32 &convert=cast<interval>($$); | ||
rdlen: uint16; | ||
|
||
switch ( self.ty ) { | ||
RDType::NS, RDType::CNAME, RDType::PTR | ||
-> rname: Name(msg); | ||
RDType::A -> a: addr &ipv4; | ||
RDType::AAAA -> a: addr &ipv6; | ||
RDType::MX -> mx: RDataMX(msg); | ||
RDType::SOA -> soa: RDataSOA(msg); | ||
RDType::SRV -> srv: RDataSRV(msg); | ||
RDType::TXT -> txt: (CharacterString(msg))[self.rdlen]; | ||
|
||
* -> rdata: bytes &size=self.rdlen; | ||
}; | ||
}; | ||
|
||
type RDataMX = unit(msg: Message) { | ||
preference: uint16; | ||
name: Name(msg); | ||
}; | ||
|
||
type RDataSOA = unit(msg: Message) { | ||
mname: Name(msg); | ||
rname: Name(msg); | ||
serial: uint32; | ||
refresh: uint32 &convert=cast<interval>($$); | ||
retry: uint32 &convert=cast<interval>($$); | ||
expire: uint32 &convert=cast<interval>($$); | ||
minimum: uint32 &convert=cast<interval>($$); | ||
}; | ||
|
||
type RDataSRV = unit(msg: Message) { | ||
priority_: uint16; | ||
weight: uint16; | ||
port_: uint16; | ||
target: Name(msg); | ||
}; | ||
|
||
type CharacterString = unit(msg: Message) { | ||
len: uint8; | ||
data: bytes &size=(self.len); | ||
}; | ||
|
||
type Name = unit(msg: Message) { | ||
: (Label(msg, self))[] &until=($$.len.offset == 0 || $$.len.compressed != 0); | ||
|
||
var label: bytes = b""; | ||
}; | ||
|
||
type Pointer = unit(msg: Message, label: Label) { | ||
len: bitfield(16) { | ||
offset: 0..13; | ||
}; | ||
|
||
name: Name(msg) &parse-at=(msg.input() + self.len.offset); | ||
}; | ||
|
||
type Label = unit(msg: Message, inout name: Name) { | ||
%random-access; | ||
|
||
len: bitfield(8) { | ||
offset: 0..5; | ||
compressed: 6..7; | ||
}; | ||
|
||
switch ( self.len.compressed ) { | ||
0 -> label: bytes &size=self.len.offset { | ||
if ( |self.label| ) { | ||
name.label += b"."; | ||
name.label += self.label; | ||
} | ||
} | ||
|
||
3 -> ptr: Pointer(msg, self) &parse-at=self.input() { | ||
name.label += self.ptr.name.label; | ||
self.adjust = 2; # Consume the additional byte in %done. | ||
} | ||
}; | ||
|
||
on %done { | ||
if ( self.adjust > 0 ) | ||
self.set_input(self.input() + self.adjust); | ||
} | ||
|
||
var adjust: uint64 = 0; | ||
}; |
Oops, something went wrong.