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

Support templates in static-responder #367

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft

Support templates in static-responder #367

wants to merge 2 commits into from

Conversation

folbricht
Copy link
Owner

@folbricht folbricht commented Mar 16, 2024

Adds support for passing a regex that's applied to the question string and can then be used to customize the answers from a static-responder like so

[groups.static]
type   = "static-responder"
question = '^(\d+)-(\d+)-(\d+)-(\d+)\.rebind\.$'
answer = ["IN A $1.$2.$3.$4"]
[groups.static]
type      = "static-responder"
question  = '^(.+)\.$'
answer    = [ "IN A 0.0.0.0" ]
edns0-ede = { code = 15, text = "IP $1 is in the blocklist" }

Implements #366

@Anuskuss
Copy link

Anuskuss commented Mar 16, 2024

Full config
[resolvers.cloudflare]
protocol = "dot"
address  = "1.1.1.1"

[groups.rebind]
type     = "static-responder"
question = '^(\d+)-(\d+)-(\d+)-(\d+)\.rebind\.$'
answer   = ["IN A $1.$2.$3.$4"]

[groups.blocklist-resolver]
type      = "static-responder"
question  = '^(.+)\.$'
answer    = [ "IN A 0.0.0.0" ]
edns0-ede = { code = 15, text = "IP $1 is in the blocklist" }

[groups.blocklist]
type               = "response-blocklist-ip"
resolvers          = [ "cloudflare" ]
blocklist-resolver = "blocklist-resolver"
blocklist          = [ "93.184.216.34" ] # example.com

[routers.router]
routes = [
  { resolver = "rebind", name = '\.rebind\.$' },
  { resolver = "blocklist", name = '^example\.com\.$' },
  { resolver = "cloudflare" }
]

[listeners.udp]
protocol = "udp"
address  = ":5300"
resolver = "router"

[listeners.tcp]
protocol = "tcp"
address  = ":5300"
resolver = "router"

First part seems to work:

$ dig @127.0.0.1 -p5300 +noall +answer +comments 1-2-3-4.rebind
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 15258
;; flags: qr rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available

;; ANSWER SECTION:
1-2-3-4.rebind.		3600	IN	A	1.2.3.4

Second part is almost correct but doesn't work how I need it to:

$ dig @127.0.0.1 -p5300 +noall +answer +comments example.com   
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 5193
;; flags: qr rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; EDE: 15 (Blocked): (IP example.com is in the blocklist)
;; ANSWER SECTION:
example.com.		3600	IN	A	0.0.0.0

The question should ideally be context-aware, meaning if the value came from a listener or e.g. blocklist-v2, the regex would parse the query name but since it came from response-blocklist-ip it should've been the IP address. Also since the IP doesn't end in a dot one can save some memory by just using $0 You'll still have to specify question though (maybe that restriction could be lifted in the future).

Edit: Actually now that I'm thinking about it, it should not strictly be the query name but rather the "reason" why the group got called, e.g. if blocklist-format = "regexp" and blocklist = [ '^.+\.example\.com\.$' ] then ideally it could return something like EDE: 15 (Blocked): (Blocked by "^.+\.example\.com"). I don't wanna feature creep this too much though but I definitely need at least the IP address.

[groups.blocklist-resolver-ip]
type      = "static-responder"
question  = '.+'
edns0-ede = { code = 15, text = "IP $0 is in the blocklist" }

[groups.blocklist-resolver-domain]
type      = "static-responder"
question  = '^(.+)\.$'
edns0-ede = { code = 15, text = "Domain $1 is in the blocklist" }

[groups.blocklist-ip]
type               = "response-blocklist-ip"
blocklist-resolver = "blocklist-resolver-ip"
blocklist          = [ "93.184.216.34" ]

[groups.blocklist-domain]
type               = "blocklist-v2"
blocklist-resolver = "blocklist-resolver-domain"
blocklist-format   = "domain"
blocklist          = [ "example.com" ]

