Skip to content

Commit

Permalink
Merge pull request #7 from FMotalleb/raw-response
Browse files Browse the repository at this point in the history
[Feat] Raw response
  • Loading branch information
FMotalleb authored Aug 1, 2023
2 parents 92d5464 + 448309c commit efc07b6
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 25 deletions.
18 changes: 13 additions & 5 deletions config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,10 @@ rules:
- (.*\.)?googlehosted.com
resolver: "shecan"
- name: 403 fallback
matcher: regex
matcherParams:
- (.*)?\.403
resolver: "403"
matcher: regex
matcherParams:
- (.*)?\.403
resolver: "403"

- name: Spotify proxy
matcher: regex
Expand Down Expand Up @@ -93,4 +93,12 @@ rules:
matcher: regex
matcherParams:
- (.*\.)?dartlang.*
resolver: "shecan"
resolver: "shecan"

- name: Raw proxy
matcher: exact
matcherParams:
- tester.com.
raw:
A: tester.com. 60 IN A 1.2.3.4
AAAA: tester.com. 60 IN AAAA FFFF:FFFF:FFFF:FFFF::FFFF
35 changes: 27 additions & 8 deletions lib/config/router_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@
package config

import (
"github.com/FMotalleb/dns-reverse-proxy-docker/lib/provider"
"net"
"strings"

"github.com/FMotalleb/dns-reverse-proxy-docker/lib/provider"

"github.com/miekg/dns"
"github.com/rs/zerolog/log"
)

