Questionable cBPF behaviour

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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



[Index of Archives]     [Linux Netfilter Development]     [Linux Kernel Networking Development]     [Netem]     [Berkeley Packet Filter]     [Linux Kernel Development]     [Advanced Routing & Traffice Control]     [Bugtraq]

  Powered by Linux