整理
This commit is contained in:
		
							parent
							
								
									ca2a3a8c24
								
							
						
					
					
						commit
						b41a60a932
					
				|  | @ -1,82 +0,0 @@ | |||
| package src | ||||
| 
 | ||||
| //import (
 | ||||
| //	"log"
 | ||||
| //	"net"
 | ||||
| //	"os"
 | ||||
| //)
 | ||||
| //
 | ||||
| //// InitSocket 初始化 socket 文件
 | ||||
| //func InitSocket() {
 | ||||
| //	log.Println("Start listen command")
 | ||||
| //	// 删除旧的 socket 文件
 | ||||
| //	if _, err := os.Stat(SocketFile); err == nil {
 | ||||
| //		os.Remove(SocketFile)
 | ||||
| //	}
 | ||||
| //
 | ||||
| //	listener, err := net.Listen("unix", SocketFile)
 | ||||
| //	if err != nil {
 | ||||
| //		log.Fatalf("Failed to listen on socket: %v", err)
 | ||||
| //	}
 | ||||
| //	defer listener.Close()
 | ||||
| //
 | ||||
| //	for {
 | ||||
| //		log.Println("Waiting for connections...")
 | ||||
| //		conn, err := listener.Accept()
 | ||||
| //		if err != nil {
 | ||||
| //			log.Printf("Failed to accept connection: %v", err)
 | ||||
| //			continue
 | ||||
| //		}
 | ||||
| //
 | ||||
| //		go handleConnection(conn)
 | ||||
| //	}
 | ||||
| //}
 | ||||
| //
 | ||||
| ///*
 | ||||
| //*
 | ||||
| //处理连接
 | ||||
| //*/
 | ||||
| //func handleConnection(conn net.Conn) {
 | ||||
| //	defer conn.Close()
 | ||||
| //
 | ||||
| //	buf := make([]byte, 1024)
 | ||||
| //	n, err := conn.Read(buf)
 | ||||
| //	if err != nil {
 | ||||
| //		log.Printf("Failed to read command: %v", err)
 | ||||
| //		return
 | ||||
| //	}
 | ||||
| //
 | ||||
| //	command := string(buf[:n])
 | ||||
| //	log.Printf("Received command: %s", command)
 | ||||
| //
 | ||||
| //	// 在这里处理接收到的命令
 | ||||
| //	switch command {
 | ||||
| //	case "stop":
 | ||||
| //		onStop()
 | ||||
| //	default:
 | ||||
| //		onCommand(command)
 | ||||
| //	}
 | ||||
| //}
 | ||||
| //
 | ||||
| ///*
 | ||||
| //*
 | ||||
| //收到停止命令
 | ||||
| //*/
 | ||||
| //func onStop() {
 | ||||
| //	log.Println("Stopping daemon...")//	os.Remove(PidFile)
 | ||||
| //	log.Println("Remove PID File...")
 | ||||
| //	os.Remove(SocketFile)
 | ||||
| //	log.Println("Remove Socket File...")
 | ||||
| //	os.Exit(0)
 | ||||
| //}
 | ||||
| //
 | ||||
| ///*
 | ||||
| //收到命令
 | ||||
| //*/
 | ||||
| //func onCommand(command string) {
 | ||||
| //
 | ||||
| //}
 | ||||
| //
 | ||||
| //func onConfig() {
 | ||||
| //
 | ||||
| //}
 | ||||
							
								
								
									
										267
									
								
								src/config.go
									
									
									
									
									
								
							
							
						
						
									
										267
									
								
								src/config.go
									
									
									
									
									
								
							|  | @ -1,267 +0,0 @@ | |||
| package src | ||||
| 
 | ||||
| //import (
 | ||||
| //	"acme-mana/src/crypto"
 | ||||
| //	"bufio"
 | ||||
| //	"fmt"
 | ||||
| //	"github.com/go-acme/lego/v4/log"
 | ||||
| //	"github.com/go-acme/lego/v4/platform/config/env"
 | ||||
| //	"gopkg.in/yaml.v3"
 | ||||
| //	"os"
 | ||||
| //	"strings"
 | ||||
| //)
 | ||||
| //
 | ||||
| //func ReadConfig() *AppConfig {
 | ||||
| //	if DnsProviderSupports != nil {
 | ||||
| //		return nil
 | ||||
| //	}
 | ||||
| //	InitConfig()
 | ||||
| //	file, err := os.ReadFile(GetEnvConf().ConfFile)
 | ||||
| //	if err != nil {
 | ||||
| //		log.Fatal(err)
 | ||||
| //	}
 | ||||
| //	var conf *AppConfig
 | ||||
| //	err = yaml.Unmarshal(file, &conf)
 | ||||
| //	if err != nil {
 | ||||
| //		log.Fatal(err)
 | ||||
| //	}
 | ||||
| //	return conf
 | ||||
| //}
 | ||||
| //
 | ||||
| //func InitConfig() {
 | ||||
| //	// 判断当前目录下是否存在配置文件 config.yml
 | ||||
| //	_, err := os.Stat(GetEnvConf().ConfFile)
 | ||||
| //
 | ||||
| //	if os.IsNotExist(err) {
 | ||||
| //		// 配置文件不存在,则创建一个
 | ||||
