Discussion:
[Pdns-users] PDNS-recursor as transparent proxy, fails for outside NS servers
Michał Zając
2018-07-31 15:08:26 UTC
Permalink
Hi *.

I have few authoritative PDNS servers that are working just fine.
Now I need to modify some responses. It has some if's, so I've decided
to do it with Lua. Unfortunately, PDNS doesn't support Lua in most
cases. But PDNS-recursor does. So quick switch, PDNS goes to
127.0.0.1, and recursor goes out to the public, with
"forward-zones=.=127.0.0.1:54". Lua is doing it's job, everything is
working fine, except when I have domain that has NS records going
outside of my server.

Let's say I have "foo.com" in my database with two NS records
"sub.foo.com NS ns1.outside.com" and "sub.foo.com NS ns2.outside.com".
When I do "dig NS sub.foo.com" to authoritative it just returns both
records. But when I do the same to recursor it tries to ask those
ns1|2.outside.com servers. But it can't, because there's no way to
find IP addresses of them. Authoritative backend doesn't know them.
I've traced my problem to this part of code
https://github.com/PowerDNS/pdns/blob/master/pdns/syncres.cc#L2312 but
there's not way to override this standard behavior. Or at least I
don't see it.

Sure, it can be simply fixed with
"forward-zones-recurse=.=8.8.8.8", but this way my recursor instead of
transparent proxy becomes full recursor, open to the world. And I
don't want that.

Any ideas how can I fix this setup? Thanks in advance.

