A security-focused telemetry agent written in Rust using eBPF.

Related tags

Utilities rust ebpf
Overview

Vesper

A security-focused telemetry agent written in Rust using eBPF.

Important: While public, this project is an educational endeavor and is not meant to be deployed to a production environment.

Why?

This project is all about getting deeper in the Rust language and exposing myself to eBPF. It's purely for educational purposes.

What's provided?

The goal of vesper is to provide transparency around what a host is doing, who it's talking to, and how it's talking.

Have you ever wondered what DNS requests your applications or the underlying host daemons were making, or what version of TLS or specific ciphers were being negotiated? Vesper's aim is to provide that information and more. Vesper will not take action against any information it finds -- it's sole goal is to report information in a way that another agent or system could consume for enforcement and alerting.

Examples

DNS Query and Response

Vesper can provide information about what DNS queries have been made from the host, who responded, and what that response was:

# DNS query made by the host
{
    "time":"2022-09-19T14:41:27.127059667+00:00",
    "type":"DnsQuery",
    "event":{
        "DnsQuery":{
            "source": {"ip":"192.168.109.2","port":54329},
            "destination":{"ip":"192.168.109.1","port":53},
            "id":57975,
            "questions":[
                {"type":"A","name":"connectivity-check.ubuntu.com"}
            ]
        }
    }
}

# Subsequent response received by the host
{
    "time":"2022-09-19T14:41:27.175101163+00:00",
    "type":"DnsResponse",
    "event":{
        "DnsResponse":{
            "source":{"ip":"192.168.109.1","port":53},
            "destination":{"ip":"192.168.109.2","port":54329},
            "id":57975,
            "status":"NoError",
            "authoritative":false,
            "recursive":true,
            "questions":[
                {"type":"A","name":"connectivity-check.ubuntu.com"}
            ],
            "answers":[
                {"type":"A","name":"connectivity-check.ubuntu.com","value":"35.224.170.84"},
                {"type":"A","name":"connectivity-check.ubuntu.com","value":"35.232.111.17"},
                {"type":"A","name":"connectivity-check.ubuntu.com","value":"34.122.121.32"}
            ]
        }
    }
}

TLS Negotiation

Vesper monitors all TCP traffic to look for packet signatures that match TLS negotiations. It currently provides information for the TLS Client Hello and Server Hello events. If you have a specific compliance need for TLS and cipher usage (e.g., TLS 1.2 only with FIPS 140-2 ciphers), Vesper can monitor and report on what's actually being used:

# TLS client hello made by the host
{
    "time":"2022-09-19T14:41:24.894583531+00:00",
    "type":"TlsClientHello",
    "event":{
        "TlsClientHello":{
            "source":{"ip":"192.168.109.2","port":33182},
            "destination":{"ip":"35.186.227.140","port":443},
            "version":"TLSv1_2",
            "ciphers":[
                "TLS_AES_128_GCM_SHA256",
                "TLS_CHACHA20_POLY1305_SHA256",
                "TLS_AES_256_GCM_SHA384",
                "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
                "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
                "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
                "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
                "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
                "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
                "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
                "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
                "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
                "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
                "TLS_RSA_WITH_AES_128_GCM_SHA256",
                "TLS_RSA_WITH_AES_256_GCM_SHA384",
                "TLS_RSA_WITH_AES_128_CBC_SHA",
                "TLS_RSA_WITH_AES_256_CBC_SHA"
            ]
        }
    }
}

# TLS server hello made by the remote server
{
    "time":"2022-09-19T14:41:24.896369601+00:00",
    "type":"TlsSeverHello",
    "event":{
        "TlsServerHello":{
            "source":{"ip":"35.186.227.140","port":443},
            "destination":{"ip":"192.168.109.2","port":33182},
            "version":"TLSv1_2",
            "cipher":"TLS_AES_128_GCM_SHA256"
        }
    }
}

Design Goals

  1. Security: It should go without saying. Although eBPF has mechanisms to protect against unsafe programs, we should consider security at every step of the pipeline.
  2. Simplicity: Focus the agent's features on getting and exposing the data. Don't add features that could be done better by another application (e.g., log offload to the cloud).
  3. Performance: Keep the packet data path as fast as possible.

Feature Goals

  • Telemetry
    • Data flow statistics for TCP and UDP
    • Protocol-specific diagnostic information (e.g., TCP retransmits)
    • DNS query and response data
    • TLS negotiation information
  • Output
    • JSON logging
    • CIM-compliant data format
  • Configuration
    • Ignore traffic from specific sources/destinations (ideally by domain or CIDR)
    • Attach to multiple network interfaces
    • Pick and choose what data to collect
    • Policies for higher-level logging (e.g., TLS version, ciphers)