| //		log.Infof("配置文件不存在,自动创建默认配置文件")
 | ||||
| //		// 生成默认配置
 | ||||
| //		conf := readNewConf()
 | ||||
| //		// 创建一个默认的配置文件
 | ||||
| //		file, err := os.Create(GetEnvConf().ConfFile)
 | ||||
| //		if err != nil {
 | ||||
| //			log.Fatal(err)
 | ||||
| //		}
 | ||||
| //		data, err := yaml.Marshal(conf)
 | ||||
| //		if err != nil {
 | ||||
| //			log.Fatal(err)
 | ||||
| //		}
 | ||||
| //		// 写入配置文件
 | ||||
| //		_, err = file.Write(data)
 | ||||
| //		if err != nil {
 | ||||
| //			log.Fatal(err)
 | ||||
| //		}
 | ||||
| //	}
 | ||||
| //
 | ||||
| //}
 | ||||
| //
 | ||||
| //func readNewConf() *AppConfig {
 | ||||
| //	conf := defaultConf()
 | ||||
| //	log.Println("无配置文件, 生成配置文件")
 | ||||
| //
 | ||||
| //	conf.CertDir = scanConfDefault("请输入证书保存目录; 默认为 cert", "cert")
 | ||||
| //	isGenMsg := "是否需要自动生成用于数据传输加密的RSA密钥对? \n请输入yes(Y)/no(N) 默认为 yes"
 | ||||
| //	isGenErrMsg := "请输入yes(Y)/no(N)"
 | ||||
| //	isGenValues := []string{"yes", "no", "Y", "N"}
 | ||||
| //	isGenEncrypt := scanConfDefaultCheck(isGenMsg, "yes", isGenValues, isGenErrMsg)
 | ||||
| //	if isGenEncrypt == "no" || isGenEncrypt == "N" {
 | ||||
| //		conf.Encrypt.PriKey = scanConf("请输入RSA私钥", "请输入RSA私钥")
 | ||||
| //		conf.Encrypt.PubKey = scanConf("请输入RSA公钥", "请输入RSA公钥")
 | ||||
| //	}
 | ||||
| //
 | ||||
| //	msg := fmt.Sprintf("请输入DNS提供商; 当前支持的: %s", strings.Join(DnsProviderSupports, ","))
 | ||||
| //	errMsg := fmt.Sprintf("不支持的DNS提供商; 当前支持的: %s", strings.Join(DnsProviderSupports, ","))
 | ||||
| //	conf.Use = scanConfDefaultCheck(msg, "", DnsProviderSupports, errMsg)
 | ||||
| //	switch conf.Use {
 | ||||
| //	case "alidns":
 | ||||
| //		fmt.Printf("阿里云DNS配置帮助页: \n%s\n", "https://go-acme.github.io/lego/dns/alidns/index.html")
 | ||||
| //		fmt.Printf("阿里云令牌获取方式:\n%s\n", "https://usercenter.console.aliyun.com/#/manage/ak")
 | ||||
| //		fmt.Printf("阿里云SDK客户端项目地址:\n%s\n", "https://github.com/aliyun/alibaba-cloud-sdk-go?tab=readme-ov-file")
 | ||||
| //		conf.Provider.Ali.RegionID = scanConf("请输入阿里云Region ID", "请输入阿里云Region ID")
 | ||||
| //		conf.Provider.Ali.APIKey = scanConf("请输入阿里云API Key", "请输入阿里云API Key")
 | ||||
| //		conf.Provider.Ali.SecretKey = scanConf("请输入阿里云Secret Key", "请输入阿里云Secret Key")
 | ||||
| //	case "tencentcloud":
 | ||||
| //		fmt.Printf("腾讯云DNS配置帮助页: \n%s\n", "https://go-acme.github.io/lego/dns/tencentcloud/index.html")
 | ||||
| //		fmt.Printf("腾讯云令牌获取方式: \n%s\n", "https://console.cloud.tencent.com/cam/capi")
 | ||||
| //		fmt.Printf("腾讯云SDK客户端项目地址: \n%s\n", "https://github.com/tencentcloud/tencentcloud-sdk-go?tab=readme-ov-file")
 | ||||
| //		conf.Provider.Tencent.SecretId = scanConf("请输入腾讯云Secret Id", "请输入腾讯云Secret Id")
 | ||||
| //		conf.Provider.Tencent.SecretKey = scanConf("请输入腾讯云Secret Key", "请输入腾讯云Secret Key")
 | ||||
| //	case "cloudflare":
 | ||||
| //		fmt.Printf("Cloudflare DNS配置帮助页: \n%s\n", "https://go-acme.github.io/lego/dns/tencentcloud/index.html")
 | ||||
| //		fmt.Printf("Cloudflare 令牌获取方式: \n%s\n", "https://blog.cloudflare.com/zh-cn/api-tokens-general-availability/")
 | ||||
| //		fmt.Printf("Cloudflare SDK客户端项目地址: \n%s\n", "https://github.com/cloudflare/cloudflare-go")
 | ||||
| //		conf.Provider.CloudFlare.Token = scanConf("请输入CloudFlare DNS API Token", "请输入CloudFlare Token")
 | ||||
| //	}
 | ||||
