做网站容易学吗,营销策划方案1000例,服务商pid是什么意思,专业制作公司网站公司代码平平无奇#xff0c;需要注意的是http client初始化部分。 因为是短连接#xff0c;如果是大量域名去验证的话#xff0c;短时间内将导致大量TIME_WAIT
package utilimport (contextcrypto/tlserrorsfmtnet需要注意的是http client初始化部分。 因为是短连接如果是大量域名去验证的话短时间内将导致大量TIME_WAIT
package utilimport (contextcrypto/tlserrorsfmtnetnet/httpstringssynctimegithub.com/panjf2000/ants/v2log github.com/sirupsen/logrus
)var client http.Client{Transport: http.Transport{// 注意如果证书已过期那么只有在关闭证书校验的情况下链接才能建立成功TLSClientConfig: tls.Config{InsecureSkipVerify: true},Proxy: http.ProxyFromEnvironment,DisableKeepAlives: true,DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {d : net.Dialer{Timeout: 10 * time.Second}conn, err : d.DialContext(ctx, network, addr)if err ! nil {return nil, err}tcpConn, ok : conn.(*net.TCPConn)if ok {tcpConn.SetLinger(0) // RST fix TIME_WAIT问题return tcpConn, nil}return conn, nil},},
}func BatchCheckSsl(domains []string, batch int) (map[string]CheckSslResp, error) {domains Uniq(domains)var domainSyncMap sync.Mapvar wg sync.WaitGrouppool, err : ants.NewPool(batch)if err ! nil {log.Errorln(err)return nil, err}defer pool.Release()wg.Add(len(domains))for _, item : range domains {err pool.Submit(wrapperCheckSSL(item, domainSyncMap, wg))if err ! nil {log.Errorln(err)continue}}wg.Wait()fmt.Printf(running goroutines: %d\n, ants.Running())fmt.Printf(finish all tasks.\n)result : make(map[string]CheckSslResp, 0)domainSyncMap.Range(func(key, value interface{}) bool {vv, ok : value.(*CheckSslResp)if !ok {log.Println(fmt.Sprintf(CheckSslResp类型转换失败:%s, key))return false}result[fmt.Sprintf(%v, key)] *vvreturn true})return result, nil
}func wrapperCheckSSL(hostname string, domainSslMap *sync.Map, wg *sync.WaitGroup) func() {return func() {checkSsl(hostname, domainSslMap, wg)}
}func checkSsl(hostname string, domainSslMap *sync.Map, wg *sync.WaitGroup) {defer wg.Done()log.Println(fmt.Sprintf(开始检查:%s, hostname))notAfter, err : CheckSSL(hostname)if err ! nil {log.Errorln(err)}log.Println(fmt.Sprintf(完成检查:%s,notAfter:%v:, hostname, notAfter))ri : new(CheckSslResp)ri.Domain hostnameif err ! nil {ri.Success falseri.Error errri.NotAfter nil} else {ri.Success trueri.NotAfter notAfter}domainSslMap.Store(hostname, ri)return
}func CheckSSL(url string) (*time.Time, error) {//client : http.Client{// Transport: http.Transport{// // 注意如果证书已过期那么只有在关闭证书校验的情况下链接才能建立成功// TLSClientConfig: tls.Config{InsecureSkipVerify: true},// },// // 10s 超时后认为服务挂了// Timeout: 10 * time.Second,//}url strings.ReplaceAll(url, http://, https://)if !strings.HasPrefix(url, https://) {url fmt.Sprintf(https://%s, url)}log.Println(url)resp, err : client.Get(url)if err ! nil {log.Errorln(err)return nil, err}defer func() { _ resp.Body.Close() }()if resp.TLS nil {return nil, errors.New(未获取到SSL信息)}// 遍历所有证书for _, cert : range resp.TLS.PeerCertificates {if cert.Issuer.CommonName Kubernetes Ingress Controller Fake Certificate {return nil, errors.New(Kubernetes Ingress Controller Fake Certificate)}// 检测证书是否已经过期if !cert.NotAfter.After(time.Now()) {log.Warningln(fmt.Sprintf(Website [%s] certificate has expired: %s, url, cert.NotAfter.Local().Format(2006-01-02 15:04:05)))}return cert.NotAfter, nil}return nil, err
}type CheckSslResp struct {Domain stringError errorSuccess boolNotAfter *time.Time
}