/DDNS allowlist

DDNS allowlist

1
v1.6.2

DDNS allowlist - Traefik plugin

Dynamic DNS allowlist plugin for Traefik: Add your dynamic hostname (your homenetwork router) to the allow list.

Have a look at the official Traefik Plugin Catalog. We would love if you leave a star on this repository.

About

The ddns-allowlist plugin for Traefik allows you to add dynamic DNS (DDNS) hosts to the allowed requesters. Requests from IP addresses that do not resolve to the specified DDNS hosts will be denied. You might also know this as whitelist instead of allowlist.

The initial idea is that you can add your home router with a floating (non-static) IP address to an allowed list of addresses. You are not limited to your DDNS supporting router - you can add any host you like. If you want so it is more likely a hostname allowlist.

The basic concept is to periodically resolve the hostname to an IP address and add it to the allowlist. Because server typically have a static IP, you should add its static IPs to the allowlist (sourceRangeIps).

:warning: IPv6 is supported but e.g. with FritzBox router you maybe have some issues because the IPv6 address your router provides is not the same as the network prefix of your network.

Installation

The installation of a Traefik plugin is pretty simple. To install the ddns-allowlist plugin follow one of the following methods.

Traefik CLI

First way to add the plugin is to add the following CLI options to your Traefik setup:

--experimental.plugins.ddns-allowlist.modulename=github.com/taskmedia/ddns-allowlist
--experimental.plugins.ddns-allowlist.version=v1.6.1

yaml / Traefik Helm chart

Another way to add the plugin is to add the following configuration to your Traefik static configuration / Helm chart:

experimental:
plugins:
ddns-allowlist:
moduleName: "github.com/taskmedia/ddns-allowlist"
version: v1.6.1

Configuration

You also need to create a middleware and add it to one of your routes. There are multiple ways to do this - this document will show you how to configure the plugin with dynamic configuration and Kubernetes CRD.

But first we will have a look about the configuration options available for the plugin.

Available options

Only mandatory option is sourceRangeHosts - all other options are optional.

  • sourceRangeHosts (required)
    Hosts to dynamically add to allowlist via DNS lookup
  • sourceRangeIps
    Additional IP addresses to add to allowlist
  • ipStrategy.*
    Strategy to determine the client IP address - see configurations below. If no strategy is specified (or value is zero), the plugin will use the RemoteAddr as default.
  • ipStrategy.cloudflareDepth
    Use Cloudflare headers (Cf-Connecting-Ip) to determine the client IP address. The cloudflareDepth option expects an integer to determ which IP address should be used (starting from the right).
  • ipStrategy.depth
    Use headers (X-Forwarded-For) to determine the client IP address. The depth option expects an integer to determ which IP address should be used (starting from the right).
  • ipStrategy.excludedIPs
    Will return the first IP address that is not in the excluded list (also uses X-Forwarded-For header).
  • rejectStatusCode
    Status code to return if the request is rejected (default: 403)
  • logLevel
    Log level for the plugin (allowed: ERROR, INFO, DEBUG, TRACE - default: ERROR)
  • lookupInterval
    Lookup interval for DNS hosts in seconds (default: 5 min)
  • allowedIPv6NetworkPrefix
    Allow any interface identifier based on given prefix from the looked up sourceRangeHosts IPv6 addresses (default: disabled)

Hint: You can only choose one of the ip strategy options. It is not possible to combine multiple. The strategies are similar to the one provided with middleware IPWhiteList.

Configuration examples

Dynamic configuration

Add the ddns-allowlist middleware to your Traefik dynamic configuration:

dynamic configuration
# Dynamic configuration
http:
routers:
my-router:
rule: host(`demo.localhost`)
service: service-foo
entryPoints:
- web
middlewares:
- ddns-allowlist-router
services:
service-foo:
loadBalancer:
servers:
- url: http://127.0.0.1:5000
middlewares:
ddns-allowlist-router:
plugin:
my-ddnswl:
# optional: log level for the plugin (allowed: ERROR, INFO, DEBUG, TRACE - default: ERROR)
logLevel: ERROR
# hosts to dynamically add to allowlist via DNS lookup
sourceRangeHosts:
- my.router.ddns.tld
# optional: IP addresses to allowlist
sourceRangeIps:
- 1.2.3.4
# optional: IP strategy to determine the client IP address (default: RemoteAddr)
# also see: https://doc.traefik.io/traefik/middlewares/http/ipwhitelist/#ipstrategy
ipStrategy:
depth: 1
cloudflareDepth: 1
excludedIPs:
- 4.3.2.1
# optional: allow IPv6 interface identifier based on given prefix
# this will skip the interface identifier validation (default: disabled)
allowedIPv6NetworkPrefix: 64
# optional: lookup interval for DNS hosts in seconds (default: 5 min)
lookupInterval: 60

Kubernetes CRD

Kubernetes CRD configuration
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: my-ddnswl
spec:
plugin:
ddns-allowlist:
sourceRangeHosts:
- my.router.ddns.tld
# see other options in dynamic configuration or in section 'Available options'

Also see more detailed in the examples section.

Examples

