aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar jremond <cfengine@remond.re> 2017-07-11 00:49:24 -0400
committerGravatar Pat Moroney <pat@moroney.email> 2017-07-10 22:49:24 -0600
commit0049230a935b8e45ffcb290723a3a17df4b59f77 (patch)
treeb7c53293344354d7604302ab8470102decc83755
parent21b0038b5408cfdf12d9afe05cdc7d1c97321762 (diff)
downloadcoredns-0049230a935b8e45ffcb290723a3a17df4b59f77.tar.gz
coredns-0049230a935b8e45ffcb290723a3a17df4b59f77.tar.zst
coredns-0049230a935b8e45ffcb290723a3a17df4b59f77.zip
add wildcard parameter to allow resolving multiple name to the same IP (#755)
* add wildcard parameter to allow resolving multiple name to the same IP * first test for the reverse wildcard middleware * update wildcard keyword test to pass code coverage
-rw-r--r--middleware/reverse/README.md7
-rw-r--r--middleware/reverse/reverse_test.go71
-rw-r--r--middleware/reverse/setup.go10
-rw-r--r--middleware/reverse/setup_test.go17
4 files changed, 104 insertions, 1 deletions
diff --git a/middleware/reverse/README.md b/middleware/reverse/README.md
index 117daeba3..a26942178 100644
--- a/middleware/reverse/README.md
+++ b/middleware/reverse/README.md
@@ -9,6 +9,7 @@ reverse NETWORK... {
hostname TEMPLATE
[ttl TTL]
[fallthrough]
+ [wildcard]
~~~
* **NETWORK** one or more CIDR formatted networks to respond on.
@@ -34,6 +35,12 @@ The `{zone[i]}` symbol is **optional** and can be replaced by a fixed (zone) str
The zone will be matched by the zones listed in *this* configuration stanza.
`i` needs to be replaced with the index of the configured listener zones, starting with 1.
+### `wildcard`
+
+If `wildcard` is true :
+any.thing.ip-1.2.3.4.example.org resolves to 1.2.3.4 (ip-{ip}.{zone} is the hostname/template)
+
+
## Examples
~~~ txt
diff --git a/middleware/reverse/reverse_test.go b/middleware/reverse/reverse_test.go
new file mode 100644
index 000000000..4b17f0971
--- /dev/null
+++ b/middleware/reverse/reverse_test.go
@@ -0,0 +1,71 @@
+package reverse
+
+import (
+ "net"
+ "regexp"
+ "testing"
+
+ "github.com/coredns/coredns/middleware"
+ "github.com/coredns/coredns/middleware/pkg/dnsrecorder"
+ "github.com/coredns/coredns/middleware/test"
+
+ "github.com/miekg/dns"
+ "golang.org/x/net/context"
+)
+
+func TestReverse(t *testing.T) {
+ _, net4, _ := net.ParseCIDR("10.1.1.0/24")
+ regexIP4, _ := regexp.Compile("^.*ip-" + regexMatchV4 + "\\.example\\.org\\.$")
+
+ em := Reverse{
+ Networks: networks{network{
+ IPnet: net4,
+ Zone: "example.org",
+ Template: "ip-{ip}.example.org.",
+ RegexMatchIP: regexIP4,
+ }},
+ Fallthrough: false,
+ }
+
+ tests := []struct {
+ next middleware.Handler
+ qname string
+ qtype uint16
+ expectedCode int
+ expectedReply string
+ expectedErr error
+ }{
+ {
+ next: test.NextHandler(dns.RcodeSuccess, nil),
+ qname: "test.ip-10.1.1.2.example.org",
+ expectedCode: dns.RcodeSuccess,
+ expectedReply: "10.1.1.2",
+ expectedErr: nil,
+ },
+ }
+
+ ctx := context.TODO()
+
+ for i, tr := range tests {
+ req := new(dns.Msg)
+
+ tr.qtype = dns.TypeA
+ req.SetQuestion(dns.Fqdn(tr.qname), tr.qtype)
+
+ rec := dnsrecorder.New(&test.ResponseWriter{})
+ code, err := em.ServeDNS(ctx, rec, req)
+
+ if err != tr.expectedErr {
+ t.Errorf("Test %d: Expected error %v, but got %v", i, tr.expectedErr, err)
+ }
+ if code != int(tr.expectedCode) {
+ t.Errorf("Test %d: Expected status code %d, but got %d", i, tr.expectedCode, code)
+ }
+ if tr.expectedReply != "" {
+ answer := rec.Msg.Answer[0].(*dns.A).A.String()
+ if answer != tr.expectedReply {
+ t.Errorf("Test %d: Expected answer %s, but got %s", i, tr.expectedReply, answer)
+ }
+ }
+ }
+}
diff --git a/middleware/reverse/setup.go b/middleware/reverse/setup.go
index 56ab620fa..ee426f852 100644
--- a/middleware/reverse/setup.go
+++ b/middleware/reverse/setup.go
@@ -38,6 +38,7 @@ func reverseParse(c *caddy.Controller) (nets networks, fall bool, err error) {
// normalize zones, validation is almost done by dnsserver
// TODO(miek): need sane helpers for these.
zones := make([]string, len(c.ServerBlockKeys))
+ wildcard := false
for i, str := range c.ServerBlockKeys {
zones[i] = middleware.Host(str).Normalize()
@@ -85,6 +86,9 @@ func reverseParse(c *caddy.Controller) (nets networks, fall bool, err error) {
return nil, false, err
}
+ case "wildcard":
+ wildcard = true
+
case "fallthrough":
fall = true
@@ -117,8 +121,12 @@ func reverseParse(c *caddy.Controller) (nets networks, fall bool, err error) {
if ipnet.IP.To4() == nil {
regexIP = regexMatchV6
}
+ prefix := "^"
+ if wildcard {
+ prefix += ".*"
+ }
regex, err := regexp.Compile(
- "^" + strings.Replace( // inject ip regex into template
+ prefix + strings.Replace( // inject ip regex into template
regexp.QuoteMeta(template), // escape dots
regexp.QuoteMeta(templateNameIP),
regexIP,
diff --git a/middleware/reverse/setup_test.go b/middleware/reverse/setup_test.go
index 88dbccf1c..5b4c04e82 100644
--- a/middleware/reverse/setup_test.go
+++ b/middleware/reverse/setup_test.go
@@ -14,6 +14,7 @@ func TestSetupParse(t *testing.T) {
_, net4, _ := net.ParseCIDR("10.1.1.0/24")
_, net6, _ := net.ParseCIDR("fd01::/64")
+ regexIP4wildcard, _ := regexp.Compile("^.*ip-" + regexMatchV4 + "\\.domain\\.com\\.$")
regexIP6, _ := regexp.Compile("^ip-" + regexMatchV6 + "\\.domain\\.com\\.$")
regexIpv4dynamic, _ := regexp.Compile("^dynamic-" + regexMatchV4 + "-intern\\.dynamic\\.domain\\.com\\.$")
regexIpv6dynamic, _ := regexp.Compile("^dynamic-" + regexMatchV6 + "-intern\\.dynamic\\.domain\\.com\\.$")
@@ -157,6 +158,22 @@ func TestSetupParse(t *testing.T) {
RegexMatchIP: regexIpv6dynamic,
}},
},
+ {
+ `reverse 10.1.1.0/24 {
+ hostname ip-{ip}.{zone[1]}
+ ttl 50
+ wildcard
+ fallthrough
+ }`,
+ false,
+ networks{network{
+ IPnet: net4,
+ Template: "ip-{ip}.domain.com.",
+ Zone: "domain.com.",
+ TTL: 50,
+ RegexMatchIP: regexIP4wildcard,
+ }},
+ },
}
for i, test := range tests {
c := caddy.NewTestController("dns", test.inputFileRules)