Skip to content

Commit cdfb5fc

Browse files
chore: cleanup header code, change default client_ip_headers
Signed-off-by: Henry <mail@henrygressmann.de>
1 parent e6611f3 commit cdfb5fc

10 files changed

Lines changed: 327 additions & 411 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,20 @@ Since this is not a library, this changelog focuses on the changes that are rele
2020
2121
## [Unreleased]
2222

23-
### Features
23+
### ⚠️ Breaking Changes
2424

25-
- Added provider presets for client IP headers and support for reading GeoIP data from provider or custom headers
25+
- Proxy-provided client IP headers are no longer trusted by default. Configure `client_ip_headers` to opt in
2626

27-
### Bug Fixes
27+
### Features
2828

29+
- Added client IP header presets for Akamai, Cloudflare, CloudFront, Fastly, and Fly
30+
- Added GeoIP header mappings and presets for Akamai, Cloudflare, CloudFront, Netlify, and Vercel, with MaxMind results taking precedence when available
2931
- Tracker requests now avoid CORS preflight requests by sending JSON as `text/plain` and the event API accepts tracker JSON regardless of content type
3032

3133
### Other
3234

3335
- Renamed `trusted_headers` to `client_ip_headers` (the old name remains supported)
36+
- Removed the redundant `use_forward_headers` option
3437

3538
## [v1.6.0] - 2026-06-20
3639

‎Cargo.lock‎

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Cargo.toml‎

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,6 @@ tokio = { version = "1.53", default-features = false, features = [
3030
] }
3131
tokio-util = { version = "0.7", features = ["io"] }
3232

33-
argon2 = { version = "0.6.0-rc.8", features = [] }
34-
async-compression = { version = "0.4", default-features = false, features = [
35-
"gzip",
36-
"tokio"
37-
] }
38-
blake3 = { version = "1.8" }
3933
# encoding
4034
hex = { version = "0.4" }
4135
md-5 = { version = "0.11.0" }
@@ -48,10 +42,23 @@ serde_json = { version = "1.0" }
4842
tokio-tar = { package = "astral-tokio-tar", version = "0.6" }
4943
zstd = { version = "0.13", default-features = false }
5044

