Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: adguard home provider #3249

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ require (
github.com/infobloxopen/infoblox-go-client/v2 v2.1.2-0.20220407114022-6f4c71443168
github.com/linki/instrumented_http v0.3.0
github.com/linode/linodego v1.9.1
github.com/markussiebert/go-adguardhome-client v0.0.1
github.com/maxatome/go-testdeep v1.12.0
github.com/miekg/dns v1.1.51
github.com/nesv/go-dynect v0.6.0
Expand Down Expand Up @@ -92,6 +93,7 @@ require (
github.com/alexbrainman/sspi v0.0.0-20180613141037-e580b900e9f5 // indirect
github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 // indirect
github.com/ans-group/go-durationstring v1.2.0 // indirect
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
Expand Down Expand Up @@ -130,6 +132,7 @@ require (
github.com/hashicorp/go-retryablehttp v0.7.2 // indirect
github.com/hashicorp/go-uuid v1.0.2 // indirect
github.com/imdario/mergo v0.3.13 // indirect
github.com/invopop/yaml v0.1.0 // indirect
github.com/jcmturner/aescts/v2 v2.0.0 // indirect
github.com/jcmturner/dnsutils/v2 v2.0.0 // indirect
github.com/jcmturner/gofork v1.0.0 // indirect
Expand All @@ -149,6 +152,7 @@ require (
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/nxadm/tail v1.4.8 // indirect
github.com/oklog/ulid v1.3.1 // indirect
Expand Down
15 changes: 13 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdko
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/Raffo/knolog v0.0.0-20211016155154-e4d5e0cc970a h1:4D87FDUGSrfLp/NJmYxybiC8+OR8s5eULyNgmmxAI9U=
github.com/Raffo/knolog v0.0.0-20211016155154-e4d5e0cc970a/go.mod h1:AsBYmtPY5rgsIyjQZDLO+Dwdx91Jmi6uxu7LO6Xf9iw=
github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk=
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
Expand Down Expand Up @@ -157,6 +158,8 @@ github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kd
github.com/aokoli/goutils v1.1.0/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ=
github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
Expand Down Expand Up @@ -188,6 +191,7 @@ github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJm
github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
github.com/bodgit/tsig v1.2.0 h1:wNfc7yTk2OuWh/s7nEFa9h+SkIfTn7e4xlFtf1Sgvr4=
github.com/bodgit/tsig v1.2.0/go.mod h1:bsN2ntwGE/s3EeoawjAoKUcAfO4Fr0nGKC72vNF/cqM=
Expand Down Expand Up @@ -425,8 +429,9 @@ github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/
github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng=
github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
github.com/go-openapi/swag v0.21.1 h1:wm0rhTb5z7qpJRHBdPOMuY4QjVUMbF6/kwoYeRAOrKU=
github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4=
github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA=
github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4=
Expand Down Expand Up @@ -684,6 +689,8 @@ github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod
github.com/infobloxopen/infoblox-go-client v1.1.1/go.mod h1:BXiw7S2b9qJoM8MS40vfgCNB2NLHGusk1DtO16BD9zI=
github.com/infobloxopen/infoblox-go-client/v2 v2.1.2-0.20220407114022-6f4c71443168 h1:EXKtVoP/44ckXpw3v2/vrtMEdKx/PA+YBl+REoV27XQ=
github.com/infobloxopen/infoblox-go-client/v2 v2.1.2-0.20220407114022-6f4c71443168/go.mod h1:+lznx4ASBSUZ2i6qwlgyn0v3eKDxBHNU5aRJzghAFbw=
github.com/invopop/yaml v0.1.0 h1:YW3WGUoJEXYfzWBjn00zIlrw7brGVD0fUKRYDPAPhrc=
github.com/invopop/yaml v0.1.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q=
github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8=
github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=
github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo=
Expand Down Expand Up @@ -727,6 +734,7 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw=
Expand Down Expand Up @@ -793,10 +801,13 @@ github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
github.com/markussiebert/go-adguardhome-client v0.0.1 h1:y7fXqxiLVb3hM0RxraP1ZW+k6ps6Xa78saIBWajddP0=
github.com/markussiebert/go-adguardhome-client v0.0.1/go.mod h1:UAaJUClUSphQzAoMo0fXNA/WNQPb5GjBJcX1yFA8cIU=
github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho=
github.com/martini-contrib/render v0.0.0-20150707142108-ec18f8345a11 h1:YFh+sjyJTMQSYjKwM4dFKhJPJC/wfo98tPUc17HdoYw=
github.com/martini-contrib/render v0.0.0-20150707142108-ec18f8345a11/go.mod h1:Ah2dBMoxZEqk118as2T4u4fjfXarE0pPnMJaArZQZsI=
Expand Down
6 changes: 6 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import (
"sigs.k8s.io/external-dns/pkg/apis/externaldns/validation"
"sigs.k8s.io/external-dns/plan"
"sigs.k8s.io/external-dns/provider"
"sigs.k8s.io/external-dns/provider/adguardhome"
"sigs.k8s.io/external-dns/provider/akamai"
"sigs.k8s.io/external-dns/provider/alibabacloud"
"sigs.k8s.io/external-dns/provider/aws"
Expand Down Expand Up @@ -178,6 +179,11 @@ func main() {

var p provider.Provider
switch cfg.Provider {
case "adguardhome":
p, err = adguardhome.NewAdguardHomeProvider(
domainFilter,
cfg.DryRun,
)
case "akamai":
p, err = akamai.NewAkamaiProvider(
akamai.AkamaiConfig{
Expand Down
2 changes: 1 addition & 1 deletion pkg/apis/externaldns/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ func (cfg *Config) ParseFlags(args []string) error {
app.Flag("exclude-target-net", "Exclude target nets (optional)").StringsVar(&cfg.ExcludeTargetNets)

// Flags related to providers
providers := []string{"akamai", "alibabacloud", "aws", "aws-sd", "azure", "azure-dns", "azure-private-dns", "bluecat", "civo", "cloudflare", "coredns", "designate", "digitalocean", "dnsimple", "dyn", "exoscale", "gandi", "godaddy", "google", "ibmcloud", "infoblox", "inmemory", "linode", "ns1", "oci", "ovh", "pdns", "pihole", "plural", "rcodezero", "rdns", "rfc2136", "safedns", "scaleway", "skydns", "tencentcloud", "transip", "ultradns", "vinyldns", "vultr"}
providers := []string{"adguaardhome", "akamai", "alibabacloud", "aws", "aws-sd", "azure", "azure-dns", "azure-private-dns", "bluecat", "civo", "cloudflare", "coredns", "designate", "digitalocean", "dnsimple", "dyn", "exoscale", "gandi", "godaddy", "google", "ibmcloud", "infoblox", "inmemory", "linode", "ns1", "oci", "ovh", "pdns", "pihole", "plural", "rcodezero", "rdns", "rfc2136", "safedns", "scaleway", "skydns", "tencentcloud", "transip", "ultradns", "vinyldns", "vultr"}
app.Flag("provider", "The DNS provider where the DNS records will be created (required, options: "+strings.Join(providers, ", ")+")").Required().PlaceHolder("provider").EnumVar(&cfg.Provider, providers...)
app.Flag("domain-filter", "Limit possible target zones by a domain suffix; specify multiple times for multiple domains (optional)").Default("").StringsVar(&cfg.DomainFilter)
app.Flag("exclude-domains", "Exclude subdomains (optional)").Default("").StringsVar(&cfg.ExcludeDomains)
Expand Down
194 changes: 194 additions & 0 deletions provider/adguardhome/adguardhome.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
/*
Copyright 2020 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package adguardhome

import (
"context"
"encoding/base64"
"encoding/json"
"fmt"
"net/http"
"os"
"regexp"

adguard "github.com/markussiebert/go-adguardhome-client/client"
log "github.com/sirupsen/logrus"

"sigs.k8s.io/external-dns/endpoint"
"sigs.k8s.io/external-dns/plan"
"sigs.k8s.io/external-dns/provider"
)

// The regex hat should identify and parse all custom rules in adguard home that are used to handle dns records
var regex = regexp.MustCompile(`(?P<dnsName>[a-zA-Z\*.-]+)\$dnstype=(?P<recordType>[A-Z]+),dnsrewrite=NOERROR;[A-Z]+;(?P<target>.*)`)

// AdguardHomeProvider is an implementation of Provider for Vultr DNS.
type AdguardHomeProvider struct {
provider.BaseProvider
client adguard.ClientWithResponses

domainFilter endpoint.DomainFilter
DryRun bool
}

// Prepare basicAuth with credentials
func basicAuth(username, password string) string {
auth := username + ":" + password
return "Basic " + base64.StdEncoding.EncodeToString([]byte(auth))
}

// NewAdguardHomeProvider initializes a new Vultr BNS based provider
func NewAdguardHomeProvider(domainFilter endpoint.DomainFilter, dryRun bool) (*AdguardHomeProvider, error) {
adguardHomeURL, adguardHomeUrlOk := os.LookupEnv("ADGUARD_HOME_URL")
if !adguardHomeUrlOk {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might want to document that the AGH URL passed here needs to be suffixed with /control/ for a regular AGH deployment. Since that's where the APIs are under.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I got confused trying to troubleshoot that with a very unhelpful error about a nil reference.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right - it took me some time to figure Out the right path...

return nil, fmt.Errorf("no url was found in environment variable ADGUARD_HOME_URL")
}

adguardHomeUser, adguardHomeUserOk := os.LookupEnv("ADGUARD_HOME_USER")
if !adguardHomeUserOk {
return nil, fmt.Errorf("no user was found in environment variable ADGUARD_HOME_USER")
}

adguardHomePass, adguardHomePassOk := os.LookupEnv("ADGUARD_HOME_PASS")
if !adguardHomePassOk {
return nil, fmt.Errorf("no password was found in environment variable ADGUARD_HOME_PASS")
}

client, clientOk := adguard.NewClientWithResponses(adguardHomeURL, adguard.ClientOption(func(client *adguard.AdguardHomeClient) error {
client.RequestEditors = append(client.RequestEditors,
adguard.RequestEditorFn(
func(ctx context.Context, req *http.Request) error {
req.Header.Add("Authorization", basicAuth(adguardHomeUser, adguardHomePass))
return nil
},
),
adguard.RequestEditorFn(
func(ctx context.Context, req *http.Request) error {
req.Header.Add("User-Agent", "ExternalDNS")
return nil
},
),
)
return nil
}))

if clientOk != nil {
return nil, fmt.Errorf("failed to create the adguard home api client")
}

p := &AdguardHomeProvider{
client: *client,
domainFilter: domainFilter,
DryRun: dryRun,
}

return p, nil
}

// ApplyChanges implements Provider, syncing desired state with the AdguardHome server Local DNS.
func (p *AdguardHomeProvider) ApplyChanges(ctx context.Context, changes *plan.Changes) error {
// Get current filter values
resp, err := p.client.FilteringStatusWithResponse(ctx)
if err != nil {
log.Errorf("Error %s", err)
return err
}

debugJ, _ := json.MarshalIndent(changes, "", " ")
log.Debugf("changes, %s", string(debugJ))
userRules := *resp.JSON200.UserRules

for _, createValue := range append(changes.Create, changes.UpdateNew...) {
newRule := genAdguardCustomRuleRecord(createValue)
log.Debugf("add custom rule %s", newRule)
userRules = append(userRules, newRule)
}

for _, deleteValue := range append(changes.UpdateOld, changes.Delete...) {
userRules = removeRule(userRules, genAdguardCustomRuleRecord(deleteValue), false)
}

apply, err := p.client.FilteringSetRulesWithResponse(ctx, adguard.SetRulesRequest{
Rules: &userRules,
})

if apply.StatusCode() != 200 {
log.Errorf("Failed to sync records %s", apply.Status())
}
return err
}

func removeRule(rules []string, ruleToRemove string, finishAfterFirst bool) []string {
userRules := rules
for userRuleIndex, userRule := range rules {
if userRule == ruleToRemove {
log.Debugf("deleted rule %s", ruleToRemove)
userRules = append(userRules[:userRuleIndex], userRules[userRuleIndex+1:]...)
if finishAfterFirst {
return userRules
}
}
}
return userRules
}

// Records implements Provider, populating a slice of endpoints from
// AdguardHome local DNS.
func (p *AdguardHomeProvider) Records(ctx context.Context) ([]*endpoint.Endpoint, error) {
resp, err := p.client.FilteringStatusWithResponse(ctx)
if err != nil {
log.Errorf("Error %s", err)
}

log.WithFields(log.Fields{
"func": "Records",
"rules": resp.JSON200.UserRules,
}).Debugf("retrieved rules")
var ret []*endpoint.Endpoint
for _, customRule := range *resp.JSON200.UserRules {
parsed := parseAdguardCustomRuleRecord(customRule)
if parsed != nil {
ret = append(ret, parsed)
}
}

return ret, nil
}

func genAdguardCustomRuleRecord(e *endpoint.Endpoint) string {
return fmt.Sprintf("%s$dnstype=%s,dnsrewrite=NOERROR;%s;%s", e.DNSName, e.RecordType, e.RecordType, e.Targets.String())
Copy link

@ruifung ruifung Jan 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest wrapping the DNSName in |%s| because otherwise a record for example.com will also match test.example.com or test.example.com.example.com

Default matching mode in AGH appears to be "contains substring"

As per https://github.com/AdguardTeam/AdGuardHome/wiki/Hosts-Blocklists#adblock-style
wrapping the record name in || to match the beginning and end should cause it to perform an exact match.

i.e. "|%s|$dnstype=%s,dnsrewrite=NOERROR;%s;%s"

}

func parseAdguardCustomRuleRecord(s string) *endpoint.Endpoint {

matched := regex.FindStringSubmatch(s)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The regex for this will likely need to be altered for the above comment too.


if matched == nil {
return nil
}

log.Debugf("successfully parsed rule %s", s)

endpoint := &endpoint.Endpoint{
DNSName: matched[1],
RecordType: matched[2],
Targets: endpoint.Targets{matched[3]},
}
debugJ, _ := json.MarshalIndent(endpoint, "", " ")
log.Debugf("returning endpoint %s", string(debugJ))
return endpoint
}
Loading