preload cachedb redis backend using python

dear all

I use cachedb with redis backend.

try to preload redis using python.

import dns.message
import dns.rcode
import dns.flags
import struct
import time
import redis

def make_minimal_nxdomain(domain: str) -> bytes:
q = dns.message.make_query(domain, 'A')
r = dns.message.make_response(q)
r.set_rcode(dns.rcode.NXDOMAIN)
r.flags |= dns.flags.QR
r.flags |= dns.flags.AA
r.flags &= ~dns.flags.RD # Clear RD
r.flags &= ~dns.flags.RA # Clear RA
r.answer = []
wire = r.to_wire()

now = int(time.time())
wire += struct.pack('>QQ', now, now + 31536000) # 1 year
return wire

def make_key(domain: str, qtype: int = 1, qclass: int = 1, secret_seed: str = "mysecretseed2025") -> str:
"""
Generate Redis key using SHA256(secret_seed + wire_name + qtype + qclass)
"""
import hashlib
import struct

if not domain.endswith('.'):
domain += '.'
labels = domain.rstrip('.').split('.')
wire = b''.join(bytes([len(label)]) + label.encode() for label in labels) + b'\x00'
qtype_n = struct.pack('!H', qtype)
qclass_n = struct.pack('!H', qclass)
data = wire + qtype_n + qclass_n + secret_seed.encode()
return hashlib.sha256(data).hexdigest().upper()

if __name__ == '__main__':
# Test domain
domain = "[tulisan.nggonku.xyz](http://tulisan.nggonku.xyz)"

# Generate NXDOMAIN response
response_wire = make_minimal_nxdomain(domain)
print(f"Generated NXDOMAIN response for {domain}, {len(response_wire)} bytes")

# Generate Redis key
key = make_key(domain)
print(f"Redis key: {key}")

# Connect to Redis
r = redis.Redis(host='127.0.0.1', port=6379, db=0, decode_responses=False)

# Set in Redis
r.set(key, response_wire)
print(f"Loaded into Redis: {key}")

# Optional: Verify
print("\nVerifying from Redis...")
retrieved = r.get(key)
if retrieved:
print(f"Retrieved {len(retrieved)} bytes")
timestamp, expiry = struct.unpack('>QQ', retrieved[-16:])
print(f"Timestamp: {time.ctime(timestamp)}")
print(f"Expiry: {time.ctime(expiry)}")
else:
print("Not found in Redis")

When I dig for my domain name (dig @127.0.0.1 tulisan.nggonku.xyz) , I got this from unbound debug

Sep 10 17:22:05 unbound unbound[25748]: [25748:0] info: 127.0.0.1 [tulisan.nggonku.xyz](http://tulisan.nggonku.xyz). A IN
Sep 10 17:22:05 unbound unbound[25748]: [25748:0] debug: udp request from ip4 127.0.0.1 port 41514 (len 16)
Sep 10 17:22:05 unbound unbound[25748]: [25748:0] debug: mesh_run: start
Sep 10 17:22:05 unbound unbound[25748]: [25748:0] debug: cachedb[module 0] operate: extstate:module_state_initial event:module_event_new
Sep 10 17:22:05 unbound unbound[25748]: [25748:0] debug: redis_lookup of BE0C12BF95D4BA92F06B0F3291977F068DE61AD2161DB013AAC4A6B999877A02
Sep 10 17:22:05 unbound unbound[25748]: [25748:0] debug: redis_lookup found 53 bytes
Sep 10 17:22:05 unbound unbound[25748]: [25748:0] debug: cachedb msg expired
Sep 10 17:22:05 unbound unbound[25748]: [25748:0] debug: cachedb msg adjusted down by -1
Sep 10 17:22:05 unbound unbound[25748]: [25748:0] info: redis ;; ->>HEADER<<- opcode: QUERY, rcode: NXDOMAIN, id: 0
;; flags: qr aa ; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
[tulisan.nggonku.xyz](http://tulisan.nggonku.xyz). IN A

;; ANSWER SECTION:

;; AUTHORITY SECTION:

;; ADDITIONAL SECTION:
;; MSG SIZE rcvd: 37
Sep 10 17:22:05 unbound unbound[25748]: [25748:0] debug: mesh_run: cachedb module exit state is module_wait_module
Sep 10 17:22:05 unbound unbound[25748]: [25748:0] debug: validator[module 1] operate: extstate:module_state_initial event:module_event_pass
Sep 10 17:22:05 unbound unbound[25748]: [25748:0] info: validator operate: query [tulisan.nggonku.xyz](http://tulisan.nggonku.xyz). A IN
Sep 10 17:22:05 unbound unbound[25748]: [25748:0] debug: validator: pass to next module
Sep 10 17:22:05 unbound unbound[25748]: [25748:0] debug: mesh_run: validator module exit state is module_wait_module
Sep 10 17:22:05 unbound unbound[25748]: [25748:0] debug: iterator[module 2] operate: extstate:module_state_initial event:module_event_pass
Sep 10 17:22:05 unbound unbound[25748]: [25748:0] debug: process_request: new external request event
Sep 10 17:22:05 unbound unbound[25748]: [25748:0] debug: iter_handle processing q with state INIT REQUEST STATE
Sep 10 17:22:05 unbound unbound[25748]: [25748:0] info: resolving [tulisan.nggonku.xyz](http://tulisan.nggonku.xyz). A IN

Looks like the message “content” is right, but timestamp/ttl/expiry is wrong.
How to write good wire message?

-wowon-