Jul 31 14:36:30 1 [1/1] question for 'sub.foo.com|NS' from 127.0.0.1
Jul 31 14:36:30 [1] sub.foo.com: Wants NO DNSSEC processing in query for NS
Jul 31 14:36:30 [1] sub.foo.com: Looking for CNAME cache hit of
'sub.foo.com|CNAME'
Jul 31 14:36:30 [1] sub.foo.com: No CNAME cache hit of 'sub.foo.com|CNAME' found
Jul 31 14:36:30 [1] sub.foo.com: No cache hit for 'sub.foo.com|NS',
trying to find an appropriate NS record
Jul 31 14:36:30 [1] sub.foo.com: Cache consultations done, have 1 NS to contact
Jul 31 14:36:30 [1] sub.foo.com.: Nameservers: <empty>(0.00ms)
Jul 31 14:36:30 [1] sub.foo.com: Domain has hardcoded nameserver
Jul 31 14:36:30 [1] sub.foo.com: Resolved '.' NS (empty) to: 127.0.0.1
Jul 31 14:36:30 [1] sub.foo.com: Trying IP 127.0.0.1:54, asking 'sub.foo.com|NS'
Jul 31 14:36:30 [1] sub.foo.com: Got 3 answers from (empty)
(127.0.0.1), rcode=0 (No Error), aa=0, in 1ms
Jul 31 14:36:30 [1] sub.foo.com: accept answer
'sub.foo.com|NS|ns1.outside.com.' from '.' nameservers? 2 YES! - This
answer was received from a server we forward to.
Jul 31 14:36:30 [1] sub.foo.com: accept answer
'sub.foo.com|NS|ns2.outside.com.' from '.' nameservers? 2 YES! - This
answer was received from a server we forward to.
Jul 31 14:36:30 [1] sub.foo.com: OPT answer '.' from '.' nameservers
Jul 31 14:36:30 [1] sub.foo.com: determining status after receiving this packet
Jul 31 14:36:30 [1] sub.foo.com: got NS record 'sub.foo.com' ->
'ns1.outside.com.'
Jul 31 14:36:30 [1] sub.foo.com: got NS record 'sub.foo.com' ->
'ns2.outside.com.'
Jul 31 14:36:30 [1] sub.foo.com: status=did not resolve, got 2 NS,
looping to them
Jul 31 14:36:30 [1] sub.foo.com.: Nameservers:
ns1.outside.com.(0.00ms), ns2.outside.com.(0.00ms)
Jul 31 14:36:30 [1] sub.foo.com: Trying to resolve NS 'ns1.outside.com' (1/2)
Jul 31 14:36:30 [1] ns1.outside.com: Wants NO DNSSEC processing in
query for A
Jul 31 14:36:30 [1] ns1.outside.com: Looking for CNAME cache hit of
'ns1.outside.com|CNAME'
Jul 31 14:36:30 [1] ns1.outside.com: No CNAME cache hit of
'ns1.outside.com|CNAME' found
Jul 31 14:36:30 [1] ns1.outside.com: No cache hit for
'ns1.outside.com|A', trying to find an appropriate NS record
Jul 31 14:36:30 [1] ns1.outside.com: Cache consultations done, have
1 NS to contact
Jul 31 14:36:30 [1] ns1.outside.com.: Nameservers: <empty>(1.05ms)
Jul 31 14:36:30 [1] ns1.outside.com: Domain has hardcoded nameserver
Jul 31 14:36:30 [1] ns1.outside.com: Resolved '.' NS (empty) to: 127.0.0.1
Jul 31 14:36:30 [1] ns1.outside.com: Trying IP 127.0.0.1:54, asking
'ns1.outside.com|A'
Jul 31 14:36:30 [1] ns1.outside.com: (empty) (127.0.0.1) returned a
Refused, trying sibling IP or NS
Jul 31 14:36:30 [1] ns1.outside.com: Failed to resolve via any of
the 1 offered NS at level '.'
Jul 31 14:36:30 [1] ns1.outside.com: failed (res=-1)
Jul 31 14:36:30 [1] sub.foo.com: Failed to get IP for NS
ns1.outside.com, trying next if available
Jul 31 14:36:30 [1] sub.foo.com: Trying to resolve NS 'ns2.outside.com' (2/2)
Jul 31 14:36:30 [1] ns2.outside.com: Wants NO DNSSEC processing in
query for A
Jul 31 14:36:30 [1] ns2.outside.com: Looking for CNAME cache hit of
'ns2.outside.com|CNAME'
Jul 31 14:36:30 [1] ns2.outside.com: No CNAME cache hit of
'ns2.outside.com|CNAME' found
Jul 31 14:36:30 [1] ns2.outside.com: No cache hit for
'ns2.outside.com|A', trying to find an appropriate NS record
Jul 31 14:36:30 [1] ns2.outside.com: Cache consultations done, have
1 NS to contact
Jul 31 14:36:30 [1] ns2.outside.com.: Nameservers: <empty>(1.05ms)
Jul 31 14:36:30 [1] ns2.outside.com: Domain has hardcoded nameserver
Jul 31 14:36:30 [1] ns2.outside.com: Resolved '.' NS (empty) to: 127.0.0.1
Jul 31 14:36:30 [1] ns2.outside.com: Trying IP 127.0.0.1:54, asking
'ns2.outside.com|A'
Jul 31 14:36:30 [1] ns2.outside.com: (empty) (127.0.0.1) returned a
Refused, trying sibling IP or NS
Jul 31 14:36:30 [1] ns2.outside.com: Failed to resolve via any of
the 1 offered NS at level '.'
Jul 31 14:36:30 [1] ns2.outside.com: failed (res=-1)
Jul 31 14:36:30 [1] sub.foo.com: Failed to get IP for NS
ns2.outside.com, trying next if available
Jul 31 14:36:30 [1] sub.foo.com: Failed to resolve via any of the 2
offered NS at level 'sub.foo.com'
Jul 31 14:36:30 [1] sub.foo.com: Ageing nameservers for level
'sub.foo.com', next query might succeed
Jul 31 14:36:30 [1] sub.foo.com: failed (res=-1)
--
Michal Zajac
Brian Candler
2018-08-08 16:49:12 UTC
Permalink
Post by Michał Zając
I have few authoritative PDNS servers that are working just fine.
Now I need to modify some responses. It has some if's, so I've decided
to do it with Lua. Unfortunately, PDNS doesn't support Lua in most
cases. But PDNS-recursor does.
PDNS-recursor is not intended for use as a DNS proxy - but dnsdist is. 
I suggest you look at that instead.
Michał Zając
2018-08-10 12:40:02 UTC
Permalink
Hi.
Post by Brian Candler
PDNS-recursor is not intended for use as a DNS proxy - but dnsdist is.
I suggest you look at that instead.
Yes, dnsdist is quite nice proxy, but without way to change it
responses in Lua.
--
Greets, Michał Zając
Brian Candler
2018-08-10 12:49:00 UTC
Permalink
Post by Michał Zając
Post by Brian Candler
PDNS-recursor is not intended for use as a DNS proxy - but dnsdist is.
I suggest you look at that instead.
Yes, dnsdist is quite nice proxy, but without way to change it
responses in Lua.
Does "DNSAction.Spoof" not do what you require?  If not, what sort of
changes do you wish to make?