Building From Source

Prerequisities

  • Rust (any version)
  • LLVM 13

Getting Started

  1. Clone the repository.
  2. Run make install

This will install Rust 1.59 so that LLVM 13 is used by both rustc and cargo-bpf, which is needed for BPF probes to work. (Read More)

Build and Run

Run make build to build both the probe and the agent binary, or make build-probes / make build-agent separately.

You can run the application with:

INTERFACE=<interface name, e.g., en0> make run
You might also like...
This crate allows you to safely initialize Dynamically Sized Types (DST) using only safe Rust.

This crate allows you to safely initialize Dynamically Sized Types (DST) using only safe Rust.

A working example of multi targets compilation for Rust using Github Actions.

A working example of multi targets compilation for Rust using Github Actions. Supports Windows, MacOSX, x86_64, ARM and Raspberry PI Linux.

Cookiecutter templates for Serverless applications using AWS SAM and the Rust programming language.

Cookiecutter SAM template for Lambda functions in Rust This is a Cookiecutter template to create a serverless application based on the Serverless Appl

Sketches I created using Rust + Nannou
Sketches I created using Rust + Nannou

Sketches Motivation I have followed generative artists like Ben Kovach and Tyler Hobbs for a while, and their artwork is truly impressive. Check them

A zsh histb browser using skim. Implemented in rust.

A zsh histb browser using skim. Implemented in rust.

Nix binary cache implemented in rust using libnix-store

harmonia Build Whole application nix-shell --run cargo b C Library Wrapper around libnixstore nix-shell --run make Note: The makefile is only to pro

Image optimization using Rust and Vips 🦀

Huffman Image optimization using Rust and Libvips. Requirements You must have the following packages installed before getting started Rust Vips pkg-co

Rust crate for creating filters with DirectX shaders. Includes Scale, Color conversion using DirectX api.

DxFilter Scale and ColorConversion done with DirectX filters. You can also create your own filters with the provided api. Crate contains various tools

Concatenate Amazon S3 files remotely using flexible patterns

S3 Concat This tool has been migrated into s3-utils, please use that crate for future updates. A small utility to concatenate files in AWS S3. Designe

