自部署 Gitea 被爬虫打爆流量的缓解措施

目录

现象

自部署的 Gitea 某天流量开始异常。服务器商控制面板里,流量额度以肉眼可见的速度消耗,月流量包很快见底。访问日志按响应大小聚合后,git 域名占了绝大多数流量,其中 /owner/repo/compare/ 这类版本对比页面是大头,单页最大响应能到 10MB 级别。

爬虫特征明显:Amazonbot、Lightpanda,以及一批伪造旧版 Chrome/Firefox UA 的轮换 IP,反复抓取 blame、compare 页面。大量独立 IP 各自只请求一两次,典型的分布式爬取。

原因

  1. 爬虫 UA 复杂,既有知名爬虫(Amazonbot、Lightpanda),也有伪造浏览器 UA 的轮换 IP。
  2. 重型页面单页体积大,compare 页面最大超过 10MB,且完全不压缩,爬虫每抓一页都是大流量。
  3. 单 IP 限流对轮换 IP 池无效,绝大多数 IP 只请求一两次就换下一个。

方法

1. Caddy 配置

UA 黑名单(@block_bots 命中直接 403)和重型页面限流(@heavy 单 IP 2 次/10s)都写在同一个站点块里,按顺序执行。UA 名单覆盖常见爬虫和扫描器,可以按需增删:

git.example.com {
	# 日志配置:按域名输出访问日志
	import log git.example.com

	# 1. UA 黑名单:命中的爬虫直接 403
	@block_bots header_regexp User-Agent "(?i)(SemrushBot|Lightpanda|GPTBot|ClaudeBot|Bytespider|AhrefsBot|MJ12bot|DataForSeoBot|Amazonbot|DotBot|CCBot|cohere-ai|Diffbot|Google-Extended|Meta-ExternalAgent|Meta-ExternalFetcher|Applebot-Extended|Timpibot|ImagesiftBot|Crawl4AI|Scrapy|ChatGLM-Spider|DeepSeekBot|cohere-training-data-crawler|AI2Bot|TikTokSpider|omgili|BLEXBot|Exabot|360Spider|80legs|MegaIndex|Barkrowler|DataCha0s|Nikto|Nmap|Nessus|OpenVAS|Sqlmap|WPScan|Nuclei|Masscan|Shodan|Acunetix|Dirbuster|Whatweb|Havij|Fimap|Jbrofuzz|Zgrab|Censys)"
	handle @block_bots {
		respond 403
	}

	# 2. 重型页面(compare/blame 等)单 IP 限流
	@heavy path_regexp heavy_path ^/[^/]+/[^/]+/(?:compare|blame|commit|commits|archive|pulls|issues)(?:/|$)
	handle @heavy {
		rate_limit {
			zone dynamic_zone {
				key {client_ip}
				events 2
				window 10s
			}
			log_key
		}
		reverse_proxy 100.64.0.10:3000
	}

	# 3. robots.txt:礼貌爬虫先读规则
	handle /robots.txt {
		respond `User-agent: *
Disallow: /blame/
Disallow: /compare/
Disallow: /commit/
Disallow: /commits/
Disallow: /archive/
Disallow: /pulls/
Disallow: /issues/`
	}

	# 4. 其余请求反代到 Gitea
	reverse_proxy 100.64.0.10:3000
}

@heavy 的路径规则同时覆盖 compare、blame、commit 等几类重型页面,单个 IP 在 10 秒内超过 2 次就返回 429。log_key 开启后,被限流的请求会在访问日志里记下对应的 IP,方便调阈值。

2. Gitea 开启源站 gzip

app.ini[server] 段,加一行后重启 Gitea:

[server]
ENABLE_GZIP = true

ENABLE_GZIP 只压缩运行时生成的内容,静态资源不受影响。放在源站而不是反代层,是因为链路是「源站 → 反代 → 访客」两段,双向计费下源站压缩两段都省;只在反代压只省一段。Caddy 的 reverse_proxy 会替缺省客户端补 Accept-Encoding: gzip 并原样透传上游的压缩响应,不需要在 Caddy 侧再配 encode。

参考链接

目录