return value;
}
- // check with Qtype 255 (*)
- qkey.qtype = 255;
+ // check with Qtype 65535 (*)
+ qkey.qtype = 65535;
return qnamefilter.lookup(&qkey);
}
from bcc import BPF
# Constants
-QTYPES = {'LOC': 29,
- '*': 255,
+QTYPES = {'*': 65535,
+ 'LOC': 29,
+ 'ANY': 255,
'IXFR': 251,
'UINFO': 100,
'NSEC3': 50,
struct QNameValue* qvalue = qnamefilter.lookup(&qkey);
if (qvalue &&
- (qvalue->qtype == 255 || qtype == qvalue->qtype)) {
+ (qvalue->qtype == 65535 || qtype == qvalue->qtype)) {
__sync_fetch_and_add(&qvalue->counter, 1);
return 0;
}
struct QNameValue* qvalue = qnamefilter.lookup(&qkey);
if (qvalue &&
- (qvalue->qtype == 255 || qtype == qvalue->qtype)) {
+ (qvalue->qtype == 65535 || qtype == qvalue->qtype)) {
__sync_fetch_and_add(&qvalue->counter, 1);
return 0;
}
void removeSocket(int sock);
void block(const ComboAddress& addr, MatchAction action);
void addRangeRule(const Netmask& address, bool force, BPFFilter::MatchAction action);
- void block(const DNSName& qname, MatchAction action, uint16_t qtype = 255);
+ void block(const DNSName& qname, MatchAction action, uint16_t qtype = 65535);
void unblock(const ComboAddress& addr);
void rmRangeRule(const Netmask& address);
- void unblock(const DNSName& qname, uint16_t qtype = 255);
+ void unblock(const DNSName& qname, uint16_t qtype = 65535);
std::vector<std::pair<ComboAddress, uint64_t>> getAddrStats();
std::vector<std::pair<Netmask, CounterAndActionValue>> getRangeRule();
BPF_MOV64_IMM(BPF_REG_7,2147483647),
BPF_JMP_IMM(BPF_JEQ,BPF_REG_0,0,7),
BPF_LDX_MEM(BPF_H,BPF_REG_1,BPF_REG_0,8),
-BPF_JMP_IMM(BPF_JEQ,BPF_REG_1,255,2),
+BPF_JMP_IMM(BPF_JEQ,BPF_REG_1,65535,2),
BPF_ALU64_IMM(BPF_AND,BPF_REG_6,65535),
BPF_JMP_REG(BPF_JNE,BPF_REG_1,BPF_REG_6,3),
BPF_MOV64_IMM(BPF_REG_1,1),
BPF_MOV64_IMM(BPF_REG_1,2147483647),
BPF_JMP_IMM(BPF_JEQ,BPF_REG_0,0,7),
BPF_LDX_MEM(BPF_H,BPF_REG_2,BPF_REG_0,8),
-BPF_JMP_IMM(BPF_JEQ,BPF_REG_2,255,2),
+BPF_JMP_IMM(BPF_JEQ,BPF_REG_2,65535,2),
BPF_ALU64_IMM(BPF_AND,BPF_REG_6,65535),
BPF_JMP_REG(BPF_JNE,BPF_REG_6,BPF_REG_2,3),
BPF_MOV64_IMM(BPF_REG_1,1),
luaCtx.registerFunction<void (std::shared_ptr<BPFFilter>::*)(const DNSName& qname, boost::optional<uint16_t> qtype, boost::optional<uint32_t> action)>("blockQName", [](const std::shared_ptr<BPFFilter>& bpf, const DNSName& qname, boost::optional<uint16_t> qtype, boost::optional<uint32_t> action) {
if (bpf) {
if (!action) {
- return bpf->block(qname, BPFFilter::MatchAction::Drop, qtype ? *qtype : 255);
+ return bpf->block(qname, BPFFilter::MatchAction::Drop, qtype ? *qtype : 65535);
}
BPFFilter::MatchAction match{};
default:
throw std::runtime_error("Unsupported action for BPFFilter::blockQName");
}
- return bpf->block(qname, match, qtype ? *qtype : 255);
+ return bpf->block(qname, match, qtype ? *qtype : 65535);
}
});
});
luaCtx.registerFunction<void (std::shared_ptr<BPFFilter>::*)(const DNSName& qname, boost::optional<uint16_t> qtype)>("unblockQName", [](const std::shared_ptr<BPFFilter>& bpf, const DNSName& qname, boost::optional<uint16_t> qtype) {
if (bpf) {
- return bpf->unblock(qname, qtype ? *qtype : 255);
+ return bpf->unblock(qname, qtype ? *qtype : 65535);
}
});
> bpf = newBPFFilter({ipv4MaxItems=1024, ipv6MaxItems=1024, qnamesMaxItems=1024})
> bpf:attachToAllBinds()
> bpf:block(newCA("2001:DB8::42"))
- > bpf:blockQName(newDNSName("evildomain.com"), 255)
+ > bpf:blockQName(newDNSName("evildomain.com"), 65535)
> bpf:getStats()
[2001:DB8::42]: 0
- evildomain.com. 255: 0
+ evildomain.com. 65535: 0
> bpf:unblock(newCA("2001:DB8::42"))
- > bpf:unblockQName(newDNSName("evildomain.com"), 255)
+ > bpf:unblockQName(newDNSName("evildomain.com"), 65535)
> bpf:getStats()
+.. note::
+ Before 2.0.0 the value used to block queries for all types was 255. This was changed because it prevented blocking only queries for the ``ANY`` (255) qtype.
+
The :meth:`BPFFilter:blockQName` method can be used to block queries based on the exact qname supplied, in a case-insensitive way, and an optional qtype.
-Using the 255 (ANY) qtype will block all queries for the qname, regardless of the qtype.
+Using the ``65535`` value for the qtype will block all queries for the qname, regardless of the qtype.
+
Contrary to source address filtering, qname filtering only works over UDP. TCP qname filtering can be done the usual way::
addAction(AndRule({TCPRule(true), QNameSuffixRule("evildomain.com")}), DropAction())
.. versionadded:: 1.8.0
- Block all IP addresses in this range.
+ Block all IP addresses in this range.
DNSDist eBPF code first checks if an exact IP match is found, then if a range matches, and finally if a DNSName does.
:param int action: set ``action`` to ``0`` to allow a range, set ``action`` to ``1`` to block a range, set ``action`` to ``2`` to truncate a range.
:param bool force: When ``force`` is set to true, DNSDist always accepts adding a new item to BPF maps, even if the item to be added may already be included in the larger network range.
- .. method:: BPFFilter:blockQName(name [, qtype=255])
+ .. method:: BPFFilter:blockQName(name [, qtype=65535])
- Block queries for this exact qname. An optional qtype can be used, defaults to 255.
+ .. versionchanged:: 2.0.0
+ Before 2.0.0 the value used to block queries for all types was 255. It also used to be the default value. This was changed because it prevented blocking only queries for the ``ANY`` (255) qtype.
+
+ Block queries for this exact qname. An optional qtype can be used, defaults to 65535 which blocks queries for all types.
:param DNSName name: The name to block
:param int qtype: QType to block
List all range rule.
- .. method:: BPFFilter:unblockQName(name [, qtype=255])
+ .. method:: BPFFilter:unblockQName(name [, qtype=65535])
+
+ .. versionchanged:: 2.0.0
+ Before 2.0.0 the value used to block queries for all types was 255. It also used to be the default value. This was changed because it prevented blocking only queries for the ``ANY`` (255) qtype.
Remove this qname from the block list.
:func:`showTLSContexts` has been renamed to :func:`showTLSFrontends`.
:func:`getTLSContext` and the associated :class:`TLSContext` have been removed, please use :func:`getTLSFrontend` and the associated :class:`TLSFrontend` instead.
+Our eBPF filtering code no longer treats the ``255``/``ANY`` qtype as a special value intended to block queries for all types, and will only block ``ANY`` queries instead. The reserved ``65535`` value now can be used to block queries for all qtypes.
+
1.8.x to 1.9.0
--------------
bpf = newBPFFilter({ipv4MaxItems=10, ipv6MaxItems=10, qnamesMaxItems=10})
setDefaultBPFFilter(bpf)
- bpf:blockQName(newDNSName("blocked.ebpf.tests.powerdns.com."), 255)
+ bpf:blockQName(newDNSName("blocked.ebpf.tests.powerdns.com."), 65535)
+ bpf:blockQName(newDNSName("blocked-any-only.ebpf.tests.powerdns.com."), 255)
addTLSLocal("127.0.0.1:%d", "%s", "%s", { provider="openssl" })
addDOHLocal("127.0.0.1:%d", "%s", "%s", {"/"}, {library="nghttp2"})
receivedResponse.id = response.id
self.assertEqual(response, receivedResponse)
+ def testQNameBlockedOnylForAny(self):
+ # unblock 127.0.0.1, just in case
+ self.sendConsoleCommand('bpf:unblock(newCA("127.0.0.1"))')
+
+ name = 'blocked-any-only.ebpf.tests.powerdns.com.'
+ query = dns.message.make_query(name, 'ANY', 'IN', use_edns=False)
+
+ # ANY should be blocked over Do53 UDP
+ for method in ["sendUDPQuery"]:
+ sender = getattr(self, method)
+ (_, receivedResponse) = sender(query, response=None, useQueue=False, timeout=0.5)
+ self.assertEqual(receivedResponse, None)
+
+ query = dns.message.make_query(name, 'A', 'IN', use_edns=False)
+ response = dns.message.make_response(query)
+ rrset = dns.rrset.from_text(name,
+ 3600,
+ dns.rdataclass.IN,
+ dns.rdatatype.A,
+ '127.0.0.1')
+ response.answer.append(rrset)
+ # but A should NOT be blocked
+ for method in ["sendUDPQuery"]:
+ sender = getattr(self, method)
+ (receivedQuery, receivedResponse) = sender(query, response, timeout=1)
+ receivedQuery.id = query.id
+ self.assertEqual(query, receivedQuery)
+ self.assertEqual(response, receivedResponse)
+
def testClientIPBlocked(self):
# block 127.0.0.1
self.sendConsoleCommand('bpf:block(newCA("127.0.0.1"))')