Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

coraza-rs

Safe Rust bindings to OWASP Coraza Web Application Firewall, based on the official C bindings.

Coraza is a Go-based WAF compatible with ModSecurity's SecLang. This repository provides Rust crates to embed Coraza into Rust applications.

Crates

Crate Description
coraza Safe, idiomatic Rust API
coraza-sys Raw FFI bindings (auto-generated from C header)
examples Usage examples

Quick Start

use coraza::WafConfig;

fn main() {
    let waf = WafConfig::new()
        .unwrap()
        .with_directives("SecRuleEngine DetectionOnly")
        .with_directives("SecRequestBodyAccess On")
        .build()
        .unwrap();

    let mut tx = waf.new_transaction();

    tx.process_connection("127.0.0.1", 8080, "localhost", 80).unwrap();
    tx.process_uri("/path", "GET", "HTTP/1.1").unwrap();
    tx.add_request_header("Host", "localhost");
    tx.process_request_headers().unwrap();
    tx.process_logging();

    if let Some(intervention) = tx.intervention() {
        eprintln!("Blocked with status {}", intervention.status);
    }
}

Build Requirements

  • Rust 1.75+ (edition 2021)
  • Go 1.21+ (for compiling the Coraza WAF engine)
  • C compiler (gcc/clang on Unix, MSVC on Windows)
  • libclang (for bindgen)

On Ubuntu/Debian:

sudo apt install golang-go libclang-dev

On macOS:

brew install go llvm

Building

cargo build

The first build compiles the Go WAF engine into a static library and generates Rust FFI bindings. Subsequent builds are fast.

Examples

cargo run --bin simple_get
cargo run --bin deny_rule
cargo run --bin with_callbacks

simple_get

Minimal WAF usage with DetectionOnly mode — processes a GET request and checks for interventions.

deny_rule

WAF with a deny rule that blocks requests from specific IPs — demonstrates handling a 403 intervention.

with_callbacks

Registers debug log and error callbacks — shows how to capture matched rule details.

API Overview

Configuration

use coraza::{WafConfig, LogLevel};

let waf = WafConfig::new()?
    .with_directives("SecRuleEngine On")
    .with_directives("SecRequestBodyAccess On")
    .with_debug_log_callback(|level, msg, fields| {
        eprintln!("[{level}] {msg} {fields}");
    })
    .with_error_callback(|rule| {
        eprintln!("Rule {} matched: {}", rule.rule_id, rule.message);
    })
    .build()?;

Transaction Processing

Transactions follow Coraza's phase-based lifecycle:

let mut tx = waf.new_transaction();

// Phase 0: Connection & URI
tx.process_connection("127.0.0.1", 8080, "localhost", 80)?;
tx.process_uri("/path", "GET", "HTTP/1.1")?;

// Phase 1: Request headers
tx.add_request_header("Host", "localhost");
tx.process_request_headers()?;  // may return Err(Intervention)

// Phase 2: Request body (if SecRequestBodyAccess On)
tx.append_request_body(b"hello=world")?;
tx.process_request_body()?;

// Phase 3: Response headers
tx.process_response_headers(200, "HTTP/1.1")?;

// Phase 4: Response body (if SecResponseBodyAccess On)
tx.append_response_body(b"<html>...</html>")?;
tx.process_response_body()?;

// Phase 5: Logging (always run, even on interruption)
tx.process_logging();

// Check for rule matches
if let Some(intervention) = tx.intervention() {
    eprintln!("Blocked: {}", intervention.status);
}

Thread Safety

Type Send Sync Notes
Waf Yes Yes Immutable after creation; safe to share for concurrent transaction creation
WafConfig Yes No Builder consumed by build()
Transaction Yes No Mutable state; must not be shared across threads

License

Licensed under the Apache License, Version 2.0.

About

Safe Rust bindings to OWASP Coraza Web Application Firewall

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages