Skip to content

Commit c291110

Browse files
DanGouldspacebear21
authored andcommitted
Add GeoIP region filtering middleware
Add access-control feature to payjoin-mailroom providing IP-based region filtering via axum middleware. Requests from blocked ISO country codes are rejected at the network layer. A free DB-IP Lite database is fetched automatically when no explicit path is configured.
1 parent 1908139 commit c291110

10 files changed

Lines changed: 429 additions & 17 deletions

File tree

Cargo-minimal.lock

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1413,9 +1413,9 @@ dependencies = [
14131413

14141414
[[package]]
14151415
name = "flate2"
1416-
version = "1.0.33"
1416+
version = "1.1.9"
14171417
source = "registry+https://github.com/rust-lang/crates.io-index"
1418-
checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253"
1418+
checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c"
14191419
dependencies = [
14201420
"crc32fast",
14211421
"miniz_oxide",
@@ -2090,6 +2090,12 @@ version = "2.10.0"
20902090
source = "registry+https://github.com/rust-lang/crates.io-index"
20912091
checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4"
20922092

2093+
[[package]]
2094+
name = "ipnetwork"
2095+
version = "0.21.1"
2096+
source = "registry+https://github.com/rust-lang/crates.io-index"
2097+
checksum = "cf370abdafd54d13e54a620e8c3e1145f28e46cc9d704bc6d94414559df41763"
2098+
20932099
[[package]]
20942100
name = "iri-string"
20952101
version = "0.7.8"
@@ -2280,6 +2286,19 @@ version = "0.8.4"
22802286
source = "registry+https://github.com/rust-lang/crates.io-index"
22812287
checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3"
22822288

2289+
[[package]]
2290+
name = "maxminddb"
2291+
version = "0.27.3"
2292+
source = "registry+https://github.com/rust-lang/crates.io-index"
2293+
checksum = "76371bd37ce742f8954daabd0fde7f1594ee43ac2200e20c003ba5c3d65e2192"
2294+
dependencies = [
2295+
"ipnetwork",
2296+
"log",
2297+
"memchr",
2298+
"serde",
2299+
"thiserror 2.0.17",
2300+
]
2301+
22832302
[[package]]
22842303
name = "memchr"
22852304
version = "2.7.4"
@@ -2311,11 +2330,12 @@ dependencies = [
23112330

23122331
[[package]]
23132332
name = "miniz_oxide"
2314-
version = "0.8.0"
2333+
version = "0.8.9"
23152334
source = "registry+https://github.com/rust-lang/crates.io-index"
2316-
checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1"
2335+
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
23172336
dependencies = [
23182337
"adler2",
2338+
"simd-adler32",
23192339
]
23202340

23212341
[[package]]
@@ -2777,6 +2797,8 @@ dependencies = [
27772797
"axum-server",
27782798
"clap",
27792799
"config",
2800+
"flate2",
2801+
"maxminddb",
27802802
"ohttp-relay",
27812803
"opentelemetry",
27822804
"opentelemetry-otlp",
@@ -3822,6 +3844,12 @@ dependencies = [
38223844
"libc",
38233845
]
38243846

3847+
[[package]]
3848+
name = "simd-adler32"
3849+
version = "0.3.8"
3850+
source = "registry+https://github.com/rust-lang/crates.io-index"
3851+
checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2"
3852+
38253853
[[package]]
38263854
name = "similar"
38273855
version = "2.7.0"

Cargo-recent.lock

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1413,9 +1413,9 @@ dependencies = [
14131413

14141414
[[package]]
14151415
name = "flate2"
1416-
version = "1.0.33"
1416+
version = "1.1.9"
14171417
source = "registry+https://github.com/rust-lang/crates.io-index"
1418-
checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253"
1418+
checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c"
14191419
dependencies = [
14201420
"crc32fast",
14211421
"miniz_oxide",
@@ -2090,6 +2090,12 @@ version = "2.10.0"
20902090
source = "registry+https://github.com/rust-lang/crates.io-index"
20912091
checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4"
20922092

2093+
[[package]]
2094+
name = "ipnetwork"
2095+
version = "0.21.1"
2096+
source = "registry+https://github.com/rust-lang/crates.io-index"
2097+
checksum = "cf370abdafd54d13e54a620e8c3e1145f28e46cc9d704bc6d94414559df41763"
2098+
20932099
[[package]]
20942100
name = "iri-string"
20952101
version = "0.7.8"
@@ -2280,6 +2286,19 @@ version = "0.8.4"
22802286
source = "registry+https://github.com/rust-lang/crates.io-index"
22812287
checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3"
22822288

2289+
[[package]]
2290+
name = "maxminddb"
2291+
version = "0.27.3"
2292+
source = "registry+https://github.com/rust-lang/crates.io-index"
2293+
checksum = "76371bd37ce742f8954daabd0fde7f1594ee43ac2200e20c003ba5c3d65e2192"
2294+
dependencies = [
2295+
"ipnetwork",
2296+
"log",
2297+
"memchr",
2298+
"serde",
2299+
"thiserror 2.0.17",
2300+
]
2301+
22832302
[[package]]
22842303
name = "memchr"
22852304
version = "2.7.4"
@@ -2311,11 +2330,12 @@ dependencies = [
23112330

23122331
[[package]]
23132332
name = "miniz_oxide"
2314-
version = "0.8.0"
2333+
version = "0.8.9"
23152334
source = "registry+https://github.com/rust-lang/crates.io-index"
2316-
checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1"
2335+
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
23172336
dependencies = [
23182337
"adler2",
2338+
"simd-adler32",
23192339
]
23202340

23212341
[[package]]
@@ -2777,6 +2797,8 @@ dependencies = [
27772797
"axum-server",
27782798
"clap",
27792799
"config",
2800+
"flate2",
2801+
"maxminddb",
27802802
"ohttp-relay",
27812803
"opentelemetry",
27822804
"opentelemetry-otlp",
@@ -3822,6 +3844,12 @@ dependencies = [
38223844
"libc",
38233845
]
38243846

3847+
[[package]]
3848+
name = "simd-adler32"
3849+
version = "0.3.8"
3850+
source = "registry+https://github.com/rust-lang/crates.io-index"
3851+
checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2"
3852+
38253853
[[package]]
38263854
name = "similar"
38273855
version = "2.7.0"

flake.nix

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@
8585
filter =
8686
path: type:
8787
(builtins.match ".*nginx.conf.template$" path != null)
88+
|| (builtins.match ".*\\.mmdb$" path != null)
8889
|| (craneLibVersions.msrv.filterCargoSources path type);
8990
name = "source";
9091
};
@@ -162,7 +163,7 @@
162163
"payjoin-cli" = "--features v1,v2";
163164
"payjoin-directory" = "";
164165
"ohttp-relay" = "";
165-
"payjoin-mailroom" = "--features acme,telemetry";
166+
"payjoin-mailroom" = "--features access-control,acme,telemetry";
166167
};
167168

168169
# nix2container for building OCI/Docker images

payjoin-mailroom/Cargo.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ acme = [
2222
"dep:rustls",
2323
"dep:tokio-stream",
2424
]
25+
access-control = ["dep:flate2", "dep:maxminddb", "dep:reqwest"]
2526
telemetry = ["dep:opentelemetry-otlp"]
2627

2728
[dependencies]
@@ -32,6 +33,8 @@ axum-server = { version = "0.8", features = [
3233
], optional = true }
3334
clap = { version = "4.5", features = ["derive", "env"] }
3435
config = "0.15"
36+
flate2 = { version = "1.1", optional = true }
37+
maxminddb = { version = "0.27", optional = true }
3538
ohttp-relay = { path = "../ohttp-relay", features = ["bootstrap"] }
3639
opentelemetry = "0.31"
3740
opentelemetry-otlp = { version = "0.31", optional = true, features = [
@@ -40,6 +43,9 @@ opentelemetry-otlp = { version = "0.31", optional = true, features = [
4043
opentelemetry_sdk = "0.31"
4144
payjoin-directory = { path = "../payjoin-directory" }
4245
rand = "0.8"
46+
reqwest = { version = "0.12", default-features = false, features = [
47+
"rustls-tls",
48+
], optional = true }
4349
rustls = { version = "0.23", default-features = false, features = [
4450
"ring",
4551
], optional = true }
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Payjoin Mailroom configuration example
2+
#
3+
# Configuration can also be set via environment variables with the `PJ_`
4+
# prefix. Nested values use double underscores as separators, e.g.
5+
# PJ_ACCESS_CONTROL__BLOCKED_REGIONS=CU,IR,KP,SY
6+
7+
# Address and port to listen on
8+
# listener = "[::]:8080"
9+
10+
# Directory for persistent storage (OHTTP keys, caches, etc.)
11+
# storage_dir = "./data"
12+
13+
# Request timeout in seconds
14+
# timeout = 30
15+
16+
# --- Access-control (requires `access-control` feature) ---
17+
# [access_control]
18+
19+
# Optional path to a MaxMind GeoIP2 / DB-IP Country database.
20+
# If omitted but blocked_regions is non-empty, a free DB-IP Lite
21+
# database will be fetched automatically and cached under storage_dir.
22+
# geo_db_path = "/path/to/GeoIP2-Country.mmdb"
23+
24+
# ISO 3166-1 alpha-2 country codes whose requests should be blocked.
25+
# blocked_regions = ["CU", "IR", "KP", "SY"]
26+
27+
# Path to a local file containing blocked Bitcoin addresses (one per line).
28+
# Used for V1 PSBT screening.
29+
# blocked_addresses_path = "/path/to/blocked_addresses.txt"
30+
31+
# URL to periodically fetch an updated blocked-address list from.
32+
# blocked_addresses_url = "https://example.com/blocked_addresses.txt"
33+
34+
# How often (in seconds) to refresh the remote address list (default: 86400).
35+
# blocked_addresses_refresh_secs = 86400

0 commit comments

Comments
 (0)