mirror of
https://gitee.com/mirrors/AllinSSL.git
synced 2026-03-08 07:41:10 +08:00
Add files via upload
This commit is contained in:
249
backend/internal/siteMonitor/monitor.go
Normal file
249
backend/internal/siteMonitor/monitor.go
Normal file
@@ -0,0 +1,249 @@
|
||||
package siteMonitor
|
||||
|
||||
import (
|
||||
"ALLinSSL/backend/public"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// SSLInfo 定义结果结构体
|
||||
type SSLInfo struct {
|
||||
Target string
|
||||
HTTPStatus int
|
||||
HTTPStatusText string
|
||||
Domains []string
|
||||
Issuer string
|
||||
NotBefore string
|
||||
NotAfter string
|
||||
DaysRemaining int
|
||||
CertificateOK bool
|
||||
CertificateNote string
|
||||
}
|
||||
|
||||
func GetSqlite() (*public.Sqlite, error) {
|
||||
s, err := public.NewSqlite("data/data.db", "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.Connect()
|
||||
s.TableName = "site_monitor"
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func GetList(search string, p, limit int64) ([]map[string]any, int, error) {
|
||||
var data []map[string]any
|
||||
var count int64
|
||||
s, err := GetSqlite()
|
||||
if err != nil {
|
||||
return data, 0, err
|
||||
}
|
||||
defer s.Close()
|
||||
|
||||
var limits []int64
|
||||
if p >= 0 && limit >= 0 {
|
||||
limits = []int64{0, limit}
|
||||
if p > 1 {
|
||||
limits[0] = (p - 1) * limit
|
||||
limits[1] = p * limit
|
||||
}
|
||||
}
|
||||
|
||||
if search != "" {
|
||||
count, err = s.Where("name like ? or site_domain like ?", []interface{}{"%" + search + "%", "%" + search + "%"}).Count()
|
||||
data, err = s.Where("name like ? or site_domain like ?", []interface{}{"%" + search + "%", "%" + search + "%"}).Order("update_time", "desc").Limit(limits).Select()
|
||||
} else {
|
||||
count, err = s.Count()
|
||||
data, err = s.Order("update_time", "desc").Limit(limits).Select()
|
||||
}
|
||||
if err != nil {
|
||||
return data, 0, err
|
||||
}
|
||||
for _, v := range data {
|
||||
v["domain"] = v["site_domain"]
|
||||
}
|
||||
|
||||
return data, int(count), nil
|
||||
}
|
||||
|
||||
func AddMonitor(name, domain, reportType string, cycle int) error {
|
||||
s, err := GetSqlite()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer s.Close()
|
||||
info, err := CheckWebsite(domain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = s.Insert(map[string]any{
|
||||
"name": name,
|
||||
"site_domain": domain,
|
||||
"report_type": reportType,
|
||||
"cycle": cycle,
|
||||
"state": info.HTTPStatusText,
|
||||
"ca": info.Issuer,
|
||||
"cert_domain": strings.Join(info.Domains, ","),
|
||||
"end_time": info.NotAfter,
|
||||
"end_day": info.DaysRemaining,
|
||||
"create_time": time.Now().Format("2006-01-02 15:04:05"),
|
||||
"update_time": time.Now().Format("2006-01-02 15:04:05"),
|
||||
"last_time": time.Now().Format("2006-01-02 15:04:05"),
|
||||
"active": 1,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func UpdMonitor(id, name, domain, reportType string, cycle int) error {
|
||||
s, err := GetSqlite()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer s.Close()
|
||||
|
||||
info, err := CheckWebsite(domain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = s.Where("id=?", []interface{}{id}).Update(map[string]any{
|
||||
"name": name,
|
||||
"site_domain": domain,
|
||||
"report_type": reportType,
|
||||
"cycle": cycle,
|
||||
"state": info.HTTPStatusText,
|
||||
"ca": info.Issuer,
|
||||
"cert_domain": strings.Join(info.Domains, ","),
|
||||
"end_time": info.NotAfter,
|
||||
"end_day": info.DaysRemaining,
|
||||
"update_time": time.Now().Format("2006-01-02 15:04:05"),
|
||||
"last_time": time.Now().Format("2006-01-02 15:04:05"),
|
||||
"active": 1,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func DelMonitor(id string) error {
|
||||
s, err := GetSqlite()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer s.Close()
|
||||
_, err = s.Where("id=?", []interface{}{id}).Delete()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetMonitor(id string, active int) error {
|
||||
s, err := GetSqlite()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer s.Close()
|
||||
_, err = s.Where("id=?", []interface{}{id}).Update(map[string]any{
|
||||
"active": active,
|
||||
"update_time": time.Now().Format("2006-01-02 15:04:05"),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func UpdInfo(id, domain string, s *public.Sqlite, reportType string) error {
|
||||
info, errCheck := CheckWebsite(domain)
|
||||
now := time.Now()
|
||||
updateData := map[string]any{
|
||||
"state": info.HTTPStatusText,
|
||||
"ca": info.Issuer,
|
||||
"cert_domain": strings.Join(info.Domains, ","),
|
||||
"end_time": info.NotAfter,
|
||||
"end_day": info.DaysRemaining,
|
||||
"last_time": now.Format("2006-01-02 15:04:05"),
|
||||
"except_end_time": now.Format("2006-01-02 15:04:05"),
|
||||
}
|
||||
if errCheck != nil {
|
||||
updateData["state"] = "异常"
|
||||
// return err
|
||||
} else {
|
||||
if info.HTTPStatus != 0 && info.CertificateOK != false {
|
||||
delete(updateData, "except_end_time")
|
||||
} else {
|
||||
errCheck = fmt.Errorf("证书异常")
|
||||
}
|
||||
}
|
||||
_, err := s.Where("id=?", []interface{}{id}).Update(updateData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return errCheck
|
||||
}
|
||||
|
||||
// CheckWebsite 实际检测函数
|
||||
func CheckWebsite(target string) (*SSLInfo, error) {
|
||||
result := &SSLInfo{Target: target}
|
||||
|
||||
// 验证格式是否是 IP 或域名
|
||||
if net.ParseIP(target) == nil {
|
||||
if _, err := net.LookupHost(target); err != nil {
|
||||
return result, fmt.Errorf("无效域名或 IP:%v", err)
|
||||
}
|
||||
}
|
||||
|
||||
hostPort := net.JoinHostPort(target, "443")
|
||||
|
||||
// result := &SSLInfo{Target: target}
|
||||
|
||||
// 1. TLS 连接(先做,否则无 HTTPS 支持直接失败)
|
||||
conn, err := tls.Dial("tcp", hostPort, &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
})
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("目标不支持 HTTPS:%v", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
// 发送 HTTPS 请求检测状态
|
||||
resp, err := http.Get("https://" + target)
|
||||
if err != nil {
|
||||
result.HTTPStatus = 0
|
||||
result.HTTPStatusText = "异常"
|
||||
} else {
|
||||
result.HTTPStatus = resp.StatusCode
|
||||
result.HTTPStatusText = "正常"
|
||||
resp.Body.Close()
|
||||
}
|
||||
|
||||
// 获取证书
|
||||
cert := conn.ConnectionState().PeerCertificates[0]
|
||||
result.Domains = cert.DNSNames
|
||||
result.Issuer = cert.Issuer.CommonName
|
||||
result.NotBefore = cert.NotBefore.Format("2006-01-02 15:04:05")
|
||||
result.NotAfter = cert.NotAfter.Format("2006-01-02 15:04:05")
|
||||
result.DaysRemaining = int(cert.NotAfter.Sub(time.Now()).Hours() / 24)
|
||||
|
||||
now := time.Now()
|
||||
switch {
|
||||
case now.Before(cert.NotBefore):
|
||||
result.CertificateOK = false
|
||||
result.CertificateNote = "尚未生效"
|
||||
case now.After(cert.NotAfter):
|
||||
result.CertificateOK = false
|
||||
result.CertificateNote = "已过期"
|
||||
default:
|
||||
result.CertificateOK = true
|
||||
result.CertificateNote = "有效"
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
21
backend/internal/siteMonitor/monitor_test.go
Normal file
21
backend/internal/siteMonitor/monitor_test.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package siteMonitor
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test(t *testing.T) {
|
||||
site := "bt.cn" // 只传域名或 IP,不要 http://
|
||||
result, err := CheckWebsite(site)
|
||||
if err != nil {
|
||||
fmt.Printf("❌ 检测失败: %v\n", err)
|
||||
return
|
||||
}
|
||||
fmt.Println(result.HTTPStatusText)
|
||||
fmt.Println(result.Domains)
|
||||
fmt.Println(result.Issuer)
|
||||
fmt.Println(result.NotAfter)
|
||||
// fmt.Println(result.Domains)
|
||||
// fmt.Println(result.Domains)
|
||||
}
|
||||
Reference in New Issue
Block a user