]>
git.ipfire.org Git - thirdparty/pdns.git/blob - contrib/xdp.py
10 QTYPES
= {'LOC': 29, '*': 255, 'IXFR': 251, 'UINFO': 100, 'NSEC3': 50, 'AAAA': 28, 'CNAME': 5, 'MINFO': 14, 'EID': 31, 'GPOS': 27, 'X25': 19, 'HINFO': 13, 'CAA': 257, 'NULL': 10, 'DNSKEY': 48, 'DS': 43, 'ISDN': 20, 'SOA': 6, 'RP': 17, 'UID': 101, 'TALINK': 58, 'TKEY': 249, 'PX': 26, 'NSAP-PTR': 23, 'TXT': 16, 'IPSECKEY': 45, 'DNAME': 39, 'MAILA': 254, 'AFSDB': 18, 'SSHFP': 44, 'NS': 2, 'PTR': 12, 'SPF': 99, 'TA': 32768, 'A': 1, 'NXT': 30, 'AXFR': 252, 'RKEY': 57, 'KEY': 25, 'NIMLOC': 32, 'A6': 38, 'TLSA': 52, 'MG': 8, 'HIP': 55, 'NSEC': 47, 'GID': 102, 'SRV': 33, 'DLV': 32769, 'NSEC3PARAM': 51, 'UNSPEC': 103, 'TSIG': 250, 'ATMA': 34, 'RRSIG': 46, 'OPT': 41, 'MD': 3, 'NAPTR': 35, 'MF': 4, 'MB': 7, 'DHCID': 49, 'MX': 15, 'MAILB': 253, 'CERT': 37, 'NINFO': 56, 'APL': 42, 'MR': 9, 'SIG': 24, 'WKS': 11, 'KX': 36, 'NSAP': 22, 'RT': 21, 'SINK': 40}
11 INV_QTYPES
= {v
: k
for k
, v
in QTYPES
.items()}
12 ACTIONS
= {1 : 'DROP', 2 : 'TC'}
17 # The list of blocked IPv4, IPv6 and QNames
18 # IP format : (IPAddress, Action)
19 # CIDR format : (IPAddress/cidr, Action)
20 # QName format : (QName, QType, Action)
21 blocked_ipv4
= [("192.0.2.1", TC_ACTION
)]
22 blocked_ipv6
= [("2001:db8::1", TC_ACTION
)]
23 blocked_cidr4
= [("192.0.1.1/24", TC_ACTION
)]
24 blocked_cidr6
= [("2001:db8::1/128", TC_ACTION
)]
25 blocked_qnames
= [("localhost", "A", DROP_ACTION
), ("test.com", "*", TC_ACTION
)]
28 parser
= argparse
.ArgumentParser(description
='XDP helper for DNSDist')
29 parser
.add_argument('--xsk', action
='store_true', help='Enable XSK (AF_XDP) mode', default
=False)
30 parser
.add_argument('--interface', '-i', type=str, default
='eth0', help='The interface on which the filter will be attached')
32 parameters
= parser
.parse_args()
35 print(f
'Enabling XSK (AF_XDP) on {parameters.interface}..')
36 cflag
.append("-DUseXsk")
39 portsStr
= ', '.join(str(port
) for port
in Ports
)
40 print(f
'Enabling XDP on {parameters.interface} and ports {portsStr}..')
41 IN_DNS_PORT_SET
= "||".join("COMPARE_PORT((x),"+str(i
)+")" for i
in Ports
)
42 cflag
.append(r
"-DIN_DNS_PORT_SET(x)=(" + IN_DNS_PORT_SET
+ r
")")
44 xdp
= BPF(src_file
="xdp-filter.ebpf.src", cflags
=cflag
)
46 fn
= xdp
.load_func("xdp_dns_filter", BPF
.XDP
)
47 xdp
.attach_xdp(parameters
.interface
, fn
, 0)
49 v4filter
= xdp
.get_table("v4filter")
50 v6filter
= xdp
.get_table("v6filter")
51 cidr4filter
= xdp
.get_table("cidr4filter")
52 cidr6filter
= xdp
.get_table("cidr6filter")
53 qnamefilter
= xdp
.get_table("qnamefilter")
56 xskDestinations
= xdp
.get_table("xskDestinationsV4")
58 for ip
in blocked_ipv4
:
59 print(f
"Blocking {ip}")
60 key
= v4filter
.Key(int(netaddr
.IPAddress(ip
[0]).value
))
61 leaf
= v4filter
.Leaf()
66 for ip
in blocked_ipv6
:
67 print(f
"Blocking {ip}")
68 ipv6_int
= int(netaddr
.IPAddress(ip
[0]).value
)
69 ipv6_bytes
= bytearray([(ipv6_int
& (255 << 8*(15-i
))) >> (8*(15-i
)) for i
in range(16)])
70 key
= (ct
.c_uint8
* 16).from_buffer(ipv6_bytes
)
71 leaf
= v6filter
.Leaf()
76 for item
in blocked_cidr4
:
77 print(f
"Blocking {item}")
78 key
= cidr4filter
.Key()
79 network
= netaddr
.IPNetwork(item
[0])
80 key
.cidr
= network
.prefixlen
81 key
.addr
= socket
.htonl(network
.network
.value
)
82 leaf
= cidr4filter
.Leaf()
85 cidr4filter
[key
] = leaf
87 for item
in blocked_cidr6
:
88 print(f
"Blocking {item}")
89 key
= cidr6filter
.Key()
90 network
= netaddr
.IPNetwork(item
[0])
91 key
.cidr
= network
.prefixlen
92 ipv6_int
= int(network
.network
.value
)
93 ipv6_bytes
= bytearray([(ipv6_int
& (255 << 8*(15-i
))) >> (8*(15-i
)) for i
in range(16)])
94 key
.addr
.in6_u
.u6_addr8
= (ct
.c_uint8
* 16).from_buffer(ipv6_bytes
)
95 leaf
= cidr6filter
.Leaf()
98 cidr6filter
[key
] = leaf
100 for qname
in blocked_qnames
:
101 print(f
"Blocking {qname}")
102 key
= qnamefilter
.Key()
104 for sub
in qname
[0].split('.'):
108 qn
.extend((0,) * (255 - len(qn
)))
109 key
.qname
= (ct
.c_ubyte
* 255).from_buffer(qn
)
110 key
.qtype
= ct
.c_uint16(QTYPES
[qname
[1]])
111 leaf
= qnamefilter
.Leaf()
113 leaf
.action
= qname
[2]
114 qnamefilter
[key
] = leaf
116 print(f
"Filter is ready on {parameters.interface}")
120 except KeyboardInterrupt:
123 for item
in v4filter
.items():
124 print(f
"{str(netaddr.IPAddress(item[0].value))} ({ACTIONS[item[1].action]}): {item[1].counter}")
125 for item
in v6filter
.items():
126 print(f
"{str(socket.inet_ntop(socket.AF_INET6, item[0]))} ({ACTIONS[item[1].action]}): {item[1].counter}")
127 for item
in cidr4filter
.items():
128 addr
= netaddr
.IPAddress(socket
.ntohl(item
[0].addr
))
129 print(f
"{str(addr)}/{str(item[0].cidr)} ({ACTIONS[item[1].action]}): {item[1].counter}")
130 for item
in cidr6filter
.items():
131 print(f
"{str(socket.inet_ntop(socket.AF_INET6, item[0].addr))}/{str(item[0].cidr)} ({ACTIONS[item[1].action]}): {item[1].counter}")
132 for item
in qnamefilter
.items():
133 print(f
"{''.join(map(chr, item[0].qname)).strip()}/{INV_QTYPES[item[0].qtype]} ({ACTIONS[item[1].action]}): {item[1].counter}")
135 xdp
.remove_xdp(parameters
.interface
, 0)