corednsyaegi

package module
v0.0.0-...-cee55bf Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 21, 2024 License: Apache-2.0 Imports: 13 Imported by: 0

README

coredns-yaegi

A CoreDNS plugin that allows loading other plugins on the fly using Yaegi engine.

Why do I need this?

So, maybe you are wondering... we already have regular CoreDNS plugins, why should I need this?

Opposite to the regular CoreDNS plugins, using this plugin, you don't need to recompile coreDNS and configure it to add them, Yaegi will be able to load them on the fly and execute as a restricted sandboxed Go runtime, however, these plugins are very limited compared to the regular plugins, Depending on the use case one or the other would be the way to go.

Pros
  • Easy to load.
  • Fast to develop and setup.
  • Easy to maintain.
  • Portable.
Cons
  • Limited to the usage standard library and some CoreDNS packages.
  • No external libraries allowed.
  • Need to be on a single file.
  • A bit less performant.
  • Limited by Yaegi features and bugs

So, checking the pros and cons, you may get the idea of these, when you need a simple plugin like blocking/allow DNS, rewriting/mutating the DNS request... these plugins are very easy to set and useful. On the opposite, if you want to connect with external services like a Redis or Kubernetes, you should stick to regular plugins.

Features and restrictions

  • Made in Go.
  • Heavily dependant on Yaegi.
  • Almost similar plugin syntax to the regular coreDNS plugins.
  • No external dependencies allowed (except some CoreDNS and helper packages).
  • Ability to measure using CoreDNS plugins Prometheus.
  • Plugin must be on a single file.
  • Configurable from a local file or to download from an HTTP endpoint (e.g public repo or public/private gist).
  • Can load multiple plugins from different files at the same time in a specific order.

Use cases

  • DNS allow/block logic.
  • Complex logic based DNS rewriting.
  • Audit.

Writing plugins

To write a plugin you only need to implement a method: func NewPlugin(next corednsplugin.Handler) corednsplugin.Handler.

This method should return the plugin itself. Example of a NOOP plugin:

package noop

import (
    "context"

    corednsplugin "github.com/coredns/coredns/plugin"
    "github.com/miekg/dns"
)

type plugin struct {
    next corednsplugin.Handler
}

func NewPlugin(next corednsplugin.Handler) corednsplugin.Handler {
   return plugin{next: next}
}

func (p plugin) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
    return corednsplugin.NextOrFailure(p.Name(), p.next, ctx, w, r)
}

func (p plugin) Name() string { return "noop" }
Allowed packages?

Besides the ability to use all the Go standard library, you can use these external packages:

Do you miss any package? Depending on the general usefulness and safety we may add it so is available.

Configuration

The configuration is very simple, a yaegi plugin can load a single plugin per block (if you need more, you can make your plugin have a chaining logic), and it can be loaded from a local file or a public HTTP URL. Lets see some examples:

Load a single plugin from a local file:

. {
    yaegi { /tmp/my-plugin.go }
    forward . 1.1.1.1
}

Load from a URL:

. {
    yaegi { https://raw.githubusercontent.com/slok/coredns-yaegi/main/_examples/allowlist/plugin.go }
    forward . 1.1.1.1
}

Multiple plugins from different sources:

   yaegi {
        /plugins/plugin1.go
        http://plugins.example.com/plugin2.go
        /plugins/plugin3.go
    }

Multiple blocks and different plugins:

slok.dev {
    log
    yaegi {/plugins/slok.go }
    forward . 1.1.1.1
}

google.com {
    log
    errors
    forward . 1.1.1.1
}

twitter.com {
    log
    yaegi { ./twitter.go }
    forward . 8.8.8.8
}

. {
    forward . 8.8.8.8
    log
    yaegi { https://example.com/generic.go }
    errors
    cache
}

Ready to use image

You can build you own coreDNS image and set this plugin using CoreDNS docs, however we provide a CoreDNS image that has the yaegi plugin ready to be used:

docker pull ghcr.io/slok/coredns-yaegi

Example

Let's load our example allowlist plugin directly from an URL file.

$ cat ./coredns.config
. {
    yaegi { https://raw.githubusercontent.com/slok/coredns-yaegi/main/_examples/allowlist/plugin.go }
    forward . 1.1.1.1
}

$ docker run --rm -it --network host \
    -v ${PWD}/coredns.config:/tmp/coredns.config \
    ghcr.io/slok/coredns-yaegi:2620714c574e80582ff0072086acbc6c53072d08 \
    --conf /tmp/coredns.config  -dns.port=1053

$ dig @localhost -p 1053 a github.com +short
$ dig @localhost -p 1053 a google.com +short
$ dig @localhost -p 1053 a xabi.dev +short
172.67.193.60
104.21.20.171

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ConfigParse

func ConfigParse(c *caddy.Controller) (pluginsSrc []string, err error)

Types

type CoreDNSPlugin

type CoreDNSPlugin struct {
	// contains filtered or unexported fields
}

func NewCoreDNSPlugin

func NewCoreDNSPlugin(config CoreDNSPluginConfig) (*CoreDNSPlugin, error)

func (CoreDNSPlugin) Name

func (c CoreDNSPlugin) Name() string

func (CoreDNSPlugin) Ready

func (c CoreDNSPlugin) Ready() bool

func (CoreDNSPlugin) ServeDNS

func (c CoreDNSPlugin) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error)

type CoreDNSPluginConfig

type CoreDNSPluginConfig struct {
	NextPlugin corednsplugin.Handler
	PluginsSrc string
}

Directories

Path Synopsis
_examples
internal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL