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
This commit is contained in:
parent
21b0038b54
commit
0049230a93
4 changed files with 104 additions and 1 deletions
|
@ -9,6 +9,7 @@ reverse NETWORK... {
|
||||||
hostname TEMPLATE
|
hostname TEMPLATE
|
||||||
[ttl TTL]
|
[ttl TTL]
|
||||||
[fallthrough]
|
[fallthrough]
|
||||||
|
[wildcard]
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
* **NETWORK** one or more CIDR formatted networks to respond on.
|
* **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.
|
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.
|
`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
|
## Examples
|
||||||
|
|
||||||
~~~ txt
|
~~~ txt
|
||||||
|
|
71
middleware/reverse/reverse_test.go
Normal file
71
middleware/reverse/reverse_test.go
Normal file
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -38,6 +38,7 @@ func reverseParse(c *caddy.Controller) (nets networks, fall bool, err error) {
|
||||||
// normalize zones, validation is almost done by dnsserver
|
// normalize zones, validation is almost done by dnsserver
|
||||||
// TODO(miek): need sane helpers for these.
|
// TODO(miek): need sane helpers for these.
|
||||||
zones := make([]string, len(c.ServerBlockKeys))
|
zones := make([]string, len(c.ServerBlockKeys))
|
||||||
|
wildcard := false
|
||||||
|
|
||||||
for i, str := range c.ServerBlockKeys {
|
for i, str := range c.ServerBlockKeys {
|
||||||
zones[i] = middleware.Host(str).Normalize()
|
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
|
return nil, false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case "wildcard":
|
||||||
|
wildcard = true
|
||||||
|
|
||||||
case "fallthrough":
|
case "fallthrough":
|
||||||
fall = true
|
fall = true
|
||||||
|
|
||||||
|
@ -117,8 +121,12 @@ func reverseParse(c *caddy.Controller) (nets networks, fall bool, err error) {
|
||||||
if ipnet.IP.To4() == nil {
|
if ipnet.IP.To4() == nil {
|
||||||
regexIP = regexMatchV6
|
regexIP = regexMatchV6
|
||||||
}
|
}
|
||||||
|
prefix := "^"
|
||||||
|
if wildcard {
|
||||||
|
prefix += ".*"
|
||||||
|
}
|
||||||
regex, err := regexp.Compile(
|
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(template), // escape dots
|
||||||
regexp.QuoteMeta(templateNameIP),
|
regexp.QuoteMeta(templateNameIP),
|
||||||
regexIP,
|
regexIP,
|
||||||
|
|
|
@ -14,6 +14,7 @@ func TestSetupParse(t *testing.T) {
|
||||||
_, net4, _ := net.ParseCIDR("10.1.1.0/24")
|
_, net4, _ := net.ParseCIDR("10.1.1.0/24")
|
||||||
_, net6, _ := net.ParseCIDR("fd01::/64")
|
_, net6, _ := net.ParseCIDR("fd01::/64")
|
||||||
|
|
||||||
|
regexIP4wildcard, _ := regexp.Compile("^.*ip-" + regexMatchV4 + "\\.domain\\.com\\.$")
|
||||||
regexIP6, _ := regexp.Compile("^ip-" + regexMatchV6 + "\\.domain\\.com\\.$")
|
regexIP6, _ := regexp.Compile("^ip-" + regexMatchV6 + "\\.domain\\.com\\.$")
|
||||||
regexIpv4dynamic, _ := regexp.Compile("^dynamic-" + regexMatchV4 + "-intern\\.dynamic\\.domain\\.com\\.$")
|
regexIpv4dynamic, _ := regexp.Compile("^dynamic-" + regexMatchV4 + "-intern\\.dynamic\\.domain\\.com\\.$")
|
||||||
regexIpv6dynamic, _ := regexp.Compile("^dynamic-" + regexMatchV6 + "-intern\\.dynamic\\.domain\\.com\\.$")
|
regexIpv6dynamic, _ := regexp.Compile("^dynamic-" + regexMatchV6 + "-intern\\.dynamic\\.domain\\.com\\.$")
|
||||||
|
@ -157,6 +158,22 @@ func TestSetupParse(t *testing.T) {
|
||||||
RegexMatchIP: regexIpv6dynamic,
|
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 {
|
for i, test := range tests {
|
||||||
c := caddy.NewTestController("dns", test.inputFileRules)
|
c := caddy.NewTestController("dns", test.inputFileRules)
|
||||||
|
|
Loading…
Add table
Reference in a new issue