mirror of
https://github.com/screego/server.git
synced 2026-11-02 03:51:40 +08:00
78 lines
1.4 KiB
Go
78 lines
1.4 KiB
Go
package ipdns
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"net"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/rs/zerolog/log"
|
|
)
|
|
|
|
type DNS struct {
|
|
sync.Mutex
|
|
|
|
DNS string
|
|
Resolver *net.Resolver
|
|
Domain string
|
|
|
|
refetch time.Time
|
|
v4 net.IP
|
|
v6 net.IP
|
|
err error
|
|
}
|
|
|
|
func (s *DNS) Get() (net.IP, net.IP, error) {
|
|
s.Lock()
|
|
defer s.Unlock()
|
|
|
|
if s.refetch.Before(time.Now()) {
|
|
oldV4, oldV6 := s.v4, s.v6
|
|
s.v4, s.v6, s.err = s.lookup()
|
|
if s.err == nil {
|
|
if !oldV4.Equal(s.v4) || !oldV6.Equal(s.v6) {
|
|
log.Info().Str("v4", s.v4.String()).
|
|
Str("v6", s.v6.String()).
|
|
Str("domain", s.Domain).
|
|
Str("dns", s.DNS).
|
|
Msg("DNS External IP")
|
|
}
|
|
s.refetch = time.Now().Add(time.Minute)
|
|
} else {
|
|
// don't spam the dns server
|
|
s.refetch = time.Now().Add(time.Second)
|
|
log.Err(s.err).Str("domain", s.Domain).Str("dns", s.DNS).Msg("DNS External IP")
|
|
}
|
|
}
|
|
|
|
return s.v4, s.v6, s.err
|
|
}
|
|
|
|
func (s *DNS) lookup() (net.IP, net.IP, error) {
|
|
ips, err := s.Resolver.LookupIP(context.Background(), "ip", s.Domain)
|
|
if err != nil {
|
|
if dns, ok := err.(*net.DNSError); ok && s.DNS != "system" {
|
|
dns.Server = ""
|
|
}
|
|
return nil, nil, err
|
|
}
|
|
|
|
var v4, v6 net.IP
|
|
for _, ip := range ips {
|
|
isV6 := strings.Contains(ip.String(), ":")
|
|
if isV6 && v6 == nil {
|
|
v6 = ip
|
|
} else if !isV6 && v4 == nil {
|
|
v4 = ip
|
|
}
|
|
}
|
|
|
|
if v4 == nil && v6 == nil {
|
|
return nil, nil, errors.New("dns record doesn't have an A or AAAA record")
|
|
}
|
|
|
|
return v4, v6, nil
|
|
}
|