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.