| Crates.io | huginn-net |
| lib.rs | huginn-net |
| version | 1.4.6 |
| created_at | 2025-07-05 12:47:59.124886+00 |
| updated_at | 2025-09-14 14:57:04.447916+00 |
| description | Multi-protocol passive fingerprinting library: TCP/HTTP (p0f-style) + TLS (JA4) analysis |
| homepage | |
| repository | https://github.com/biandratti/huginn-net |
| max_upload_size | |
| id | 1739051 |
| size | 1,615,019 |

Huginn Net combines p0f TCP fingerprinting with JA4 TLS client analysis, achieving the same detection accuracy as the original p0f tool while adding modern TLS fingerprinting capabilities. This Rust implementation has been thoroughly validated against real-world traffic and consistently delivers reliable fingerprinting results.
Passive Traffic Fingerprinting is a technique that allows you to infer information about remote hosts and applications without sending any probes. By analyzing characteristics of the TCP/IP packets and TLS handshakes that are exchanged during normal network conversations, Huginn Net provides insights into:
| Layer | Protocol / Feature | Huginn Net Analysis |
|---|---|---|
| 7 | TLS | JA4 (FoxIO-style) |
| 7 | HTTP | HTTP/1 & HTTP/2 - Headers, User-Agent, Lang |
| 4 | TCP | OS Fingerprinting (p0f-style) |
[dependencies]
huginn-net = "1.4.6"
use huginn_net::{Database, HuginnNet};
use std::sync::mpsc;
// Load signature database and create analyzer
let db = match Database::load_default() {
Ok(db) => db,
Err(e) => {
error!("Failed to load default database: {}", e);
return;
}
};
let (sender, receiver) = mpsc::channel();
let mut analyzer = match HuginnNet::new(Some(&db), 100, None) {
Ok(analyzer) => analyzer,
Err(e) => {
error!("Failed to create HuginnNet analyzer: {}", e);
return;
}
};
// Analyze network traffic (choose one)
std::thread::spawn(move || {
// Live network capture
analyzer.analyze_network("eth0", sender, None);
// OR PCAP file analysis
// analyzer.analyze_pcap("traffic.pcap", sender, None);
});
// Process results
for output in receiver {
if let Some(syn) = output.syn {
info!("{}", syn);
}
if let Some(syn_ack) = output.syn_ack {
info!("{}", syn_ack);
}
if let Some(mtu) = output.mtu {
info!("{}", mtu);
}
if let Some(uptime) = output.uptime {
info!("{}", uptime);
}
if let Some(http_request) = output.http_request {
info!("{}", http_request);
}
if let Some(http_response) = output.http_response {
info!("{}", http_response);
}
if let Some(tls_client) = output.tls_client {
info!("{}", tls_client);
}
}
.-[ 1.2.3.4/1524 -> 4.3.2.1/80 (syn) ]-
|
| client = 1.2.3.4/1524
| os = Windows XP
| dist = 8
| params = none
| raw_sig = 4:120+8:0:1452:65535,0:mss,nop,nop,sok:df,id+:0
`----
.-[ 1.2.3.4/1524 -> 4.3.2.1/80 (syn+ack) ]-
|
| server = 4.3.2.1/80
| os = Linux 3.x
| dist = 0
| params = none
| raw_sig = 4:64+0:0:1460:mss*10,0:mss,nop,nop,sok:df:0
`----
.-[ 1.2.3.4/1524 -> 4.3.2.1/80 (mtu) ]-
|
| client = 1.2.3.4/1524
| link = DSL
| raw_mtu = 1492
`----
.-[ 1.2.3.4/1524 -> 4.3.2.1/80 (uptime) ]-
|
| client = 1.2.3.4/1524
| uptime = 0 days 11 hrs 16 min (modulo 198 days)
| raw_freq = 250.00 Hz
`----
.-[ 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:
`----
.-[ 192.168.1.10/45234 -> 172.217.5.46/443 (tls client) ]-
|
| client = 192.168.1.10/45234
| ja4 = t13d1516h2_8daaf6152771_b0da82dd1658
| ja4_r = t13d1516h2_002f,0035,009c,009d,1301,1302,1303_0005,000a,000b,000d,0012,0015,002b,0033,002d
| ja4_o = t13d1516h2_8daaf6152771_b0da82dd1658
| ja4_or = t13d1516h2_002f,0035,009c,009d,1301,1302,1303_0005,000a,000b,000d,0012,0015,002b,0033,002d
| sni = www.google.com
| version = 1.3
`----
See benches/README.md for detailed performance analysis.
Based on signatures available in the p0f database. See config/p0f.fp for complete signature list.
The current signature database includes patterns for:
Huginn Net provides intelligent quality scoring for all fingerprint matches, helping you assess the reliability of each detection. The quality score is calculated based on the distance between observed network characteristics and known signatures. To achieve the best quality in matching, a rich database will be needed.
This implementation follows the official JA4 specification by FoxIO, LLC for TLS client fingerprinting. For full attribution and licensing details, please see the Licensing & Attribution section. We do not implement JA4+ components which are under FoxIO License 1.1.
For visual analysis and experimentation, use our companion web application:
huginn-net-profiler: Passive Network Profile Analyzer
Live Demo: https://huginn-net.duckdns.org/
Features:
We welcome contributions! Please see our Contributing Guide for detailed information on how to get started.
Your signature contributions directly improve detection accuracy for the entire community!
Dual-licensed under MIT or Apache 2.0.
huginn-net is an independent Rust implementation inspired by the methodologies of p0f and JA4.
huginn-net and does not use any code from the original JA4 repository. JA4 methodology and specification are Copyright (c) 2023, FoxIO, LLC.