点击在线阅读,体验更好 | 链接 |
---|---|
现代JavaScript高级小册 | 链接 |
深入浅出Dart | 链接 |
现代TypeScript高级小册 | 链接 |
linwu的算法笔记📒 | 链接 |
引言
最近我的主站编程时光证书过期了,导致用户访问网站时候出错,后面续上免费的证书,由于我是使用的免费的证书,所以证书的有效期只有一年。为了避免证书过期导致网站无法访问,我决定写一个小程序来自动检查证书的过期时间,并在证书快过期时通知我及时更换证书。
自动巡检SSL证书过期时间
我们首先定义了一个checkCertificates
函数,该函数的主要任务是读取一个名为domain.txt
的文件,该文件中列出了需要检查的域名和对应的IP地址。
go
func checkCertificates() {
file, err := os.Open("domain.txt")
if err != nil {
panic(err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
parts := strings.Split(line, ":")
domain := parts[0]
ipPool := strings.Split(strings.ReplaceAll(parts[1], ",", " "), " ")
// ipPool [43.138.235.240]
fmt.Println("ipPool", ipPool)
for _, ip := range ipPool {
conn, err := tls.Dial("tcp", ip+":443", &tls.Config{
ServerName: domain,
InsecureSkipVerify: true, // We're only checking expiration, not validity
})
if err != nil {
fmt.Printf("Error! %s\n", ip)
fmt.Println(domain)
continue
}
defer conn.Close()
cert := conn.ConnectionState().PeerCertificates[0]
endDate := cert.NotAfter
currentTime := time.Now()
remainingDays := endDate.Sub(currentTime).Hours() / 24
fmt.Printf("ip: %s\ndomain: %s\n", ip, domain)
sendEmail("SSL证书过期提醒", fmt.Sprintf("The certificate for domain %s (IP: %s) will expire in less than %f days!", domain, ip, remainingDays))
if remainingDays < 7 && remainingDays >= 0 {
fmt.Println("剩余时间小于七天!请及时更换证书!")
fmt.Printf("ip: %s, %s\n", ip, domain)
} else if remainingDays < 0 {
fmt.Println("证书已过期!请及时更换证书!")
} else {
fmt.Printf("剩余天数为:%f\n", remainingDays)
}
}
}
if err := scanner.Err(); err != nil {
panic(err)
}
}
邮件通知
当我们知道了证书的剩余有效期后,下一步是通知相关人员。在
sendEmail
函数中,我们使用了gomail
库来发送邮件。
go
func sendEmail(subject, body string) {
from := "linwu.hi@gmail.com"
pass := "xxx"
to := "linwu.hi@gmail.com"
m := gomail.NewMessage()
m.SetHeader("From", from)
m.SetHeader("To", to)
m.SetHeader("Subject", subject)
m.SetBody("text/plain", body)
d := gomail.NewDialer("smtp.gmail.com", 587, from, pass)
if err := d.DialAndSend(m); err != nil {
log.Fatal(err)
}
}
定时任务
为了确保我们能够及时地检测到证书的状态,我们需要定期执行上述的检查任务。在
main
函数中,我们使用了cron
库来创建一个定时任务。
go
func main() {
c := cron.New(cron.WithSeconds())
c.AddFunc("0 0 0 * * ?", checkCertificates) // 每日凌晨0点执行, 检查证书过期时间,通知到老板
c.Start()
select {} // 阻止主goroutine退出
}
完整代码
go
package main
import (
"bufio"
"crypto/tls"
"fmt"
gomail "gopkg.in/gomail.v2"
"log"
"os"
"strings"
"time"
)
func sendEmail(subject, body string) {
from := "linwu.hi@gmail.com"
pass := "lbqhjuvomebvwtox"
to := "linwu.hi@gmail.com"
m := gomail.NewMessage()
m.SetHeader("From", from)
m.SetHeader("To", to)
m.SetHeader("Subject", subject)
m.SetBody("text/plain", body)
d := gomail.NewDialer("smtp.gmail.com", 587, from, pass)
// Send the email
if err := d.DialAndSend(m); err != nil {
log.Fatal(err)
}
}
func checkCertificates() {
file, err := os.Open("domain.txt")
if err != nil {
panic(err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
parts := strings.Split(line, ":")
domain := parts[0]
ipPool := strings.Split(strings.ReplaceAll(parts[1], ",", " "), " ")
// ipPool [43.138.235.240]
fmt.Println("ipPool", ipPool)
for _, ip := range ipPool {
conn, err := tls.Dial("tcp", ip+":443", &tls.Config{
ServerName: domain,
InsecureSkipVerify: true, // We're only checking expiration, not validity
})
if err != nil {
fmt.Printf("Error! %s\n", ip)
fmt.Println(domain)
continue
}
defer conn.Close()
cert := conn.ConnectionState().PeerCertificates[0]
endDate := cert.NotAfter
currentTime := time.Now()
remainingDays := endDate.Sub(currentTime).Hours() / 24
fmt.Printf("ip: %s\ndomain: %s\n", ip, domain)
sendEmail("SSL证书过期提醒", fmt.Sprintf("The certificate for domain %s (IP: %s) will expire in less than %f days!", domain, ip, remainingDays))
if remainingDays < 7 && remainingDays >= 0 {
fmt.Println("剩余时间小于七天!请及时更换证书!")
fmt.Printf("ip: %s, %s\n", ip, domain)
} else if remainingDays < 0 {
fmt.Println("证书已过期!请及时更换证书!")
} else {
fmt.Printf("剩余天数为:%f\n", remainingDays)
}
}
}
if err := scanner.Err(); err != nil {
panic(err)
}
}
func main() {
c := cron.New(cron.WithSeconds()) // 创建一个新的cron实例
c.AddFunc("0 0 0 * * ?", checkCertificates) // 每日凌晨0点执行
c.Start() // 开始执行定时任务
select {} // 阻止主goroutine退出
}
小册
整理两本小册,一本是前端面试小册,一本是图解算法,阅读体验都很好,欢迎添加我微信
linwu-hi
获取