diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d7b6d6..693bc48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,17 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [0.1.18] - 2024-10-08 + +## Added +- 'Automatic Ban' section. +- Support for 'External Account Binding' in ACME providers. + +### Changed + +### Fixed +- Include nonce in OAuth code request. + ## [0.1.17] - 2024-10-07 ## Added diff --git a/Cargo.lock b/Cargo.lock index 4f2a51b..569adef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2387,7 +2387,7 @@ dependencies = [ [[package]] name = "webadmin" -version = "0.1.17" +version = "0.1.18" dependencies = [ "ahash", "base64", diff --git a/Cargo.toml b/Cargo.toml index 42ffe14..e6dabbd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ homepage = "https://stalw.art" keywords = ["web", "admin", "email", "mail", "server"] categories = ["email"] license = "AGPL-3.0-only OR LicenseRef-SEL" -version = "0.1.17" +version = "0.1.18" edition = "2021" resolver = "2" diff --git a/src/pages/config/mod.rs b/src/pages/config/mod.rs index 454888d..ab2216e 100644 --- a/src/pages/config/mod.rs +++ b/src/pages/config/mod.rs @@ -473,9 +473,9 @@ impl LayoutBuilder { // Security .create("Security") .icon(view! { }) - // Fail2ban - .create("Fail2ban") - .route("/fail2ban/edit") + // Threat Shield + .create("Automatic Ban") + .route("/auto-ban/edit") .insert(true) // Blocked IPs .create("Blocked IPs") diff --git a/src/pages/config/schema/server.rs b/src/pages/config/schema/server.rs index ac7ebc5..347e853 100644 --- a/src/pages/config/schema/server.rs +++ b/src/pages/config/schema/server.rs @@ -305,34 +305,74 @@ impl Builder { .list_fields(["_id"]) .no_list_action(Action::Modify) .build() - // Fail2ban settings - .new_schema("fail2ban") - .new_field("server.fail2ban.authentication") + // Auto-ban settings + .new_schema("auto-ban") + .new_field("server.auto-ban.auth.rate") .label("Auth failures") .help("The maximum number of failed login attempts before the IP is banned") .typ(Type::Rate) .default("100/1d") .build() - .new_field("server.fail2ban.invalid-rcpt") - .label("Brute force") - .help("The maximum number of brute force attempts before the IP is banned") + .new_field("server.auto-ban.scan.rate") + .label("Scanning attempts") + .help(concat!( + "The maximum number of port scanning attempts before the IP is banned" + )) + .typ(Type::Rate) + .default("30/1d") + .build() + .new_field("server.auto-ban.abuse.rate") + .label("Abuse attempts") + .help(concat!( + "The maximum number of abuse attempts (relaying or failed ", + "RCPT TO attempts) before the IP is banned" + )) .typ(Type::Rate) .default("35/1d") .build() - .new_field("server.fail2ban.loitering") + .new_field("server.auto-ban.loiter.rate") .label("Loitering") .help("The maximum number of loitering disconnections before the IP is banned") .typ(Type::Rate) .default("150/1d") .build() + .new_field("server.auto-ban.scan.paths") + .label("HTTP banned paths") + .help(concat!( + "The paths that will trigger an immediate ban if accessed. ", + "Each path should be a glob expression" + )) + .typ(Type::Array) + .input_check([Transformer::Trim], []) + .default( + &[ + "*.php*", + "*.cgi*", + "*.asp*", + "*/wp-*", + "*/php*", + "*/cgi-bin*", + "*xmlrpc*", + "*../*", + "*/..*", + "*joomla*", + "*wordpress*", + "*drupal*", + ][..], + ) + .build() .new_form_section() - .title("Fail2ban settings") + .title("Automatic banning") .fields([ - "server.fail2ban.authentication", - "server.fail2ban.invalid-rcpt", - "server.fail2ban.loitering", + "server.auto-ban.auth.rate", + "server.auto-ban.abuse.rate", + "server.auto-ban.loiter.rate", ]) .build() + .new_form_section() + .title("Port scanning ban") + .fields(["server.auto-ban.scan.rate", "server.auto-ban.scan.paths"]) + .build() .build() // Clustering .new_schema("cluster") diff --git a/src/pages/config/schema/tls.rs b/src/pages/config/schema/tls.rs index bb82213..9e44b78 100644 --- a/src/pages/config/schema/tls.rs +++ b/src/pages/config/schema/tls.rs @@ -25,6 +25,20 @@ impl Builder { .input_check([Transformer::Trim], [Validator::Required, Validator::IsUrl]) .default("https://acme-v02.api.letsencrypt.org/directory") .build() + // EAB Key + .new_field("eab.kid") + .label("Key ID") + .help("The External Account Binding (EAB) key ID") + .typ(Type::Input) + .input_check([Transformer::Trim], []) + .build() + // EAB Key + .new_field("eab.hmac-key") + .label("HMAC Key") + .help("The External Account Binding (EAB) HMAC key") + .typ(Type::Secret) + .input_check([Transformer::Trim], []) + .build() // Domains .new_field("domains") .typ(Type::Array) @@ -220,6 +234,10 @@ impl Builder { ]) .build() .new_form_section() + .title("External Account Binding") + .fields(["eab.kid", "eab.hmac-key"]) + .build() + .new_form_section() .title("DNS settings") .display_if_eq("challenge", ["dns-01"]) .fields([ diff --git a/src/pages/config/schema/tracing.rs b/src/pages/config/schema/tracing.rs index 34e26f1..8944c14 100644 --- a/src/pages/config/schema/tracing.rs +++ b/src/pages/config/schema/tracing.rs @@ -659,16 +659,20 @@ pub static EVENT_NAMES: &[&str] = &[ "acme.tls-alpn-error", "acme.tls-alpn-received", "acme.token-not-found", + "ai.api-error", + "ai.llm-response", "arc.broken-chain", "arc.chain-too-long", "arc.has-header-tag", "arc.invalid-cv", "arc.invalid-instance", "arc.sealer-not-found", + "auth.client-registration", "auth.error", "auth.failed", "auth.missing-totp", "auth.success", + "auth.token-expired", "auth.too-many-attempts", "cluster.decryption-error", "cluster.empty-packet", @@ -1021,10 +1025,11 @@ pub static EVENT_NAMES: &[&str] = &[ "resource.error", "resource.not-found", "resource.webadmin-unpacked", + "security.abuse-ban", "security.authentication-ban", - "security.brute-force-ban", "security.ip-blocked", "security.loiter-ban", + "security.scan-ban", "security.unauthorized", "server.licensing", "server.shutdown", diff --git a/src/pages/enterprise/dashboard.rs b/src/pages/enterprise/dashboard.rs index cf8fc4e..4c32230 100644 --- a/src/pages/enterprise/dashboard.rs +++ b/src/pages/enterprise/dashboard.rs @@ -315,7 +315,8 @@ pub fn Dashboard() -> impl IntoView { &metrics, &[ &["security.authentication-ban"], - &["security.brute-force-ban"], + &["security.abuse-ban"], + &["security.scan-ban"], &["security.loiter-ban"], &["security.ip-blocked"], ], @@ -675,7 +676,8 @@ pub fn Dashboard() -> impl IntoView { .sum( &[ "security.authentication-ban", - "security.brute-force-ban", + "security.abuse-ban", + "security.scan-ban", "security.loiter-ban", ], )