| //	isAddDomainMsg := "是否需要添加证书获取配置?\n您可以在此处通过控制台交互添加;也可以在配置文件创建后,直接修改配置文件.\n请输入yes(Y)/no(N) 默认为 yes"
 | ||||
| //	isAddDomain := scanConfDefaultCheck(isAddDomainMsg, "yes", isGenValues, isGenErrMsg)
 | ||||
| //	if isAddDomain == "no" || isAddDomain == "N" {
 | ||||
| //		fmt.Printf("您可以通过手动修改%s文件, 调整证书获取配置.", GetEnvConf().ConfFile)
 | ||||
| //		conf.Domains = []Domain{}
 | ||||
| //		return conf
 | ||||
| //	}
 | ||||
| //	conf.Domains = []Domain{}
 | ||||
| //	for {
 | ||||
| //		name := scanConf("请输入配置名称", "配置名称不能为空")
 | ||||
| //		email := scanConf("请输入邮箱", "邮箱不能为空")
 | ||||
| //		host := scanConf("请输入主机名;支持泛解析;\n支持多个域名,多个域名用,(英文逗号)分割;\n如: example.com,*.example.com\n", "主机名不能为空")
 | ||||
| //		// 将host通过,分割为数组
 | ||||
| //		hosts := strings.Split(host, ",")
 | ||||
| //		conf.Domains = append(conf.Domains, Domain{
 | ||||
| //			Name:  name,
 | ||||
| //			Email: email,
 | ||||
| //			Host:  hosts,
 | ||||
| //		})
 | ||||
| //		isAddNextDomainMsg := "是否需要继续添加证书获取配置?\n请输入yes(Y)/no(N) 默认为 yes"
 | ||||
| //		isAddNextDomain := scanConfDefaultCheck(isAddNextDomainMsg, "yes", isGenValues, isGenErrMsg)
 | ||||
| //		if isAddNextDomain == "no" || isAddNextDomain == "N" {
 | ||||
| //			fmt.Printf("您后续可以通过手动修改%s文件, 调整证书获取配置.", GetEnvConf().ConfFile)
 | ||||
| //			return conf
 | ||||
| //		}
 | ||||
| //	}
 | ||||
| //}
 | ||||
| //
 | ||||
| //// 读取用户输入
 | ||||
| //func scanConf(msg string, errMsg string) string {
 | ||||
| //	for {
 | ||||
| //		log.Println(msg)
 | ||||
| //		reader := bufio.NewReader(os.Stdin)
 | ||||
| //		name, err := reader.ReadString('\n')
 | ||||
| //		if err != nil {
 | ||||
| //			fmt.Println("读取失败;", err)
 | ||||
| //			continue
 | ||||
| //		}
 | ||||
| //		name = strings.Trim(name, "\r\n")
 | ||||
| //		if name == "" {
 | ||||
| //			fmt.Println(errMsg)
 | ||||
| //			continue
 | ||||
| //		}
 | ||||
| //		return name
 | ||||
| //	}
 | ||||
| //}
 | ||||
| //
 | ||||
| //func scanConfDefault(msg string, defaultContent string) string {
 | ||||
| //	for {
 | ||||
| //		log.Println(msg)
 | ||||
| //		reader := bufio.NewReader(os.Stdin)
 | ||||
| //		name, err := reader.ReadString('\n')
 | ||||
| //		if err != nil {
 | ||||
| //			fmt.Println("读取失败;", err)
 | ||||
| //			continue
 | ||||
| //		}
 | ||||
| //		name = strings.Trim(name, "\r\n")
 | ||||
| //		if name == "" {
 | ||||
| //			return defaultContent
 | ||||
| //		}
 | ||||
| //		return name
 | ||||
| //	}
 | ||||
| //}
 | ||||
| //
 | ||||
| //func scanConfDefaultCheck(msg string, defaultContent string, values []string, errMsg string) string {
 | ||||
| //	for {
 | ||||
| //		content := scanConfDefault(msg, defaultContent)
 | ||||
| //		// 判断内容是否在values中
 | ||||
| //		for _, value := range values {
 | ||||
| //			if value == content {
 | ||||
| //				return content
 | ||||
| //			}
 | ||||
| //		}
 | ||||
| //		log.Println(errMsg)
 | ||||
| //	}
 | ||||
| //}
 | ||||
| //
 | ||||
| //func defaultConf() *AppConfig {
 | ||||
| //	//priKey, pubKey, err := GenRsa()
 | ||||
| //	priKey, pubKey, err := crypto.GenRSA()
 | ||||
| //	if err != nil {
 | ||||
| //		log.Fatal(err)
 | ||||
| //	}
 | ||||
| //	return &AppConfig{
 | ||||
| //		Use:     "Ali",
 | ||||
| //		CertDir: "cert",
 | ||||
| //		Provider: AppProvider{
 | ||||
| //			Ali: AliProvider{
 | ||||
| //				RegionID:  "cn-hangzhou",
 | ||||
| //				APIKey:    "api_key",
 | ||||
| //				SecretKey: "secret_key",
 | ||||
| //			},
 | ||||
| //			Tencent: TencentProvider{
 | ||||
| //				SecretId:  "secret_id",
 | ||||
| //				SecretKey: "secret_key",
 | ||||
| //			},
 | ||||
| //			CloudFlare: CloudFlareProvider{
 | ||||
| //				Token: "token",
 | ||||
