欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

如何使用工具自動(dòng)監(jiān)測(cè)SSL證書(shū)有效期并發(fā)送提醒郵件

 更新時(shí)間:2024年10月01日 16:46:31   作者:花酒鋤作田  
本文介紹了如何開(kāi)發(fā)一個(gè)工具,用于每日檢測(cè)SSL證書(shū)剩余有效天數(shù)并通過(guò)郵件發(fā)送提醒,工具基于命令行,通過(guò)SMTP協(xié)議發(fā)送郵件,需配置SMTP連接信息,本文還提供了配置文件樣例及代碼實(shí)現(xiàn),幫助用戶輕松部署和使用該工具

前言

自從云廠商的免費(fèi)ssl證書(shū)改成3個(gè)月,而且證書(shū)數(shù)量還是20個(gè)之后,自己網(wǎng)站的ssl證書(shū)就換成了其它免費(fèi)方案。但是免費(fèi)方案不會(huì)提醒證書(shū)過(guò)期,所以寫(xiě)個(gè)工具每天定時(shí)查詢證書(shū)剩余有效天數(shù),如果證書(shū)即將過(guò)期,就發(fā)送郵件提醒。

基本實(shí)現(xiàn)

最基本的代碼功能就是檢測(cè)網(wǎng)站ssl證書(shū)的有效天數(shù),可以用命令行傳參的方式指定網(wǎng)站域名。

package main

import (
	"crypto/tls"
	"flag"
	"fmt"
	"net"
	"os"
	"sync"
	"time"
)

var (
	port int
	wg   sync.WaitGroup
)

func checkssl(domain string, port int) {
	defer wg.Done()
	host := fmt.Sprintf("%s:%d", domain, port)
	conn, err := tls.DialWithDialer(&net.Dialer{
		Timeout:  time.Second * 5,
		Deadline: time.Now().Add(time.Second * 5),
	}, "tcp", host, &tls.Config{InsecureSkipVerify: true})
	if err != nil {
		fmt.Println(err)
		return
	}
	defer conn.Close()

	stats := conn.ConnectionState()
	certs := stats.PeerCertificates[0]
	localtz, _ := time.LoadLocation("Asia/Shanghai")
	issueTime := certs.NotBefore.In(localtz)
	expireTime := certs.NotAfter.In(localtz)

	today := time.Now().In(localtz)
	dayLeft := int(expireTime.Sub(today).Hours() / 24)
	fmt.Printf("%s, issue time: %v, expire time: %v, days left: %v\n", domain, issueTime, expireTime, dayLeft)
}

func main() {
	flag.IntVar(&port, "p", 443, "port, example: ./checkssl -p 1443 <domain name>")
	flag.Parse()
	positionArgs := flag.Args()
	if len(positionArgs) == 0 {
		fmt.Println("Error: Missing domain name")
		fmt.Println("Usage: ./checkssl <domain name>")
		os.Exit(1)
	}

	wg.Add(len(positionArgs))
	for _, arg := range positionArgs {
		go checkssl(arg, port)
	}
	wg.Wait()
}

使用示例

# 1. 編譯
go build
# 2. 命令行傳參的方式指定域名
./check-ssl baidu.com ithome.com qq.com

# 輸出
baidu.com, issue time: 2024-01-30 08:00:00 +0800 CST, expire time: 2025-03-02 07:59:59 +0800 CST, days left: 187
ithome.com, issue time: 2024-01-22 08:00:00 +0800 CST, expire time: 2025-02-22 07:59:59 +0800 CST, days left: 179
qq.com, issue time: 2024-06-04 08:00:00 +0800 CST, expire time: 2025-06-11 07:59:59 +0800 CST, days left: 288

完善功能

需要完善的功能主要是發(fā)送郵件,這里使用SMTP協(xié)議來(lái)發(fā)送郵件。如果跟我一樣用的是163郵箱,則需要先去獲取一個(gè)SMTP的授權(quán)碼。

因?yàn)樾枰渲肧MTP的連接信息,所以改成了用文件來(lái)傳入配置,也方便后期修改。配置文件config.yaml示例:

domains:
  - baidu.com
  - qq.com

email:
  smtp:
    host: "smtp.163.com"  # smtp服務(wù)器的地址
    port: 465  # 因?yàn)樵品?wù)器屏蔽了25端口, 只能使用tls加密的465端口
    from: ""   # 發(fā)送方郵箱
    token: ""  # 授權(quán)碼
  sendto:
    - "qq@qq.com"  # 接收方的郵箱地址
  expire: 7  # 證書(shū)剩余有效天數(shù), 小于7天時(shí)發(fā)送郵件提醒