// Route will redirect dns request to resolvable provider
func (c *Config) Route(w dns.ResponseWriter, req *dns.Msg) {

if len(req.Question) == 0 || !c.allowed(w, req) {
provider.ResponseErrorToRequest(w, req)
return
Expand All @@ -23,13 +23,32 @@ func (c *Config) Route(w dns.ResponseWriter, req *dns.Msg) {
rule := c.findRuleFor(lcName)
if rule != nil {
log.Debug().Msgf("found rule for %s using findProvider: %v", lcName, rule.Resolver)
findProvider := c.findProvider(*rule.Resolver)
if findProvider != nil {
findProvider.HandleRequest(w, req)
return

raw := rule.GetRaw(dns.TypeToString[req.Question[0].Qtype])
if raw != nil {
msg, err := dns.NewRR(*raw)
if err != nil {
log.Debug().Msgf("cannot parse raw response: %v", err)
}
if msg != nil {
result := make([]dns.RR, 0)
result = append(result, msg)
req.Answer = result
log.Info().Msgf("cannot parse raw response: %v", req)
_ = w.WriteMsg(req)
return
}
}
if rule.Resolver != nil {
findProvider := c.findProvider(*rule.Resolver)
if findProvider != nil {
findProvider.HandleRequest(w, req)
return
}
log.Debug().Msgf("requested findProvider was missing please add `%v` to providers in config file", rule.Resolver)
panic("default findProvider is missing")
}
log.Debug().Msgf("requested findProvider was missing please add `%v` to providers in config file", rule.Resolver)
panic("default findProvider is missing")

}

p := c.getDefaultProvider()
Expand Down
39 changes: 29 additions & 10 deletions lib/rule/rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,37 @@ package rule
import (
"fmt"
"regexp"
"strings"

"github.com/rs/zerolog/log"
)

// Rule set of rules to find resolver of each request
type Rule struct {
Name *string `yaml:"name"`
Matcher string `yaml:"matcher"`
MatcherParams []string `yaml:"matcherParams"`
Resolver *string `yaml:"resolver"`
Name *string `yaml:"name"`
Matcher string `yaml:"matcher"`
MatcherParams []string `yaml:"matcherParams"`
Resolver *string `yaml:"resolver"`
Raw *map[string]string `yaml:"raw"`
}

func (r *Rule) String() string {
return fmt.Sprintf("rule(Name: %v,Matcher: %s,MatcherParams: %v,Resolver: %v)", r.Name, r.Matcher, r.MatcherParams, r.Resolver)
}

// GetRaw will try to find raw response in the rule
func (r *Rule) GetRaw(qType string) *string {
if r.Raw == nil {
return nil
}
for key, value := range *r.Raw {
if strings.ToLower(qType) == strings.ToLower(key) {
return &value
}
}
return nil
}

// Match returns true if given address matches this rule
func (r *Rule) Match(address string) bool {
switch r.Matcher {
Expand All @@ -44,6 +59,14 @@ func (r *Rule) Match(address string) bool {
return false
}

func (r *Rule) validateResolveMethod() bool {
if (r.Resolver == nil) && (r.Raw == nil) {
log.Debug().Msgf("no resolver or raw response found for rule: %s", r)
return false
}
return true
}

// Validate this rule is correctly configured
func (r *Rule) Validate() bool {
switch r.Matcher {
Expand All @@ -64,17 +87,13 @@ func (r *Rule) Validate() bool {
log.Debug().Msgf("validation succeeded for an Unnamed Rule - regexp: `%s`", rule)
}
}
if r.Resolver == nil {
log.Debug().Msgf("resolver is empty in rule: %s", r)
return false
}
return true
return r.validateResolveMethod()
case "exact":
if len(r.MatcherParams) == 0 {
log.Debug().Msgf("failed to validate rule:%s, received exact matcher with no params", r)
return false
}
return true
return r.validateResolveMethod()
}
log.Debug().Msgf("failed to validate rule:%s", r)
return false
Expand Down
62 changes: 60 additions & 2 deletions lib/rule/rule_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ func TestValidateExactFail(t *testing.T) {
Name: &name,
}
if item.Validate() {
t.Error("Item has valid params and configuration it must pass")
t.Error("Item has invalid configuration it must fail")
}
}
func TestExactMatcherPass(t *testing.T) {
Expand All @@ -164,6 +164,64 @@ func TestExactMatcherFail(t *testing.T) {
Resolver: &name,
}
if item.Match("google.com") {
t.Error("matcher is working incorrectly, expected to match `google.com`")
t.Error("matcher is working incorrectly, expected to fail matching `google.com`")
}
}

func TestRawGetCorrectItem(t *testing.T) {
rgp := make([]string, 0)
rgp = append(rgp, "google.com.")
rawMap := make(map[string]string, 0)
rawMap["A"] = "tester.com. 60 IN A 1.2.3.4"
item := rule.Rule{
Matcher: "exact",
MatcherParams: rgp,
// Resolver: &name,
Raw: &rawMap,
}
if item.GetRaw("A") == nil {
t.Error("matcher is working incorrectly, expected to find A record")
}
}
func TestRawGetResolveItemEvenInCaseMismatch(t *testing.T) {
rgp := make([]string, 0)
rgp = append(rgp, "google.com.")
rawMap := make(map[string]string, 0)
rawMap["a"] = "tester.com. 60 IN A 1.2.3.4"
item := rule.Rule{
Matcher: "exact",
MatcherParams: rgp,
// Resolver: &name,
Raw: &rawMap,
}
if item.GetRaw("AAAA") != nil {
t.Error("matcher is working incorrectly, expected to find A record(with case mismatch)")
}
}
func TestRawGetCannotResolveItemMissingRaw(t *testing.T) {
rgp := make([]string, 0)
rgp = append(rgp, "google.com.")
rawMap := make(map[string]string, 0)
rawMap["A"] = "tester.com. 60 IN A 1.2.3.4"
item := rule.Rule{
Matcher: "exact",
MatcherParams: rgp,
Raw: &rawMap,
}
if item.GetRaw("AAAA") != nil {
t.Error("AAAA record was not set in raw map this test must fail")
}
}
func TestRawGetCannotResolveItemNoRaw(t *testing.T) {
rgp := make([]string, 0)
rgp = append(rgp, "google.com.")
name := "test"
item := rule.Rule{
Matcher: "exact",
MatcherParams: rgp,
Resolver: &name,
}
if item.GetRaw("A") != nil {
t.Error("no record was set for this rule this test must fail")
}
}

0 comments on commit efc07b6

Please sign in to comment.