feat(frp): frps vhost 回源端口支持 80/443,公网反代在该配置下不再适用

- 服务端表单不再硬性拒绝 vhostHTTPPort=80 / vhostHTTPSPort=443,改为保存时弹窗二次确认;
  确认后请求携带 allow_privileged_vhost_ports 提交并由后端校验放行,未携带标记的请求(含直接调 API)仍被拒绝
- frps.toml 生成改为写入风险注释、不再报错;各规则的公网反代回源地址随 80/443 自动跟随
- 「公网反代」页检测到 80/443 后显示说明卡片并隐藏统计/Nginx/规则台账/漂移区块,
  同时跳过 agent 的路由、漂移与健康请求
- 后端 DeployAgentRoute 与 RedeployAllRoutes(含漂移一键修复)拒绝下发,自动下发路径 syncAgentRoute 跳过
- 新增 internal/frp/vhost_port_test.go:校验、二次确认、frps.toml 生成、反代回源跟随与守卫对照
This commit is contained in:
2026-10-11 15:07:07 +08:00
parent d1c498a286
commit aafff522d8
11 changed files with 370 additions and 22 deletions
+19 -2
View File
@@ -30,8 +30,10 @@ func validateServerInput(in ServerInput) error {
if in.Options.VhostHTTPSPort != 0 && !validPort(in.Options.VhostHTTPSPort) {
return fmt.Errorf("frps HTTPS 回源端口无效")
}
if in.Options.VhostHTTPPort == 80 || in.Options.VhostHTTPSPort == 443 {
return fmt.Errorf("frps vhost 回源端口不能使用 80/443(通常由 VPS 上的 Nginx 占用);请使用 8080/8443")
// 80/443 默认由 VPS 上的 Nginx 占用,frps 再监听会因端口冲突启动失败;
// 仍允许使用(例如 VPS 上不跑 Nginx、由 frps 直接对外),但必须由前端二次确认后带标记提交。
if (in.Options.VhostHTTPPort == 80 || in.Options.VhostHTTPSPort == 443) && !in.AllowPrivilegedVhostPorts {
return fmt.Errorf("frps vhost 回源端口 80/443 通常由 VPS 上的 Nginx 占用;确认该端口已释放后,请确认风险提示再保存")
}
if !validDashboardAddr(in.Options.DashboardAddr) {
return fmt.Errorf("frps 管理接口地址无效")
@@ -366,6 +368,21 @@ func validPort(port int) bool {
return port > 0 && port <= 65535
}
// privilegedVhostPorts 判断 frps 回源端口是否落在 80/443(未配置时按默认 8080/8443 计)。
// 这种拓扑下 VPS 上由 frps 直接对外,没有 Nginx 监听 80/443 的位置,
// 公网反代(Nginx 路由下发)既不适用、也不应该部署。
func privilegedVhostPorts(options ServerOptions) bool {
httpPort := options.VhostHTTPPort
if httpPort <= 0 {
httpPort = 8080
}
httpsPort := options.VhostHTTPSPort
if httpsPort <= 0 {
httpsPort = 8443
}
return httpPort == 80 || httpsPort == 443
}
func validHost(host string) bool {
host = strings.TrimSpace(host)
if host == "" || len(host) > 253 || strings.ContainsAny(host, " \t\r\n/\\\"'") {