Skip to content

feat(bpf): implement allow_dns program#43

Open
leodido wants to merge 5 commits intofeat/allow-portfrom
feat/allow-dns
Open

feat(bpf): implement allow_dns program#43
leodido wants to merge 5 commits intofeat/allow-portfrom
feat/allow-dns

Conversation

@leodido
Copy link
Copy Markdown
Owner

@leodido leodido commented Apr 26, 2026

Description

Drops DNS packets (UDP/TCP port 53) not destined for the input resolver IP address. Non-DNS traffic passes through unaffected.

Intended for agent quarantine: restrict DNS resolution to a controlled resolver without affecting other traffic. The agent's resolv.conf should point to the approved resolver; this program enforces that no DNS escapes to unauthorized resolvers.

Depends on #42 (allow_port) → #41 (allow_ip).

Commits

  1. feat(bpf): implement allow_dns program — BPF program, api.lua registration, input_parse.h wiring
  2. test(bpf): add allow_dns tests — 7 new tests (50 total)
  3. docs: add allow_dns to built-in programs — README.txt, docs/README.md

How to test

xmake clean -a
xmake f --generate-vmlinux=y
xmake
sudo XMAKE_ROOT=y xmake run test

All 50 tests pass (43 from PR #42 + 7 new).

Design notes

  • DNS is identified by dest port 53 (both UDP and TCP)
  • Does NOT cover DNS-over-HTTPS (port 443) or DNS-over-TLS (port 853) — those need separate blocking via allow_port or block_port in a chain
  • Uses the same ip input field type as allow_ip and block_ip

@leodido leodido self-assigned this Apr 26, 2026
@leodido leodido changed the title feat(bpf): implement allow_dns program feat(bpf): implement allow_dns program Apr 26, 2026
@leodido leodido marked this pull request as ready for review April 27, 2026 11:30
@leodido leodido requested a review from fntlnz April 28, 2026 09:32
Copy link
Copy Markdown
Collaborator

@fntlnz fntlnz left a comment

Choose a reason for hiding this comment

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

almost the same comments as the other ones

Comment thread bpf/allow_dns.bpf.c Outdated
}

struct iphdr *ip_header = data + l3_offset;
const int l4_offset = l3_offset + sizeof(*ip_header);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

not sure this is right in this pr as well

Comment thread bpf/allow_dns.bpf.c Outdated
return TC_ACT_OK;
}

if (ip_is_fragment(skb, l3_offset))
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

ditto

@leodido leodido force-pushed the feat/allow-port branch from cf84def to 4bd31ad Compare May 3, 2026 20:44
@leodido leodido force-pushed the feat/allow-port branch from 75076e2 to fd418f7 Compare May 3, 2026 22:37
@leodido leodido changed the base branch from feat/allow-port to main May 3, 2026 22:47
leodido and others added 4 commits May 4, 2026 00:37
Drops DNS packets (UDP/TCP port 53) not destined for the input
resolver IP address. Non-DNS traffic passes through unaffected.

Intended for agent quarantine: restrict DNS resolution to a
controlled resolver without affecting other traffic.

Co-authored-by: Ona <no-reply@ona.com>
CLI functional: permits DNS to approved resolver, blocks DNS to other
resolvers, does not block non-DNS traffic. CLI flags: missing input,
invalid IP. CNI functional: allow_dns via JSON config. CNI flags:
missing input rejected.

7 new tests (50 total).

Co-authored-by: Ona <no-reply@ona.com>
Co-authored-by: Ona <no-reply@ona.com>
…ry checks

- Use IHL field for dynamic IP header length instead of fixed sizeof(iphdr)
- Validate IHL >= 5 and bounds-check the full IP header
- Drop subsequent fragments (no L4 headers to verify)
- Fail-closed (TC_ACT_SHOT) on all boundary check failures
- Document passthroughs: non-IPv4, non-TCP/UDP, and non-DNS traffic passes through

Co-authored-by: Ona <no-reply@ona.com>
@leodido leodido changed the base branch from main to feat/allow-port May 4, 2026 00:42
@leodido leodido requested a review from fntlnz May 4, 2026 09:51
The allow_dns CNI test uses python3 for a TCP socket listener on
port 53. The Arch Linux container image does not include python
by default, causing the test to fail with 'python3: command not found'.

Co-authored-by: Ona <no-reply@ona.com>
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