Skip to content

Adds delegation checker#1174

Open
nils-wisiol wants to merge 7 commits intomainfrom
20260110_delegation_checker
Open

Adds delegation checker#1174
nils-wisiol wants to merge 7 commits intomainfrom
20260110_delegation_checker

Conversation

@nils-wisiol
Copy link
Copy Markdown
Contributor

  • periodically checks delegation status of all domains
  • implements limits on insecure domains per user
  • sets default limit to unlimited
  • updates the UI to show the detected delegation status
  • updates the UI to allow triggering of the delegation check for a given domain

delegation checker run times on my laptop on a 1000 domains sample (5 repeats):

Threads Mean (s) Stdev (s) Speedup vs 1x 100k extrapolation
1 178.07 21.53 1.00x ~296.8 min (4.95 h)
10 39.12 13.79 4.55x ~65.2 min (1.09 h)
20 33.20 8.06 5.36x ~55.3 min (0.92 h)
50 23.89 6.38 7.46x ~39.8 min (0.66 h)
100 26.10 6.14 6.82x ~43.5 min (0.73 h)
200 27.16 6.15 6.55x ~45.3 min (0.75 h)

The delegation checker is not comparing keys against nslord to avoid making many requests to nslord.

nils-wisiol and others added 7 commits January 10, 2026 12:00
AI-assisted changes.

I played with everything I could think of on the website:

    direct debit donation
    account creation, login, 2fa enabled, change email, delete account
    domain list, filtering
    rrset creation and deletion
    scrolled through all pages of the web site
Copy link
Copy Markdown
Contributor Author

@nils-wisiol nils-wisiol left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

review of the first commit

CELERY_EMAIL_MESSAGE_EXTRA_ATTRIBUTES = ["connection"]

LIMIT_USER_DOMAIN_COUNT_DEFAULT = 15
LIMIT_USER_DOMAIN_COUNT_DEFAULT = None
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should stay 15

)
REGISTER_LPS = bool(int(os.environ.get("DESECSTACK_API_REGISTER_LPS", "1")))
_delegation_recheck_raw = os.environ.get(
"DESECSTACK_API_DELEGATION_SECURE_RECHECK_HOURS", "24"
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's the purpose of this? In crontab, we set it to every half hour

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This determines if a domain is skipped by the CLI command or not, not how often the command is run


# Compute overlap of delegation NS hostnames and IP addresses with ours
ns_intersection = self.our_ns_set & {name.target for name in answer}
update["has_all_nameservers"] = ns_intersection == self.our_ns_set
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't we want to compute if all desec nameservers are in here? This looks like it computes the check if all nameservers given in NS records are there.

has_ds = False
# AD bit indicates the resolver validated the DS answer.
authenticated = bool(res.flags & dns.flags.AD)
update["is_secured"] = bool(has_ds and authenticated)
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this computes if the parent zone is correctly signed. We should test for intersection/equality of DS sets, no? Or perhaps successful authentication of the SOA record of domain_name?


def get_insecure_delegated_domains(self, obj):
return obj.domains.filter(is_registered=True, is_delegated=True).exclude(
is_secured=True
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this includes undelegated 'toy' domains, so they count towards the limit - do we want that?

self.assertContains(
response,
"Insecure delegation limit",
status_code=status.HTTP_403_FORBIDDEN,
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be accepted as the domain is guaranteed to be delegated securely and thus shouldn't count towards the insecure domain limit

self.assertContains(
response,
"Insecure delegation limit",
status_code=status.HTTP_403_FORBIDDEN,
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comment as above

insecure_count = request.user.domains.filter(
is_registered=True, is_delegated=True
).exclude(is_secured=True).count()
return insecure_count < limit
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

grant permission if the domain in question is an autodelegation domain


The API does not change or delete domains based on these checks. However, if
you have at least one domain delegated to deSEC without DNSSEC, you cannot
create additional domains until that domain is secured.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rephrase to accurately reflect limit policy

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants