-
Notifications
You must be signed in to change notification settings - Fork 0
/
gslb.go
113 lines (91 loc) · 3.05 KB
/
gslb.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// Package gslb implements a plugin that returns details about the resolving
// querying it.
package gslb
import (
"context"
"net"
"strconv"
clog "github.com/coredns/coredns/plugin/pkg/log"
"github.com/coredns/coredns/request"
"github.com/miekg/dns"
)
// Define log to be a logger with the plugin name in it. This way we can just use log.Info and
// friends to log.
var log = clog.NewWithPlugin("gslb")
// Gslb is a plugin that returns your IP address, port and the protocol used for connecting
// to CoreDNS.
type Gslb struct{}
// ServeDNS implements the plugin.Handler interface.
func (wh Gslb) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
state := request.Request{W: w, Req: r}
msg := new(dns.Msg)
msg.SetReply(r)
msg.Authoritative = true
ip := getRealRequestIP(state)
var rr dns.RR
var rrs dns.RR
url := getIPNetURL(ipToZoneURL, ip)
log.Infof("request url=%s", url)
log.Infof("state IP=%s, QName=%s, QClass=%d, QType=%d, Proto=%s, Family=%d", ip, state.QName(), state.QClass(),
state.QType(), state.Proto(), state.Family())
switch state.Family() {
case 1:
rr = new(dns.A)
rr.(*dns.A).Hdr = dns.RR_Header{Name: state.QName(), Rrtype: dns.TypeA, Class: state.QClass()}
rr.(*dns.A).A = net.ParseIP(ip).To4()
zoneIP, err := requestURL(url)
if err != nil {
log.Errorf("request url for fecth zone ip error=%s", err)
}
rrs = new(dns.A)
rrs.(*dns.A).Hdr = dns.RR_Header{Name: state.QName(), Rrtype: dns.TypeA, Class: state.QClass()}
rrs.(*dns.A).A = net.ParseIP(zoneIP).To4()
case 2:
rr = new(dns.AAAA)
rr.(*dns.AAAA).Hdr = dns.RR_Header{Name: state.QName(), Rrtype: dns.TypeAAAA, Class: state.QClass()}
rr.(*dns.AAAA).AAAA = net.ParseIP(ip)
rrs = new(dns.AAAA)
rrs.(*dns.AAAA).Hdr = dns.RR_Header{Name: state.QName(), Rrtype: dns.TypeAAAA, Class: state.QClass()}
rrs.(*dns.AAAA).AAAA = net.ParseIP("fe80::b2d2:77b5:ced3:4e40").To16()
}
srv := new(dns.SRV)
srv.Hdr = dns.RR_Header{Name: "_" + state.Proto() + "." + state.QName(), Rrtype: dns.TypeSRV, Class: state.QClass()}
if state.QName() == "." {
srv.Hdr.Name = "_" + state.Proto() + state.QName()
}
port, _ := strconv.Atoi(state.Port())
srv.Port = uint16(port)
srv.Target = "."
msg.Answer = []dns.RR{rrs}
msg.Extra = []dns.RR{rr, srv}
w.WriteMsg(msg)
return 0, nil
}
// Name implements the Handler interface.
func (wh Gslb) Name() string { return "Gslb" }
func getRealRequestIP(req request.Request) string {
r := req.Req
if opt := r.IsEdns0(); opt != nil {
// for i := len(r.Extra) - 1; i >= 0; i-- {
// log.Infof("%d.opt=%+v", i, r.Extra[i])
// if r.Extra[i].Header().Rrtype == dns.TypeOPT {
// log.Infof("%d.opt=%s", i, r.Extra[i].(*dns.OPT).String())
// }
// }
log.Infof("return opt=%v", opt)
log.Infof("return opt Header=%v", opt.Hdr.String())
for _, o := range opt.Option {
switch v := o.(type) {
case *dns.EDNS0_SUBNET:
log.Info("get ip from ESubnet0")
switch v.Family {
case 1:
return v.Address.To4().String()
case 2:
return v.Address.String()
}
}
}
}
return req.IP()
}