45+
# general
5146
ahash = "0.8"
47+
aide = { version = "0.16.0-alpha.4", default-features = false, features = [
48+
"axum",
49+
"axum-extra-cookie",
50+
"axum-extra-headers",
51+
"axum-json",
52+
"axum-matched-path",
53+
] }
5254
anyhow = { version = "1.0" }
53-
# general
5455
argh = { version = "0.1", default-features = false, features = ["help"] }
56+
argon2 = { version = "0.6.0-rc.8", features = [] }
57+
async-compression = { version = "0.4", default-features = false, features = [
58+
"gzip",
59+
"tokio"
60+
] }
61+
blake3 = { version = "1.8" }
5562
chrono = { version = "0.4", default-features = false, features = [
5663
"now",
5764
"serde",
@@ -67,13 +74,6 @@ rand = { version = "0.10", default-features = false, features = [
6774
tracing = { version = "0.1", default-features = false, features = ["std"] }
6875
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
6976

70-
aide = { version = "0.16.0-alpha.4", default-features = false, features = [
71-
"axum",
72-
"axum-extra-cookie",
73-
"axum-extra-headers",
74-
"axum-json",
75-
"axum-matched-path",
76-
] }
7777
# web
7878
axum = { version = "0.8", default-features = false, features = [
7979
"http1",
@@ -89,7 +89,7 @@ axum-extra = { version = "0.12", default-features = false, features = [
8989
] }
9090
headers = "0.4"
9191
http = "1.5"
92-
ipnet = "2.12"
92+
ipnet = { version = "2.12", features = ["serde"] }
9393
reqwest = { version = "0.13", default-features = false, features = [
9494
"charset",
9595
"json",

‎data/config.example.toml‎

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,35 @@
11
base_url = "http://localhost:9042" # The base URL of the Liwan instance
22
listen = 9042 # The port to listen on (http)
33

4-
# Disable favicon fetching from the DuckDuckGo API.
4+
# # Disable favicon fetching from the DuckDuckGo API.
55
# disable_favicons=false
66

77
# # Folder to store the database in (Will be created if it doesn't exist)
88
# # defaults to $HOME/.local/share/liwan/data on linux/macos
99
# # defaults to ./liwan-data on other platforms
1010
# data_dir="./liwan-data"
1111

12-
# Trusted client IP headers (used in order).
13-
# Defaults to all supported headers.
14-
# Presets: cloudflare, fastly, fly, cloudfront, akamai.
12+
# # Trusted client IP headers (used in order).
13+
# # Empty by default, meaning only the direct peer IP is used.
14+
# # Presets: cloudflare, fastly, fly, cloudfront, akamai.
1515
# client_ip_headers="cloudflare"
16-
# Provider presets can be combined with standard or custom headers.
16+
# # Provider presets can be combined with standard or custom headers.
1717
# client_ip_headers=["cloudflare", "fly", "X-Forwarded-For", "X-Client-IP"]
1818

19-
# Trusted reverse proxies (IP or CIDR).
20-
# Empty by default, meaning all proxies are trusted.
19+
# # Trusted reverse proxies (IP or CIDR).
20+
# # Empty by default, meaning all proxies are trusted.
2121
# trusted_proxies=["127.0.0.1", "10.0.0.0/8"]
2222

23-
# Whether to use forwarded IP headers at all.
24-
# If false, only the direct peer IP is used.
25-
# use_forward_headers=true
26-
27-
# Hour of day, in the server's local timezone, when visitor grouping salts rotate.
28-
# Defaults to 4, meaning 4am local time.
23+
# # Hour of day, in the server's local timezone, when visitor grouping salts rotate.
24+
# # Defaults to 4, meaning 4am local time.
2925
# visitor_group_rotation_hour=4
3026

3127
# GeoIp settings (Optional)
3228
[geoip]
33-
# Read location data supplied by a trusted proxy.
34-
# Presets: cloudflare, cloudfront, vercel.
29+
# # Read location data supplied by a trusted proxy.
30+
# # Presets: akamai, cloudflare, cloudfront, netlify, vercel.
3531
# headers="cloudflare"
36-
# Multiple presets and custom mappings are also supported, in priority order.
32+
# # Multiple presets and custom mappings are also supported, in priority order.
3733
# headers=["cloudflare", { country="X-Country", city="X-City" }]
3834

3935
# # MaxMind account ID and license key
@@ -47,6 +43,6 @@ listen = 9042 # The port to listen on (http)
4743
# maxmind_db_path="./GeoLite2-City.mmdb"
4844

4945
[duckdb]
50-
# See https://liwan.dev/guides/duckdb
46+
# # See https://liwan.dev/guides/duckdb for guidance
5147
# threads=2
5248
# memory_limit=2G

‎src/app/core/geoip.rs‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ impl LiwanGeoIP {
8888

8989
let maxmind_edition = &self.geoip.maxmind_edition;
9090
let maxmind_account_id =
91-
self.geoip.maxmind_account_id.as_deref().ok_or_else(|| anyhow!("MaxMind account ID not found"))?;
91+
self.geoip.maxmind_account_id.as_ref().ok_or_else(|| anyhow!("MaxMind account ID not found"))?.to_string();
9292
let maxmind_license_key =
9393
self.geoip.maxmind_license_key.as_deref().ok_or_else(|| anyhow!("MaxMind license key not found"))?;
9494

@@ -97,7 +97,7 @@ impl LiwanGeoIP {
9797

9898
let mut update = !db_exists;
9999
if db_exists {
100-
match get_latest_md5(maxmind_edition, maxmind_account_id, maxmind_license_key).await {
100+
match get_latest_md5(maxmind_edition, &maxmind_account_id, maxmind_license_key).await {
101101
Ok(latest_md5) => {
102102
if latest_md5 != db_md5 {
103103
tracing::info!("GeoIP database outdated, downloading...");
@@ -113,7 +113,7 @@ impl LiwanGeoIP {
113113
}
114114

115115
if update {
116-
let file = match download_maxmind_db(maxmind_edition, maxmind_account_id, maxmind_license_key).await {
116+
let file = match download_maxmind_db(maxmind_edition, &maxmind_account_id, maxmind_license_key).await {
117117
Ok(file) => file,
118118
Err(e) => {
119119
tracing::warn!(error = ?e, "Failed to download GeoIP database, skipping update");

0 commit comments

Comments
 (0)