Comments
  • Handle TCP segmentation

    Handle TCP segmentation

    With 9300b76f440de3bd9c92b86d5eefe8dcea416f0d we're officially processing TCP packets. The actual TLS message(s) may be segmented across a stream.

    For example, occasionally a TLS server hello message may also contain other messages (certificate, certificate status, server hello done), which is then split across TCP segments, causing an error in the packet processor:

    2022-09-19T14:40:49.447264Z ERROR vesper::processors::tls: Could not parse TLS packet: Incomplete(Size(4487)) (packet=SlicedPacket { link: Some(Ethernet2(Ethernet2HeaderSlice { slice: [216, 242, 202, 184, 67, 239, 182, 251, 228, 240, 103, 151, 8, 0] })), vlan: None, ip: Some(Ipv4(Ipv4HeaderSlice { slice: [69, 32, 5, 220, 2, 85, 64, 0, 111, 6, 62, 81, 13, 66, 138, 105, 192, 168, 109, 2] }, Ipv4ExtensionsSlice { auth: None })), transport: Some(Tcp(TcpHeaderSlice { slice: [1, 187, 171, 32, 69, 134, 20, 106, 164, 99, 241, 244, 128, 16, 4, 5, 107, 108, 0, 0, 1, 1, 8, 10, 83, 104, 125, 54, 139, 234, 35, 41] })), payload: [22, 3, 3, 23, 42, 2, 0, 0, 100, 3, 3, 99, 40, 126, 41, 58, 228, 100, 120, 190, 199, 72, 116, 178, 68, 90, 146, 165, 70, 137, 202, 226, 92, 57, 68, 154, 153, 112, 55, 43, 214, 171, 251, 32, 117, 25, 0, 0, 4, 13, 74, 206, 162, 247, 120, 177, 177, 234, 95, 178, 29, 84, 106, 73, 184, 60, 252, 70, 202, 131, 75, 141, 66, 40, 141, 32, 192, 48, 0, 0, 28, 0, 5, 0, 0, 0, 16, 0, 11, 0, 9, 8, 104, 116, 116, 112, 47, 49, 46, 49, 0, 23, 0, 0, 255, 1, 0, 1, 0, 11, 0, 14, 116, 0, 14, 113, 0, 8, 116, 48, 130, 8, 112, 48, 130, 6, 88, 160, 3, 2, 1, 2, 2, 19, 51, 0, 81, 154, 76, 172, 179, 162, 82, 173, 128, 156, 191, 0, 0, 0, 81, 154, 76, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 12, 5, 0, 48, 89, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 49, 30, 48, 28, 6, 3, 85, 4, 10, 19, 21, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 67, 111, 114, 112, 111, 114, 97, 116, 105, 111, 110, 49, 42, 48, 40, 6, 3, 85, 4, 3, 19, 33, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 65, 122, 117, 114, 101, 32, 84, 76, 83, 32, 73, 115, 115, 117, 105, 110, 103, 32, 67, 65, 32, 48, 54, 48, 30, 23, 13, 50, 50, 48, 57, 49, 52, 49, 51, 53, 56, 49, 54, 90, 23, 13, 50, 51, 48, 51, 49, 51, 49, 51, 53, 56, 49, 54, 90, 48, 117, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 49, 11, 48, 9, 6, 3, 85, 4, 8, 19, 2, 87, 65, 49, 16, 48, 14, 6, 3, 85, 4, 7, 19, 7, 82, 101, 100, 109, 111, 110, 100, 49, 30, 48, 28, 6, 3, 85, 4, 10, 19, 21, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 67, 111, 114, 112, 111, 114, 97, 116, 105, 111, 110, 49, 39, 48, 37, 6, 3, 85, 4, 3, 19, 30, 118, 115, 99, 111, 100, 101, 45, 115, 121, 110, 99, 46, 116, 114, 97, 102, 102, 105, 99, 109, 97, 110, 97, 103, 101, 114, 46, 110, 101, 116, 48, 130, 1, 34, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 130, 1, 15, 0, 48, 130, 1, 10, 2, 130, 1, 1, 0, 184, 223, 108, 6, 91, 72, 181, 151, 92, 122, 109, 113, 174, 145, 142, 156, 178, 39, 204, 58, 173, 26, 39, 144, 192, 100, 252, 184, 88, 110, 83, 170, 128, 121, 0, 207, 184, 226, 123, 30, 23, 238, 66, 211, 55, 22, 191, 117, 150, 179, 110, 251, 57, 8, 175, 84, 12, 145, 197, 8, 75, 41, 1, 108, 87, 47, 234, 75, 229, 201, 80, 88, 247, 110, 255, 214, 122, 104, 40, 219, 191, 31, 42, 221, 169, 181, 236, 24, 115, 199, 107, 223, 43, 187, 67, 75, 17, 220, 175, 115, 238, 197, 1, 15, 59, 76, 58, 44, 130, 217, 133, 28, 61, 243, 132, 92, 61, 214, 174, 194, 249, 184, 12, 67, 56, 60, 237, 192, 255, 53, 40, 183, 158, 219, 48, 119, 105, 107, 31, 203, 244, 195, 170, 136, 34, 182, 5, 218, 82, 74, 71, 218, 248, 104, 208, 240, 115, 164, 3, 233, 41, 28, 94, 126, 170, 12, 177, 171, 169, 132, 234, 198, 161, 91, 134, 238, 255, 160, 247, 237, 80, 109, 51, 48, 252, 35, 213, 126, 33, 17, 202, 2, 168, 125, 206, 57, 40, 166, 158, 2, 194, 196, 79, 31, 255, 226, 121, 225, 215, 1, 117, 241, 172, 8, 116, 109, 0, 78, 37, 89, 9, 245, 130, 98, 21, 136, 66, 174, 112, 113, 6, 252, 108, 186, 210, 141, 157, 35, 82, 87, 87, 27, 220, 168, 46, 220, 104, 11, 121, 124, 172, 153, 7, 159, 43, 241, 2, 3, 1, 0, 1, 163, 130, 4, 19, 48, 130, 4, 15, 48, 130, 1, 125, 6, 10, 43, 6, 1, 4, 1, 214, 121, 2, 4, 2, 4, 130, 1, 109, 4, 130, 1, 105, 1, 103, 0, 118, 0, 173, 247, 190, 250, 124, 255, 16, 200, 139, 157, 61, 156, 30, 62, 24, 106, 180, 103, 41, 93, 207, 177, 12, 36, 202, 133, 134, 52, 235, 220, 130, 138, 0, 0, 1, 131, 60, 84, 68, 126, 0, 0, 4, 3, 0, 71, 48, 69, 2, 32, 91, 89, 188, 73, 140, 169, 235, 206, 140, 4, 139, 255, 138, 162, 43, 249, 235, 201, 125, 3, 239, 12, 233, 223, 20, 22, 96, 175, 13, 157, 131, 48, 2, 33, 0, 147, 6, 18, 32, 98, 172, 59, 253, 197, 53, 255, 95, 171, 203, 79, 236, 178, 32, 132, 53, 84, 39, 56, 0, 49, 239, 185, 221, 106, 33, 130, 6, 0, 118, 0, 179, 115, 119, 7, 225, 132, 80, 248, 99, 134, 214, 5, 169, 220, 17, 9, 74, 121, 45, 177, 103, 12, 11, 135, 220, 240, 3, 14, 121, 54, 165, 154, 0, 0, 1, 131, 60, 84, 68, 237, 0, 0, 4, 3, 0, 71, 48, 69, 2, 32, 100, 214, 1, 101, 31, 118, 157, 224, 109, 155, 11, 141, 29, 16, 140, 99, 118, 83, 215, 22, 41, 98, 162, 88, 169, 57, 88, 114, 178, 82, 199, 62, 2, 33, 0, 238, 187, 69, 103, 86, 16, 217, 160, 245, 192, 83, 22, 101, 86, 139, 163, 248, 28, 226, 176, 125, 98, 2, 114, 147, 25, 4, 16, 54, 245, 83, 8, 0, 117, 0, 232, 62, 208, 218, 62, 245, 6, 53, 50, 231, 87, 40, 188, 137, 107, 201, 3, 211, 203, 209, 17, 107, 236, 235, 105, 225, 119, 125, 109, 6, 189, 110, 0, 0, 1, 131, 60, 84, 68, 173, 0, 0, 4, 3, 0, 70, 48, 68, 2, 32, 124, 221, 153, 116, 11, 2, 136, 191, 155, 177, 58, 218, 19, 198, 139, 152, 104, 212, 194, 1, 121, 0, 48, 126, 122, 206, 134, 244, 140, 168, 153, 255, 2, 32, 122, 215, 199, 74, 34, 24, 59, 217, 198, 136, 203, 141, 51, 245, 19, 21, 186, 19, 104, 157, 125, 44, 204, 174, 165, 209, 156, 90, 203, 79, 150, 69, 48, 39, 6, 9, 43, 6, 1, 4, 1, 130, 55, 21, 10, 4, 26, 48, 24, 48, 10, 6, 8, 43, 6, 1, 5, 5, 7, 3, 2, 48, 10, 6, 8, 43, 6, 1, 5, 5, 7, 3, 1, 48, 60, 6, 9, 43, 6, 1, 4, 1, 130, 55, 21, 7, 4, 47, 48, 45, 6, 37, 43, 6, 1, 4, 1, 130, 55, 21, 8, 135, 189, 215, 27, 129, 231, 235, 70, 130, 129, 157, 46, 142, 208, 12, 135, 240, 218, 29, 93, 130, 171, 231, 48, 135, 237, 241, 31, 2, 1, 100, 2, 1, 41, 48, 129, 174, 6, 8, 43, 6, 1, 5, 5, 7, 1, 1, 4, 129, 161, 48, 129, 158, 48, 109, 6, 8, 43, 6, 1, 5, 5, 7, 48, 2, 134, 97, 104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 109, 105, 99, 114, 111, 115, 111, 102, 116, 46, 99, 111, 109, 47, 112, 107, 105, 111, 112, 115, 47, 99, 101, 114, 116, 115, 47, 77, 105, 99, 114, 111, 115, 111, 102, 116, 37, 50, 48, 65, 122, 117, 114, 101, 37, 50, 48, 84, 76, 83, 37, 50, 48, 73, 115, 115, 117, 105, 110, 103, 37, 50, 48, 67, 65, 37, 50, 48, 48, 54, 37, 50, 48, 45, 37, 50, 48, 120, 115, 105, 103, 110, 46, 99, 114, 116, 48, 45, 6, 8, 43, 6, 1, 5, 5, 7, 48, 1, 134, 33, 104, 116, 116, 112, 58, 47, 47, 111, 110, 101, 111, 99, 115, 112, 46, 109, 105, 99, 114, 111, 115, 111, 102, 116, 46, 99, 111, 109, 47, 111, 99, 115, 112, 48, 29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 168, 113, 216, 214, 175, 4, 126, 85, 238, 65, 214, 221, 107, 51, 70, 26, 10, 59, 45, 0, 48, 14, 6, 3, 85, 29, 15, 1, 1, 255, 4, 4, 3, 2, 4, 176, 48, 41, 6, 3, 85, 29, 17, 4, 34, 48, 32, 130, 30, 118, 115, 99, 111, 100, 101, 45, 115, 121, 110, 99] })
    
    bug 
    opened by bcelenza 0
  • Normalize to IPv6

    Normalize to IPv6

    Normalizes all address to IPv6, updates fmt::Display impls to pretty-print based on whether the IP is a v4 or v6. Adds unit tests for conversion logic.

    opened by bcelenza 0
  • Enums and booleans require large type declaration for FFI

    Enums and booleans require large type declaration for FFI

    Example: socket close state

    If represented as anything other than a u64, an invalid memory access error is throwing during validation of the BPF program.

    https://github.com/bcelenza/vesper/blob/f178bf7a4d462e60640d922e15b640a3a8d3fc8f/probes/src/network/mod.rs#L36

    https://github.com/bcelenza/vesper/blob/f178bf7a4d462e60640d922e15b640a3a8d3fc8f/probes/src/network/mod.rs#L5-L9

    Some related info: https://github.com/foniod/redbpf/issues/150, https://rust-lang.github.io/unsafe-code-guidelines/layout/enums.html

    I'm probably just misunderstanding something trivial.

    invalid 
    opened by bcelenza 0
  • Improve identification of DNS packets

    Improve identification of DNS packets

    https://github.com/bcelenza/vesper/blob/f178bf7a4d462e60640d922e15b640a3a8d3fc8f/probes/src/dns/main.rs#L18-L21

    Helpful: https://stackoverflow.com/questions/7565300/identifying-dns-packets

    enhancement 
    opened by bcelenza 0
