There are two preconditions for the attack:
- One of the queries results in 2k valid answer
- One of the queries soft-fails and will be retried
Mitigating (1) with UDP is simple: set maximum UDP buffer size to <2048B [1] That leaves TCP.
3 | 0.979429111596 | |
---|---|---|
4 | 0.979429111596 | |
5 | 0.979429111596 | |
6 | 0.979429111596 | |
7 | 0.979429111596 | |
8 | 0.979429111596 | |
9 | 0.979429111596 | |
10 | 0.979429111596 | |
11 | 0.979429111596 | |
12 | 0.979429111596 |
Near-stretch ideas | |
------------------ | |
* I *quite* like how it's built, but it's too much *PowerDNS*-y, hacking on it is a pain (if you work on cheap virtuals like me) because of long build times and dependencies (I know, but try it yourself on the budget DigitalOcean droplet...), I'd say lose the legacy and make it really a standalone thing. | |
* The configuration is sometimes confusing, like if I set it up to listen on local interfaces, it happily does so but it silently drops all queries because the ACL allows localhost only (uhm, maybe it needs to say something in verbose mode or documentation update). | |
* The config format for IPv6 has a poor choice of ':' as a separator, it's not possible to forward to IPv6 address on a custom port. | |
Far-stretch ideas | |
----------------- |
local slowdrip = { | |
tracked = {}, | |
blocked = {}, | |
window = 60, -- Length of the tracking window | |
threshold = 100, -- Number of NXDOMAINs before blocking | |
-- Track suffixes of names leading to NXDOMAIN | |
layer = { | |
finish = function(state, req, answer) | |
local parent = answer:qname() | |
parent = parent:sub(parent:find('.',0,true), -1) |
#include <stdio.h> | |
#include <string.h> | |
#include <lua.h> | |
#include <lualib.h> | |
#include <lauxlib.h> | |
#include <arpa/inet.h> | |
/* Get/set opcode */ | |
static int msg_op(lua_State *L) | |
{ |
## How it deals with bad CDNs | |
The query is `who.ami.here.com. A` | |
1. It's going to ask at `.` to `com. NS` and get a referral | |
2. it's going to ask `com.` nameserver about `here.com. NS` and get a referral | |
... see the pattern, it just appends labels, but bear with me | |
3. We're asking `here.com` nameserver about `ami.here.com. NS` , but he's a prick and tells us 'NXDOMAIN'. |
local mod = {} | |
mod.layer = { | |
consume = function (state, req, answer) | |
if state == kres.FAIL then | |
return state | |
end | |
answer = kres.pkt_t(answer) | |
req = kres.request_t(req) | |
if answer:qtype() == kres.type.NS then | |
local qry = req:push(answer:qname(), kres.type.SOA, kres.class.IN) |
var net = require('net'); | |
var dgram = require('dgram'); | |
function ntohs(arr) { | |
return ((arr[0] & 0xFF) << 8) | (arr[1] & 0xFF); | |
} | |
function parse_name(data, pos) | |
{ | |
for (base = pos; pos < data.length;) { |
[22:54:07] : [build] CMAKE_FLAGS_ADD="-DENABLE_MYSQL=OFF" REVISION=54276-cf0 AUTHOR=mvavrusa@cloudflare.com DEB_CLANG=$(which clang-3.8) DEB_CXX=$(which g++-6) DEB_CC=$(which gcc-6) THREAD_COUNT=4 ./release && \ | |
[22:54:07] : [build] mv ../*.deb /build/clickhouse/pkg | |
[22:54:07] : [build] | |
[22:54:07] : [build] Current revision is 54276-cf0 | |
[22:54:08] : [build] dpkg-buildpackage -rfakeroot -us -uc -b | |
[22:54:08] : [build] dpkg-buildpackage: info: source package clickhouse | |
[22:54:08] : [build] dpkg-buildpackage: info: source version 1.1.54276-cf0 | |
[22:54:08] : [build] dpkg-buildpackage: info: source distribution unstable | |
[22:54:08] : [build] dpkg-buildpackage: info: source changed by mvavrusa@cloudflare.com <builder@yandex-team.ru> | |
[22:54:08] : [build] dpkg-source --before-build clickhouse |
$ sudo luarocks install https://raw.githubusercontent.com/iovisor/bcc/master/src/lua/bpf-scm-1.rockspec | |
$ cat bpf_ttl.lua | |
local S = require('syscall') | |
local bpf = require('bpf') | |
-- Kernel-space part of the program | |
local map = bpf.map('array', 256) | |
local prog = assert(bpf(function () | |
local net = pkt.net_off -- Socket filter on TCP starts from TCP otherwise | |
if net.ver == 4 then -- Check for IPv4 |