目录

GO语言开发实践-域名证书探测工具tls-checker

域名证书探测工具 tls-checker 设计理念。

动机

不知道你们有没有过公司N多域名的经历,N家云提供商 + N多个域名,然后域名解析做了一大堆,lb也一大堆,虽然国内有些厂商有提供 ssl 证书过期检测的功能,但是对于部署到自建nginx服务器的这种情况就检测不到,然后就经常出现域名证书漏检测到,从而导致过期的情况,经常措手不及。

架构图

/go%E8%AF%AD%E8%A8%80%E5%BC%80%E5%8F%91%E5%AE%9E%E8%B7%B5-%E5%9F%9F%E5%90%8D%E8%AF%81%E4%B9%A6%E6%8E%A2%E6%B5%8B%E5%B7%A5%E5%85%B7tls-checker/tls-checker.png
架构图

设计理念

总体来说就是分3点:

为了解决证书过期经常没法及时更换的问题,我们针对各个不同的厂商,抽象出一个接口,每个厂商的 sdk 根据这个接口去实现域名列表获取,域名解析遍历获取,入库,便于后续其他操作。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
// 接口抽象,不同厂商实现同一接口
type ISyncDomainService interface {
    SyncSingleDomainItems([]string) ([]cmdb.DomainNameItem, error)
    GetAllDomainLists() ([]string, error)
}

func SyncAllDomainItems(vname, vtype, ak, sk, region string) ([]cmdb.DomainNameItem, error) {
    ...
}

// 此处省略 n 多代码....

func (tc *TlsChecker) TlsChecker() {
    tc.DomainsSyncTrigger()         // 触发域名同步
    tc.GetDomainItemsFromDatabase() // 检测域名信息
}

然后再探测 443 端口是否存在(这个需要公司内网互通,需要一定的网络基础,如果网络没有互通,探测不通可以先不管,等过期再更换),存在则探测域名证书是否过期,有些域名不需要或者不在通过网络内或者其他原因不想探测,则可以将域名加入到黑名单。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
func (tc *TlsChecker) GetDomainItemsFromDatabase() {
    var (
        data         []model.DomainNameItem
        day          = config.Conf.ExtraConfig.ExpireDays
        exclude      = config.Conf.ExtraConfig.Exclude
        filteredData []string
    )
    err := common.DB.Find(&data).Error
    if err != nil {
        common.Log.Errorln("从数据库获取域名条目失败", err)
        panic(err)
    }
    if len(data) == 0 {
        return
    }

    for _, i := range data {
        if lo.Contains(exclude, i.Record) {
            continue
        }
        if i.Status == "ENABLE" && i.ExpiredAt != nil && *i.ExpiredAt < day {
            common.Log.Infof("%s 证书即将过期还剩余 %d 天\n", i.Record, *i.ExpiredAt)
            filteredData = append(filteredData, i.Record+"    剩余 "+fmt.Sprint(*i.ExpiredAt)+" 天")
        }
    }
    if len(filteredData) != 0 {
        title := fmt.Sprintf("以下域名证书将在 %d 天内过期,请注意及时更换", day)
        tc.Notify.SendMessage(title, strings.Join(filteredData, "\n"))
    }
}

然后发送通知到钉钉/飞书/微信群。

微信通知内容格式如下。

1
2
3
4
5
以下域名证书将在 15 天内过期,请注意及时更换
xx.xxx.com.cn    剩余 31xx.xxx.com.cn    剩余 230xx.xxx.com.cn    剩余 101...

最后

总体来说开发不难,都是些小工具,后面我都会将这些小工具集成到管理后台,方便数据展示。仅个人笔记用途,不喜勿喷。