Penne is a config-driven pipeline oriented DNS resolver that allows complex workflows to be defined in a simple way. Penne is built using the darvaza sidecar engine and the darvaza resolver interface.
Penne is designed upon the idea of split horizons, where DNS answers depend on the IP address of the client.
A Horizon is a named set of network patterns (aka CIDR
) that can optionally
choose a custom Resolver
,
and can annotate or filter requests before passing them to the next Horizon on
a chain.
On the config file you define a series of resolvers in charge of handling DNS requests. Each Resolver has a unique name. Names are not case sensitive and allow unicode text.
Resolvers have three operation modes:
- Iterative goes to the root servers and iterates through authoritative servers until the answer is found.
- Forwarder connects to a specific server to get the answer, optionally allowing recursion to be performed remotely.
- and Chained, where requests are passed to the Next resolver, optionally modified.
Resolvers act as middlewares, optionally restricted to specific domains (suffixes).
Resolvers can also be configured to discard various entries (like AAAA
for example)
and execute request rewrites.
We use globing instead of regular expressions for the name rewrites and suffix matching on Resolvers.
For this purpose we worked with pachyderm's Oh my glob! library, which in turn was derived from the excellent github.com/gobwas/glob with the following syntax.
pattern:
{ term }
term:
`*` matches any sequence of non-separator characters
`**` matches any sequence of characters
`?` matches any single non-separator character
`[` [ `!` ] { character-range } `]`
character class (must be non-empty)
`{` pattern-list `}`
pattern alternatives
c matches character c (c != `*`, `**`, `?`, `\`, `[`, `{`, `}`)
`\` c matches character c
character-range:
c matches character c (c != `\\`, `-`, `]`)
`\` c matches character c
lo `-` hi matches character c for lo <= c <= hi
pattern-list:
pattern { `,` pattern }
comma-separated (without spaces) patterns
capture:
`(` { `|` pattern } `)`
`@(` { `|` pattern } `)`
match and capture one of pipe-separated sub-patterns
`*(` { `|` pattern } `)`
match and capture any number of the pipe-separated sub-patterns
`+(` { `|` pattern } `)`
match and capture one or more of the pipe-separated sub-patterns
`?(` { `|` pattern } `)`
match and capture zero or one of the pipe-separated sub-patterns
`!(` { `|` pattern } `)`
match and capture anything except one of the pipe-separated sub-patterns
And for replacements ${n}
and $n
to indicate the index on the capture slice inside a literal string.
TBD ...
TBD ...
TBD ...
TBD ...
TBD ...
TBD ...