Unbound python code errors

I am trying to run some python code to dynamically update nftables sets of IPs from selected domains. The domains IPs change so setting static IPs will not do.

included packages:
unbound-1.26.1-1
python3-unbound-1.26.1-1
python3-3.14.8-1

/etc/unbound/unbound.conf (among other thing)

server:
    module-config: "validator python iterator"

python:
    python-script: "/etc/unbound/nft_container_domains.py"

/etc/unbound/nft_container_domains.py

import unbound
import os

# Define the domains you want to allowlist
ALLOWLIST = [
    "docker.io.",
    "ghcr.io.",
    "lscr.io."
]

def init(id, cfg):
    return True

def deinit(id):
    return True

def inform_super(id, qstate, superqstate):
    return True

def operate(id, event, qstate, qdata):
    if event == unboundmod.MODULE_EVENT_NEW or event == unboundmod.MODULE_EVENT_PASS:

        # Check if the query has a valid response and in allowlist
        if qstate.return_msg and qstate.return_msg.rep:
            reply = qstate.return_msg.rep
            
            # Loop through answer records
            for i in range(reply.an_numrrsets):
                rrset = reply.rrsets[i]
                rk = rrset.rk
                
                # Check for A (IPv4) or AAAA (IPv6) records
                if rk.type_str in ["A", "AAAA"]:
                    data = rrset.entry.data

                    # Loop through all returned IP blocks
                    for j in range(data.num):

                        # Extract the raw IP byte string (skip first 2 bytes length data)
                        raw_ip = data.data[j][2:]
                        
                        # Format bytes into readable IP string
                        if rk.type_str == "A":
                            ip_str = ".".join(str(b) for b in raw_ip)
                        else:
                            ip_str = ":".join(f"{raw_ip[m]:02x}{raw_ip[m+1]:02x}" for m in range(0, len(raw_ip), 2))
                        
                        # Push dynamically to an online nftables set named 'container_domains'
                        try:
                            subprocess.run(["nft", "add", "element", "ip", "filter", "container_domains", f"{{ {ip_str} }}"], check=True)
                        except Exception:
                            pass # Handle or log system execution errors here

    qstate.ext_state[id] = unboundmod.MODULE_TYPE_SETRESULT
    return True

I’m getting errors:

unbound[1983]: [1983:3] error: pythonmod: Exception occurred in function operate, event: module_event_pass

unbound[1983]: [1983:3] error: pythonmod: cannot print exception, cannot ImportModule cStringIO or StringIO or io

I know I have to put in a check for allowlist. But how can I fix the errors? Is this python2 vs python3 code? This unbound-user mailing list looks dead.

Thanks for help.

No.

You need to track down where this error is coming from.

This could be, have a look here. An article when the version 2 to 3 change has been discussed:

From Python 3.0 changelog:

The StringIO and cStringIO modules are gone. Instead, import the io module and use io.StringIO or io.BytesIO for text and data respectively.

From the Python 3 email documentation it can be seen that io.StringIO should be used instead:

from io import StringIO
from email.generator import Generator

fp = StringIO()
g = Generator(fp, mangle_from_=True, maxheaderlen=60)
g.flatten(msg)
text = fp.getvalue()

Source  https://stackoverflow.com/questions/28200366/python-3-x-importerror-no-module-named-cstringio```

Use module io.stringIO instead of cStringIO

Fedora has not shipped anything that uses python2 for a long time.

If the code is not from Fedora that you are right it looks like code that was not ported in python3.