| //			},
 | ||||
| //		},
 | ||||
| //		Domains: []Domain{
 | ||||
| //			{
 | ||||
| //				Name:  "example.com",
 | ||||
| //				Email: "email@example.com",
 | ||||
| //				Host:  []string{"www.example.com"},
 | ||||
| //			},
 | ||||
| //		},
 | ||||
| //		Encrypt: Encrypt{
 | ||||
| //			PriKey: priKey,
 | ||||
| //			PubKey: pubKey,
 | ||||
| //		},
 | ||||
| //	}
 | ||||
| //}
 | ||||
| //
 | ||||
| //type AppConfig struct {
 | ||||
| //	Use string
 | ||||
| //
 | ||||
| //	CertDir string
 | ||||
| //
 | ||||
| //	Provider AppProvider
 | ||||
| //
 | ||||
| //	Domains []Domain
 | ||||
| //
 | ||||
| //	Encrypt Encrypt
 | ||||
| //}
 | ||||
| //
 | ||||
| //type AppProvider struct {
 | ||||
| //	Ali        AliProvider
 | ||||
| //	Tencent    TencentProvider
 | ||||
| //	CloudFlare CloudFlareProvider
 | ||||
| //}
 | ||||
| //type AliProvider struct {
 | ||||
| //	RegionID  string
 | ||||
| //	APIKey    string
 | ||||
| //	SecretKey string
 | ||||
| //}
 | ||||
| //type TencentProvider struct {
 | ||||
| //	SecretId  string
 | ||||
| //	SecretKey string
 | ||||
| //}
 | ||||
| //type CloudFlareProvider struct {
 | ||||
| //	Token string
 | ||||
| //}
 | ||||
| //type Domain struct {
 | ||||
| //	Name  string
 | ||||
| //	Email string
 | ||||
| //	Host  []string
 | ||||
| //}
 | ||||
| //type Encrypt struct {
 | ||||
| //	PriKey string
 | ||||
| //	PubKey string
 | ||||
| //}
 | ||||
| //
 | ||||
| //func (conf AppConfig) FindDomain(name string) *Domain {
 | ||||
| //	for _, domain := range conf.Domains {
 | ||||
| //		if domain.Name == name {
 | ||||
| //			return &domain
 | ||||
| //		}
 | ||||
| //	}
 | ||||
| //	return nil
 | ||||
| //}
 | ||||
| //
 | ||||
| //const ENV_CONF_FILE = "ACME_MANA_CONF_FILE"
 | ||||
| //
 | ||||
| //func InitRuntimeConf() *EnvConf {
 | ||||
| //	return &EnvConf{
 | ||||
| //		ConfFile: env.GetOrDefaultString(ENV_CONF_FILE, "config.yml"),
 | ||||
| //	}
 | ||||
| //}
 | ||||
| //
 | ||||
| //type EnvConf struct {
 | ||||
| //	ConfFile string
 | ||||
| //}
 | ||||
							
								
								
									
										269
									
								
								src/daemon.go
									
									
									
									
									
								
							
							
						
						
									
										269
									
								
								src/daemon.go
									
									
									
									
									
								
							|  | @ -1,269 +0,0 @@ | |||
| package src | ||||
| 
 | ||||
| //import (
 | ||||
| //	"encoding/json"
 | ||||
| //	"log"
 | ||||
| //	"net"
 | ||||
| //	"os"
 | ||||
| //	"os/exec"
 | ||||
| //	"path"
 | ||||
| //	"path/filepath"
 | ||||
| //	"strconv"
 | ||||
| //	"syscall"
 | ||||
| //)
 | ||||
| //
 | ||||
| //var stdout *os.File
 | ||||
| //var stderr *os.File
 | ||||
| //
 | ||||
| //// Start 启动/*
 | ||||
| //func Start() {
 | ||||
| //	initLog()
 | ||||
| //	args := os.Args
 | ||||
| //	if len(args) <= 1 {
 | ||||
| //		//daemonStart()
 | ||||
| //		doTask()
 | ||||
| //		return
 | ||||
| //	}
 | ||||
| //	command := args[1]
 | ||||
| //	switch command {
 | ||||
| //	case "help":
 | ||||
| //		showHelp()
 | ||||
| //	case "block":
 | ||||
| //		doTask()
 | ||||
| //	case "start":
 | ||||
| //		daemonStart()
 | ||||
| //	case "stop":
 | ||||
| //		daemonStop()
 | ||||
| //	case "status":
 | ||||
| //		daemonStatus()
 | ||||
| //	case "dump":
 | ||||
| //		dumpConfig()
 | ||||
| //	case "domains":
 | ||||
| //		showDomains()
 | ||||
| //	case "pubkey":
 | ||||
| //		showPubkey()
 | ||||
| //	case "apply":
 | ||||
| //		applyOnce()
 | ||||
| //	case "-s":
 | ||||
| //		daemonCommand()
 | ||||
| //	default:
 | ||||
| //		log.Fatalf("Unknown command: %s", command)
 | ||||
| //	}
 | ||||
| //}
 | ||||
| //
 | ||||
| //// 初始化日志文件
 | ||||
| //func initLog() {
 | ||||
| //	pwd, err := os.Getwd()
 | ||||
| //	if err != nil {
 | ||||
