nftsync

package module
v0.3.1 Latest Latest
Warning

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

Go to latest
Published: Mar 19, 2026 License: Apache-2.0 Imports: 19 Imported by: 0

README

Build Status

What is this

This is an unofficial plugin for CoreDNS.

Name

nftsync - synchronizes dns and nftables sets.

Description

nftsync inspects DNS responses and adds the resolved IP addresses to a specified nftset. It is designed to bridge the gap between DNS resolution and firewall dynamic filtering.

Syntax

nftsync [debug] FAMILY TABLE_NAME [MINTTL] {
        sync host|tree NAME IPv4_SET_NAME IPv6_SET_NAME
}
  • debug will mocks Netlink socket to fake connection. It also records the operation it attempted to perform to stdout. It simulates the presence of the following nftables configuration.
  table inet t {
          set s4 {
                  type ipv4_addr
                  flags dynamic,timeout
          }

          set s6 {
                  type ipv6_addr
                  flags dynamic,timeout
          }

          // This set exists at startup
          // but always behaves as if it fails when updating elements.
          set e {
                  type ipv4_addr
                  flags dynamic,timeout
          }
  }
  • FAMILY and TABLE_NAME are the nftables table and its family containing the target sets.

  • MINTTL - determines the minimum timeout value of the IP elements. The default is 5 seconds, which is the minTTL of the cache plugin. (In other words, by default, IP addresses are retained in the set for at least 5 seconds.)
    If this value is set shorter than cache plugin's minTTL, you will be unable to update set using the query response until the cache entry expires. Therefore, we recommend setting a value equal to or greater than the minimum minTTL specified in the cache plugin configuration.

  • sync - qname of a request, or a name used in a CNAME contained within RRs, matches the NAME, add the result of the A record to IPv4_SET_NAME and the result of the AAAA record to IPv6_SET_NAME.

    • When adding query results to a nftset, the Timeout/Expires parameters of the set elements are updated atomically via Netlink socket. These parameters will be set to values that include a small margin (5 seconds) added to the entry's TTL.
      Elements are only removed by Expires. When a query resolves, old IPs are not explicitly cleared.
      Note: Results returned in the additional section are not processed by nftsync.
  • host|tree - when you want to target all leaves of NAME (if specifying each hostname individually is cumbersome), using tree will target all subdomains.

You can declare as many syncs consecutively as you like.

Metrics

If monitoring is enabled (via the prometheus plugin) then the following metrics are exported:

  • coredns_nftsync_update_failure_count_total{"server", "zone", "view", "name"} - Counter for the number of failed updates to ip elements.
    If this value is increasing, it is likely that set operations failed due to factors such as the set being deleted after the CoreDNS startup.

Examples

In this configration, nftsync adds the IP address to set s4/s6 when a response related to example.org is returned.
This setting applies not only to example.org. but also to subdomains such as sub.example.org.

. {
        forward . 9.9.9.9
        nftsync inet t {
                sync tree example.org s4 s6
        }
}

At this point, the nftables configuration looks like this:

table inet t {
        set s4 {
                type ipv4_addr
                flags dynamic,timeout
                // It will be added when name resolution occurs.
                + elements = { 104.18.26.120 timeout 1m36s expires 1m34s576ms, ... }
        }

        set s6 {
                type ipv6_addr
                flags dynamic,timeout
        }
}

Considerations

  1. Only works on Linux
  2. Requires POSIX capabilities for Netlink
  3. I recommend placing nftsync after cache
  4. Currently, it is not possible to specify a particular namespace.

Regarding the possibility of race conditions

When used in combination with plugins such as view, individual query and nftsync blocks may cause race conditions regarding the timeout parameter for the same nftset.
The following settings are recommended:

  • one set pair(IPv4/IPv6) per domain name
  • Avoid using the EXACTLY THE SAME domain name settings across multiple query routings
    (When the destination is AD or similar and the resolved domain name is local, duplicates are allowed, but use a different set pair.)

Documentation

Index

Constants

View Source
const (
	TimeoutOffset uint32 = 5
)

Variables

This section is empty.

Functions

This section is empty.

Types

type Flag

type Flag string

type NetlinkConn

type NetlinkConn interface {
	ListTableOfFamily(name string, family nftables.TableFamily) (*nftables.Table, error)
	GetSetByName(t *nftables.Table, name string) (*nftables.Set, error)
	SetDestroyElements(s *nftables.Set, vals []nftables.SetElement) error
	SetAddElements(s *nftables.Set, vals []nftables.SetElement) error
	Flush() error
}

NetlinkConn consists of the Netlink socket operations required by nftsync.

func NewConnector

func NewConnector() (NetlinkConn, error)

type NetlinkFake

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

NetlinkFake implements NetlinkConn.

func NewNetlinkFake

func NewNetlinkFake() *NetlinkFake

func (*NetlinkFake) Flush

func (n *NetlinkFake) Flush() error

func (*NetlinkFake) GetSetByName

func (n *NetlinkFake) GetSetByName(t *nft.Table, name string) (*nft.Set, error)

func (*NetlinkFake) ListTableOfFamily

func (n *NetlinkFake) ListTableOfFamily(name string, family nft.TableFamily) (*nft.Table, error)

func (*NetlinkFake) SetAddElements

func (n *NetlinkFake) SetAddElements(s *nft.Set, vals []nft.SetElement) error

func (*NetlinkFake) SetDestroyElements

func (n *NetlinkFake) SetDestroyElements(s *nft.Set, vals []nft.SetElement) error

func (*NetlinkFake) String

func (n *NetlinkFake) String() string

String implements Stringer.

type NftSync

type NftSync struct {
	Next plugin.Handler
	// contains filtered or unexported fields
}

NftSync is a plugin that synchronizes dns and nftables set.

func NewNftSync

func NewNftSync() *NftSync

NewNftSync returns an initialized NftSync with default settings. It's up to the caller to set the Next handler.

func NftSyncParse

func NftSyncParse(c *caddy.Controller) (*NftSync, error)

func (*NftSync) Name

func (n *NftSync) Name() string

Name implements plugin.Handler.

func (*NftSync) ServeDNS

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

ServeDNS implements plugin.Handler.

func (*NftSync) SetConn

func (n *NftSync) SetConn(c NetlinkConn)

SetConn injects connection to NftSync.

func (*NftSync) SetTree

func (n *NftSync) SetTree(t Tree)

SetTree injects tree to NftSync.

type ResponseWriter

type ResponseWriter struct {
	dns.ResponseWriter
	*NftSync
	// contains filtered or unexported fields
}

ResponseWriter observes the RRs and adds the results to nftset via netlink conn.

func NewResponseWriter

func NewResponseWriter(srv string, w dns.ResponseWriter, n *NftSync, c context.Context) *ResponseWriter

NewResponseWriter returns a pointer to a new ResponseWriter

func (*ResponseWriter) WriteMsg

func (r *ResponseWriter) WriteMsg(res *dns.Msg) error

type Tree

type Tree interface {
	Search(string) []ipSet
	Build(map[string]ipSet)
}

Tree is an object that functions like a map linking domain names to sets. It will not be modified later. A new one will be created each time settings are changed.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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