[−][src]Crate m_captcha
mCaptcha is a proof of work based Denaial-of-Service attack protection system. This is is a server library that you can embed in your services to protect your servers.
A commercial managed solution is in the works but I'd much rather prefer folks host their own instances as it will make the more decentralized and free.
In mCaptcha, defense is adjusted in discrete levels that depend on the ammount of traffic that a service is experiencing. So users of this library are requested to benchmark their target machines before configuring their mCaptcha component.
Terminology:
- Difficulty(Factor): Minimum ammount of work that a client must do to make a valid request.
- Defense: A datatype that various visitor-difficulty mappigns
- Visitor: Smallest unit of traffic, usually a single request. The more you have, the busier your service is. Determines mCaptcha defense defense
- Visitor threshold: The threshold at which MCaptcha will adjust defense defense
- Cache : A datatype that implements Save. Used to store PoW requirements to defend against replay attacks and dictionary attacks.
- Master: A datatype that manages MCaptcha actors. Works like a DNS for AddVisitor messages.
- System: mCaptcha system that manages cache, master and provides useful abstractions. An mCaptcha system/instance can have only a single System
Example:
use m_captcha::{ cache::HashCache, master::{AddSiteBuilder, Master}, pow::{ConfigBuilder, Work}, system::SystemBuilder, DefenseBuilder, LevelBuilder, MCaptchaBuilder, }; // traits from actix needs to be in scope for starting actor use actix::prelude::*; #[actix_rt::main] async fn main() -> std::io::Result<()> { // start cahce actor // cache is used to store PoW requirements that are sent to clients // This way, it can be verified that the client computed work over a config // that _we_ sent. Offers protection against rainbow tables powered dictionary attacks let cache = HashCache::default().start(); // create PoW config with unique salt. Salt has to be safely guarded. // salts protect us from replay attacks let pow = ConfigBuilder::default() .salt("myrandomsaltisnotlongenoug".into()) .build() .unwrap(); // start master actor. Master actor is responsible for managing MCaptcha actors // each mCaptcha system should have only one master let master = Master::new(5).start(); // Create system. System encapsulates master and cache and provides useful abstraction // each mCaptcha system should have only one system let system = SystemBuilder::default() .master(master) .cache(cache) .pow(pow.clone()) .build() .unwrap(); // configure defense. This is a per site configuration. A site can have several levels // of defenses configured let defense = DefenseBuilder::default() // add as many defense as you see fit .add_level( LevelBuilder::default() // visitor_threshold is the threshold/limit at which // mCaptcha will adjust difficulty defense // it is advisable to set small values for the first // defense visitor_threshold and difficulty_factor // as this will be the work that clients will be // computing when there's no load .visitor_threshold(50) .difficulty_factor(500) .unwrap() .build() .unwrap(), ) .unwrap() .add_level( LevelBuilder::default() .visitor_threshold(5000) .difficulty_factor(50000) .unwrap() .build() .unwrap(), ) .unwrap() .build() .unwrap(); // create and start MCaptcha actor that uses the above defense configuration // This is what manages the difficulty factor of sites that an mCaptcha protects let mcaptcha = MCaptchaBuilder::default() .defense(defense) // leaky bucket algorithm's emission interval .duration(30) // .cache(cache) .build() .unwrap() .start(); // unique value identifying an MCaptcha actor let mcaptcha_name = "batsense.net"; // add MCaptcha to Master let msg = AddSiteBuilder::default() .id(mcaptcha_name.into()) .addr(mcaptcha.clone()) .build() .unwrap(); system.master.send(msg).await.unwrap(); // Get PoW config. Should be called everytime there's a visitor for a // managed site(here mcaptcha_name) let work_req = system.get_pow(mcaptcha_name.into()).await.unwrap(); // the following computation should be done on the client but for the purpose // of this illustration, we are going to do it on the server it self let work = pow .prove_work(&work_req.string, work_req.difficulty_factor) .unwrap(); // the payload that the client sends to the server let payload = Work { string: work_req.string, result: work.result, nonce: work.nonce, }; // Server evaluates client's work. Returns true if everything // checksout and Err() if something fishy is happening let res = system.verify_pow(payload.clone()).await.unwrap(); assert!(res); Ok(()) }
Re-exports
pub use crate::cache::hashcache::HashCache; |
pub use defense::Defense; |
pub use defense::DefenseBuilder; |
pub use defense::LevelBuilder; |
pub use mcaptcha::MCaptcha; |
pub use mcaptcha::MCaptchaBuilder; |
Modules
cache | message datatypes to interact with MCaptcha actor Cache is used to save proofof work details and nonces to prevent replay attacks and rainbow/dictionary attacks |
defense | Defense datatypes |
errors | Errors and Result module |
master | |
mcaptcha | MCaptcha actor module that manages defense levels |
pow | PoW datatypes used in client-server interaction |
system | module describing mCaptcha system |