Owner
Brian Celenza
Brian Celenza
A Rust library for managing eBPF programs.

oxidebpf oxidebpf is a permissive licensed Rust library for managing eBPF programs. Motivation The motivation behind oxidebpf is to create a permissiv

Red Canary 87 Sep 2, 2022
Fox Ear is a Linux process behavior trace tool powered by eBPF

Fox Ear Fox Ear is a Linux process behavior trace tool powered by eBPF. Banner image by Birger Strahl on Unsplash. Features Log process and its subpro

Rui Li 76 Sep 22, 2022
Simple git/hg tui client focused on keyboard shortcuts

verco A simple Git/Hg tui client focused on keyboard shortcuts Screenshots Platforms This project uses Cargo and pure Rust stable and works on latest

Matheus Lessa Rodrigues 207 Sep 24, 2022
supply-chain security for Rust

cargo-vet Note: cargo-vet is under heavy development and not quite ready for general use. Feel free to give it a try you're feeling adventerous — feed

Mozilla 249 Sep 7, 2022
Ultralight, security-first service mesh for Kubernetes. Main repo for Linkerd 2.x.

Linkerd ?? Welcome to Linkerd! ?? Linkerd is an ultralight, security-first service mesh for Kubernetes. Linkerd adds critical security, observability,

Linkerd 8.9k Sep 26, 2022
Garden monitoring system using m328p Arduino Uno boards. 100% Rust [no_std] using the avr hardware abstraction layer (avr-hal)

uno-revive-rs References Arduino Garden Controller Roadmap uno-revive-rs: roadmap Components & Controllers 1-2 Uno R3 m328p Soil moisture sensor: m328

Ethan Gallucci 1 May 4, 2022
Universal changelog generator using conventional commit+ with monorepo support. Written in Rust.

chlog Universal changelog generator using conventional commit+ with monorepo support. chlog can generate the changelog from the conventional commits w

Jeff Yang 2 Jun 13, 2022
k-mer counter in Rust using the rust-bio and rayon crates

krust is a k-mer counter written in Rust and run from the command line that will output canonical k-mers and their frequency across the records in a f

null 11 Jul 31, 2022
🦀 Rust-based implementation of a Snowflake Generator which communicates using gRPC

Clawflake Clawflake is a Rust application which implements Twitter Snowflakes and communicates using gRPC. Snowflake ID numbers are 63 bits integers s

n1c00o 4 Sep 6, 2022
A pure Rust PLONK implementation using arkworks as a backend.

PLONK This is a pure Rust implementation of the PLONK zk proving system Usage use ark_plonk::prelude::*; use ark_ec::bls12::Bls12; use rand_core::OsRn

rust-zkp 172 Sep 21, 2022