| //		log.Fatalf("Failed to get current working directory: %v", err)
 | ||||
| //	}
 | ||||
| //	dir := path.Join(pwd, "log")
 | ||||
| //	_, err = os.Stat(dir)
 | ||||
| //	if os.IsNotExist(err) {
 | ||||
| //		err := os.Mkdir(dir, 0777)
 | ||||
| //		if err != nil {
 | ||||
| //			log.Fatalf("Failed to create directory: %v", err)
 | ||||
| //		}
 | ||||
| //	}
 | ||||
| //	outFile, err := os.OpenFile(path.Join(dir, "out.log"), os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
 | ||||
| //	defer outFile.Close()
 | ||||
| //	stdout = outFile
 | ||||
| //
 | ||||
| //	errFile, err := os.OpenFile(path.Join(dir, "err.log"), os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
 | ||||
| //	defer stderr.Close()
 | ||||
| //	stderr = errFile
 | ||||
| //}
 | ||||
| //
 | ||||
| //func showHelp() {
 | ||||
| //}
 | ||||
| //
 | ||||
| //// 守护进程启动
 | ||||
| //func daemonStart() {
 | ||||
| //	GetAppConfig()
 | ||||
| //	isDaemon := os.Getenv("GO_DAEMON")
 | ||||
| //	log.Println("Run Daemon, DAEMON Is " + isDaemon)
 | ||||
| //	if isDaemon != "1" {
 | ||||
| //		// 直接启动
 | ||||
| //		if isRunning() {
 | ||||
| //			log.Println("Daemon is already running.")
 | ||||
| //			return
 | ||||
| //		}
 | ||||
| //
 | ||||
| //		workPath, err := os.Executable()
 | ||||
| //		if err != nil {
 | ||||
| //			log.Fatalf("Failed to get executable path: %v", err)
 | ||||
| //		}
 | ||||
| //		cmd := exec.Cmd{
 | ||||
| //			Path: workPath,
 | ||||
| //			Args: os.Args,
 | ||||
| //			Dir:  filepath.Dir(workPath),
 | ||||
| //			Env:  append(os.Environ(), "GO_DAEMON=1"),
 | ||||
| //			//Stdin:       os.Stdin,
 | ||||
| //			Stdout: stdout,
 | ||||
| //			Stderr: stderr,
 | ||||
| //			//Stdin:       os.Stdin,
 | ||||
| //			//Stdout:      os.Stdout,
 | ||||
| //			//Stderr:      os.Stderr,
 | ||||
| //			SysProcAttr: &syscall.SysProcAttr{},
 | ||||
| //		}
 | ||||
| //
 | ||||
| //		log.Println("Starting daemon...")
 | ||||
| //		err = cmd.Start()
 | ||||
| //		if err != nil {
 | ||||
| //			log.Fatalf("Failed to start daemon: %v", err)
 | ||||
| //		}
 | ||||
| //		err = os.WriteFile(PidFile, []byte(strconv.Itoa(cmd.Process.Pid)), 0644)
 | ||||
| //		if err != nil {
 | ||||
| //			log.Fatalf("Failed to write PID file: %v", err)
 | ||||
| //		}
 | ||||
| //		log.Printf("Daemon started with PID: %d", cmd.Process.Pid)
 | ||||
| //		os.Exit(0)
 | ||||
| //
 | ||||
| //	} else {
 | ||||
| //		// 子进程
 | ||||
| //		doTask()
 | ||||
| //	}
 | ||||
| //
 | ||||
| //}
 | ||||
| //
 | ||||
| //// 守护进程停止
 | ||||
| //func daemonStop() {
 | ||||
| //	sendCommand("stop")
 | ||||
| //}
 | ||||
| //
 | ||||
| //// 守护进程状态
 | ||||
| //func daemonStatus() {
 | ||||
| //	if isRunning() {
 | ||||
| //		log.Println("Daemon is running.")
 | ||||
| //	} else {
 | ||||
| //		log.Println("Daemon is not running.")
 | ||||
| //	}
 | ||||
| //}
 | ||||
| //
 | ||||
| //// 输出配置文件
 | ||||
| //func dumpConfig() {
 | ||||
| //	//config, err := json.Marshal(GetAppConfig())
 | ||||
| //	config, err := json.MarshalIndent(GetAppConfig(), "", "    ")
 | ||||
| //	if err != nil {
 | ||||
| //		log.Fatalf("Failed to marshal config: %v", err)
 | ||||
| //	}
 | ||||
| //	log.Println(string(config))
 | ||||
| //}
 | ||||
| //
 | ||||
| //// 手动执行一次证书申请
 | ||||
| //func applyOnce() {
 | ||||
| //	if len(os.Args) < 3 {
 | ||||
| //		log.Fatalf("Please enter domain name!")
 | ||||
| //	}
 | ||||
| //	name := os.Args[2]
 | ||||
| //	if name == "" {
 | ||||
| //		log.Fatalf("No domain specified!")
 | ||||
| //	}
 | ||||
| //	domain := GetAppConfig().FindDomain(name)
 | ||||
| //	if domain == nil {
 | ||||
| //		log.Fatalf("Domain not found: %s", name)
 | ||||
| //	}
 | ||||
| //	Apply(*domain)
 | ||||
| //}
 | ||||
| //
 | ||||
