The following ddos.js script is modified to use the REST API to send Network Command Line Utility - NCLU commands to add and remove ACLs, see Installing and Managing ACL Rules with NCLU:
var user = "cumulus";
var password = "CumulusLinux!";
var thresh = 10000;
var block_minutes = 1;
setFlow('udp_target',{keys:'ipdestination,udpsourceport',value:'frames'});
setThreshold('attack',{metric:'udp_target', value:thresh, byFlow:true, timeout:10});
function restCmds(agent,cmds) {
for(var i = 0; i < cmds.length; i++) {
let msg = {cmd:cmds[i]};
http("https://"+agent+":8080/nclu/v1/rpc",
"post","application/json",JSON.stringify(msg),user,password);
}
}
var controls = {};
var id = 0;
setEventHandler(function(evt) {
var key = evt.agent + ',' + evt.flowKey;
if(controls[key]) return;
var ifname = metric(evt.agent,evt.dataSource+".ifname")[0].metricValue;
if(!ifname) return;
var now = (new Date()).getTime();
var name = 'ddos'+id++;
var [ip,port] = evt.flowKey.split(',');
var cmds = [
'add acl ipv4 '+name+' drop udp source-ip any source-port '+port+' dest-ip '+ip+' dest-port any',
'add int '+ifname+' acl ipv4 '+name+' inbound',
'commit'
];
controls[key] = {time:now, target: ip, port: port, agent:evt.agent, metric:evt.dataSource+'.'+evt.metric, key:evt.flowKey, name:name};
try { restCmds(evt.agent, cmds); }
catch(e) { logSevere('failed to add ACL, '+e); }
logInfo('block target='+ip+' port='+port+' agent=' + evt.agent);
},['attack']);
setIntervalHandler(function() {
var now = (new Date()).getTime();
for(var key in controls) {
if(now - controls[key].time < 1000 * 60 * block_minutes) continue;
var ctl = controls[key];
if(thresholdTriggered('attack',ctl.agent,ctl.metric,ctl.key)) continue;
delete controls[key];
var cmds = [
'del acl ipv4 '+ctl.name,
'commit'
];
try { restCmds(ctl.agent,cmds); }
catch(e) { logSevere('failed to remove ACL, ' + e); }
logInfo('allow target='+ctl.target+' port='+ctl.port+' agent='+ctl.agent);
}
});
The quickest way test the script is to use docker to run sFlow-RT:docker run -v $PWD/ddos.js:/sflow-rt/ddos.js \ -e "RTPROP=-Dscript.file=ddos.js -Dhttp.timeout.read=60000" \ -p 6343:6343/udp -p 8008:8008 sflow/sflow-rtThis solution can be tested using freely available software. The setup shown at the top of this article was constructed using a Cumulus VX virtual machine running on VirtualBox. The Attacker and Target virtual machines are Linux virtual machines used to simulate the DDoS attack.
A DNS amplification attack can be simulated using hping3. Run the following command on the Attacker host:
sudo hping3 --flood --udp -k -s 53 192.168.2.1Run tcpdump on the Target host to see if the attack is getting through:
sudo tcpdump -i eth1 udp port 53Each time an attack is launched a new ACL will be added that matches the attack signature and drops the traffic. The ACL is kept in place for at least block_minutes and removed once the attack ends. The following sFlow-RT log messages show the results:
2017-08-26T17:01:24+0000 INFO: Listening, sFlow port 6343 2017-08-26T17:01:24+0000 INFO: Listening, HTTP port 8008 2017-08-26T17:01:24+0000 INFO: ddos.js started 2017-08-26T17:03:07+0000 INFO: block target=192.168.2.1 port=53 agent=10.0.0.61 2017-08-26T17:03:49+0000 INFO: allow target=192.168.2.1 port=53 agent=10.0.0.61REST API for Cumulus Linux ACLs describes the acl_server daemon that was used in the original article. The acl_server daemon is optimized for real-time performance, supporting use cases in which multiple traffic controls need to be quickly added and removed, e.g DDoS mitigation, marking large flows, ECMP load balancing, packet brokers.
A key benefit of the openness of Cumulus Linux is that you can install software to suite your use case, other examples include: BGP FlowSpec on white box switch, Internet router using Cumulus Linux, Topology discovery with Cumulus Linux, Black hole detection, and Docker networking with IPVLAN and Cumulus Linux.
