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.
-- C definitions | |
local ffi = require('ffi') | |
local csym = ffi.C | |
ffi.cdef[[ | |
/* DHCP header format */ | |
struct __attribute__((packed)) dhcp_msg { | |
/* Header */ | |
uint8_t op; | |
uint8_t htype; | |
uint8_t hlen; |
#!/usr/bin/python | |
# | |
# Copyright 2016 Google Inc | |
# | |
# Licensed under the Apache License, Version 2.0 (the "License"); | |
# you may not use this file except in compliance with the License. | |
# You may obtain a copy of the License at | |
# | |
# http://www.apache.org/licenses/LICENSE-2.0 | |
# |
$ kdig @9.9.9.9 akamai.com +subnet=111.111.111.0/24 | |
;; ->>HEADER<<- opcode: QUERY; status: NOERROR; id: 9698 | |
;; Flags: qr rd ra; QUERY: 1; ANSWER: 1; AUTHORITY: 0; ADDITIONAL: 1 | |
;; EDNS PSEUDOSECTION: | |
;; Version: 0; flags: ; UDP size: 4096 B; ext-rcode: NOERROR | |
;; CLIENT-SUBNET: 73.231.144.0/20/0 | |
;; QUESTION SECTION: | |
;; akamai.com. IN A |
$ 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 |
[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 |
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;) { |
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) |
## 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'. |
#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) | |
{ |