P.S. Also you should probably get rid of that warning at some point (it's probably very low on your todo list).

@folbricht
Copy link
Owner Author

It's not possible to pass information about where a query came from to a group, that's by design. Based on your example though, perhaps adding something like edns0-ede = { code = 15, text = "IP $0 is in the blocklist" } directly to the blocklist would make a lot more sense. Giving the blocklist the ability to block and respond with extended error codes.

@folbricht
Copy link
Owner Author

The warning should be fixed now too

@Anuskuss
Copy link

Based on your example though, perhaps adding something like edns0-ede = { code = 15, text = "IP $0 is in the blocklist" } directly to the blocklist would make a lot more sense.

I think that's a good compromise 👍

@folbricht
Copy link
Owner Author

#373 adds edns0-ede to blocklist-v2 directly. It's actually more powerful than just the regex implementation here. I'll probably change this one to match.

@Anuskuss
Copy link

Any news on this? I've been using this branch for 4 months now and the first part works great. Maybe you should split this up so the second part can be merged later.

The only things that I can say about the first part is that question needs to match the whole string, so I have to add a superfluous .+ (question='^(\d+)-(\d+)-(\d+)-(\d+)\..+'). If you could lift that restriction that'd save me 2 bytes ;)

@folbricht
Copy link
Owner Author

I was thinking of closing this in favor of #378. It's already on master. Does that work for your use-case? I imagine it being a bit cleaner than the regex as well

@Anuskuss
Copy link

The Go template format is really unfamiliar to me but after a bit of experimentation it seems to work for my use case:

[listeners.udp]
protocol = "udp"
address  = ":5300"
resolver = "static"

[groups.static]
type   = "static-template"
answer = [
  '{{ .Question }} {{ .QuestionClass }} {{ .QuestionType }} {{ replaceAll ( index ( split .Question "." ) 0 ) "-" "." }}'
]
$ dig -p 5300 +noall +answer 1-2-3-4.rebind
1-2-3-4.rebind.		3600	IN	A	1.2.3.4

How is the second part coming along though? I still want to use "reason" in edns0-ede, or at the very least the IP address.

@folbricht
Copy link
Owner Author

EDE is actually supported as well, I just didn't have anything in the docs for it yet. Added an example. And I also included your example since it may be useful to others. Try this

[groups.static]
type   = "static-template"
edns0-ede = {code = 15, text = '{{ .Question }} is banned!'}

@Anuskuss
Copy link

Yeah but this is "question" - I want the "reason":

[groups.blocklist-resolver]
type      = "static-template"
edns0-ede = { code = 15, text = '"{{ .Reason }}" is banned!' }

[groups.blocklist-ip]
type               = "response-blocklist-ip"
blocklist-resolver = "blocklist-resolver"
blocklist          = [ "93.184.215.14" ] # example.com

[groups.blocklist-v2]
type               = "blocklist-v2"
blocklist-resolver = "blocklist-resolver"
blocklist          = [ '(^|\.)example\.org\.$' ]

Such that example.com returns

; EDE: 15 (Blocked): ("93.184.215.14" is banned!)

while example.org returns

; EDE: 15 (Blocked): ("(^|\.)example\.org\.$" is banned!)

Because what's the point of returning the question to the user? The user already knows the question.

@folbricht
Copy link
Owner Author

Unable to test this right now, but you would use the EDE on the blocklist itself for this. Though I don't believe the template has access to the raw blocklist rule that matched (yet). That could be added which would also cover the response blocklist.

[groups.blocklist-v2]
type               = "blocklist-v2"
blocklist-resolver = "blocklist-resolver"
blocklist          = [ '(^|\.)example\.org\.$' ]
edns0-ede = { code = 15, text = '"{{ .Question }}" is banned!' }

@Anuskuss
Copy link

Though I don't believe the template has access to the raw blocklist rule that matched (yet).

Yeah.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants