firewall

Crates.iofirewall
lib.rsfirewall
version0.3.7
sourcesrc
created_at2023-12-24 01:18:08.929746
updated_at2024-09-22 17:59:38.204414
descriptionConnection rejection abstraction
homepage
repositoryhttps://github.com/programingjd/firewall
max_upload_size
id1079391
size74,011
DAVID, Jerome (programingjd)

documentation

README

Firewall   LICENSE crates.io Version Documentation

The Firewall trait is meant to be used by servers to abstract the logic of blocking incoming requests.

Its accept method is provided an ip address (v4 or v6) and if the connection is over TLS, access to the server name from the SNI extension, and the client supported protocols from the ALPN extension.

The ClientHello trait is used to make the Firewall trait agnostic over the TLS implementation.


For servers who only need/want those 2 traits, the default features should be disabled.

Cargo.toml

[dependencies.firewall]
version = "0.1"
default-features = false

The rustls feature provides an implementation of the ClientHello trait for rustls.

The openssl feature provides an implementation of the ClientHello trait for openssl.


The builder feature provides an implementation of the Firewall trait.

let firewall = Firewall::default()
    .require_sni()
    .allow_server_name("example.com")
    .allow_ip_range("1.2.3.4/30");

You can have a list of allowed ip ranges, and a list of denied ip ranges (both ipv4 and ipv6).

You can also add an exception based on the TLS ClientHello content.

A good use case for this is if you want to renew Let's Encrypt certificates with the TLS-ALPN-01 challenge. Let's Encrypt doesn't provide a list of ips that they use to validate the challenges. You can add an exception to bypass the allow list if the acme-tls/1 protocol is listed in the TLS ALPN extension.

struct AcmeTlsSni01Exception {}

impl TlsAccept for AcmeTlsSni01Exception {
    fn accept(&self, client_hello: impl ClientHello) -> AcceptDenyOverride {
        if client_hello.has_alpn(b"acme-tls/1") {
            AcceptDenyOverride::AcceptAndBypassAllowList
        } else if client_hello.has_alpn(b"http/1.1") {
            AcceptDenyOverride::Accept
        } else {
            AcceptDenyOverride::Deny
        }
    }
}

let firewall = firewall
    .with_exception(AcmeTlsSni01Exception {});

The cloudflare feature adds a method on Firewall to apply the official allow list for Cloudflare servers.

let firewall = Firewall::default()
    .try_allow_cloudflare_ips()
    .await
    .unwrap();

This is useful if your server is behind the Cloudflare CDN and you don't want to allow any other server to contact your origin server directly.

There's a public fetch_cloudflare_ip_ranges() function available if you want to make sure that the list is up to date.


The github_webhook feature adds a method on Firewall to apply the official allow list for Github webhook servers.

let firewall = Firewall::default()
    .try_allow_github_webhook_ips()
    .await
    .unwrap();

There's a public fetch_github_webhook_ip_ranges() function available if you want to make sure that the list is up to date.

Commit count: 26

cargo fmt