https://dnsdist.org/reference/constants.html#dnsaction
https://github.com/PowerDNS/pdns/blob/master/pdns/dnsdistconf.lua
Michał Zając
2018-08-10 13:25:33 UTC
Permalink
Hi.
Does "DNSAction.Spoof" not do what you require? If not, what sort of changes do you wish to make?
Spoof works… almost. I'd like to return some IPs for type-A
queries, but only if original response equals to IP A.B.C.D. And I
cannot do this with domain names, becase this list is too big (over
30k), and too dynamic.
--
Greets, Michał Zając
Michał Zając
2018-09-20 19:57:24 UTC
Permalink
Hi *.

I'll commit a shameless bump, but maybe someone will throw an
idea. So I need to modify (probably by lua) some answers from pdns
server, but after MySQL backend returns it, not before. And as we
established, I cannot use:
- pure pdns server, because it doesn't have lua action to modify answers,
- dnsdist, because it can create reply in lua via
"DNSAction.Spoof", but cannot modify answer given from it's backend
(pdns server),
- pdns-recursor with pdns backend via forward-zones=, because it
doesn't work with NS records pointing outside for subdomains.

Any ideas?
--
Greets, Michał Zając
Chris Hofstaedtler
2018-09-21 08:05:07 UTC
Permalink
Post by Michał Zając
Hi *.
I'll commit a shameless bump, but maybe someone will throw an
idea. So I need to modify (probably by lua) some answers from pdns
server, but after MySQL backend returns it, not before. And as we
- pure pdns server, because it doesn't have lua action to modify answers,
- dnsdist, because it can create reply in lua via
"DNSAction.Spoof", but cannot modify answer given from it's backend
(pdns server),
- pdns-recursor with pdns backend via forward-zones=, because it
doesn't work with NS records pointing outside for subdomains.
Any ideas?
Just add the code in pdns-server to modify outgoing answers using Lua.
I’m sure that’d be a well-received feature.

Chris
Michał Zając
2018-09-21 09:42:49 UTC
Permalink
Hi.
Post by Chris Hofstaedtler
Just add the code in pdns-server to modify outgoing answers using Lua.
I’m sure that’d be a well-received feature.
"Just"… Anyone willing to do it for reasonable price to share it
with the community?
--
Greets, Michał Zając
Chris Stradtman
2018-09-21 16:30:48 UTC
Permalink
If you feel comfortable with python, you could create a custom proxy using
the twisted DNS package.
I did one for an unusual thing we were doing with DNS on a project we were
working on.
In the end, it only took about a dozen lines to change flags in particular
DNS responses and implement a cache.

Chris Stradtman
Hi.
Post by Chris Hofstaedtler
Just add the code in pdns-server to modify outgoing answers using Lua.
I’m sure that’d be a well-received feature.
"Just"
 Anyone willing to do it for reasonable price to share it
with the community?
--
Greets, Michał Zając
_______________________________________________
Pdns-users mailing list
https://mailman.powerdns.com/mailman/listinfo/pdns-users
--
Michał Zając
2018-09-21 16:37:50 UTC
Permalink
Hi
In the end, it only took about a dozen lines to change flags in particular DNS responses and implement a cache.
And how's the overhead and performance? My servers are doing
around 150req/s with peak around 500req/s.

Also, is it an option for you to share that dozen lines? Simplest
version, without cache, etc.
--
Michał Zając
c***@maurand.com
2018-09-22 14:17:18 UTC
Permalink
Have you thought about using dnsdist as the proxy instead? It's built specifically for this. It also has lua scripting. very fast.
September 21 2018 12:31 PM, "Chris Stradtman" wrote:

If you feel comfortable with python, you could create a custom proxy using the twisted DNS package.
I did one for an unusual thing we were doing with DNS on a project we were working on.
In the end, it only took about a dozen lines to change flags in particular DNS responses and implement a cache.

Chris Stradtman
On Fri, Sep 21, 2018 at 5:43 AM Michał Zając wrote: Hi.
Post by Chris Hofstaedtler
Just add the code in pdns-server to modify outgoing answers using Lua.
I’m sure that’d be a well-received feature.
"Just"
 Anyone willing to do it for reasonable price to share it
with the community?

--
Greets, Michał Zając
Michał Zając
2018-09-23 17:56:35 UTC
Permalink
Hi.
Have you thought about using dnsdist as the proxy instead? It's built specifically for this. It also has lua scripting. very fast.
As I already wrote 2 posts ago, dnsdist doesn't work for me. Via
"DNSAction.Spoof" you can create answer, but there's no way to modify
with lua answer received from backend.
--
Michał Zając
Loading...