Performance aware software defined networking describes how sFlow and OpenFlow can be combined to create SDN applications such as DDoS mitigation, load balancing large flows, and packet capture. This article takes a deep dive, describing how to build a test bed for developing performance aware SDN applications. The test bed is used to build and test a basic DDoS mitigation application and demonstrate how quickly the controller can adapt the network changing traffic conditions.
Inti atau goal pada lab kali ini adalah untuk membuat SDN Application yang bertujuan untuk mendeteksi sekaligus mem-block DDoS packet ketika masuk ke dalam jaringan kita.
Pada lab ini menggunakan komponen berikut :
- System Operasi Ubuntu 14.04 64-bit
- Mininet 2.2.0 : Sebagai virtual node
- Floodlight : Sebagai openflow controler dan network topology
- sFlow-RT : Digunakan untuk monitor route atau traffic dalam network
- Nodejs & Phyton : Bahasa yang akan digunakan untuk aplikasi SDN lab ini
Research Background
- switch samples packets
- switch mengirimkan header dari sampled packets ke sFlow-RT
- sFlow-RT akan menerjemahkan ke bahasa yang lebih terstructur (e.g. tcpflags=SYN, icmptype=3…)
- jika packet sudah melewati batas threshold yang sudah di tentukan kemudian akan men-trigger event
- events ini nantinya akan di akses external aplikasi melalui REST API
Scheme Design
ICMP Flood Attack
Mekanism:
Perangkat akan mengirimkan flood ping ke satu server dalam jumlah besarFlow Definition:
ipsource=0.0.0.0/0, ipdestination=10.0.0.5/32, #h3 dijadikan sbg server target outputifindex!=discard, #digunakan untuk detect flow yang tidak terblock ipprotocol=1 #ICMP
Match Field in blocking flow entry:
ether-type, protocol, src-ip, dst-ip
Application Development
Sebelum melanjutkan diharapkan sudah menginstall mininet dan floodlight terlebih dahulu. Dan juga pastikan mininet dan floodlight sudah terintegrasi dengan baik.
wget http://www.inmon.com/products/sFlow-RT/sflow-rt.tar.gz tar -xvzf sflow-rt.tar.g
- Jalankan floodlight
java -jar target/floodlight.jar
- Jalankan mininet
root@randymukti-virtual-machine:/home/randymukti# mn --controller=remote,127.0.0.1,port=6653 --topo=single,3 *** Creating network *** Adding controller *** Adding hosts: h1 h2 h3 *** Adding switches: s1 *** Adding links: (h1, s1) (h2, s1) (h3, s1) *** Configuring hosts h1 h2 h3 *** Starting controller c0 *** Starting 1 switches s1 *** Starting CLI: mininet> mininet> pingall *** Ping: testing ping reachability h1 -> h2 h3 h2 -> h1 h3 h3 -> h1 h2 *** Results: 0% dropped (6/6 received) mininet>
Pastikan mininet sudah terkomunikasi dengan controller dan juga hasil tes ping 0% dropped artinya semua node bisa saling ping 1 sama lain.
Dan juga default port disini sudah dirubah menyesuaikan dengan default port floodlight yang saya pakai sekarang merupakan versi terbaru. Kemungkinan jika anda menggunakan floodlight versi lama akan menggunakan port 6633.
Pastikan pada floodlight web manager node mininet terdaftar dengan benar dengan mengunjungi http://ipserver:8080/ui/pages/topology.html
Di gambar diatas ada beberapa switch yang sudah saya bikin sebelumnya jadi keliatan banyak, abaikan saja 😀
- Konfigurasikan sFlow monitor pada tiap switch
sudo ovs-vsctl -- --id=@sflow create sflow agent=eth0 target=\"127.0.0.1:6343\" sampling=10 polling=20 -- -- set bridge s1 sflow=@sflow
Itu semisal kalau ada 1 switch saja seperti di lab ini, kalau terdapat lebih dari 1 switch tinggal bikin saja berikutnya semisal switch 2
sudo ovs-vsctl -- --id=@sflow create sflow agent=eth0 target=\"127.0.0.1:6343\" sampling=10 polling=20 -- -- set bridge s2 sflow=@sflow
- Jalankan sFlow-RT
cd sflow-rt ./start.sh
Untuk memastikan sFlow-RT berfungsi dengan baik bisa mengunjungi http://ipserver:8008/html/index.html
- DDoS Mitigation Aplication
Berikut ini adalah script yang digunakan untuk detect dan block ddos dijalankan yang saya dapatkan dari http://blog.sflow.com/2013/06/large-flow-detection.htmlvar fs = require("fs"); var http = require('http'); var keys = 'inputifindex,ethernetprotocol,macsource,macdestination,ipprotocol,ipsource,ipdestination'; var value = 'frames'; var filter = 'sourcegroup=external&destinationgroup=internal&outputifindex!=discard'; var thresholdValue = 100; var metricName = 'ddos'; // mininet mapping between sFlow ifIndex numbers and switch/port names var ifindexToPort = {}; var nameToPort = {}; var path = '/sys/devices/virtual/net/'; var devs = fs.readdirSync(path); for(var i = 0; i < devs.length; i++) { var dev = devs[i]; var parts = dev.match(/(.*)-(.*)/); if(!parts) continue; var ifindex = fs.readFileSync(path + dev + '/ifindex'); var port = {"switch":parts[1],"port":dev}; ifindexToPort[parseInt(ifindex).toString()] = port; nameToPort[dev] = port; } var fl = { hostname: 'localhost', port: 8080 }; var groups = {'external':['0.0.0.0/0'],'internal':['10.0.0.2/32']}; var rt = { hostname: 'localhost', port: 8008 }; var flows = {'keys':keys,'value':value,'filter':filter}; var threshold = {'metric':metricName,'value':thresholdValue}; function extend(destination, source) { for (var property in source) { if (source.hasOwnProperty(property)) { destination[property] = source[property]; } } return destination; } function jsonGet(target,path,callback) { var options = extend({method:'GET',path:path},target); var req = http.request(options,function(resp) { var chunks = []; resp.on('data', function(chunk) { chunks.push(chunk); }); resp.on('end', function() { callback(JSON.parse(chunks.join(''))); }); }); req.end(); }; function jsonPut(target,path,value,callback) { var options = extend({method:'PUT',headers:{'content-type':'application/json'} ,path:path},target); var req = http.request(options,function(resp) { var chunks = []; resp.on('data', function(chunk) { chunks.push(chunk); }); resp.on('end', function() { callback(chunks.join('')); }); }); req.write(JSON.stringify(value)); req.end(); }; function jsonPost(target,path,value,callback) { var options = extend({method:'POST',headers:{'content-type':'application/json'},"path":path},target); var req = http.request(options,function(resp) { var chunks = []; resp.on('data', function(chunk) { chunks.push(chunk); }); resp.on('end', function() { callback(chunks.join('')); }); }); req.write(JSON.stringify(value)); req.end(); } function lookupOpenFlowPort(agent,ifIndex) { return ifindexToPort[ifIndex]; } function blockFlow(agent,dataSource,topKey) { var parts = topKey.split(','); var port = lookupOpenFlowPort(agent,parts[0]); if(!port || !port.dpid) return; var message = {"switch":port.dpid, "name":"dos-1", "ingress-port":port.portNumber.toString, "ether-type":parts[1], "protocol":parts[4], "src-ip":parts[5], "dst-ip":parts[6], "priority":"32767", "active":"true"}; console.log("message=" + JSON.stringify(message)); jsonPost(fl,'/wm/staticflowentrypusher/json',message, function(response) { console.log("result=" + JSON.stringify(response)); }); } function getTopFlows(event) { jsonGet(rt,'/metric/' + event.agent + '/' + event.dataSource + '.' + event.metric + '/json', function(metrics) { if(metrics && metrics.length == 1) { var metric = metrics[0]; if(metric.metricValue > thresholdValue && metric.topKeys && metric.topKeys.length > 0) { var topKey = metric.topKeys[0].key; blockFlow(event.agent,event.dataSource,topKey); } } } ); } function getEvents(id) { jsonGet(rt,'/events/json?maxEvents=10&timeout=60&eventID='+ id, function(events) { var nextID = id; if(events.length > 0) { nextID = events[0].eventID; events.reverse(); for(var i = 0; i < events.length; i++) { if(metricName == events[i].thresholdID) getTopFlows(events[i]); } } getEvents(nextID); } ); } // use port names to link dpid and port numbers from Floodlight function getSwitches() { jsonGet(fl,'/wm/core/controller/summary/json', function(switches) { for(var i = 0; i < switches.length; i++) { var sw = switches[i]; var ports = sw.ports; for(var j = 0; j < ports.length; j++) { var port = nameToPort[ports[j].name]; if(port) { port.dpid = sw.dpid; port.portNumber = ports[j].portNumber; } } } setGroup(); } ); } function setGroup() { jsonPut(rt,'/group/json', groups, function() { setFlows(); } ); } function setFlows() { jsonPut(rt,'/flow/' + metricName + '/json', flows, function() { setThreshold(); } ); } function setThreshold() { jsonPut(rt,'/threshold/' + metricName + '/json', threshold, function() { getEvents(-1); } ); } function initialize() { getSwitches(); } initialize();
Test & Evaluation
a) Without mitigation
h1 ICMP attack ke h3 dengan : h1 ping h3 -f
network traffic flow
b) With mitigation
Kemudian jalankan ddos script tadi
Setelah script dijalankan, kemudian attack ping lagi dan traffic flow berubah.
Note :
Script mitigati diatas tidak akan berhenti meski attack sudah di stop, perlu command dibawah supaya hilang.
curl http://localhost:8080/wm/staticflowentrypusher/clear/all/json
Sumber :
assalamualaikum.wr.wb mas.
mas saya coba nerapin sdn pakai controller floodlight kok mininetnya ga bisa conect ya? selalu X terus host di mininet kalo pingall. sedangkan kalo saya coba pake controller opendaylight, mininetnya bisa conect mas, topologi ny tampil.
terus saya coba script nodejs untuk mitigation ddos kok selalu error ya? gimana sih mas cara jalanin script js tersebut? 😦 mohon pencerahannya mas. terima kasih.
wassalamualaikum.wr.wb
gan bisa minta nmr Wa?