infra(traefik,gitea): rate-limit filtered project-board views per source IP and serve a robots.txt disallowing filtered views — the label-permutation crawler trap (refs #656)
Some checks failed
CI / lint (push) Successful in 30s
CI / notebooks-smoke (push) Successful in 1m33s
Deploy / notebooks (push) Has been skipped
Deploy / zotero (push) Has been skipped
Deploy / docs (push) Has been skipped
Deploy / api (push) Has been skipped
Deploy / llm (push) Has been skipped
Deploy / mc (push) Has been skipped
Infra CI / notebooks (push) Successful in 52s
Infra CI / zotero (push) Successful in 14s
Infra CI / docs (push) Successful in 19s
Infra CI / api (push) Successful in 58s
Infra CI / llm (push) Successful in 50s
Infra CI / mc (push) Failing after 16s
Deploy / report (push) Successful in 12s
CI / test (push) Has been cancelled

This commit is contained in:
kert
2026-09-11 16:46:49 -04:00
parent 2b71d414e4
commit 3a225c620f
2 changed files with 52 additions and 0 deletions

View File

@@ -0,0 +1,22 @@
# Served by Gitea at /robots.txt (GITEA_CUSTOM/public). #656: a crawler
# permuted every label-filter combination of the project board about once
# a second for weeks — filtered views are a combinatorial trap and carry
# nothing worth indexing. The traefik router `git-projects-filter` rate
# limits the same URLs for clients that ignore this file.
User-agent: *
Disallow: /*/*/projects
Disallow: /*/*/issues?
Disallow: /*/*/pulls?
Disallow: /*/*/milestones?
Disallow: /*?labels=
Disallow: /*?state=
Disallow: /*?sort=
Disallow: /*?q=
Disallow: /*/*/compare/
Disallow: /*/*/commits/
Disallow: /*/*/blame/
Disallow: /*/*/raw/
Disallow: /*/*/search
Disallow: /explore
Disallow: /api/
Crawl-delay: 10

View File

@@ -27,6 +27,15 @@ http:
frameDeny: true
browserXssFilter: true
contentTypeNosniff: true
# #656: a crawler permuting project-board label filters at ~1 req/s
# (216.73.216.0/24). Per-source-IP limit on the filtered project views
# only — a person clicking filters stays well under 10/min; the crawler
# gets 429s. Pairs with infra/gitea/custom/public/robots.txt.
projects-ratelimit:
rateLimit:
average: 10
period: 1m
burst: 20
# SSO: auth-handler (nginx) wraps oauth2-proxy to convert 401 → 302.
# Same logic as corwins.media: auth_request + error_page 401 = @signin.
git-sso:
@@ -64,6 +73,27 @@ http:
entryPoints:
- websecure
tls: {}
# #656: filtered project-board views on git — same service, higher
# priority than the generic `git` router, rate limited per source IP.
git-projects-filter:
rule: "Host(`git.{{ $domain }}`) && PathRegexp(`^/[^/]+/[^/]+/projects(/|$)`) && QueryRegexp(`labels`, `.+`)"
priority: 1000
service: git
entryPoints:
- web
middlewares:
- projects-ratelimit
- secure-headers
git-projects-filter-tls:
rule: "Host(`git.{{ $domain }}`) && PathRegexp(`^/[^/]+/[^/]+/projects(/|$)`) && QueryRegexp(`labels`, `.+`)"
priority: 1000
service: git
entryPoints:
- websecure
tls: {}
middlewares:
- projects-ratelimit
- secure-headers
{{- range $name, $svc := $reef }}
{{ $name }}:
rule: "Host(`{{ get $svc "subdomain" | default $name }}.{{ $domain }}`){{ range get $svc "extra_hosts" | default list }} || Host(`{{ . }}`){{ end }}"