This section contains example configurations for the ddns-allowlist plugin. The examples are provided as in Kubernetes CRD but also can be defined in other formats. You need to expand the configuration example in each section on the triangle.

It shows different common configuration options. Keep note that the IP strategies can not be combined with each other.

The following examples are alphabetically sorted and not according to the frequency of use.

Allowed IPv6 network prefix

When using IPv6 your home router will report its full address to the DDNS provider. This address contains the network prefix and the interface identifier. When an device inside your network tries to access your service it will be rejected because the interface identifier is not the same as the one from your router. With this option you can allow any interface identifier based on the given prefix from the looked up sourceRangeHosts IPv6 addresses.

The common value used for that is 64. This is the common value which splits the address into network prefix and interface identifier. If your routers DNS lookup resolves in IP address aaaa:bbbb:cccc:dddd:1111:2222:3333:4444, the addresses in network aaaa:bbbb:cccc:dddd::/64 will be allowed.

example: Allowed IPv6 network prefix
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: ddnswl-dnsonly
spec:
plugin:
ddns-allowlist:
sourceRangeHosts:
- my.router.ddns.tld
allowedIPv6NetworkPrefix: 64

Cloudflare - DNS only

If you are using Cloudflare as DNS nameserver (without proxy), you need to use the default configuration using RemoteAddr (no IP strategy required in plugin config).

Also see RemoteAddr example.

example: Cloudflare - DNS only
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: ddnswl-cloudflare-dnsonly
spec:
plugin:
ddns-allowlist:
sourceRangeHosts:
- my.router.ddns.tld

Cloudflare - proxy

If you are using Cloudflare as DNS nameserver (with proxy), you need to get the IP address of the client from the Cf-Connecting-Ip header. Therefore use the cloudflareDepth configuration option.

Usually the header only contains one IP address - so you can use 1 as value. To ensure the same implementation as in ipStrategy.depth you are allowed to specify a higher value. But this configuration should not be necessary.

example: Cloudflare - proxy
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: ddnswl-cloudflare-proxy
spec:
plugin:
ddns-allowlist:
sourceRangeHosts:
- my.router.ddns.tld
ipStrategy:
cloudflareDepth: 1

Excluded IPs

If you want to get the client IP address from the X-Forwarded-For header but exclude some IPs from the list (eg. your reverse proxies), you can use the excludedIPs option. This will allow you to exclude some IPs from the list and return the first IP address that is not in the excluded list.

example: Excluded IPs
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: ddnswl-excludeips
spec:
plugin:
ddns-allowlist:
sourceRangeHosts:
- my.router.ddns.tld
ipStrategy:
excludedIPs:
- 1.2.3.4

Log level

If you want to see more logs from the plugin, you can set the log level to a more detailed level. The allowed values are ERROR (default), INFO, DEBUG, TRACE.

example: Log level
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: ddnswl-dnsonly
spec:
plugin:
ddns-allowlist:
sourceRangeHosts:
- my.router.ddns.tld
logLevel: DEBUG

Lookup interval

If you want to change the lookup interval for DNS hosts, you can set the lookupInterval option. The default value is 300 seconds (5 minutes).

The lookup will only happen if the middleware is triggered from a new client request.

example: Lookup interval
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: ddnswl-dnsonly
spec:
plugin:
ddns-allowlist:
sourceRangeHosts:
- my.router.ddns.tld
lookupInterval: 30 # seconds

Rejection code

If you feel more like a tea pot feel free to change the rejection code:

example: Rejection code
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: ddnswl-dnsonly
spec:
plugin:
ddns-allowlist:
sourceRangeHosts:
- my.router.ddns.tld
rejectStatusCode: 418

RemoteAddr

If you are not using any proxy in front of your Traefik instance, you can just use the RemoteAddr as default IP strategy. You only need to specify a host to be allowlisted.

example: RemoteAddr
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: ddnswl-dnsonly
spec:
plugin:
ddns-allowlist:
sourceRangeHosts:
- my.router.ddns.tld

Sourcerange IPs

If you want to add additional IP addresses to the allowlist (e.g. a server), you can use the sourceRangeIps option. This might also be interesting to add your static IPv6 address (network prefix).

You are not only able to add IPv4 addresses but also IPv6 addresses. Also it is possible to add an IP range (CIDR notation) to the list.

Keep note that you always need to specify a source range host.

example: Sourcerange IPs
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: ddnswl-dnsonly
spec:
plugin:
ddns-allowlist:
sourceRangeHosts:
- my.router.ddns.tld
sourceRangeIps:
- "1.2.3.4"
- "192.168.1.0/24"
- "2a02:aaaa:bbbb:cccc::/64"

X-Forwarded-For

If you are using a reverse proxy in front of your Traefik instance, you can use the X-Forwarded-For header to determine the client IP address. You can specify the depth of the IP address in the header to use. The default value is 1 and will select the first IP address from the header (position starting from the right).

You are not able to specify a depth of 0 - otherwise the RemoteAddr method (default) will be used.

example: X-Forwarded-For
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: ddnswl-dnsonly
spec:
plugin:
ddns-allowlist:
sourceRangeHosts:
- my.router.ddns.tld
ipStrategy:
depth: 1