You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Go Fiber中无需重启应用更新HTTPS服务器TLS配置

无需重启Go Fiber应用动态更新TLS配置(Autocert HostPolicy)

核心思路

autocert.Manager的HostPolicy本质是一个函数类型,我们可以自定义支持动态更新的HostPolicy实现,通过并发安全的方式修改允许的域名列表。由于tls.Config的GetCertificate指向autocert.Manager的方法,只要Manager的HostPolicy是动态的,新的TLS请求就会自动使用最新规则,无需重启应用。

实现步骤与代码示例

1. 定义可动态更新的HostPolicy结构体

import (
    "context"
    "sync"
    "golang.org/x/crypto/acme/autocert"
)

// DynamicHostPolicy 支持动态更新域名白名单的HostPolicy实现
type DynamicHostPolicy struct {
    mu    sync.RWMutex
    hosts map[string]bool
}

// NewDynamicHostPolicy 创建带初始域名列表的DynamicHostPolicy
func NewDynamicHostPolicy(hosts ...string) *DynamicHostPolicy {
    hp := &DynamicHostPolicy{
        hosts: make(map[string]bool),
    }
    for _, h := range hosts {
        hp.hosts[h] = true
    }
    return hp
}

// HostPolicy 实现autocert.HostPolicy接口
func (hp *DynamicHostPolicy) HostPolicy(ctx context.Context, host string) error {
    hp.mu.RLock()
    defer hp.mu.RUnlock()
    if hp.hosts[host] {
        return nil
    }
    return autocert.ErrHostPolicyDenied
}

// UpdateHosts 更新域名白名单,替换现有列表
func (hp *DynamicHostPolicy) UpdateHosts(hosts ...string) {
    hp.mu.Lock()
    defer hp.mu.Unlock()
    // 清空原有域名
    for k := range hp.hosts {
        delete(hp.hosts, k)
    }
    // 添加新域名
    for _, h := range hosts {
        hp.hosts[h] = true
    }
}

2. 修改原Fiber TLS服务器代码

将固定的autocert.HostWhitelist替换为自定义的动态实现,并添加更新接口:

package main

import (
    "crypto/tls"
    "log"
    "github.com/gofiber/fiber/v2"
    "golang.org/x/crypto/acme/autocert"
)

// 上面的DynamicHostPolicy代码放在此处或单独文件中

func main() {
    app := fiber.New()

    // 初始化动态HostPolicy,初始域名:example.com、example.net
    dynamicHP := NewDynamicHostPolicy("example.com", "example.net")

    m := &autocert.Manager{
        Prompt:     autocert.AcceptTOS,
        HostPolicy: dynamicHP.HostPolicy, // 绑定动态HostPolicy
        Cache:      autocert.DirCache("./certs"),
    }

    cfg := &tls.Config{
        GetCertificate: m.GetCertificate,
        NextProtos: []string{
            "http/1.1", "acme-tls/1",
        },
    }
    ln, err := tls.Listen("tcp", ":443", cfg)
    if err != nil {
        panic(err)
    }

    // 添加域名更新接口(生产环境需加身份验证,比如API密钥)
    app.Post("/update-hosts", func(c *fiber.Ctx) error {
        var req struct {
            Hosts []string `json:"hosts"`
        }
        if err := c.BodyParser(&req); err != nil {
            return c.Status(fiber.StatusBadRequest).SendString("请求格式错误")
        }
        if len(req.Hosts) == 0 {
            return c.Status(fiber.StatusBadRequest).SendString("域名列表不能为空")
        }
        dynamicHP.UpdateHosts(req.Hosts...)
        return c.SendString("域名列表更新成功")
    })

    log.Fatal(app.Listener(ln))
}

3. 触发动态更新

发送POST请求到https://你的域名/update-hosts,请求体为JSON格式:

{
    "hosts": ["example1.org", "example1.info"]
}

更新完成后,新的TLS请求会自动使用最新的域名白名单规则。

关键说明

  • 并发安全:使用读写锁sync.RWMutex保证域名列表更新时不阻塞正常请求。
  • 即时生效:每次TLS握手都会调用HostPolicy函数,读取最新的域名列表,更新后立即生效。
  • 生产环境防护:更新接口必须添加安全验证(如API密钥、IP白名单),避免未授权修改。

内容的提问来源于stack exchange,提问作者Vyacheslav

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 06:45:35