-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathecs.go
93 lines (77 loc) · 2.04 KB
/
ecs.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
// Package example is a CoreDNS plugin that prints "example" to stdout on every packet received.
//
// It serves as an example CoreDNS plugin with numerous code comments.
package ecs
import (
"context"
"net"
"net/netip"
"github.com/coredns/coredns/plugin"
clog "github.com/coredns/coredns/plugin/pkg/log"
"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("ecs_remap")
type cidr struct {
ip net.IP
family uint16
mask uint8
}
// Ecs is an example plugin to show how to write a plugin.
type Ecs struct {
Next plugin.Handler
lookup map[netip.Addr]cidr
}
// setupEdns0Opt will retrieve the EDNS0 OPT or create it if it does not exist.
func setupEdns0Opt(r *dns.Msg) *dns.OPT {
o := r.IsEdns0()
if o == nil {
r.SetEdns0(4096, false)
o = r.IsEdns0()
}
return o
}
// ServeDNS implements the plugin.Handler interface. This method gets called when example is used
// in a Server.
func (e *Ecs) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
o := setupEdns0Opt(r)
var srcOrig net.IP
ip := w.RemoteAddr()
if i, ok := ip.(*net.UDPAddr); ok {
srcOrig = i.IP
}
if i, ok := ip.(*net.TCPAddr); ok {
srcOrig = i.IP
}
var src netip.Addr
tmp := srcOrig.To4()
if tmp != nil {
src, _ = netip.AddrFromSlice(tmp)
} else {
src, _ = netip.AddrFromSlice(srcOrig)
}
var entry cidr
var ok bool
if entry, ok = e.lookup[src]; !ok {
return plugin.NextOrFailure(e.Name(), e.Next, ctx, w, r)
}
var ecs *dns.EDNS0_SUBNET
for _, s := range o.Option {
if ecs, ok = s.(*dns.EDNS0_SUBNET); ok {
break
}
}
// add option if not found
if ecs == nil {
ecs = &dns.EDNS0_SUBNET{Code: dns.EDNS0SUBNET}
o.Option = append(o.Option, ecs)
}
ecs.SourceNetmask = entry.mask
ecs.Address = entry.ip
ecs.Family = entry.family
ecs.SourceScope = 0
return plugin.NextOrFailure(e.Name(), e.Next, ctx, w, r)
}
// Name implements the Handler interface.
func (e *Ecs) Name() string { return "ecs_remap" }