Coder Social home page Coder Social logo

actix-ip-filter's Introduction

actix-ip-filter

Actix Middleware for IP filter. Support glob pattern.

Documentation

Usage

use actix_web::{App, HttpServer, HttpRequest, web, middleware};
use actix_ip_filter::IPFilter;

async fn index(req: HttpRequest) -> &'static str {
    "Hello world"
}

#[tokio::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| App::new()
        // enable logger
        .wrap(middleware::Logger::default())
        // setup ip filters
        .wrap(
            IPFilter::new()
                .allow(vec!["172.??.6*.12"])
                .block(vec!["192.168.1.222"])
        )
        // register simple route, handle all methods
        .service(web::resource("/").to(index))
    )
        .bind("0.0.0.0:8080")?;
    Ok(())
}

Limiting to certain paths

You can limit the allow/block actions to a certain set of patterns representing URL paths. The following code will only allow/block to paths matching the patterns /my/path* and /my/other/*.csv.

use actix_web::{App, HttpServer, HttpRequest, web, middleware};
use actix_ip_filter::IPFilter;

async fn i_am_protected() -> &'static str {
    "I am a protected resource"
}

async fn i_am_unprotected() -> &'static str {
    "I am NOT a protected resource"
}

#[tokio::main]
async fn main() -> std::io::Result<()> {


    HttpServer::new(|| App::new()
        // enable logger
        .wrap(middleware::Logger::default())
        // setup ip filters
        .wrap(
            IPFilter::new()
                .allow(vec!["172.??.6*.12"])
                .block(vec!["192.168.1.222"])
                .limit_to(vec!["/my/path/*"])
        )
        // register simple protected route
        .service(web::resource("/my/path/resource").to(i_am_protected))
        // register simple unprotected route
        .service(web::resource("/other/path/resource").to(i_am_unprotected))
    )
        .bind("0.0.0.0:8000");
    Ok(())
}

Allow and block callbacks

You can add an allow handler and a block handler. These handlers will be called whenever a request succeeds at passing an ip filter (allow handler) or it is blocked (block handler). This last allows you to customize the error response. The callbacks will not be called on unprotected paths.

The allow handler.

The allow handler must take three positional arguments and no return type:

use actix_ip_filter::IPFilter;
use actix_web::dev::ServiceRequest;

fn my_allow_handler(flt: &IPFilter, ip: &str, req: &ServiceRequest) {
    //Do smth
}

The parameters passed to the functions are borrows of the IPFilter, the ip of the request and the request.

You can attach the handler to an IPFilter like this:

use actix_web::{App, HttpServer, HttpRequest, web, middleware};
use actix_ip_filter::IPFilter;
use actix_web::dev::ServiceRequest;

fn my_allow_handler(flt: &IPFilter, ip: &str, req: &ServiceRequest) {
    //Do smth
}

async fn i_am_protected() -> &'static str {
    "I am a protected resource"
}

async fn i_am_unprotected() -> &'static str {
    "I am NOT a protected resource"
}

#[tokio::main]
async fn main() -> std::io::Result<()> {


    HttpServer::new(|| App::new()
        // enable logger
        .wrap(middleware::Logger::default())
        // setup ip filters
        .wrap(
            IPFilter::new()
                .allow(vec!["172.??.6*.12"])
                .block(vec!["192.168.1.222"])
                .limit_to(vec!["/my/path/*"])
                .on_allow(my_allow_handler)
        )
        // register simple protected route
        .service(web::resource("/my/path/resource").to(i_am_protected))
        // register simple unprotected route
        .service(web::resource("/other/path/resource").to(i_am_unprotected))
    )
        .bind("0.0.0.0:8000");
    Ok(())
}

The block handler

The allow handler must take three positional arguments and and optional body response as a response:

use actix_ip_filter::IPFilter;
use actix_web::dev::ServiceRequest;
use actix_web::HttpResponse;

fn my_block_handler(flt: &IPFilter, ip: &str, req: &ServiceRequest) -> Option<HttpResponse> {
    Some(HttpResponse::UseProxy().json("{\"result\": \"error\"}"))
}

The parameters passed to the functions are borrows of the IPFilter, the ip of the request and the request.

If the handler returns None, then the default error response is used. You can attach the handler to an IPFilter like this:

use actix_web::{App, HttpServer, HttpRequest, web, middleware};
use actix_ip_filter::IPFilter;
use actix_web::dev::ServiceRequest;
use actix_web::HttpResponse;

fn my_block_handler(flt: &IPFilter, ip: &str, req: &ServiceRequest) -> Option<HttpResponse> {
    Some(HttpResponse::UseProxy().json("{\"result\": \"error\"}"))
}

async fn i_am_protected() -> &'static str {
    "I am a protected resource"
}

async fn i_am_unprotected() -> &'static str {
    "I am NOT a protected resource"
}

#[tokio::main]
async fn main() -> std::io::Result<()> {


    HttpServer::new(|| App::new()
        // enable logger
        .wrap(middleware::Logger::default())
        // setup ip filters
        .wrap(
            IPFilter::new()
                .allow(vec!["172.??.6*.12"])
                .block(vec!["192.168.1.222"])
                .limit_to(vec!["/my/path/*"])
                .on_block(my_block_handler)
        )
        // register simple protected route
        .service(web::resource("/my/path/resource").to(i_am_protected))
        // register simple unprotected route
        .service(web::resource("/other/path/resource").to(i_am_unprotected))
    )
        .bind("0.0.0.0:8000");
    Ok(())
}

License: MIT

actix-ip-filter's People

Contributors

jhen0409 avatar paumava avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

Forkers

paumava

actix-ip-filter's Issues

Blocking a single path?

Hello!

I was wondering if there is any support to block a single path or pattern of paths instead of all requests app-wide.

For example, let's say I want to block /myapi/v1/protected but not the rest of the endpoints.

I know I could probably end up using wrap_fn and checking for the request path in the ServiceRequest and then returning:

IPFilter::new().allow(vec!["127.0.0.1"]).block(vec!["*.*.*.*"])

or

IPFilter::new().allow()

But I want something more idiomatic and concise. If this library doesn't support it I can try to implement it and open a PR if you are interested.

I have in mind using a vec of structs containing the IP pattern and the path pattern or also chaining a call to another function:

IPFilter::new().allow(
    vec![SingleFilter {
        ip: "127.0.0.1",
        path: "/myapi/v1/protected/*"     
    }]
).block(vec!["*.*.*.*"])

or

IPFilter::new().allow(vec!["127.0.0.1"]).block(vec!["*.*.*.*"]).limit_to("/myapi/v1/protected/*")

Let me know what you think about it ๐Ÿ˜„ !

no default features for actix-web

The dependency in Cargo.toml should ideally be:

- actix-web = "3.0.2"
+ actix-web = { version = "3.0.2", default-features = false }

Custom block response

There should be a way to modify the default Forbidden error response using a function handler.
For example:

fn my_custom_handler(filter: IPFilter, ip: &str) -> ServiceResponse {
     // Do smth
}
IPFilter::new().block(vec!["192.168.*.11?"]).on_block(my_custom_handler);

This would also bring the possibility to add an allow callback so that the user can do something like logging an IP when it is allowed through the IP filter:

fn my_custom_handler(filter: IPFilter, ip: &str) -> impl ServiceResponse {
     // Do smth
}

fn log_ip(filter: IPFilter, ip: &str) {
    // Do smth
}
IPFilter::new().block(vec!["192.168.*.11?"]).on_block(my_custom_handler).on_allow(log_ip);

I will try to implement this when #3 is merged or closed.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.