| //// 输出域名列表
 | ||||
| //func showDomains() {
 | ||||
| //	domains := GetAppConfig().Domains
 | ||||
| //	// 格式化为json并打印
 | ||||
| //	config, err := json.MarshalIndent(domains, "", "    ")
 | ||||
| //	if err != nil {
 | ||||
| //		log.Fatalf("Failed to marshal config: %v", err)
 | ||||
| //	}
 | ||||
| //	log.Println(string(config))
 | ||||
| //}
 | ||||
| //
 | ||||
| //// 输出公钥
 | ||||
| //func showPubkey() {
 | ||||
| //	key := GetAppConfig().Encrypt.PubKey
 | ||||
| //	log.Println(key)
 | ||||
| //}
 | ||||
| //
 | ||||
| //// 守护进程接收命令
 | ||||
| //func daemonCommand() {
 | ||||
| //	log.Println("Sending command...")
 | ||||
| //	command := os.Args[2]
 | ||||
| //	sendCommand(command)
 | ||||
| //
 | ||||
| //}
 | ||||
| //
 | ||||
| //// 发送命令
 | ||||
| //func sendCommand(command string) {
 | ||||
| //	conn, err := net.Dial("unix", SocketFile)
 | ||||
| //	if err != nil {
 | ||||
| //		log.Fatalf("Failed to connect to daemon: %v", err)
 | ||||
| //	}
 | ||||
| //	defer func(conn net.Conn) {
 | ||||
| //		err := conn.Close()
 | ||||
| //		if err != nil {
 | ||||
| //			log.Fatalf("Failed to close connection: %v", err)
 | ||||
| //		}
 | ||||
| //	}(conn)
 | ||||
| //
 | ||||
| //	_, err = conn.Write([]byte(command))
 | ||||
| //	if err != nil {
 | ||||
| //		log.Fatalf("Failed to send command: %v", err)
 | ||||
| //	}
 | ||||
| //
 | ||||
| //	log.Printf("Sending command '%s' to daemon with PID: %d", command, 0)
 | ||||
| //}
 | ||||
| //
 | ||||
| //// 业务进程执行任务
 | ||||
| //func doTask() {
 | ||||
| //
 | ||||
| //	// 监听主进程下发的指令
 | ||||
| //	go InitSocket()
 | ||||
| //
 | ||||
| //	// 监听HTTP请求
 | ||||
| //	go InitHttpServer("0.0.0.0", 10000)
 | ||||
| //
 | ||||
| //	// 自动执行域名证书更新
 | ||||
| //	go AutoRefreshCert()
 | ||||
| //
 | ||||
| //	// 阻止退出
 | ||||
| //	select {}
 | ||||
| //}
 | ||||
| //
 | ||||
| //// 是否已启动
 | ||||
| //func isRunning() bool {
 | ||||
| //	log.Println("Checking if daemon is running...")
 | ||||
| //	pid, err := readPID()
 | ||||
| //	if err != nil {
 | ||||
| //		return false
 | ||||
| //	}
 | ||||
| //
 | ||||
| //	process, err := os.FindProcess(pid)
 | ||||
| //	log.Println("Found process:", process)
 | ||||
| //	if err != nil {
 | ||||
| //		log.Println("Failed to find process:", err)
 | ||||
| //		return false
 | ||||
| //	}
 | ||||
| //	return true
 | ||||
| //	//err = process.Signal(syscall.Signal(0))
 | ||||
| //	//log.Println("Signal result:", err)
 | ||||
| //	//return err == nil
 | ||||
| //}
 | ||||
| //
 | ||||
| //// 读取PID文件
 | ||||
| //func readPID() (int, error) {
 | ||||
| //	log.Println("Reading PID file...")
 | ||||
| //	data, err := os.ReadFile(PidFile)
 | ||||
| //	if err != nil {
 | ||||
| //		log.Println("Failed to read PID file:", err)
 | ||||
| //		return 0, err
 | ||||
| //	}
 | ||||
| //	log.Println("PID file content:", string(data))
 | ||||
| //
 | ||||
| //	pid, err := strconv.Atoi(string(data))
 | ||||
| //	if err != nil {
 | ||||
| //		log.Println("Failed to parse PID:", err)
 | ||||
| //		return 0, err
 | ||||
| //	}
 | ||||
| //	log.Println("PID:", pid)
 | ||||
| //
 | ||||
| //	return pid, nil
 | ||||
| //}
 | ||||
							
								
								
									
										145
									
								
								src/http.go
									
									
									
									
									
								
							
							
						
						
									
										145
									
								
								src/http.go
									
									
									
									
									
								
							|  | @ -1,145 +0,0 @@ | |||
| package src | ||||
| 
 | ||||
| //import (
 | ||||
| //	"acme-mana/src/crypto"
 | ||||
| //	"encoding/base64"
 | ||||
| //	"encoding/hex"
 | ||||
| //	"encoding/json"
 | ||||
| //	"github.com/gin-gonic/gin"
 | ||||
| //	"log"
 | ||||
| //	"os"
 | ||||
| //	"path"
 | ||||
| //	"path/filepath"
 | ||||
| //	"strconv"
 | ||||
| //)
 | ||||
| //
 | ||||
| //func InitHttpServer(host string, port int) {
 | ||||
| //
 | ||||
