feat(client): Add RDAP support for domain expiration (#1181)

Fixes #1083

Fixes #1254

Co-authored-by: TwiN <twin@linux.com>
This commit is contained in:
ju-ef
2025-09-11 23:32:19 +03:00
committed by GitHub
parent 39bfc51ce4
commit af4fbac84d
4 changed files with 48 additions and 1 deletions

View File

@@ -21,6 +21,8 @@ import (
"github.com/ishidawataru/sctp"
"github.com/miekg/dns"
ping "github.com/prometheus-community/pro-bing"
"github.com/registrobr/rdap"
"github.com/registrobr/rdap/protocol"
"golang.org/x/crypto/ssh"
"golang.org/x/net/websocket"
)
@@ -35,6 +37,7 @@ var (
whoisClient = whois.NewClient().WithReferralCache(true)
whoisExpirationDateCache = gocache.NewCache().WithMaxSize(10000).WithDefaultTTL(24 * time.Hour)
rdapClient = rdap.NewClient(nil)
)
// GetHTTPClient returns the shared HTTP client, or the client from the configuration passed
@@ -62,7 +65,12 @@ func GetDomainExpiration(hostname string) (domainExpiration time.Duration, err e
return domainExpiration, nil
}
}
if whoisResponse, err := whoisClient.QueryAndParse(hostname); err != nil {
whoisResponse, err := rdapQuery(hostname)
if err != nil {
// fallback to WHOIS protocol
whoisResponse, err = whoisClient.QueryAndParse(hostname)
}
if err != nil {
if !retrievedCachedValue { // Add an error unless we already retrieved a cached value
return 0, fmt.Errorf("error querying and parsing hostname using whois client: %w", err)
}
@@ -453,3 +461,23 @@ func QueryDNS(queryType, queryName, url string) (connected bool, dnsRcode string
func InjectHTTPClient(httpClient *http.Client) {
injectedHTTPClient = httpClient
}
// rdapQuery returns domain expiration via RDAP protocol
func rdapQuery(hostname string) (*whois.Response, error) {
data, _, err := rdapClient.Query(hostname, nil, nil)
if err != nil {
return nil, err
}
domain, ok := data.(*protocol.Domain)
if !ok {
return nil, errors.New("invalid domain type")
}
response := whois.Response{}
for _, e := range domain.Events {
if e.Action == "expiration" {
response.ExpirationDate = e.Date.Time
break
}
}
return &response, nil
}