The IP Set plugin in lazydns supports IP address and CIDR network matching for IP-based filtering rules. This document describes the complete IP matching rule system.
# Load an IP list file
- name: ip_set
tag: whitelist
args:
files:
- whitelist-ips.txt
# With auto-reload for dynamic updates
- name: ip_set
tag: blacklist
args:
files:
- blacklist-ips.txt
auto_reload: true
# Comments start with #
# This is a comment
# Single IPv4 address
192.168.1.1
# IPv4 CIDR network
192.168.0.0/16
10.0.0.0/8
172.16.0.0/12
# Single IPv6 address
2001:db8::1
# IPv6 CIDR network
2001:db8::/32
fe80::/10
# Empty lines are ignored
192.168.1.1 # Single host
8.8.8.8 # Google Public DNS
1.1.1.1 # Cloudflare DNS
127.0.0.1 # Localhost
Single addresses are automatically converted to /32 CIDR notation for internal matching.
192.168.0.0/16 # Class B private network (65,536 hosts)
10.0.0.0/8 # Class A private network (16,777,216 hosts)
172.16.0.0/12 # Class B private network (1,048,576 hosts)
8.8.8.0/24 # Subnet with 256 hosts
192.168.1.128/25 # Subnet with 128 hosts
2001:db8::1 # Single host
::1 # Localhost
fe80::1 # Link-local address
Single addresses are automatically converted to /128 CIDR notation for internal matching.
2001:db8::/32 # Typical allocation (2^96 addresses)
fe80::/10 # Link-local addresses
ff00::/8 # Multicast addresses
::/0 # Entire IPv6 address space (rarely used)
2001:db8:1234::/48 # Subnet allocation
- name: ip_set
tag: whitelist
args:
files:
- whitelist-ips.txt
Loads all IP addresses and CIDR ranges from the file.
- name: ip_set
tag: combined
args:
files:
- trusted-networks.txt
- partner-ips.txt
- cdn-networks.txt
auto_reload: true
Combines rules from multiple files with automatic reloading.
You can specify IP rules inline using the ips parameter instead of external files:
Single IP (string format):
- name: ip_set
tag: local
args:
ips: "192.168.1.0/24"
Multiple IPs (array format):
- name: ip_set
tag: trusted
args:
ips:
- "192.168.1.0/24"
- "10.0.0.0/8"
- "2001:db8::/32"
- "127.0.0.1"
Mixed files and inline addresses:
- name: ip_set
tag: comprehensive
args:
files:
- network-ranges.txt
ips:
- "192.168.0.0/16"
- "10.0.0.0/8"
- "172.16.0.0/12"
auto_reload: true
The ips parameter supports:
192.168.0.0/24)# Private networks
10.0.0.0/8
172.16.0.0/12
192.168.0.0/16
# Link-local and loopback
127.0.0.1
::1
# Data center and cloud providers
13.107.0.0/16 # Microsoft
34.64.0.0/10 # Google Cloud
18.0.0.0/7 # AWS
# Specific services
8.8.8.8 # Google DNS
1.1.1.1 # Cloudflare DNS
8.8.4.4 # Google DNS secondary
# IPv6 examples
2001:4860:4860::8888 # Google Public DNS
2606:4700:4700::1111 # Cloudflare DNS
fe80::/10 # Link-local
IP addresses are matched against CIDR networks using network containment logic:
Rule: 192.168.0.0/24
192.168.0.0 → ✓ Match (network address)
192.168.0.1 → ✓ Match
192.168.0.128 → ✓ Match
192.168.0.255 → ✓ Match (broadcast address)
192.168.1.0 → ✗ No match (different network)
192.167.255.255 → ✗ No match
Rule: 10.0.0.0/8 (16,777,216 addresses)
10.0.0.0 → ✓ Match
10.1.2.3 → ✓ Match
10.255.255.255 → ✓ Match
11.0.0.0 → ✗ No match
Single addresses are treated as /32 (IPv4) or /128 (IPv6) networks:
Rule: 192.168.1.100 (stored internally as 192.168.1.100/32)
192.168.1.100 → ✓ Match (exact)
192.168.1.101 → ✗ No match
192.168.1.99 → ✗ No match
Both IPv4 and IPv6 rules can coexist in the same IP Set:
- name: ip_set
tag: dual_stack
args:
files:
- dual-stack-networks.txt
File contents:
# IPv4 private ranges
10.0.0.0/8
172.16.0.0/12
192.168.0.0/16
# IPv6 private ranges
fd00::/7
fe80::/10
# Single addresses
8.8.8.8
2001:4860:4860::8888
The plugin automatically detects and handles both address families.
Network lookup: O(n)
Where n = number of CIDR rules
Matching algorithm: Linear scan of all networks
No optimization for sorted/indexed lookups
Typical query times:
IPv4 networks: ~12 bytes each
IPv6 networks: ~20 bytes each
Single IPs stored as /32 or /128
Memory per 10,000 networks:
name: ip_set tag: private args: ips: - “10.0.0.0/8” - “172.16.0.0/12” - “192.168.0.0/16”
name: ip_set tag: public_cdn args: ips: - “8.8.8.0/24” - “1.1.1.0/24” ```
# Example file structure
trusted-networks.txt:
- 10.0.0.0/8 # Internal corporate
- 192.168.0.0/16 # Office locations
partner-ips.txt:
- 203.0.113.0/24 # Partner A
- 198.51.100.0/24 # Partner B
Problem: Expected IP to match but it doesn’t
Common causes:
ips:
ips:
ips:
ips:
10.0.0.0/24 matches 10.0.0.1 through 10.0.0.25410.0.0.255 is technically in the network but not always matched depending on kernelProblem: Rules not loading from file
Check:
Problem: DNS queries are slow with IP Set plugin
Solutions:
- name: ip_set
tag: <unique-identifier>
args:
files: # Optional: list of files to load
- path/to/file1.txt
- path/to/file2.txt
ips: # Optional: inline IP addresses/networks
- "192.168.0.0/24"
- "10.0.0.0/8"
- "127.0.0.1"
- "::1"
auto_reload: true # Optional: auto-reload files (default: false)
# auto_reload interval: ~200ms (not configurable)
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
tag |
string | Yes | - | Unique plugin identifier |
files |
array | No | empty | File paths containing IP rules |
ips |
array/string | No | empty | Inline IP addresses or networks |
auto_reload |
bool | No | false | Auto-reload files on change |
All IP Set plugin operations return a boolean:
true → IP is in the matched set
false → IP is not in the set
Allow only specific networks:
- name: ip_set
tag: whitelist
args:
ips:
- "10.0.0.0/8" # Internal
- "203.0.113.0/24" # Partner
Deny specific networks:
- name: ip_set
tag: blacklist
args:
files:
- blocked-ranges.txt
ips:
- "192.0.2.0/24" # Malicious actor
Match against CDN provider networks:
- name: ip_set
tag: cdn_networks
args:
files:
- cdn-ip-ranges.txt # Updated regularly
auto_reload: true
Combined with other plugins to filter by region (basic approach):
- name: ip_set
tag: china_ips
args:
files:
- china-ip-ranges.txt
auto_reload: true
Allow traffic from specific regions only:
- name: ip_set
tag: allowed_regions
args:
ips:
- "198.51.100.0/24" # US region
- "203.0.113.0/24" # EU region
- "192.0.2.0/24" # APAC region