From 3616ac7d70907431e25c76ee5dfd9b3ab7cc3fd4 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Mon, 22 Jul 2024 14:32:50 +0200 Subject: [PATCH] add whois as RDAP fallback --- CHANGELOG.md | 4 ++++ README.md | 2 ++ checker/domains.go | 51 +++++++++++++++++++++++++++++++++++++++++++++- go.mod | 4 +++- go.sum | 6 ++++++ 5 files changed, 65 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f4bec74..02b45eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ [Unreleased] +## v1.2.0 +### Added +- add whois as RDAP fallback + ## v1.1.0 ### Added - add output formats diff --git a/README.md b/README.md index 7b81882..ea0281e 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,8 @@ Expiration check Checks the expiration dates of domains et certificates. +Domain expiration check uses [`RDAP`](https://about.rdap.org/) and fallback with a `whois` request. + ## Usage Go to [releases](https://gitnet.fr/deblan/expiration-check/releases) and download the latest version. diff --git a/checker/domains.go b/checker/domains.go index 27704c0..119d229 100644 --- a/checker/domains.go +++ b/checker/domains.go @@ -5,8 +5,11 @@ import ( "fmt" "math" "net/http" + "regexp" "strings" "time" + + "github.com/likexian/whois" ) type RdapResponseData struct { @@ -72,6 +75,52 @@ func RdapCheck(domain, service string) Domain { return Domain{Name: domain, Failed: true} } +func WhoisCheck(domain string) Domain { + domainFailed := Domain{Name: domain, Failed: true} + result, err := whois.Whois(domain) + if err != nil { + return domainFailed + } + + now := time.Now() + formats := []string{ + "expiration date", + "expiry date", + "expires on", + "paid-till", + "renewal", + "expires", + "domain_datebilleduntil", + "expiration", + "registry expiry", + "registrar registration expiration", + } + + result = strings.ToLower(result) + + for _, format := range formats { + r, _ := regexp.Compile(fmt.Sprintf(`%s\s*:?\s*([^\s]+)`, format)) + + for i, match := range r.FindStringSubmatch(result) { + if i%2 == 1 { + date, err := time.Parse(time.RFC3339, strings.ToUpper(match)) + + if err == nil { + daysLeft := date.Sub(now).Hours() / 24 + + return Domain{ + Name: domain, + DaysLeft: math.Floor(daysLeft), + Date: date.Format(time.DateTime), + } + } + } + } + } + + return domainFailed +} + func CheckDomains(domains []string) []Domain { values := []Domain{} services := GetRdapServices() @@ -83,7 +132,7 @@ func CheckDomains(domains []string) []Domain { if service != "" { values = append(values, RdapCheck(domain, service)) } else { - values = append(values, Domain{Name: domain, Failed: true}) + values = append(values, WhoisCheck(domain)) } } diff --git a/go.mod b/go.mod index f57937e..46f32d2 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( github.com/google/uuid v1.6.0 // indirect github.com/jedib0t/go-pretty v4.3.0+incompatible // indirect github.com/jedib0t/go-pretty/v6 v6.5.9 // indirect + github.com/likexian/whois v1.15.4 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/oklog/ulid v1.3.1 // indirect @@ -18,5 +19,6 @@ require ( github.com/urfave/cli/v2 v2.27.2 // indirect github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // indirect go.mongodb.org/mongo-driver v1.14.0 // indirect - golang.org/x/sys v0.17.0 // indirect + golang.org/x/net v0.27.0 // indirect + golang.org/x/sys v0.22.0 // indirect ) diff --git a/go.sum b/go.sum index 7f8bb64..fd52307 100644 --- a/go.sum +++ b/go.sum @@ -12,6 +12,8 @@ github.com/jedib0t/go-pretty v4.3.0+incompatible h1:CGs8AVhEKg/n9YbUenWmNStRW2PH github.com/jedib0t/go-pretty v4.3.0+incompatible/go.mod h1:XemHduiw8R651AF9Pt4FwCTKeG3oo7hrHJAoznj9nag= github.com/jedib0t/go-pretty/v6 v6.5.9 h1:ACteMBRrrmm1gMsXe9PSTOClQ63IXDUt03H5U+UV8OU= github.com/jedib0t/go-pretty/v6 v6.5.9/go.mod h1:zbn98qrYlh95FIhwwsbIip0LYpwSG8SUOScs+v9/t0E= +github.com/likexian/whois v1.15.4 h1:r5En62c+S9HKFgJtdh2WsdmRGTcxE4WUtGBdZkSBXmM= +github.com/likexian/whois v1.15.4/go.mod h1:rXFTPcQdNlPQBJCQpPWTSIDGzzmgKBftmhdOOcLpwXk= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= @@ -28,5 +30,9 @@ github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 h1:+qGGcbkzsfDQNPPe github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913/go.mod h1:4aEEwZQutDLsQv2Deui4iYQ6DWTxR14g6m8Wv88+Xqk= go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80= go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=