I'm using NEPacketTunnelProvider to intercept DNS queries, forward them upstream,
and inject the responses back via writePacketObjects().
This works correctly for responses under ~500 bytes. For larger responses (~893
bytes, e.g. DNS CERT records), writePacketObjects() returns without error but
mDNSResponder never receives the packet — it retries 3–4 times and then times out.
What I have verified:
- IP and UDP checksums are correct
- UDP length and IP total length fields are correct
- Maximum packet size (MTU) set to 1500 in NEIPv4Settings/NEIPv6Settings
Approaches tried:
- Injecting the full 921-byte packet — writePacketObjects() succeeds but the packet never reaches mDNSResponder
- IP-level fragmentation — fragments appear to be silently dropped
- Setting the TC (truncation) bit — mDNSResponder does not retry over TCP
- Truncating the response to ≤512 bytes — the packet arrives but the data is incomplete
Questions:
- Is there a supported way to deliver a DNS response larger than 512 bytes through NEPacketTunnelFlow?
- Does NEPacketTunnelProvider impose an undocumented packet size limit below the configured MTU?
- Does mDNSResponder silently discard responses larger than 512 bytes when the original query had no EDNS0 OPT record? Is there a way to signal that larger responses are supported?
- Are IP-level fragments reliably delivered through writePacketObjects()?
Tested on iOS 26.3, physical device.