This commit is contained in:
+49
-49
@@ -26,14 +26,14 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/fonu/fonu/internal/fsutil"
|
||||
"github.com/fonu/fonu/internal/nginxtmpl"
|
||||
"github.com/fonu/fonu/internal/sysinfo"
|
||||
"github.com/havline/havline/internal/fsutil"
|
||||
"github.com/havline/havline/internal/nginxtmpl"
|
||||
"github.com/havline/havline/internal/sysinfo"
|
||||
)
|
||||
|
||||
// AgentVersion 随每次 agent 行为变更手动递增;status/ping 与安装脚本都会回报,用于确认 VPS 上跑的是哪个版本。
|
||||
// 0.5.0:目录判定改用 nginx -T 自省(dump 完整生效配置,按 "# configuration file" 标记
|
||||
// 找出真正被加载的文件所在目录,零猜测);include 链递归与 FONU_AGENT_NGINX_CONF_DIR 保留为回退。
|
||||
// 找出真正被加载的文件所在目录,零猜测);include 链递归与 HAVLINE_AGENT_NGINX_CONF_DIR 保留为回退。
|
||||
// 0.9.0:Nginx 可用性显式探测(status 暴露 nginx_ok/nginx_missing)、部署前预检、一键安装 Nginx 端点。
|
||||
// 0.9.1:status 补充 nginx_running / nginx_version,供页面展示 Nginx 状态卡片。
|
||||
// 0.9.2:Basic Auth 哈希改为纯 Go apr1(去掉对 VPS openssl 的依赖);安装脚本 token 改用 /dev/urandom。
|
||||
@@ -61,9 +61,9 @@ import (
|
||||
// 证书不匹配时回滚并回报实际指纹与端口占用进程,区分「nginx 未生效」与「公网链路被接管」。
|
||||
// 0.14.0:HTTPS 端口自动选择(7443/8443/9443)、当前证书信息查询、主机防火墙检测与 ufw/firewalld 显式放行。
|
||||
// 0.14.1:vhost 模板迁出到 internal/nginxtmpl,统一 TLS、安全头、allow/deny、WebSocket 与限流输出。
|
||||
const AgentVersion = "0.14.1"
|
||||
const AgentVersion = "0.15.0"
|
||||
|
||||
// Config 是 fonu-agent 的运行配置。agent 只在 VPS 本地管理自己的 Nginx 片段、证书和 frps 配置。
|
||||
// Config 是 havline-agent 的运行配置。agent 只在 VPS 本地管理自己的 Nginx 片段、证书和 frps 配置。
|
||||
type Config struct {
|
||||
ListenAddr string
|
||||
AllowRemote bool
|
||||
@@ -157,7 +157,7 @@ func NewServer(cfg Config) (*Server, error) {
|
||||
cfg.NginxBinary = "nginx"
|
||||
}
|
||||
if strings.TrimSpace(cfg.CertsDir) == "" {
|
||||
cfg.CertsDir = "/var/lib/fonu-agent/certs"
|
||||
cfg.CertsDir = "/var/lib/havline-agent/certs"
|
||||
}
|
||||
if strings.TrimSpace(cfg.FrpsConfigPath) == "" {
|
||||
cfg.FrpsConfigPath = "/etc/frp/frps.toml"
|
||||
@@ -169,7 +169,7 @@ func NewServer(cfg Config) (*Server, error) {
|
||||
cfg.FrpsBinary = "/usr/local/bin/" + filepath.Base(cfg.FrpsBinary)
|
||||
}
|
||||
if strings.TrimSpace(cfg.DataDir) == "" {
|
||||
cfg.DataDir = "/var/lib/fonu-agent"
|
||||
cfg.DataDir = "/var/lib/havline-agent"
|
||||
}
|
||||
if strings.TrimSpace(cfg.Token) == "" {
|
||||
return nil, errors.New("agent token is required")
|
||||
@@ -201,7 +201,7 @@ func validateListenAddr(addr string, allowRemote bool) (bool, error) {
|
||||
loopback = ip.IsLoopback()
|
||||
}
|
||||
if !loopback && !allowRemote {
|
||||
return false, fmt.Errorf("检测到 Agent 将监听非回环地址 %s;默认安全模式只监听 127.0.0.1:7700。如确认需要远程监听,请设置 FONU_AGENT_ALLOW_REMOTE=1", addr)
|
||||
return false, fmt.Errorf("检测到 Agent 将监听非回环地址 %s;默认安全模式只监听 127.0.0.1:7700。如确认需要远程监听,请设置 HAVLINE_AGENT_ALLOW_REMOTE=1", addr)
|
||||
}
|
||||
return loopback, nil
|
||||
}
|
||||
@@ -303,7 +303,7 @@ func secureTokenEqual(got, want string) bool {
|
||||
}
|
||||
|
||||
func (s *Server) ping(w http.ResponseWriter, _ *http.Request) {
|
||||
writeJSON(w, http.StatusOK, map[string]any{"ok": true, "service": "fonu-agent"})
|
||||
writeJSON(w, http.StatusOK, map[string]any{"ok": true, "service": "havline-agent"})
|
||||
}
|
||||
|
||||
func (s *Server) status(w http.ResponseWriter, _ *http.Request) {
|
||||
@@ -312,7 +312,7 @@ func (s *Server) status(w http.ResponseWriter, _ *http.Request) {
|
||||
frpsActive := exec.Command("systemctl", "is-active", "--quiet", "frps").Run() == nil
|
||||
httpsState, httpsConfigured := readHTTPSProxyState(s.cfg.DataDir)
|
||||
writeJSON(w, http.StatusOK, map[string]any{
|
||||
"service": "fonu-agent",
|
||||
"service": "havline-agent",
|
||||
"agent_version": AgentVersion,
|
||||
"listen_addr": s.cfg.ListenAddr,
|
||||
"listen_scope": listenScope(s.listenLoopback),
|
||||
@@ -460,7 +460,7 @@ func (s *Server) installFRPS(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
if writeUnit {
|
||||
unit := fmt.Sprintf("[Unit]\nDescription=frps service (managed by fonu-agent)\nAfter=network-online.target\nWants=network-online.target\n\n[Service]\nType=simple\nExecStart=%s -c %s\nRestart=on-failure\nRestartSec=3\n\n[Install]\nWantedBy=multi-user.target\n", installPath, s.cfg.FrpsConfigPath)
|
||||
unit := fmt.Sprintf("[Unit]\nDescription=frps service (managed by havline-agent)\nAfter=network-online.target\nWants=network-online.target\n\n[Service]\nType=simple\nExecStart=%s -c %s\nRestart=on-failure\nRestartSec=3\n\n[Install]\nWantedBy=multi-user.target\n", installPath, s.cfg.FrpsConfigPath)
|
||||
if err := atomicWrite(unitPath, []byte(unit), 0o644); err != nil {
|
||||
writeJSON(w, http.StatusBadGateway, map[string]string{"error": "写入 frps.service 失败: " + err.Error()})
|
||||
return
|
||||
@@ -624,7 +624,7 @@ func execCommandOutput(name string, args ...string) string {
|
||||
return string(output)
|
||||
}
|
||||
|
||||
// dashboardAddr 已废弃:面板地址改由 Fonu 前端从服务端表单的「frps 管理接口」字段拼出,agent 不再解析 frps.toml。
|
||||
// dashboardAddr 已废弃:面板地址改由 Havline 前端从服务端表单的「frps 管理接口」字段拼出,agent 不再解析 frps.toml。
|
||||
func dashboardAddr(configPath string) string {
|
||||
data, err := os.ReadFile(configPath)
|
||||
if err != nil {
|
||||
@@ -754,7 +754,7 @@ func nginxBinaryPath(configured string) string {
|
||||
func detectNginxConfDir(binary string) (string, error) {
|
||||
nginx := nginxBinaryPath(binary)
|
||||
if nginx == "" {
|
||||
return "", fmt.Errorf("未找到可用的 nginx 可执行文件;请先在 VPS 安装 Nginx(apt install nginx / yum install nginx),或用 FONU_AGENT_NGINX_BIN 显式指定路径")
|
||||
return "", fmt.Errorf("未找到可用的 nginx 可执行文件;请先在 VPS 安装 Nginx(apt install nginx / yum install nginx),或用 HAVLINE_AGENT_NGINX_BIN 显式指定路径")
|
||||
}
|
||||
// 旧版 Agent 可能把 <配置>.versions 目录留在 include 范围内,先按常见目录清理,避免 nginx -T 直接失败。
|
||||
for _, dir := range []string{"/etc/nginx/sites-enabled", "/etc/nginx/conf.d", "/etc/nginx"} {
|
||||
@@ -802,8 +802,8 @@ func detectNginxConfDir(binary string) (string, error) {
|
||||
lastReason = fmt.Sprintf("%s: %v", dir, err)
|
||||
continue
|
||||
}
|
||||
probe := filepath.Join(dir, "fonu-probe.conf")
|
||||
probeBody := "# Managed by fonu-agent. Do not edit.\nserver {\n listen 127.0.0.1:1;\n server_name fonu-probe.invalid;\n}\n"
|
||||
probe := filepath.Join(dir, "havline-probe.conf")
|
||||
probeBody := "# Managed by havline-agent. Do not edit.\nserver {\n listen 127.0.0.1:1;\n server_name havline-probe.invalid;\n}\n"
|
||||
if err := atomicWrite(probe, []byte(probeBody), 0o644); err != nil {
|
||||
lastReason = fmt.Sprintf("%s: %v", dir, err)
|
||||
continue
|
||||
@@ -822,11 +822,11 @@ func detectNginxConfDir(binary string) (string, error) {
|
||||
continue
|
||||
}
|
||||
// 该目录不接受完整 server 块(片段目录):删除 probe 文件。
|
||||
// 若 -t 失败信息指向历史残留的 fonu-*.conf,也一并清理(仅限 Agent 生成的文件)。
|
||||
// 若 -t 失败信息指向历史残留的 havline-*.conf,也一并清理(仅限 Agent 生成的文件)。
|
||||
_ = os.Remove(probe)
|
||||
if tOut, tErr := exec.Command(nginx, "-t").CombinedOutput(); tErr != nil {
|
||||
lastReason = fmt.Sprintf("%s: nginx -t 失败:%s", dir, tailText(string(tOut), 300))
|
||||
cleanupLegacyFonuConf(string(tOut))
|
||||
cleanupLegacyHavlineConf(string(tOut))
|
||||
if err := runCommand(nginx, "-t"); err == nil {
|
||||
continue // 清理残留后配置恢复可用,换下一个目录
|
||||
}
|
||||
@@ -837,7 +837,7 @@ func detectNginxConfDir(binary string) (string, error) {
|
||||
if lastReason == "" {
|
||||
lastReason = "没有可尝试的目录"
|
||||
}
|
||||
return "", fmt.Errorf("在 %d 个被加载目录中均无法放置完整 server 配置(已尝试: %s);最后一次失败原因:%s;也可用 FONU_AGENT_NGINX_CONF_DIR 显式指定(Debian/Ubuntu 通常是 /etc/nginx/conf.d 或 /etc/nginx/sites-enabled)", len(dirs), strings.Join(dirs, ", "), lastReason)
|
||||
return "", fmt.Errorf("在 %d 个被加载目录中均无法放置完整 server 配置(已尝试: %s);最后一次失败原因:%s;也可用 HAVLINE_AGENT_NGINX_CONF_DIR 显式指定(Debian/Ubuntu 通常是 /etc/nginx/conf.d 或 /etc/nginx/sites-enabled)", len(dirs), strings.Join(dirs, ", "), lastReason)
|
||||
}
|
||||
|
||||
// dirHasVhostConf 判断目录下是否已有含 server_name 的 .conf(HTTP vhost 语义)。
|
||||
@@ -857,10 +857,10 @@ func dirHasVhostConf(dir string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// cleanupLegacyFonuConf 根据 nginx -t 的报错文本清理 Agent 历史生成的坏文件(仅限 fonu- 前缀)。
|
||||
func cleanupLegacyFonuConf(nginxTestOutput string) {
|
||||
// cleanupLegacyHavlineConf 根据 nginx -t 的报错文本清理 Agent 历史生成的坏文件(仅限 havline- 前缀)。
|
||||
func cleanupLegacyHavlineConf(nginxTestOutput string) {
|
||||
for _, line := range strings.Split(nginxTestOutput, "\n") {
|
||||
idx := strings.Index(line, "fonu-")
|
||||
idx := strings.Index(line, "havline-")
|
||||
if idx < 0 {
|
||||
continue
|
||||
}
|
||||
@@ -878,7 +878,7 @@ func cleanupLegacyFonuConf(nginxTestOutput string) {
|
||||
if !strings.HasSuffix(path, ".conf") {
|
||||
continue
|
||||
}
|
||||
if data, err := os.ReadFile(path); err == nil && strings.HasPrefix(string(data), "# Managed by fonu-agent.") {
|
||||
if data, err := os.ReadFile(path); err == nil && strings.HasPrefix(string(data), "# Managed by havline-agent.") {
|
||||
_ = os.Remove(path)
|
||||
}
|
||||
}
|
||||
@@ -905,10 +905,10 @@ func (s *Server) routeDetails() []map[string]any {
|
||||
}
|
||||
details := []map[string]any{}
|
||||
for _, entry := range entries {
|
||||
if entry.IsDir() || !strings.HasPrefix(entry.Name(), "fonu-") || !strings.HasSuffix(entry.Name(), ".conf") {
|
||||
if entry.IsDir() || !strings.HasPrefix(entry.Name(), "havline-") || !strings.HasSuffix(entry.Name(), ".conf") {
|
||||
continue
|
||||
}
|
||||
domain := strings.TrimSuffix(strings.TrimPrefix(entry.Name(), "fonu-"), ".conf")
|
||||
domain := strings.TrimSuffix(strings.TrimPrefix(entry.Name(), "havline-"), ".conf")
|
||||
path := filepath.Join(s.cfg.NginxConfDir, entry.Name())
|
||||
item := map[string]any{
|
||||
"domain": domain,
|
||||
@@ -935,7 +935,7 @@ type routeRequest struct {
|
||||
TLS bool `json:"tls"`
|
||||
CertDir string `json:"cert_dir,omitempty"`
|
||||
WebSocket bool `json:"websocket,omitempty"`
|
||||
VhostPort int `json:"vhost_port,omitempty"` // 回源自检用:Fonu 传入本次部署的 frps vhost 端口
|
||||
VhostPort int `json:"vhost_port,omitempty"` // 回源自检用:Havline 传入本次部署的 frps vhost 端口
|
||||
RedirectTLS bool `json:"redirect_https,omitempty"` // HTTP 80 强制跳转 HTTPS
|
||||
AllowIPs []string `json:"allow_ips,omitempty"` // IP 白名单;空则不限制
|
||||
BasicAuthUser string `json:"basic_auth_user,omitempty"` // Basic Auth 用户名;空则不启用(密码自动生成)
|
||||
@@ -1143,7 +1143,7 @@ type nginxInstallResult struct {
|
||||
// 需要 agent 以 root 运行(systemd 单元默认如此)。
|
||||
func (s *Server) installNginx(w http.ResponseWriter, r *http.Request) {
|
||||
if os.Geteuid() != 0 {
|
||||
writeJSON(w, http.StatusForbidden, map[string]string{"error": "安装 Nginx 需要 root 权限:请以 root 运行 fonu-agent"})
|
||||
writeJSON(w, http.StatusForbidden, map[string]string{"error": "安装 Nginx 需要 root 权限:请以 root 运行 havline-agent"})
|
||||
return
|
||||
}
|
||||
if probe := s.probeNginx(); probe.OK {
|
||||
@@ -1196,7 +1196,7 @@ type chinaCIDRRequest struct {
|
||||
Content string `json:"content"`
|
||||
}
|
||||
|
||||
// putChinaCIDR 接收 Fonu 下发的中国 IP 段(geo include 格式),写入 geo 变量文件并重载。
|
||||
// putChinaCIDR 接收 Havline 下发的中国 IP 段(geo include 格式),写入 geo 变量文件并重载。
|
||||
func (s *Server) putChinaCIDR(w http.ResponseWriter, r *http.Request) {
|
||||
var req chinaCIDRRequest
|
||||
if err := json.NewDecoder(http.MaxBytesReader(w, r.Body, 16<<20)).Decode(&req); err != nil {
|
||||
@@ -1226,7 +1226,7 @@ func (s *Server) putChinaCIDR(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, http.StatusBadGateway, map[string]string{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
geo := "# Managed by fonu-agent. Do not edit.\ngeo $fonu_china_client {\n default 0;\n include " + chinaListPath() + ";\n}\n"
|
||||
geo := "# Managed by havline-agent. Do not edit.\ngeo $havline_china_client {\n default 0;\n include " + chinaListPath() + ";\n}\n"
|
||||
if err := atomicWrite(s.chinaGeoFilePath(), []byte(geo), 0o640); err != nil {
|
||||
writeJSON(w, http.StatusBadGateway, map[string]string{"error": err.Error()})
|
||||
return
|
||||
@@ -1256,7 +1256,7 @@ func (s *Server) writeRoute(req routeRequest) error {
|
||||
if certDir == "" {
|
||||
certDir = filepath.Join(s.cfg.CertsDir, req.Domain)
|
||||
}
|
||||
// 仅中国大陆 IP 依赖已下发的 IP 段(geo 变量在 fonuagent-china.conf 中定义)
|
||||
// 仅中国大陆 IP 依赖已下发的 IP 段(geo 变量在 havlineagent-china.conf 中定义)
|
||||
if req.ChinaOnly {
|
||||
if _, err := os.Stat(chinaListPath()); err != nil {
|
||||
return fmt.Errorf("启用「仅中国大陆 IP」前需先同步中国 IP 段(请在公网反代页触发同步后重试)")
|
||||
@@ -1265,7 +1265,7 @@ func (s *Server) writeRoute(req routeRequest) error {
|
||||
content := nginxRoute(req, certDir)
|
||||
path := s.routePath(req.Domain)
|
||||
// 清理历史版本写到其他目录的同域名 Agent 文件:从 nginx -T 的生效清单反向比对,
|
||||
// 非当前目录但内容带 Agent 标记的 fonu-<domain>.conf 一律删除(不碰宝塔自己的配置)。
|
||||
// 非当前目录但内容带 Agent 标记的 havline-<domain>.conf 一律删除(不碰宝塔自己的配置)。
|
||||
if nginx := s.nginxPath(); nginx != "" {
|
||||
if tOut, tErr := exec.Command(nginx, "-T").CombinedOutput(); tErr == nil {
|
||||
for _, line := range strings.Split(string(tOut), "\n") {
|
||||
@@ -1273,8 +1273,8 @@ func (s *Server) writeRoute(req routeRequest) error {
|
||||
if value, found := strings.CutPrefix(line, "# configuration file "); found {
|
||||
p := strings.TrimSuffix(strings.TrimSpace(value), ":")
|
||||
base := filepath.Base(p)
|
||||
if p != path && base == "fonu-"+req.Domain+".conf" {
|
||||
if data, readErr := os.ReadFile(p); readErr == nil && strings.HasPrefix(string(data), "# Managed by fonu-agent.") {
|
||||
if p != path && base == "havline-"+req.Domain+".conf" {
|
||||
if data, readErr := os.ReadFile(p); readErr == nil && strings.HasPrefix(string(data), "# Managed by havline-agent.") {
|
||||
_ = os.Remove(p)
|
||||
}
|
||||
}
|
||||
@@ -1299,17 +1299,17 @@ func (s *Server) routeNames() []string {
|
||||
}
|
||||
var result []string
|
||||
for _, entry := range entries {
|
||||
if entry.IsDir() || !strings.HasPrefix(entry.Name(), "fonu-") || !strings.HasSuffix(entry.Name(), ".conf") {
|
||||
if entry.IsDir() || !strings.HasPrefix(entry.Name(), "havline-") || !strings.HasSuffix(entry.Name(), ".conf") {
|
||||
continue
|
||||
}
|
||||
result = append(result, strings.TrimSuffix(strings.TrimPrefix(entry.Name(), "fonu-"), ".conf"))
|
||||
result = append(result, strings.TrimSuffix(strings.TrimPrefix(entry.Name(), "havline-"), ".conf"))
|
||||
}
|
||||
sort.Strings(result)
|
||||
return result
|
||||
}
|
||||
|
||||
func (s *Server) routePath(domain string) string {
|
||||
return filepath.Join(s.cfg.NginxConfDir, "fonu-"+domain+".conf")
|
||||
return filepath.Join(s.cfg.NginxConfDir, "havline-"+domain+".conf")
|
||||
}
|
||||
|
||||
func (s *Server) validateNginx() error {
|
||||
@@ -1380,7 +1380,7 @@ func migrateVersionDirsFromNginxOutput(output string) bool {
|
||||
func (s *Server) reloadNginx() error {
|
||||
nginx := s.nginxPath()
|
||||
if nginx == "" {
|
||||
return errors.New("未找到 nginx 可执行文件:请先在「公网反代」页安装 Nginx,或用 FONU_AGENT_NGINX_BIN 指定路径")
|
||||
return errors.New("未找到 nginx 可执行文件:请先在「公网反代」页安装 Nginx,或用 HAVLINE_AGENT_NGINX_BIN 指定路径")
|
||||
}
|
||||
return runCommand(nginx, "-s", "reload")
|
||||
}
|
||||
@@ -1530,7 +1530,7 @@ func validDomain(value string) bool {
|
||||
|
||||
func nginxRoute(req routeRequest, certDir string) string {
|
||||
var b strings.Builder
|
||||
b.WriteString("# Managed by fonu-agent. Do not edit.\n")
|
||||
b.WriteString("# Managed by havline-agent. Do not edit.\n")
|
||||
// HTTPSDisabled 显式关闭 HTTPS:即使证书已推送也不监听 443(字段缺省 = 沿用现有行为)
|
||||
tlsEnabled := req.TLS && !req.HTTPSDisabled
|
||||
if req.RedirectTLS && tlsEnabled {
|
||||
@@ -1557,7 +1557,7 @@ func nginxRoute(req routeRequest, certDir string) string {
|
||||
Enabled: req.SecurityHeaders,
|
||||
HTTPS: tlsEnabled,
|
||||
}))
|
||||
// 限流/连接数的 zone 定义在 fonuagent-limits.conf(http 上下文),此处只声明状态码
|
||||
// 限流/连接数的 zone 定义在 havlineagent-limits.conf(http 上下文),此处只声明状态码
|
||||
if req.RateLimitRate > 0 {
|
||||
b.WriteString(" limit_req_status 429;\n")
|
||||
}
|
||||
@@ -1572,7 +1572,7 @@ func nginxRoute(req routeRequest, certDir string) string {
|
||||
// 顺序由共享模板统一:deny → 仅大陆规则 → allow → deny all。
|
||||
chinaDeny := ""
|
||||
if req.ChinaOnly {
|
||||
chinaDeny = " if ($fonu_china_client = 0) { return 403; }\n"
|
||||
chinaDeny = " if ($havline_china_client = 0) { return 403; }\n"
|
||||
}
|
||||
aclText := nginxtmpl.AccessDirectives(nginxtmpl.AccessControl{
|
||||
Allow: req.AllowIPs,
|
||||
@@ -1585,15 +1585,15 @@ func nginxRoute(req routeRequest, certDir string) string {
|
||||
if user := strings.TrimSpace(req.BasicAuthUser); user != "" {
|
||||
if password := strings.TrimSpace(req.BasicAuthPassword); password != "" {
|
||||
if err := writeBasicAuthSecret(req.Domain, user, password); err == nil {
|
||||
authLine = fmt.Sprintf(" auth_basic \"Fonu Protected\";\n auth_basic_user_file %s;\n", basicAuthFilePath(req.Domain))
|
||||
authLine = fmt.Sprintf(" auth_basic \"Havline Protected\";\n auth_basic_user_file %s;\n", basicAuthFilePath(req.Domain))
|
||||
}
|
||||
} else if _, err := ensureBasicAuthSecret(req.Domain, user); err == nil {
|
||||
authLine = fmt.Sprintf(" auth_basic \"Fonu Protected\";\n auth_basic_user_file %s;\n", basicAuthFilePath(req.Domain))
|
||||
authLine = fmt.Sprintf(" auth_basic \"Havline Protected\";\n auth_basic_user_file %s;\n", basicAuthFilePath(req.Domain))
|
||||
}
|
||||
}
|
||||
// 限流 / 连接数(zone 在 http 上下文定义)
|
||||
limitText := nginxtmpl.LimitDirectives(nginxtmpl.LimitConfig{
|
||||
Zone: nginxtmpl.ZoneName("fonu", req.Domain),
|
||||
Zone: nginxtmpl.ZoneName("havline", req.Domain),
|
||||
Rate: req.RateLimitRate,
|
||||
Burst: req.RateLimitBurst,
|
||||
Conn: req.ConnLimitMax,
|
||||
@@ -1603,21 +1603,21 @@ func nginxRoute(req routeRequest, certDir string) string {
|
||||
}
|
||||
|
||||
// agentStateDir 存放 Agent 的持久状态(htpasswd、geo IP 段、限流参数)。
|
||||
const agentStateDir = "/var/lib/fonu-agent"
|
||||
const agentStateDir = "/var/lib/havline-agent"
|
||||
|
||||
// zoneKey 把域名转成合法的 nginx zone 名(仅保留小写字母与数字,其余换下划线)。
|
||||
func zoneKey(domain string) string {
|
||||
return nginxtmpl.ZoneName("fonu", domain)
|
||||
return nginxtmpl.ZoneName("havline", domain)
|
||||
}
|
||||
|
||||
// limitsFilePath 返回 zone 定义文件(放在 vhost 目录,顶层指令即 http 上下文)。
|
||||
func (s *Server) limitsFilePath() string {
|
||||
return filepath.Join(s.cfg.NginxConfDir, "fonuagent-limits.conf")
|
||||
return filepath.Join(s.cfg.NginxConfDir, "havlineagent-limits.conf")
|
||||
}
|
||||
|
||||
// chinaGeoFilePath 返回 geo 变量定义文件(同样位于 http 上下文)。
|
||||
func (s *Server) chinaGeoFilePath() string {
|
||||
return filepath.Join(s.cfg.NginxConfDir, "fonuagent-china.conf")
|
||||
return filepath.Join(s.cfg.NginxConfDir, "havlineagent-china.conf")
|
||||
}
|
||||
|
||||
// chinaListPath 返回中国 IP 段文件(geo include 格式:<cidr> 1;)。
|
||||
@@ -1678,7 +1678,7 @@ func (s *Server) writeLimitState(state map[string]routeLimit) error {
|
||||
return nil
|
||||
}
|
||||
var b strings.Builder
|
||||
b.WriteString("# Managed by fonu-agent. Do not edit.\n")
|
||||
b.WriteString("# Managed by havline-agent. Do not edit.\n")
|
||||
domains := make([]string, 0, len(state))
|
||||
for domain := range state {
|
||||
domains = append(domains, domain)
|
||||
@@ -1744,7 +1744,7 @@ func writeBasicAuthSecret(domain, user, password string) error {
|
||||
|
||||
// basicAuthFilePath 返回指定域名的 htpasswd 文件路径(与反代配置同目录管理)。
|
||||
func basicAuthFilePath(domain string) string {
|
||||
return filepath.Join("/var/lib/fonu-agent", "basicauth", domain+".htpasswd")
|
||||
return filepath.Join("/var/lib/havline-agent", "basicauth", domain+".htpasswd")
|
||||
}
|
||||
|
||||
// ensureBasicAuthSecret 读取已有 Basic Auth 密码;不存在则生成随机密码并写入 htpasswd 文件。
|
||||
|
||||
Reference in New Issue
Block a user