| //	log.Println("Start http server, Listen " + strconv.Itoa(port))
 | ||||
| //	h := gin.Default()
 | ||||
| //	h.GET("/api/v1/refresh", refreshCert)
 | ||||
| //	h.GET("/api/v1/cert", getCert)
 | ||||
| //	h.GET("/api/v1/domain/list", domainList)
 | ||||
| //	err := h.Run(host + ":" + strconv.Itoa(port))
 | ||||
| //	if err != nil {
 | ||||
| //		return
 | ||||
| //	}
 | ||||
| //}
 | ||||
| //
 | ||||
| //func domainList(c *gin.Context) {
 | ||||
| //	token := getToken(c)
 | ||||
| //	domains := GetAppConfig().Domains
 | ||||
| //	data, err := json.Marshal(domains)
 | ||||
| //	if err != nil {
 | ||||
| //		log.Fatal(err)
 | ||||
| //	}
 | ||||
| //
 | ||||
| //	encryptData := encryptResult(string(data), token)
 | ||||
| //	c.JSON(200, gin.H{
 | ||||
| //		"code": 200,
 | ||||
| //		"msg":  "success",
 | ||||
| //		"data": encryptData,
 | ||||
| //	})
 | ||||
| //}
 | ||||
| //
 | ||||
| //func getCert(c *gin.Context) {
 | ||||
| //	name := c.Query("name")
 | ||||
| //	token := getToken(c)
 | ||||
| //
 | ||||
| //	dir := GetAppConfig().CertDir
 | ||||
| //	dir = filepath.Join(dir, name)
 | ||||
| //	_, err := os.Stat(dir)
 | ||||
| //	if os.IsNotExist(err) {
 | ||||
| //		c.JSON(200, gin.H{
 | ||||
| //			"code": 500,
 | ||||
| //			"msg":  "Name does not exist.",
 | ||||
| //		})
 | ||||
| //		return
 | ||||
| //	}
 | ||||
| //	crtFilePath := path.Join(dir, CertFileName)
 | ||||
| //	crtContent, err := os.ReadFile(crtFilePath)
 | ||||
| //	if err != nil {
 | ||||
| //		c.JSON(200, gin.H{
 | ||||
| //			"code": 500,
 | ||||
| //			"msg":  "Failed to read crt file.",
 | ||||
| //		})
 | ||||
| //		return
 | ||||
| //	}
 | ||||
| //	crt := string(crtContent)
 | ||||
| //
 | ||||
| //	keyFilePath := path.Join(dir, KeyFileName)
 | ||||
| //	keyContent, err := os.ReadFile(keyFilePath)
 | ||||
| //	if err != nil {
 | ||||
| //		c.JSON(200, gin.H{
 | ||||
| //			"code": 500,
 | ||||
| //			"msg":  "Failed to read key file.",
 | ||||
| //		})
 | ||||
| //		return
 | ||||
| //	}
 | ||||
| //	key := string(keyContent)
 | ||||
| //
 | ||||
| //	certInfoFilePath := path.Join(dir, CertInfoFileName)
 | ||||
| //	certInfoContent, err := os.ReadFile(certInfoFilePath)
 | ||||
| //	if err != nil {
 | ||||
| //		c.JSON(200, gin.H{
 | ||||
| //			"code": 500,
 | ||||
| //			"msg":  "Failed to read cert info file.",
 | ||||
| //		})
 | ||||
| //		return
 | ||||
| //	}
 | ||||
| //	certInfo := string(certInfoContent)
 | ||||
| //
 | ||||
| //	data, err := json.Marshal(&DomainData{
 | ||||
| //		Fullchain: crt,
 | ||||
| //		Key:       key,
 | ||||
| //		Info:      certInfo,
 | ||||
| //	})
 | ||||
| //	if err != nil {
 | ||||
| //		log.Fatal(err)
 | ||||
| //	}
 | ||||
| //
 | ||||
| //	encryptData := encryptResult(string(data), token)
 | ||||
| //	c.JSON(200, gin.H{
 | ||||
| //		"code": 200,
 | ||||
| //		"msg":  "Success",
 | ||||
| //		"data": encryptData,
 | ||||
| //	})
 | ||||
| //}
 | ||||
| //
 | ||||
| //func refreshCert(c *gin.Context) {
 | ||||
| //	name := c.Param("name")
 | ||||
| //	domain := GetAppConfig().FindDomain(name)
 | ||||
| //	if domain == nil {
 | ||||
| //		c.JSON(200, gin.H{
 | ||||
| //			"code": 500,
 | ||||
| //			"msg":  "Name does not exist.",
 | ||||
| //		})
 | ||||
| //		return
 | ||||
| //	}
 | ||||
| //	Apply(*domain)
 | ||||
| //	c.JSON(200, gin.H{
 | ||||
| //		"code": 200,
 | ||||
| //		"msg":  "Success",
 | ||||
| //	})
 | ||||
| //}
 | ||||
| //
 | ||||
| //func getToken(c *gin.Context) (token string) {
 | ||||
| //	token = c.Query("token")
 | ||||
| //	token = decryptParam(token)
 | ||||
| //	return
 | ||||
| //}
 | ||||
| //
 | ||||
| //func decryptParam(param string) string {
 | ||||
| //	priKey := GetAppConfig().Encrypt.PriKey
 | ||||
