Preface
Since the free ssl certificate of cloud manufacturers has been changed to 3 months, and the number of certificates is still 20, the ssl certificate of its own website has been replaced with other free solutions. However, the free plan will not remind the certificate to expire, so write a tool to check the remaining valid days of the certificate every day. If the certificate is about to expire, send an email reminder.
Basic implementation
The most basic code function is to detect the valid number of days of the website SSL certificate. You can specify the website domain name by passing parameters on the command line.
package main import ( "crypto/tls" "flag" "fmt" "net" "os" "sync" "time" ) var ( port int wg ) func checkssl(domain string, port int) { defer () host := ("%s:%d", domain, port) conn, err := (&{ Timeout: * 5, Deadline: ().Add( * 5), }, "tcp", host, &{InsecureSkipVerify: true}) if err != nil { (err) return } defer () stats := () certs := [0] localtz, _ := ("Asia/Shanghai") issueTime := (localtz) expireTime := (localtz) today := ().In(localtz) dayLeft := int((today).Hours() / 24) ("%s, issue time: %v, expire time: %v, days left: %v\n", domain, issueTime, expireTime, dayLeft) } func main() { (&port, "p", 443, "port, example: ./checkssl -p 1443 <domain name>") () positionArgs := () if len(positionArgs) == 0 { ("Error: Missing domain name") ("Usage: ./checkssl <domain name>") (1) } (len(positionArgs)) for _, arg := range positionArgs { go checkssl(arg, port) } () }
Example of usage
# 1. Compilationgo build # 2. Specify the domain name by passing parameters on the command line./check-ssl #Output, issue time: 2024-01-30 08:00:00 +0800 CST, expire time: 2025-03-02 07:59:59 +0800 CST, days left: 187 , issue time: 2024-01-22 08:00:00 +0800 CST, expire time: 2025-02-22 07:59:59 +0800 CST, days left: 179 , issue time: 2024-06-04 08:00:00 +0800 CST, expire time: 2025-06-11 07:59:59 +0800 CST, days left: 288
Improve functions
The main function that needs to be improved is to send emails, and the SMTP protocol is used here to send emails. If you use 163 email like me, you need to get an SMTP authorization code first.
Because SMTP connection information needs to be configured, it has been changed to using files to pass in the configuration, which is also convenient for later modification. Configuration FileExample:
domains: - - email: smtp: host: "smtp." # smtp server address port: 465 # Because the cloud server blocks port 25, it can only use port 465 encrypted by TLS from: "" # Sender's email token: "" # Authorization code sendto: - "qq@" # The recipient's email address expire: 7 # The number of valid days remaining for the certificate, send an email reminder if it is less than 7 days
Read the configuration code file,use
viper
to read the configuration file.
package main import "/spf13/viper" var ( v * ) type SMTPServer struct { Host string Port int Token string From string } func initViper() { v = () (".") ("yaml") (configfile) err := () 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: (""), Port: (""), Token: (""), From: (""), } } func (c configer) GetDomains() []string { return ("domains") } func (c configer) GetSendTos() []string { return ("") } func (c configer) GetExpiry() int { return ("") }
Related code files for sending emails:
package main import ( "crypto/tls" "fmt" "net/smtp" "/jordan-wright/email" ) type Postman struct { SmtpServer SMTPServer SendTos []string } func (p Postman) SendEmail(domain string, dayleft int) { auth := ("", , , ) e := &{ To: , From: ("YXHYW <%s>", ), Subject: ("Domain name %s SSL certificate expiration reminder", domain), Text: []byte(("The SSL certificate for domain name %s is about to expire, and the remaining validity period is %d days", domain, dayleft)), } // err := (("%s:%d", , ), auth) addr := ("%s:%d", , ) ("SMTP Server addr: ", addr) err := (addr, auth, &{ InsecureSkipVerify: false, ServerName: , }) if err != nil { ("Send email failed, %v\n", err) } }
Body code file, Main modification: after detecting that the certificate is about to expire, call the relevant method of sending the email.
package main import ( "crypto/tls" "flag" "fmt" "net" "sync" "time" ) var ( port int configfile string wg c configer = NewConfiger() ) func checkssl(domain string, port int) { defer () host := ("%s:%d", domain, port) conn, err := (&{ Timeout: * 5, Deadline: ().Add( * 5), }, "tcp", host, &{InsecureSkipVerify: true}) if err != nil { (err) return } defer () stats := () certs := [0] localtz, _ := ("Asia/Shanghai") issueTime := (localtz) expireTime := (localtz) today := ().In(localtz) dayLeft := int((today).Hours() / 24) ("%s, issue time: %v, expire time: %v, days left: %v\n", domain, issueTime, expireTime, dayLeft) // c := NewConfiger() if dayLeft < () { p := Postman{SmtpServer: (), SendTos: ()} (domain, dayLeft) } } func main() { (&port, "p", 443, "port, example: ./check-ssl -p 1443 <domain name>") (&configfile, "c", "", "config file") () conf := NewConfiger() domains := () (len(domains)) for _, arg := range domains { go checkssl(arg, port) } () }
After the local test is passed, it can be configured to the server.crontab
Perform every day.
This is the article about how to use tools to automatically monitor the validity period of SSL certificates and send reminder emails. For more related [golang] to query the remaining valid days of SSL certificates, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!