讀取配置的代碼文件config.go,使用viper來(lái)讀取配置文件。

package main

import "github.com/spf13/viper"

var (
	v *viper.Viper
)

type SMTPServer struct {
	Host  string
	Port  int
	Token string
	From  string
}

func initViper() {
	v = viper.New()
	v.AddConfigPath(".")
	v.SetConfigType("yaml")
	v.SetConfigFile(configfile)
	err := v.ReadInConfig()
	if err != nil {
		panic(err)
	}
}

type configer struct{}

func NewConfiger() configer {
	if v == nil {
		initViper()
	}
	return configer{}
}

func (c configer) GetSMTPServer() SMTPServer {
	return SMTPServer{
		Host:  v.GetString("email.smtp.host"),
		Port:  v.GetInt("email.smtp.port"),
		Token: v.GetString("email.smtp.token"),
		From:  v.GetString("email.smtp.from"),
	}
}

func (c configer) GetDomains() []string {
	return v.GetStringSlice("domains")
}

func (c configer) GetSendTos() []string {
	return v.GetStringSlice("email.sendto")
}

func (c configer) GetExpiry() int {
	return v.GetInt("email.expire")
}

發(fā)送郵件的相關(guān)代碼文件:notify.go

package main

import (
	"crypto/tls"
	"fmt"
	"net/smtp"

	"github.com/jordan-wright/email"
)

type Postman struct {
	SmtpServer SMTPServer
	SendTos    []string
}

func (p Postman) SendEmail(domain string, dayleft int) {
	auth := smtp.PlainAuth("", p.SmtpServer.From, p.SmtpServer.Token, p.SmtpServer.Host)
	e := &email.Email{
		To:      p.SendTos,
		From:    fmt.Sprintf("YXHYW <%s>", p.SmtpServer.From),
		Subject: fmt.Sprintf("域名 %s SSL證書(shū)過(guò)期提醒", domain),
		Text:    []byte(fmt.Sprintf("域名 %s 的SSL證書(shū)即將過(guò)期, 剩余有效期 %d 天", domain, dayleft)),
	}
	// err := e.Send(fmt.Sprintf("%s:%d", p.SmtpServer.Host, p.SmtpServer.Port), auth)
	addr := fmt.Sprintf("%s:%d", p.SmtpServer.Host, p.SmtpServer.Port)
	fmt.Println("SMTP Server addr: ", addr)
	err := e.SendWithTLS(addr, auth, &tls.Config{
		InsecureSkipVerify: false,
		ServerName:         p.SmtpServer.Host,
	})
	if err != nil {
		fmt.Printf("Send email failed, %v\n", err)
	}
}

主體代碼文件main.go,主要修改地方:檢測(cè)到證書(shū)即將過(guò)期后,調(diào)用發(fā)送郵件的相關(guān)方法。

package main

import (
	"crypto/tls"
	"flag"
	"fmt"
	"net"
	"sync"
	"time"
)

var (
	port       int
	configfile string
	wg         sync.WaitGroup
	c          configer = NewConfiger()
)

func checkssl(domain string, port int) {
	defer wg.Done()
	host := fmt.Sprintf("%s:%d", domain, port)
	conn, err := tls.DialWithDialer(&net.Dialer{
		Timeout:  time.Second * 5,
		Deadline: time.Now().Add(time.Second * 5),
	}, "tcp", host, &tls.Config{InsecureSkipVerify: true})
	if err != nil {
		fmt.Println(err)
		return
	}
	defer conn.Close()

	stats := conn.ConnectionState()
	certs := stats.PeerCertificates[0]
	localtz, _ := time.LoadLocation("Asia/Shanghai")
	issueTime := certs.NotBefore.In(localtz)
	expireTime := certs.NotAfter.In(localtz)

	today := time.Now().In(localtz)
	dayLeft := int(expireTime.Sub(today).Hours() / 24)
	fmt.Printf("%s, issue time: %v, expire time: %v, days left: %v\n", domain, issueTime, expireTime, dayLeft)

	// c := NewConfiger()
	if dayLeft < c.GetExpiry() {
		p := Postman{SmtpServer: c.GetSMTPServer(), SendTos: c.GetSendTos()}
		p.SendEmail(domain, dayLeft)
	}
}

