访问控制 #
概述 #
访问控制是保护网站安全的重要手段,Caddy 提供了多种访问控制机制,包括 IP 限制、Basic 认证、请求限制等。
text
┌─────────────────────────────────────────────────────────────┐
│ 访问控制层次 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. 网络层 - IP 地址限制 │
│ ↓ │
│ 2. 传输层 - TLS 客户端证书 │
│ ↓ │
│ 3. 应用层 - HTTP 认证 │
│ ↓ │
│ 4. 资源层 - 路径权限控制 │
│ │
└─────────────────────────────────────────────────────────────┘
IP 地址限制 #
允许特定 IP #
caddyfile
example.com {
@allowed {
remote_ip 192.168.1.0/24 10.0.0.0/8
}
handle @allowed {
respond "Access granted"
}
respond "Access denied" 403
}
禁止特定 IP #
caddyfile
example.com {
@blocked {
remote_ip 192.168.100.0/24
}
respond @blocked "Access denied" 403
respond "Welcome"
}
多 IP 规则 #
caddyfile
example.com {
# 管理区域 - 只允许内网
@admin {
path /admin/*
remote_ip 192.168.1.0/24 10.0.0.0/8
}
handle @admin {
reverse_proxy localhost:8080
}
# 公共区域 - 允许所有
handle {
reverse_proxy localhost:3000
}
}
IP 黑名单 #
caddyfile
example.com {
# 定义黑名单
@blacklist {
remote_ip 1.2.3.4 5.6.7.8 9.10.11.0/24
}
# 拒绝黑名单 IP
respond @blacklist "Forbidden" 403
# 正常处理
reverse_proxy localhost:3000
}
使用 CIDR 表示法 #
caddyfile
example.com {
@internal {
remote_ip 10.0.0.0/8 # 私有网络 A 类
172.16.0.0/12 # 私有网络 B 类
192.168.0.0/16 # 私有网络 C 类
127.0.0.1/32 # 本地回环
}
handle @internal {
respond "Internal access"
}
respond "External access"
}
Basic 认证 #
基本配置 #
caddyfile
example.com {
basicauth {
admin $2a$14$Zkx...
}
respond "Protected content"
}
生成密码哈希 #
bash
# 使用 caddy 命令生成
caddy hash-password --plaintext 'your-password'
# 输出
$2a$14$Zkx...
# 或使用 htpasswd
htpasswd -nbB admin your-password
多用户认证 #
caddyfile
example.com {
basicauth {
admin $2a$14$Zkx...
user1 $2a$14$Abc...
user2 $2a$14$Def...
}
respond "Protected content"
}
路径级认证 #
caddyfile
example.com {
root * /var/www/html
file_server
# 管理路径需要认证
handle /admin/* {
basicauth {
admin $2a$14$Zkx...
}
file_server
}
# 公共路径不需要认证
handle {
file_server
}
}
不同路径不同用户 #
caddyfile
example.com {
# 用户区域
handle /user/* {
basicauth {
user1 $2a$14$hash1...
user2 $2a$14$hash2...
}
reverse_proxy localhost:3000
}
# 管理区域
handle /admin/* {
basicauth {
admin $2a$14$adminhash...
}
reverse_proxy localhost:8080
}
# 公共区域
handle {
respond "Public content"
}
}
JWT 认证 #
基本配置(需要插件) #
caddyfile
example.com {
# 使用 JWT 插件
jwt {
primary rsa /etc/keys/public.pem
}
respond "Protected by JWT"
}
JWT 验证配置 #
caddyfile
api.example.com {
jwt {
# 公钥验证
primary rsa /etc/keys/public.pem
# 或使用密钥
# primary hs256 your-secret-key
# 验证声明
issuer my-app
audience api
}
reverse_proxy localhost:3000
}
路径级 JWT #
caddyfile
api.example.com {
# 公共 API
handle /public/* {
reverse_proxy localhost:3000
}
# 私有 API
handle /private/* {
jwt {
primary rsa /etc/keys/public.pem
}
reverse_proxy localhost:3000
}
}
请求限制 #
请求频率限制 #
caddyfile
example.com {
# 限制请求频率
rate_limit {
zone dynamic {
key {remote_host}
events 100
window 1m
}
}
reverse_proxy localhost:3000
}
连接限制 #
caddyfile
example.com {
# 限制并发连接
# 需要配置服务器选项
servers {
max_header_size 16KB
}
reverse_proxy localhost:3000
}
请求体大小限制 #
caddyfile
example.com {
# 限制请求体大小
request_body {
max_size 10MB
}
reverse_proxy localhost:3000
}
地理位置限制 #
基于国家限制(需要插件) #
caddyfile
example.com {
# 使用 GeoIP 插件
geoip {
allow_countries US CA GB
deny_countries CN RU
}
respond "Geo-restricted content"
}
User-Agent 限制 #
禁止特定 User-Agent #
caddyfile
example.com {
# 禁止爬虫
@badbots {
header User-Agent *bot* *crawler* *spider* *scraper*
}
respond @badbots "Forbidden" 403
respond "Welcome"
}
只允许特定 User-Agent #
caddyfile
api.example.com {
@allowed {
header User-Agent *MyApp/*
}
handle @allowed {
reverse_proxy localhost:3000
}
respond "Invalid client" 403
}
## Referer 限制
### 防盗链配置
```caddyfile
example.com {
@images path *.jpg *.png *.gif
# 允许的 Referer
@allowedReferer {
header Referer *example.com* *trusted-site.com*
}
# 图片请求检查 Referer
handle @images {
respond @allowedReferer {
root * /var/www/html
file_server
}
respond "Hotlinking not allowed" 403
}
}
组合访问控制 #
多重验证 #
caddyfile
admin.example.com {
# 1. IP 限制
@allowed_ip remote_ip 192.168.1.0/24 10.0.0.0/8
respond @allowed_ip "IP not allowed" 403
# 2. Basic 认证
basicauth {
admin $2a$14$Zkx...
}
# 3. 后端服务
reverse_proxy localhost:8080
}
分层访问控制 #
caddyfile
example.com {
# 公共区域
handle /public/* {
respond "Public content"
}
# 用户区域 - 需要登录
handle /user/* {
basicauth {
user $2a$14$hash...
}
reverse_proxy localhost:3000
}
# 管理区域 - IP + 认证
handle /admin/* {
@allowed remote_ip 192.168.1.0/24
respond @allowed "IP not allowed" 403
basicauth {
admin $2a$14$adminhash...
}
reverse_proxy localhost:8080
}
# API 区域 - JWT
handle /api/* {
jwt {
primary rsa /etc/keys/public.pem
}
reverse_proxy localhost:3001
}
}
安全头部 #
基本安全头部 #
caddyfile
example.com {
header {
# 防止点击劫持
X-Frame-Options "SAMEORIGIN"
# 防止 MIME 类型嗅探
X-Content-Type-Options "nosniff"
# XSS 保护
X-XSS-Protection "1; mode=block"
# 引用策略
Referrer-Policy "strict-origin-when-cross-origin"
# 内容安全策略
Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'"
# 权限策略
Permissions-Policy "geolocation=(), microphone=(), camera=()"
# 移除服务器标识
-Server
}
respond "Secure content"
}
HSTS 配置 #
caddyfile
example.com {
header {
# HTTP Strict Transport Security
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
}
respond "HSTS enabled"
}
CORS 配置 #
caddyfile
api.example.com {
@cors {
method OPTIONS
header Origin *
}
# CORS 预检
handle @cors {
header {
Access-Control-Allow-Origin "{http.request.header.Origin}"
Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
Access-Control-Allow-Headers "Content-Type, Authorization"
Access-Control-Max-Age "3600"
}
respond "" 204
}
# CORS 响应头
header {
Access-Control-Allow-Origin "*"
Access-Control-Allow-Methods "GET, POST, PUT, DELETE"
Access-Control-Allow-Headers "Content-Type, Authorization"
}
reverse_proxy localhost:3000
}
完整示例 #
企业内网应用 #
caddyfile
internal.example.com {
# IP 白名单
@allowed remote_ip 10.0.0.0/8 192.168.0.0/16
respond @allowed "Access denied" 403
# Basic 认证
basicauth {
admin $2a$14$Zkx...
}
# 安全头部
header {
X-Frame-Options "SAMEORIGIN"
X-Content-Type-Options "nosniff"
-Server
}
reverse_proxy localhost:8080
}
API 网关 #
caddyfile
api.example.com {
# 公共 API
handle /public/* {
# 速率限制
rate_limit {
zone public {
key {remote_host}
events 100
window 1m
}
}
reverse_proxy localhost:3000
}
# 私有 API
handle /private/* {
# JWT 验证
jwt {
primary rsa /etc/keys/public.pem
}
# 速率限制
rate_limit {
zone private {
key {remote_host}
events 1000
window 1m
}
}
reverse_proxy localhost:3000
}
# 管理 API
handle /admin/* {
# IP 限制
@allowed remote_ip 10.0.0.0/8
respond @allowed "Access denied" 403
# Basic 认证
basicauth {
admin $2a$14$adminhash...
}
reverse_proxy localhost:8080
}
# CORS
header {
Access-Control-Allow-Origin "*"
Access-Control-Allow-Methods "GET, POST, PUT, DELETE"
Access-Control-Allow-Headers "Content-Type, Authorization"
}
}
多租户 SaaS #
caddyfile
app.example.com {
# JWT 验证
jwt {
primary rsa /etc/keys/public.pem
}
# 添加租户信息到请求头
reverse_proxy localhost:3000 {
header_up X-Tenant-ID {jwt.tenant_id}
header_up X-User-ID {jwt.sub}
}
}
# 自定义域名
*.app.example.com {
jwt {
primary rsa /etc/keys/public.pem
}
reverse_proxy localhost:3000 {
header_up X-Tenant-Domain {host}
}
}
访问控制最佳实践 #
1. 最小权限原则 #
caddyfile
# 只开放必要的访问
handle /admin/* {
@allowed remote_ip 192.168.1.100/32
respond @allowed "Access denied" 403
# ...
}
2. 多层防护 #
caddyfile
# IP + 认证 + 安全头部
@allowed remote_ip 10.0.0.0/8
respond @allowed "Access denied" 403
basicauth {
admin $2a$14$hash...
}
header {
X-Frame-Options "SAMEORIGIN"
X-Content-Type-Options "nosniff"
}
3. 日志记录 #
caddyfile
example.com {
log {
output file /var/log/caddy/access.log
format json
}
# 访问控制...
}
4. 定期更新密码 #
bash
# 定期生成新密码哈希
caddy hash-password --plaintext 'new-password'
下一步 #
现在你已经掌握了访问控制配置,接下来学习 日志管理 了解如何记录和分析访问日志!
最后更新:2026-03-28