Hello everybody! I try to filter (DROP) DNS ANY queries using the classic BPF (Berkley Packet Filter). Unfortunately there are lots of poorly written documentation on BPF assembler usage so I really need some help. The task is to load BPF opcodes into xt_bpf to filter the UDP DNS packets by their payload. I use cbpf compiler from the netsniff-ng package to convert assembler to opcodes and bpf_dbg from Cloudflare bpftools to debug the code. (I test the code against tcpdump'ed packets containing DNS ANY queries.) I load the filtering code using: iptables -I INPUT 1 -m bpf --bytecode '<bytecode>' I don't know if I have to add -j DROP or -j ACCEPT because there is no information regarding further behaviour of iptables after getting cBPF program return code. The problem is that despite the packet counter ticks of catched packets and despite addition or removal of -j ACCEPT/DROP I still see the DNS ANY queries in BIND9 logs. I will appreciate any help and am ready to give further comments regarding the code behaviour. Here is the filter's code: ; Check if we've got the IP packet on top of Ethernet frame: check_ip: ldh [12] ; Load the value from offset 12 into A register. jneq #0x800, pass ; Check if we're dealing with IP packet or pass it AS IS. ; Check the protocol field for packet type == 17 (UDP) check_proto: ldb [23] ; Check. tcpdump has advised me to use offset 23 instead of 27. jneq #0x11, pass ; Pass the packet if it's type is not UDP. ; Check for the packet dport == 53. check_dport: ldh [36] ; Load the u16 into A register from offset 36. jneq #0x35, pass ; Check if the dport is 53. ; Check if we have the unfragmented packet (or the first fragment). check_fragmentation: ldh [20] ; Skip all headers right to UDP payload (Load UDP Fragment Offset). jset #0x1fff, pass ; Returns 0. Test if we have the unfragmented packet or packet's first fragment, drop the packet otherwise. ldxb 4*([14]&0xf) ldb [x + 24] jset #0x80, pass ; Check for DNS QTYPE == ANY and QCLASS == IN find_qtype: ldb [54] ; Load first byte of the query RR into A. It contains relative count/offset of query bytes or 0x00 in the end. add #0x37 ; Add 54 (query offset byte position) + 1 (+ 1 byte forward) to the offset value in A to make the offset absolute. tax ; Move the absolute offset to X. ldb [x + 0x0] ; Load the value from the absolute offset. jeq #0x00, check_qtype ; Move to the QTYPE check code if it's the end of the query string. add x ; Add the absolute offset from A to relative offset in X. add #0x1 ; Move the absolute offset 1 byte forward, to the next offset value. tax ; Move the new (adjusted) absolute offset from A to X. ldb [x + 0x0] ; Load the value by the new calcaulated offset. jeq #0x00, check_qtype ; Check against end of the query once again. add x add #0x1 tax ldb [x + 0x0] jeq #0x00, check_qtype ; And again, and again... jmp pass ; Pass the packet if we were unable to find the desired value. A little failover. ; Check the query type in case we were able to find the end of the string! check_qtype: txa ; Move the absolute offset from X into A. add #0x1 ; Move the offset 1 byte forward from query end. tax ; Move the absolute offset value to the X register from A. ld [x + 0x0] ; Load the u32 from absolute offset specified in X register. jeq #0x00FF0001, drop ; Drop the packet if the value in A is 0x00FF0001 or else pass the packet. pass: ret #-1 ; Label/Return code signaling to pass the inspected packet. drop: ret #0 ; Label/Return code signaling to drop packet. -- With best regards/Mit freundlichen Grüßen, Igor Chudov TransTelecom-Volga JSC, Russian Federation Leading Engineer/Network Maintainance Department, Tel. (24/7/365): +7 937 266-51-34 -- To unsubscribe from this list: send the line "unsubscribe netfilter" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html