feat(api): count the quota by the CDN's client IP and refuse direct calls

Two optional settings for deployments behind a CDN such as Cloudflare.

CLIENT_IP_HEADER names the header that holds the visitor's real IP
(cf-connecting-ip on Cloudflare). The per-IP daily quota used the first
X-Forwarded-For entry, which visitors can set to anything, so a made-up
IP on every request got a fresh quota.

ORIGIN_SECRET makes proxy.ts refuse /api requests whose X-Origin-Secret
header does not match. The CDN adds the header, so a call that skips the
CDN, and could fake the IP header, gets 403. Pages are not checked, which
keeps health checks on / working.

Both are unset by default, and nothing changes then.
This commit is contained in:
dayuan.jiang
2026-10-06 10:12:15 +09:00
parent 802f0ada9f
commit 74ca64f5e8
4 changed files with 101 additions and 6 deletions
+10
View File
@@ -163,6 +163,16 @@ AI_MODEL=global.anthropic.claude-sonnet-4-5-20250929-v1:0
# Set to "false" to block private IPs, localhost, and internal hostnames
# ALLOW_PRIVATE_URLS=false
# Behind a CDN such as Cloudflare (Optional)
# The daily quota is counted per IP. By default the IP is the first
# X-Forwarded-For entry, which visitors can set to anything. Name the header
# your CDN fills with the visitor's real IP instead:
# CLIENT_IP_HEADER=cf-connecting-ip
# Then have the CDN add an X-Origin-Secret header with this value to every
# request. API calls without it get 403, so nobody can skip the CDN and fake
# the IP header above.
# ORIGIN_SECRET=a-long-random-string
# Self-hosted deployment (Optional)
# Self-hosted users may implement custom quota-management solutions,
# which triggers the client UI to display messages suggesting self-hosting or sponsorship.