huginn-net-http 1.5.2

HTTP fingerprinting (p0f-style) analysis for huginn-net
Documentation

huginn-net-http

docs crates.io Downloads License CI Security Pure Rust

HTTP fingerprinting and browser detection for Huginn Net.

Overview

This crate provides HTTP-based passive fingerprinting capabilities. It analyzes HTTP/1.x and HTTP/2 headers to identify browsers, web servers, and detect preferred languages.

Why choose huginn-net-http?

  • No third-party tools - No tshark, wireshark, or external tools required
  • Comprehensive analysis - Browser, server, and language detection
  • Pure Rust implementation - No system libraries required
  • High performance - 562.1K pps for full analysis, 200M pps detection
  • HTTP/1.x & HTTP/2 - Support for both major protocol versions
  • Type-safe architecture - Prevents entire classes of bugs at compile time

Features

  • Browser Detection - Identify browsers from HTTP request headers
  • Web Server Detection - Identify servers from HTTP response headers
  • Language Detection - Extract preferred languages from Accept-Language headers
  • HTTP/1.x & HTTP/2 - Support for both major HTTP versions
  • Quality Scoring - Confidence metrics for all matches

Quick Start

Installation

Add this to your Cargo.toml:

[dependencies]
huginn-net-http = "1.5.2"

Basic Usage

Live Network Analysis

use huginn_net_http::{HuginnNetHttp, HttpAnalysisResult, HuginnNetHttpError};
use huginn_net_db::Database;
use std::sync::mpsc;
use std::thread;

fn main() -> Result<(), HuginnNetHttpError> {
    let db = Database::load_default()?;
    let mut analyzer = HuginnNetHttp::new(Some(&db), 1000)?;
    
    let (sender, receiver) = mpsc::channel::<HttpAnalysisResult>();
    
    let handle = thread::spawn(move || {
        analyzer.analyze_network("eth0", sender, None)
    });
    
    for result in receiver {
        if let Some(http_request) = result.http_request {
            println!("{http_request}");
        }
        if let Some(http_response) = result.http_response {
            println!("{http_response}");
        }
    }
    
    handle.join().unwrap()?;
    Ok(())
}

PCAP File Analysis

use huginn_net_http::{HuginnNetHttp, HttpAnalysisResult, HuginnNetHttpError};
use huginn_net_db::Database;
use std::sync::mpsc;
use std::thread;

fn main() -> Result<(), HuginnNetHttpError> {
    let db = Database::load_default()?;
    let mut analyzer = HuginnNetHttp::new(Some(&db), 1000)?;
    
    let (sender, receiver) = mpsc::channel::<HttpAnalysisResult>();
    
    let handle = thread::spawn(move || {
        analyzer.analyze_pcap("capture.pcap", sender, None)
    });
    
    for result in receiver {
        if let Some(http_request) = result.http_request {
            println!("{http_request}");
        }
        if let Some(http_response) = result.http_response {
            println!("{http_response}");
        }
    }
    
    handle.join().unwrap()?;
    Ok(())
}

For a complete working example, see examples/capture-http.rs.

Example Output

.-[ 1.2.3.4/1524 -> 4.3.2.1/80 (http request) ]-
|
| client   = 1.2.3.4/1524
| app      = Firefox:10.x or newer
| lang     = English
| params   = none
| raw_sig  = 1:Host,User-Agent,Accept=[,*/*;q=],?Accept-Language=[;q=],Accept-Encoding=[gzip, deflate],?DNT=[1],Connection=[keep-alive],?Referer:Accept-Charset,Keep-Alive:Firefox/
`----

.-[ 192.168.1.22/58494 -> 91.189.91.21/80 (http response) ]-
|
| server   = 91.189.91.21/80
| app      = nginx/1.14.0 (Ubuntu)
| params   = anonymous
| raw_sig  = server=[nginx/1.14.0 (Ubuntu)],date=[Tue, 17 Dec 2024 13:54:16 GMT],x-cache-status=[from content-cache-1ss/0],connection=[close]:Server,Date,X-Cache-Status,Connection:
`----

Documentation

For complete documentation, examples, and integration guides, see the main huginn-net README.

License

Dual-licensed under MIT or Apache 2.0.