Bläddra i källkod

添加客户端TLS证书支持

在配置中增加了客户端证书和密钥的支持,并在请求时使用这些证书进行身份验证。如果提供了客户端证书和密钥,将使用它们创建TLS证书并应用于HTTP请求。
SongZihuan 4 veckor sedan
förälder
incheckning
59af1c457e
2 ändrade filer med 38 tillägg och 7 borttagningar
  1. 16 0
      src/config/watcher.go
  2. 22 7
      src/watcher/watcher.go

+ 16 - 0
src/config/watcher.go

@@ -1,6 +1,7 @@
 package config
 
 import (
+	"crypto/tls"
 	"fmt"
 	"github.com/SongZihuan/web-watcher/src/utils"
 	"strconv"
@@ -11,6 +12,10 @@ type URLConfig struct {
 	URL           string           `yaml:"url"`
 	SkipTLSVerify utils.StringBool `yaml:"skip-tls-verify"`
 	Status        []string         `yaml:"status"`
+	ClientCert    string           `yaml:"client-cert"`
+	ClientKey     string           `yaml:"client-key"`
+
+	ClientKeyPair *tls.Certificate `yaml:"-"`
 }
 
 type WatcherConfig struct {
@@ -70,6 +75,17 @@ func (w *WatcherConfig) check() (err ConfigError) {
 				continue StatusCycle
 			}
 		}
+
+		if url.ClientCert != "" && url.ClientKey != "" {
+			cert, err := tls.X509KeyPair([]byte(url.ClientCert), []byte(url.ClientKey))
+			if err != nil {
+				return NewConfigError(fmt.Sprintf("the cert/key of '%s' is not valid", url.URL))
+			}
+			url.ClientKeyPair = &cert
+			fmt.Printf("%s load client tls cert\n", url.URL)
+		} else {
+			url.ClientKeyPair = nil
+		}
 	}
 
 	return nil

+ 22 - 7
src/watcher/watcher.go

@@ -6,6 +6,7 @@ import (
 	"github.com/SongZihuan/web-watcher/src/config"
 	"github.com/SongZihuan/web-watcher/src/logger"
 	"github.com/SongZihuan/web-watcher/src/notify"
+	"io"
 	"net/http"
 	"strings"
 )
@@ -18,7 +19,7 @@ func Run() error {
 	for _, url := range config.GetConfig().Watcher.URLs {
 		logger.Infof("开始请求 %s", url.Name)
 
-		_, err := httpProcessRetry(url.URL, url.Name, url.Status, url.SkipTLSVerify.IsEnable(false))
+		_, err := httpProcessRetry(url.URL, url.Name, url.Status, url.ClientKeyPair, url.SkipTLSVerify.IsEnable(false))
 		if err != nil {
 			logger.Errorf("请求 %s 出现异常:%s", url.Name, err.Error())
 			notify.NewRecord(url.Name, url.URL, err.Error())
@@ -32,21 +33,21 @@ func Run() error {
 	return nil
 }
 
-func httpProcessRetry(url string, name string, statusList []string, skipTLSVerify bool) (int, error) {
+func httpProcessRetry(url string, name string, statusList []string, cert *tls.Certificate, skipTLSVerify bool) (int, error) {
 	var err1, err2, err3 error
 	var statusCode int
 
-	statusCode, err1 = httpProcessGet(url, name, statusList, skipTLSVerify)
+	statusCode, err1 = httpProcessGet(url, name, statusList, cert, skipTLSVerify)
 	if err1 == nil {
 		return statusCode, nil
 	}
 
-	statusCode, err2 = httpProcessGet(url, name, statusList, skipTLSVerify)
+	statusCode, err2 = httpProcessGet(url, name, statusList, cert, skipTLSVerify)
 	if err2 == nil {
 		return statusCode, nil
 	}
 
-	statusCode, err3 = httpProcessGet(url, name, statusList, skipTLSVerify)
+	statusCode, err3 = httpProcessGet(url, name, statusList, cert, skipTLSVerify)
 	if err3 == nil {
 		return statusCode, nil
 	}
@@ -68,16 +69,23 @@ func httpProcessRetry(url string, name string, statusList []string, skipTLSVerif
 	return -1, err
 }
 
-func httpProcessGet(url string, name string, statusList []string, skipTLSVerify bool) (int, error) {
+func httpProcessGet(url string, name string, statusList []string, cert *tls.Certificate, skipTLSVerify bool) (int, error) {
 	// 创建一个自定义的Transport,这样我们可以访问TLS连接状态
+	tc := &tls.Config{InsecureSkipVerify: skipTLSVerify}
+
+	if cert != nil {
+		tc.Certificates = []tls.Certificate{*cert}
+	}
+
 	tr := &http.Transport{
-		TLSClientConfig: &tls.Config{InsecureSkipVerify: skipTLSVerify}, // 忽略服务器证书验证
+		TLSClientConfig: tc, // 忽略服务器证书验证
 	}
 
 	// 使用自定义的Transport创建一个HTTP客户端
 	client := &http.Client{Transport: tr}
 
 	// 发送请求
+	fmt.Printf("请求URL:%s\n", url)
 	resp, err := client.Get(url)
 	if err != nil {
 		return 0, fmt.Errorf("获取 GET %s 请求错误:%s", name, err.Error())
@@ -88,6 +96,13 @@ func httpProcessGet(url string, name string, statusList []string, skipTLSVerify
 
 	statusCode := resp.StatusCode
 
+	data, err := io.ReadAll(resp.Body)
+	if err != nil {
+		return statusCode, err
+	}
+
+	fmt.Printf("statusCode: %d\n%s\n", statusCode, string(data))
+
 	for _, s := range statusList {
 		switch s {
 		case "xxx":