func main() {
	flag.IntVar(&port, "p", 443, "port, example: ./check-ssl -p 1443 <domain name>")
	flag.StringVar(&configfile, "c", "config.yaml", "config file")
	flag.Parse()

	conf := NewConfiger()
	domains := conf.GetDomains()

	wg.Add(len(domains))
	for _, arg := range domains {
		go checkssl(arg, port)
	}
	wg.Wait()
}

本地測(cè)試通過(guò)后,可以配到服務(wù)器的crontab中每天執(zhí)行。

到此這篇關(guān)于如何使用工具自動(dòng)監(jiān)測(cè)SSL證書(shū)有效期并發(fā)送提醒郵件的文章就介紹到這了,更多相關(guān)[golang]查詢ssl證書(shū)剩余有效天數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Golang小數(shù)操作指南之判斷小數(shù)點(diǎn)位數(shù)與四舍五入

    Golang小數(shù)操作指南之判斷小數(shù)點(diǎn)位數(shù)與四舍五入

    這篇文章主要給大家介紹了關(guān)于Golang小數(shù)操作指南之判斷小數(shù)點(diǎn)位數(shù)與四舍五入的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2022-03-03
  • GO語(yǔ)言如何手動(dòng)處理TCP粘包詳解

    GO語(yǔ)言如何手動(dòng)處理TCP粘包詳解

    最近在用golang開(kāi)發(fā)人工客服系統(tǒng)的時(shí)候碰到了粘包問(wèn)題,那么什么是粘包呢?下面這篇文章就來(lái)給大家介紹了關(guān)于GO語(yǔ)言如何手動(dòng)處理TCP粘包的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒。
    2017-12-12
  • golang bad file descriptor問(wèn)題的解決方法

    golang bad file descriptor問(wèn)題的解決方法

    這篇文章主要給大家介紹了golang bad file descriptor問(wèn)題的解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-02-02
  • Go語(yǔ)言單例模式詳解

    Go語(yǔ)言單例模式詳解

    本文主要介紹了Go語(yǔ)言單例模式詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • golang中按照結(jié)構(gòu)體的某個(gè)字段排序?qū)嵗a

    golang中按照結(jié)構(gòu)體的某個(gè)字段排序?qū)嵗a

    在任何編程語(yǔ)言中,關(guān)乎到數(shù)據(jù)的排序都會(huì)有對(duì)應(yīng)的策略,下面這篇文章主要給大家介紹了關(guān)于golang中按照結(jié)構(gòu)體的某個(gè)字段排序的相關(guān)資料,需要的朋友可以參考下
    2022-05-05
  • GoFrame錯(cuò)誤處理常用方法及錯(cuò)誤碼使用示例

    GoFrame錯(cuò)誤處理常用方法及錯(cuò)誤碼使用示例

    這篇文章主要為大家介紹了GoFrame錯(cuò)誤處理常用方法及錯(cuò)誤碼使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • Go語(yǔ)言break跳轉(zhuǎn)語(yǔ)句怎么使用

    Go語(yǔ)言break跳轉(zhuǎn)語(yǔ)句怎么使用

    這篇文章主要介紹了Go語(yǔ)言break跳轉(zhuǎn)語(yǔ)句怎么使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧
    2023-01-01
  • 詳解golang channel有無(wú)緩沖區(qū)的區(qū)別

    詳解golang channel有無(wú)緩沖區(qū)的區(qū)別

    這篇文章主要給大家介紹了golang channel有無(wú)緩沖區(qū)的區(qū)別,無(wú)緩沖是同步的,有緩沖是異步的,文中通過(guò)代碼示例給大家講解的非常詳細(xì),需要的朋友可以參考下
    2024-01-01
  • 深入理解Go語(yǔ)言中接口的使用

    深入理解Go語(yǔ)言中接口的使用

    在現(xiàn)代編程語(yǔ)言中,接口是不可或缺的一個(gè)重要特性,這篇文章將為大家詳細(xì)介紹Go語(yǔ)言中的接口,從而能夠更好得使用Go語(yǔ)言,需要的可以參考一下
    2023-06-06
  • Qt6.5 grpc組件使用 + golang grpc server示例詳解

    Qt6.5 grpc組件使用 + golang grpc server

    這篇文章主要介紹了Qt6.5 grpc組件使用+golang grpc server示例,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-05-05

最新評(píng)論