前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >5分钟教你SSL证书自动巡检与过期提醒

5分钟教你SSL证书自动巡检与过期提醒

作者头像
linwu
发布2023-08-13 09:37:30
5280
发布2023-08-13 09:37:30
举报
文章被收录于专栏:编程时光编程时光

深入浅出Dart

现代TypeScript高级小册

linwu的算法笔记📒

引言

最近我的主站编程时光证书过期了,导致用户访问网站时出错,后面续上免费的证书,由于我是使用的免费的证书,所以证书的有效期只有一年。为了避免证书过期导致网站无法访问,我决定写一个小程序来自动检查证书的过期时间,并在证书快过期时通知我及时更换证书。

image.png
image.png

自动巡检SSL证书过期时间

我们首先定义了一个checkCertificates函数,该函数的主要任务是读取一个名为domain.txt的文件,该文件中列出了需要检查的域名和对应的IP地址。

代码语言:javascript
复制
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 &amp;&amp; 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库来发送邮件。

代码语言:javascript
复制
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库来创建一个定时任务。

代码语言:javascript
复制
func main() {
    c := cron.New(cron.WithSeconds())
    c.AddFunc("0 0 0 * * ?", checkCertificates) // 每日凌晨0点执行, 检查证书过期时间,通知到老板
    c.Start()
    select {} // 阻止主goroutine退出
}

完整代码

代码语言:javascript
复制
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", &amp;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 &amp;&amp; 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获取

image.png
image.png
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-08-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 引言
  • 自动巡检SSL证书过期时间
  • 邮件通知
  • 定时任务
  • 完整代码
  • 小册
相关产品与服务
SSL 证书
腾讯云 SSL 证书(SSL Certificates)为您提供 SSL 证书的申请、管理、部署等服务,为您提供一站式 HTTPS 解决方案。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档