| //	tokenBytes, err := hex.DecodeString(param)
 | ||||
| //	tokenPlain, err := crypto.DecryptRSABase64(priKey, tokenBytes)
 | ||||
| //	if err != nil {
 | ||||
| //		log.Fatal(err)
 | ||||
| //	}
 | ||||
| //	return string(tokenPlain)
 | ||||
| //}
 | ||||
| //
 | ||||
| //func encryptResult(content string, token string) string {
 | ||||
| //	result := crypto.EncryptAES([]byte(token), []byte(content))
 | ||||
| //	return base64.StdEncoding.EncodeToString(result)
 | ||||
| //}
 | ||||
							
								
								
									
										86
									
								
								src/task.go
									
									
									
									
									
								
							
							
						
						
									
										86
									
								
								src/task.go
									
									
									
									
									
								
							|  | @ -1,86 +0,0 @@ | |||
| package src | ||||
| 
 | ||||
| //import (
 | ||||
| //	"encoding/json"
 | ||||
| //	"log"
 | ||||
| //	"os"
 | ||||
| //	"path"
 | ||||
| //	"time"
 | ||||
| //)
 | ||||
| //
 | ||||
| //var AutoRefreshCertTicker = time.NewTicker(time.Hour)
 | ||||
| //
 | ||||
| //func AutoRefreshCert() {
 | ||||
| //	log.Println("Start auto refresh cert")
 | ||||
| //	defer AutoRefreshCertTicker.Stop()
 | ||||
| //	for {
 | ||||
| //		select {
 | ||||
| //		case <-AutoRefreshCertTicker.C:
 | ||||
| //			doRefreshCert()
 | ||||
| //		}
 | ||||
| //	}
 | ||||
| //}
 | ||||
| //
 | ||||
| //func doRefreshCert() {
 | ||||
| //	domains := GetAppConfig().Domains
 | ||||
| //	for _, domain := range domains {
 | ||||
| //		doRefreshCertOnce(domain)
 | ||||
| //	}
 | ||||
| //}
 | ||||
| //
 | ||||
| //func doRefreshCertOnce(domain Domain) {
 | ||||
| //	name := domain.Name
 | ||||
| //	dir := GetAppConfig().CertDir
 | ||||
| //	certDir := path.Join(dir, name)
 | ||||
| //	if !ValidExist(certDir, domain) {
 | ||||
| //		Apply(domain)
 | ||||
| //	}
 | ||||
| //	infoFile := path.Join(certDir, CertInfoFileName)
 | ||||
| //	certInfo := ParseCertInfo(infoFile, domain)
 | ||||
| //	log.Println("Checking if the certificate is expired, Domain: {}", name)
 | ||||
| //	if certInfo.Info.NotAfter.Sub(time.Now()) < 14*24*time.Hour {
 | ||||
| //		log.Println("Apply for a certificate that is about to expire, domain name:", name)
 | ||||
| //		Apply(domain)
 | ||||
| //	}
 | ||||
| //}
 | ||||
| //
 | ||||
| //func ValidExist(certDir string, domain Domain) bool {
 | ||||
| //	_, err := os.Stat(certDir)
 | ||||
| //	if os.IsNotExist(err) {
 | ||||
| //		log.Printf("Applying for a certificate, Domain: %s certificate directory does not exist!", domain.Name)
 | ||||
| //		return false
 | ||||
| //	}
 | ||||
| //	if !ExistFile(certDir, CertFileName) {
 | ||||
| //		log.Printf("Applying for a certificate, Domain: %s %s does not exist!", domain.Name, CertFileName)
 | ||||
| //		return false
 | ||||
| //	}
 | ||||
| //	if !ExistFile(certDir, KeyFileName) {
 | ||||
| //		log.Printf("Applying for a certificate, Domain: %s %s does not exist!", domain.Name, KeyFileName)
 | ||||
| //		return false
 | ||||
| //	}
 | ||||
| //	if !ExistFile(certDir, CertInfoFileName) {
 | ||||
| //		log.Printf("Applying for a certificate, Domain: %s %s does not exist!", domain.Name, CertInfoFileName)
 | ||||
| //		return false
 | ||||
| //	}
 | ||||
| //	return true
 | ||||
| //}
 | ||||
| //
 | ||||
| //func ParseCertInfo(infoFile string, domain Domain) CertInfo {
 | ||||
| //	infoBytes, err := os.ReadFile(infoFile)
 | ||||
| //	if err != nil {
 | ||||
| //		log.Println("Failed to read cert info file, Domain: {}", domain.Name)
 | ||||
| //	}
 | ||||
| //	var certInfo CertInfo
 | ||||
| //	err = json.Unmarshal(infoBytes, &certInfo)
 | ||||
| //	//if err != nil {
 | ||||
| //	//	log.Println("Failed to parse cert info file, Domain: {}", domain.Name)
 | ||||
| //	//}
 | ||||
| //	return certInfo
 | ||||
| //}
 | ||||
| //
 | ||||
| //func ExistFile(dir string, fileName string) bool {
 | ||||
| //	f := path.Join(dir, fileName)
 | ||||
| //	_, err := os.Stat(f)
 | ||||
| //	return !os.IsNotExist(err)
 | ||||
| //
 | ||||
| //}
 | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user