ipsets fqdn resolving
Concept
- Use a Sqlite3 database to store the list of entries that need to be updated.
- A script run on an interval will perform lookups for each fqdn, no more frequent than the DNS record's TTL
next_lookup_dtis set after a lookup to the current time plus the lookup's ttl in secondsUPDATE entries SET last_lookup_dt = datetime('now'), next_lookup_dt = datetime('now', '+$ttl seconds') WHERE fqdn=$fqdn and ipset=$ipset;
- Query for a list of entries that need to be checked due to expired ttl of last lookup
SELECT * FROM entries WHERE next_lookup_dt <= datetime('now');
We have two options for dealing with changed IPs.
The first involves creating a new ipset, swapping it with the current in-memory set, and then destroying the old ipset.
The second involves locating and deleting the entry that needs to be updated.
Code
# CREATE the sqlite3 database and table(s)
sqlite3 /opt/ipsets-dynamic/ipsets-dynamic.db <<EOF
CREATE TABLE entries (
fqdn TEXT NOT NULL,
ipset TEXT NOT NULL,
last_ip_address TEXT,
last_lookup_dt DATETIME DEFAULT (datetime('now')),
next_lookup_dt DATETIME DEFAULT (datetime('now')),
last_change_dt DATETIME DEFAULT (datetime('now')),
added DATETIME DEFAULT (datetime('now')),
comment TEXT,
PRIMARY KEY (fqdn, ipset)
);
EOF
Example
Assuming the ipset list exists as below:
ipset list unifisiteallowlist -output json | grep -v initval
# OUTPUT
[
{
"name" : "unifisiteallowlist",
"type" : "hash:net",
"revision" : 7,
"header" : {
"family" : "inet",
"hashsize" : 1024,
"maxelem" : 65536,
"comment" : true,
"bucketsize" : 12,
"memsize" : 1800,
"references" : 1,
"numentries" : 10
},
"members" : [
{
"elem" : "1.2.3.4",
"comment" : "resolve:some-fqdn.domain.com"
},
]
}
]
ipset list unifisiteallowlist -output json | grep -v initval | jq '.[].members[] | select(.comment | contains("resolve:some-fqdn.domain.com")) | .elem'
# OUTPUT
"1.2.3.4"