Support multiple A entries refer: #17
This commit is contained in:
parent
dcf31e1b22
commit
21448a51e2
16
README.md
16
README.md
@ -90,10 +90,6 @@ host-file = "/etc/hosts"
|
|||||||
Hosts file format is described in [linux man pages](http://man7.org/linux/man-pages/man5/hosts.5.html).
|
Hosts file format is described in [linux man pages](http://man7.org/linux/man-pages/man5/hosts.5.html).
|
||||||
More than that , `*.` wildcard is supported additional.
|
More than that , `*.` wildcard is supported additional.
|
||||||
|
|
||||||
```
|
|
||||||
127.0.0.1 *.example.com
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
__redis hosts__
|
__redis hosts__
|
||||||
|
|
||||||
@ -114,6 +110,18 @@ _Insert hosts records into redis_
|
|||||||
redis > hset godns:hosts www.test.com 1.1.1.1
|
redis > hset godns:hosts www.test.com 1.1.1.1
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Compared with file-backend records, redis-backend hosts support two advanced records formatting.
|
||||||
|
|
||||||
|
1. `*.` wildcard
|
||||||
|
|
||||||
|
```
|
||||||
|
redis > hset 127.0.0.1 *.example.com
|
||||||
|
```
|
||||||
|
2. Multiple A entries, delimited by commas
|
||||||
|
|
||||||
|
```
|
||||||
|
redis > hset www.test.com 1.1.1.1,2.2.2.2
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## Benchmark
|
## Benchmark
|
||||||
|
@ -98,7 +98,7 @@ func (h *GODNSHandler) do(Net string, w dns.ResponseWriter, req *dns.Msg) {
|
|||||||
|
|
||||||
// Query hosts
|
// Query hosts
|
||||||
if settings.Hosts.Enable && IPQuery > 0 {
|
if settings.Hosts.Enable && IPQuery > 0 {
|
||||||
if ip, ok := h.hosts.Get(Q.qname, IPQuery); ok {
|
if ips, ok := h.hosts.Get(Q.qname, IPQuery); ok {
|
||||||
m := new(dns.Msg)
|
m := new(dns.Msg)
|
||||||
m.SetReply(req)
|
m.SetReply(req)
|
||||||
|
|
||||||
@ -110,8 +110,10 @@ func (h *GODNSHandler) do(Net string, w dns.ResponseWriter, req *dns.Msg) {
|
|||||||
Class: dns.ClassINET,
|
Class: dns.ClassINET,
|
||||||
Ttl: settings.Hosts.TTL,
|
Ttl: settings.Hosts.TTL,
|
||||||
}
|
}
|
||||||
|
for _, ip := range ips {
|
||||||
a := &dns.A{rr_header, ip}
|
a := &dns.A{rr_header, ip}
|
||||||
m.Answer = append(m.Answer, a)
|
m.Answer = append(m.Answer, a)
|
||||||
|
}
|
||||||
case _IP6Query:
|
case _IP6Query:
|
||||||
rr_header := dns.RR_Header{
|
rr_header := dns.RR_Header{
|
||||||
Name: q.Name,
|
Name: q.Name,
|
||||||
@ -119,9 +121,11 @@ func (h *GODNSHandler) do(Net string, w dns.ResponseWriter, req *dns.Msg) {
|
|||||||
Class: dns.ClassINET,
|
Class: dns.ClassINET,
|
||||||
Ttl: settings.Hosts.TTL,
|
Ttl: settings.Hosts.TTL,
|
||||||
}
|
}
|
||||||
|
for _, ip := range ips {
|
||||||
aaaa := &dns.AAAA{rr_header, ip}
|
aaaa := &dns.AAAA{rr_header, ip}
|
||||||
m.Answer = append(m.Answer, aaaa)
|
m.Answer = append(m.Answer, aaaa)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
w.WriteMsg(m)
|
w.WriteMsg(m)
|
||||||
logger.Debug("%s found in hosts file", Q.qname)
|
logger.Debug("%s found in hosts file", Q.qname)
|
||||||
|
42
hosts.go
42
hosts.go
@ -34,29 +34,38 @@ func NewHosts(hs HostsSettings, rs RedisSettings) Hosts {
|
|||||||
/*
|
/*
|
||||||
Match local /etc/hosts file first, remote redis records second
|
Match local /etc/hosts file first, remote redis records second
|
||||||
*/
|
*/
|
||||||
func (h *Hosts) Get(domain string, family int) (ip net.IP, ok bool) {
|
func (h *Hosts) Get(domain string, family int) ([]net.IP, bool) {
|
||||||
|
|
||||||
var sip string
|
var sips []string
|
||||||
|
var ip net.IP
|
||||||
|
var ips []net.IP
|
||||||
|
|
||||||
if sip, ok = h.fileHosts.Get(domain); !ok {
|
sips, ok := h.fileHosts.Get(domain)
|
||||||
|
if !ok {
|
||||||
if h.redisHosts != nil {
|
if h.redisHosts != nil {
|
||||||
sip, ok = h.redisHosts.Get(domain)
|
sips, ok = h.redisHosts.Get(domain)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if sip == "" {
|
if sips == nil {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, sip := range sips {
|
||||||
switch family {
|
switch family {
|
||||||
case _IP4Query:
|
case _IP4Query:
|
||||||
ip = net.ParseIP(sip).To4()
|
ip = net.ParseIP(sip).To4()
|
||||||
case _IP6Query:
|
case _IP6Query:
|
||||||
ip = net.ParseIP(sip).To16()
|
ip = net.ParseIP(sip).To16()
|
||||||
default:
|
default:
|
||||||
return nil, false
|
continue
|
||||||
}
|
}
|
||||||
return ip, (ip != nil)
|
if ip != nil {
|
||||||
|
ips = append(ips, ip)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ips, (ips != nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -85,21 +94,21 @@ type RedisHosts struct {
|
|||||||
hosts map[string]string
|
hosts map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RedisHosts) Get(domain string) (ip string, ok bool) {
|
func (r *RedisHosts) Get(domain string) ([]string, bool) {
|
||||||
ip, ok = r.hosts[domain]
|
ip, ok := r.hosts[domain]
|
||||||
if ok {
|
if ok {
|
||||||
return
|
return strings.Split(ip, ","), true
|
||||||
}
|
}
|
||||||
|
|
||||||
for host, ip := range r.hosts {
|
for host, ip := range r.hosts {
|
||||||
if strings.HasPrefix(host, "*.") {
|
if strings.HasPrefix(host, "*.") {
|
||||||
upperLevelDomain := strings.Split(host, "*.")[1]
|
upperLevelDomain := strings.Split(host, "*.")[1]
|
||||||
if strings.HasSuffix(domain, upperLevelDomain) {
|
if strings.HasSuffix(domain, upperLevelDomain) {
|
||||||
return ip, true
|
return strings.Split(ip, ","), true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RedisHosts) Set(domain, ip string) (bool, error) {
|
func (r *RedisHosts) Set(domain, ip string) (bool, error) {
|
||||||
@ -120,9 +129,12 @@ type FileHosts struct {
|
|||||||
hosts map[string]string
|
hosts map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FileHosts) Get(domain string) (ip string, ok bool) {
|
func (f *FileHosts) Get(domain string) ([]string, bool) {
|
||||||
ip, ok = f.hosts[domain]
|
ip, ok := f.hosts[domain]
|
||||||
return
|
if !ok {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
return []string{ip}, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FileHosts) Refresh() {
|
func (f *FileHosts) Refresh() {
|
||||||
|
Loading…
Reference in New Issue
Block a user