一个基于 Go 的本地优先反向代理,支持:
- 路由规则热更新
- 全局认证接入(登录跳转 + 预检)
- 同端口 HTTP/HTTPS(动态证书切换)
- 内置管理 API(含 Swagger)
- iptables/ip6tables 白黑名单与默认拒绝策略
go-reauth-proxy 适合部署在内网或本机网关位置,把多个本地服务统一收口到一个代理端口,并通过独立认证服务做访问控制。
它的设计重点是:
- 管理接口只监听
127.0.0.1 - 代理目标限制为内网/回环地址
- 配置改动自动持久化到
config.json
- 动态路由规则(
POST /api/rules全量替换) - 路径前缀匹配 +
StripPath+ HTML 绝对路径重写 UseAuth场景下自动插入悬浮切换工具栏UseRootMode支持:将命中路径写入 cookie 后重定向到根路径- 认证前置预检(
HEAD preflight,返回X-Option: deny可拒绝请求) - 认证失败自动跳转到
/__auth__/login?redirect_uri=... - 动态 SSL 证书上传/清除(同一代理端口自动启停 HTTPS)
- 代理流量统计(入/出字节、活跃登录用户、5xx 计数)
- iptables/ip6tables 链初始化、白名单、黑名单、block-all/allow-all
- 代理服务端口:默认
7999 - 管理服务端口:默认
7996(固定绑定127.0.0.1) - 认证服务端口:默认
7997(由auth_config.auth_port指定)
代理端口通过 cmux 同时处理:
- 明文 HTTP
- TLS(HTTPS)
当配置了证书后,明文 HTTP 请求会被 307 重定向到 HTTPS。
proxy_protocol_force=true 时,代理监听地址会从 0.0.0.0/:: 切换为 127.0.0.1/::1,并优先从 X-Forwarded-For / X-Real-IP 获取客户端 IP。
- Go
1.25+(见go.mod) - 可选:
task(推荐) - 可选:
bun(运行example/auth-server) - 可选:
swag(生成 Swagger) - 若使用防火墙 API:Linux +
iptables/ip6tables+sudo权限
使用 Task:
task run -- -proxy-port 7999 -admin-port 7996 -c ./config.json或直接运行:
go run ./cmd/server/main.go -proxy-port 7999 -admin-port 7996 -c ./config.json可用启动参数:
-proxy-port:代理端口,默认7999-admin-port:管理端口,默认7996。传0时回退到配置文件admin_port-c:配置文件路径(可传目录,自动补config.json)
- Swagger UI:
http://127.0.0.1:7996/docs/index.html
配置文件默认名:config.json
默认值(首次运行自动写入):
{
"rules": [],
"default_route": "/__select__",
"auth_config": {
"auth_port": 7997,
"auth_url": "/api/auth/verify",
"login_url": "/login",
"logout_url": "/api/auth/logout",
"preflight_url": "/api/auth/preflight",
"public_http_port": 80,
"public_https_port": 443
},
"admin_port": 7996,
"proxy_protocol_force": false,
"reverse_proxy_throttle": {
"enabled": true,
"requests_per_second": 100,
"burst": 200,
"block_seconds": 30
},
"iptables_chain_name": "",
"ssl_cert": "",
"ssl_key": ""
}字段说明:
rules: 路由规则数组default_route: 根路径/的默认去向,默认"/__select__"auth_config: 全局认证配置auth_config.aliyun_esa_enabled: 启用阿里云 ESA / 腾讯 EdgeOne 兼容模式;来源 IP 优先读取Ali-Real-Client-IP,缺失时回退到X-Forwarded-Forauth_config.public_http_port: 可选,显式指定对外暴露的 HTTP 端口auth_config.public_https_port: 可选,显式指定对外暴露的 HTTPS 端口admin_port: 管理端口(仅在-admin-port=0时作为回退)proxy_protocol_force: 是否强制按 PROXY protocol 场景处理来源 IPreverse_proxy_throttle: 反代数据面节流配置,作用于命中 host/path 规则的请求以及__auth__认证代理路径,不影响admin-port、/__select__reverse_proxy_throttle.enabled: 是否启用节流reverse_proxy_throttle.requests_per_second: 单个客户端 IP 每秒允许的请求数reverse_proxy_throttle.burst: 单个客户端 IP 可瞬时突发的令牌数reverse_proxy_throttle.block_seconds: 超限后直接断开连接的封禁时长;被中断的请求不会写 access logiptables_chain_name: iptables 链名(默认REAUTH_FW)ssl_cert/ssl_key: PEM 证书与私钥(由 API 写入)
一个常见配置示例:
{
"reverse_proxy_throttle": {
"enabled": true,
"requests_per_second": 100,
"burst": 200,
"block_seconds": 30
}
}当网关运行在非标准本地端口上,但前面存在 NAT 或转发时,这两个字段可用于修正网关生成的公开跳转地址。
例如本地监听 7999,并希望外部访问 http://fnos.fnknock.xyz/ 时跳转到 https://fnos.fnknock.xyz:7999/,可配置:
{
"auth_config": {
"public_http_port": 80,
"public_https_port": 7999,
"public_auth_base_url": "https://auth.fnknock.xyz:7999"
}
}单条规则结构:
{
"path": "/app",
"target": "http://127.0.0.1:8080",
"use_auth": true,
"strip_path": true,
"rewrite_html": true,
"use_root_mode": false
}行为细节:
- 按最长前缀匹配
path GET /app会 301 到/app/(规则非/时)strip_path=true:转发时去掉匹配前缀rewrite_html=true:重写 HTML 中href/src/action/<base href>的绝对路径use_auth=true:转发前调用认证服务,并在 HTML 注入悬浮工具栏use_root_mode=true:命中后写入__proxy_pathcookie 并 302 到/
未命中时:
- 请求
/且未配置任何 path/host 规则:返回 Welcome 页面 - 请求
/且有 path 规则:- 若
__proxy_pathcookie 对应到某条规则,则优先按该规则转发 - 若
default_route对应到某条规则,则按该规则转发 - 否则跳转到
/__select__
- 若
- 其他未命中场景(包括 host 未命中,或仅配置 host 规则时访问
/):返回 No Matching Route 页面(404)
代理会请求本地认证服务:
- 鉴权:
GET http://127.0.0.1:{auth_port}{auth_url} - 预检:
HEAD http://127.0.0.1:{auth_port}{preflight_url}
会透传/注入的关键头:
CookieAuthorizationAli-Real-Client-IP(启用auth_config.aliyun_esa_enabled时)X-Real-IPX-Forwarded-ForX-Forwarded-Path
/api/auth/verify(或自定义 auth_url)响应体需要能被解析为:
{
"success": true,
"message": "ok"
}success=true:放行success=false:代理重定向到/__auth__/login?redirect_uri=原地址
/__auth__/login->auth_config.login_url/__auth__/api/auth/logout->auth_config.logout_url/__auth__/*-> 透传到认证服务对应路径
统一响应结构:
{
"success": true,
"code": 200,
"message": "Success",
"data": {},
"timestamp": 1700000000000
}GET /api/infoGET /api/trafficGET /api/rulesPOST /api/rules(全量替换)DELETE /api/rulesGET /api/config/default-routePOST /api/config/default-routeGET /api/config/proxy-protocolPOST /api/config/proxy-protocolGET /api/authPOST /api/authGET /api/sslPOST /api/sslDELETE /api/ssl
POST /api/iptables/initPOST /api/iptables/cleanPOST /api/iptables/flushPOST /api/iptables/allowPOST /api/iptables/blockPOST /api/iptables/removePOST /api/iptables/block-allPOST /api/iptables/allow-allGET /api/iptables/list
设置认证配置:
curl -X POST http://127.0.0.1:7996/api/auth \
-H "Content-Type: application/json" \
-d '{
"auth_port": 7997,
"auth_url": "/api/auth/verify",
"login_url": "/login",
"logout_url": "/api/auth/logout",
"preflight_url": "/api/auth/preflight"
}'设置路由规则:
curl -X POST http://127.0.0.1:7996/api/rules \
-H "Content-Type: application/json" \
-d '[
{
"path": "/app",
"target": "http://127.0.0.1:8080",
"use_auth": true,
"strip_path": true,
"rewrite_html": true,
"use_root_mode": false
}
]'上传 SSL:
curl -X POST http://127.0.0.1:7996/api/ssl \
-H "Content-Type: application/json" \
-d '{"cert":"-----BEGIN CERTIFICATE-----\\n...","key":"-----BEGIN PRIVATE KEY-----\\n..."}'init 后会创建/重建自定义链,并应用基础规则:
- 放行
lo - 放行
ESTABLISHED,RELATED - 放行本地网段(v4/v6)
- 放行 ICMP(IPv4
icmp/ IPv6ipv6-icmp) - 放行
exempt_ports - 默认
DROP
说明:
- 默认链名:
REAUTH_FW - 默认父链:
INPUT和DOCKER-USER - 命令通过
sudo iptables/sudo ip6tables执行
- HTTP 请求日志为 JSON 行(method/path/status/duration/user_agent/remote_ip)
GET /api/traffic返回:total_in/total_outactive_conns(最近 2 分钟活跃已登录身份)error_5xx
cmd/server/ # 入口与 swagger 文档
pkg/admin/ # 管理 API
pkg/proxy/ # 反向代理核心逻辑
pkg/config/ # 配置加载与持久化
pkg/iptables/ # iptables 管理
pkg/response/ # 内置页面与响应封装
pkg/middleware/ # 日志/CORS 中间件
example/auth-server/ # Bun 示例认证服务
task build # 构建 macOS ARM64 + Linux AMD64/ARM64
task build:mac
task build:linux
task build:linux-arm64
task run
task run:auth-server
task test
task docs- 管理 API 仅监听本地回环地址,不会对外暴露
- 代理目标不再限制为内网地址;仅阻止把目标直接指向本机管理端口
POST /api/rules是全量覆盖,不是增量追加- SSL 证书与私钥会写入
config.json明文保存,请注意文件权限 - 仓库中的
example/auth-server当前实现返回的是纯文本鉴权结果;若直接联调,请将鉴权接口改为返回 JSON{"success":...}以满足代理解析逻辑