Alcatel-Lucent LAB – SDN & OS6900. (Part III – last one-)

Hello !!

Wish you’re enjoying this Tech-Tip…

After Part-I and Part-II, now you should have the sFlow-RT server, the Floodlight SDN controller, the SDN-APP VM, the Mininet VM, and two PCs for testing (either metal or virtual).

But we are missing the corner stone… The OmniSwitch OS6900 !!! It’s time to enter into the configuration.

Configuring OmniSwitch 6900 (OS6900)

Initial Setup

Although configuration could have been done from a SDN-APP, using the REST-JSON interface, we’ll go directly to the switch and configure it by CLI.

First let’s start configuring the IP address for the out-of-band management port (assuming we’re using the console):

ip interface emp address 159.23.224.154 mask 255.255.255.128

And the in-band management, using VLAN2, and port 1/3 for connecting to the VLAN where the IT-Systems are (sFlow, Floodlight, SDN-App, etc.)

vlan 2 name “Sistemas”
vlan 2 members port 1/3 untagged
ip interface “Sistemas” address 159.23.223.143 mask 255.255.255.128 vlan 2

Now, if everything is properly connected, OS6900 should reach the IT-systems:

Let’s allow user authentication with the local user DB in the OS6900 (it’s served completely secured) for access via Telnet, SSH, HTTP, etc.

aaa authentication default local

Connectivity for PC1 and PC2

VLANs for “FrontEnd” (PC1, the attacker) and “BackEnd” (PC2, the server to protect):

vlan 10 name “FrontEnd”
vlan 20 name “BackEnd”

Let’s assign the access ports to VLANs

vlan 10 members port 1/1 untagged
vlan 20 members port 1/2 untagged

The OS6900 will act as the default gateway for both VLANs:

ip interface “FrontEnd” address 1.1.1.1 mask 255.255.255.0 vlan 10
ip interface “BackEnd” address 2.2.2.1 mask 255.255.255.0 vlan 20

The PC1 and PC2 must be configured with a default gateway pointing to the OS6900 or, if the PCs have Internet connection, a static route to the other side.

At this time you should be able to ping from PC1 to PC2:

Stop the ping for now.

sFlow configuration

It’s time for sFlow configuration:

sflow agent ip 159.23.223.143
sflow receiver 1 name SDN-sFlow address 159.23.223.141
sflow sampler 1 port 1/1 receiver 1 rate 1 sample-hdr-size 128
sflow poller 1 port 1/1 receiver 1 interval 5

Go to the sFlow-RT VM and start sFlow (see Part-II). Open Firefox with the local sFlow-RT URL and OS6900 should be seen as an agent in the sFlow-RT server (may take some seconds):

The sFlow configuration allows more details (UDP Port, Version, packet-size and timeout), if not introduced, will take values by default.

OpenFlow configuration

Before configuring the OS6900, let’s prepare the Floodlight environment, it will be nice to see the OF vswitch registration process. Open the Floodlight VM, stop Floodlight if already running and start Wireshark (See Part-II).

Now type “of” in the protocol filter and apply:

Open a Terminal and start Floodlight:

cd
cd floodlight
./floodlight.sh

Let’s move to OS6900 and configure SDN-OpenFlow:

openflow back-off-max 10
openflow logical-switch vswitch1 mode api version 1.0
openflow logical-switch vswitch1 controller 159.23.223.140

Again, the controller allows to specify the TCP Port. If not specified, the standard 6633 is used.

Go to Floodlight, and check Wireshark, the OF negotiation should be seen:

Open Firefox with the Floodlight URL and the OS6900 should be there (may take up to 10 seconds – the back-off-max timer):

Configuration snapshot

Write the changes:

write memory flash-synchro

The configuration of the OmniSwitch (boot.cfg) is:

OS6900-6> show configuration snapshot
! Chassis:
system name “OS6900-6″
system contact “ALU Enterprise”
system location “Maria Tubau 9″

! Configuration:
! Capability Manager:
! Multi-Chassis:
! Virtual Chassis Manager:
! Virtual Flow Control:
! LFP
! Interface:
! Link Aggregate:
! VLAN:
vlan 1-2 admin-state enable
vlan 2 name “Sistemas”
vlan 10 admin-state enable
vlan 10 name “FrontEnd”
vlan 20 admin-state enable
vlan 20 name “BackEnd”
vlan 2 members port 1/3 untagged
vlan 10 members port 1/1 untagged
vlan 20 members port 1/2 untagged

! Spanning Tree:
spantree mode flat
spantree vlan 1 admin-state enable
spantree vlan 2 admin-state enable
spantree vlan 10 admin-state enable
spantree vlan 20 admin-state enable
spantree vlan 90 admin-state disable
spantree vlan 91 admin-state disable

! Bridging:
! Port Mirroring:
sflow agent ip 159.23.223.143
sflow receiver 1 name SDN-sFlow address 159.23.223.141 udp-port 6343 packet-size 1400 version 5 timeout 0
sflow sampler 1 port 1/1 receiver 1 rate 1 sample-hdr-size 128
sflow poller 1 port 1/1 receiver 1 interval 5

! Port Mapping:
! IP:
ip interface emp address 159.23.224.154 mask 255.255.255.128
ip interface “Sistemas” address 159.23.223.143 mask 255.255.255.128 vlan 2 ifindex 1
ip interface “FrontEnd” address 1.1.1.1 mask 255.255.255.0 vlan 10 ifindex 2
ip interface “BackEnd” address 2.2.2.1 mask 255.255.255.0 vlan 20 ifindex 3

! IPv6:
! IPSec:
! IPMS:
! AAA:
aaa authentication default “local”
aaa authentication console “local”
aaa authentication ftp “local”
aaa authentication http “local”
aaa authentication snmp “local”
aaa authentication ssh “local”

aaa accounting session “local”

! NTP:
! QOS:
! Policy Manager:
! VLAN Stacking:
! ERP:
! MVRP:
! LLDP:
! UDLD:
! Server Load Balance:
! High Availability Vlan:
! Session Manager:
session cli banner “/flash/banner.txt”
session cli timeout 596523
session http timeout 200
session prompt default “OS6900-6>”
session login-timeout 300

! Web:
! Trap Manager:
! Health Monitor:
! System Service:
! SNMP:
! BFD:
! IP Route Manager:
! VRRP:
ip load vrrp

! UDP Relay:
! RIP:
! OSPF:
! IP Multicast:
! DVMRP:
! IPMR:
! RIPng:
! OSPF3:
! BGP:
! ISIS:
! Netsec:
! Module:
! RDP:
! DA-UNP:
! DHL:
! Ethernet-OAM:
! SAA:
! SPB-ISIS:
! SVCMGR:
! LDP:
! EVB:
! APP-FINGERPRINT:
! FCOE:
fibre-channel vsan 1 admin-state enable name DEFAULT

! Dynamic auto-fabric
! SIP Snooping
! OPENFLOW:
openflow back-off-max 10
openflow logical-switch vswitch1 mode api version 1.0
openflow logical-switch vswitch2 version 1.3.1
openflow logical-switch vswitch1 controller 159.23.223.140:6633
openflow logical-switch vswitch2 controller 159.23.223.138:6633
openflow logical-switch vswitch2 interfaces port 1/4-5

! WLAN:
! DHCP Server:
! DHCPv6 Relay:
! Dhcpv6Srv:
! QIP Message Service:
! QIP Active Lease Service:

SDN-App

It’s time now to unveil the Brain of our system, the SDN Application that will glue all this components to create a solution. SDN Applications are the real value behind the hype of SDN.

Our SDN-App is done in Python, but obviously feel free to “translate” to your favorite programming language (Perl, Ruby, C++, Java, etc.). JSON is intensively used along the script. Some atom JSON Python scripts are provided, just for easing the learning path.

This script is a modification of one of the examples the sFlow-RT (~/sflow-rt/extras), to adapt it to our design. In that directory there are some examples that can help you understand sFlow.

Before coding like crazy, we should know what are we going to do:

  1. Clean existing used-defined flows with the same name as ours (ddos) in sFlow-RT – JSON with sFlow-RT
  2. Create the interesting flow in sFlow-RT (ddos), and wait for events – JSON with sFlow-RT
  3. If events exists, check that there is one of our interest (event raised by our “ddos” flow) – JSON with sFlow-RT
  4. If there is an event, and it’s for us, we have the IP address of the switch raising the event…
  5. Let’s ask Floodlight for the list of registered switches and see which one has that IP address – JSON with Floodlight
  6. Get the DPID of the switch
  7. Command Floodlight to block the flow in the switch with DPID – JSON with Floodlight
  8. Wait to see if attack stops
  9. Command Floodlight to release the block
  10. Back to #3

Let’s go through the script, explaining each part (Sorry for space indentation… this blog tool seems to cut off all starting spaces – the download has the right Python indention):

#!/usr/bin/env python
# Jorge Arasanz – jorge.arasanz@alcatel-lucent.com
# Alcatel-Lucent Enterprise
# This script is provided as is, feel free to modify it

# Importing the needed modules
import requests #For HTTP transactions
import simplejson as json #For handling JSON requests
import signal #For asynchronous events, threads and modules sync (program start, etc.)
import time #For time management.

# Floodlight REST. Change the IP for your setup
floodlight = “http://159.23.223.140:8080/

# sFlow-rt REST. Change the IP for your setup
sflow_rt = ‘http://159.23.223.141:8008

# This function cleans the existing “ddos” definition in sFlow-RT
def sig_handler(signal,frame):
requests.delete(sflow_rt + ‘/group/ddos/json’);
requests.delete(sflow_rt + ‘/flow/ddos/json’)
requests.delete(sflow_rt + ‘/threshold/ddos/json’)
exit(0)
signal.signal(signal.SIGINT, sig_handler)

def pushflow(flow):
“”"Push a flow to the SDN controller, using the flow definition passed as param”"”
fl_flowpusher = floodlight+’wm/staticflowentrypusher/json’

  # Let’s format the params in JSON
body = json.dumps(flow)

headers = {
‘Content-type’:'application/json’,
‘Accept’:'application/json’,
}

  # Do the POST in HTTP and return the Floodlight returned values
return requests.post(fl_flowpusher,data=body,headers=headers)

def deleteflow(flow):
“”"Delete a flow from the SDN controller, using the flow name passed as param”"”
fl_flowpusher = floodlight+’wm/staticflowentrypusher/json’

  # Let’s format the params in JSON
body = json.dumps(flow)

headers = {
‘Content-type’:'application/json’,
‘Accept’:'application/json’,
}

  # Do the DELETE in HTTP and return the Floodlight returned values
return requests.delete(fl_flowpusher,data=body,headers=headers)

def listflows(switch):
“”"List all flows of a switch, given the DPID, “”"
“”"or ALL FLOWS if parameter equals “all” “”"
fl_listflows = floodlight+’wm/staticflowentrypusher/list/’+switch+’/json’

  # Do the GET in HTTP and return the Floodlight returned values
return requests.get(fl_listflows)

def clearflows(switch):
“”"Clear all flows of a switch, given the DPID, “”"
“”"or ALL FLOWS if parameter equals “all” “”"
fl_clearflows = floodlight+’wm/staticflowentrypusher/clear/’+switch+’/json’

  # Do the GET in HTTP and return the Floodlight returned values
return requests.get(fl_clearflows)

def listofswitches():
“”"List all OF switches controlled by the Controller “”"
fl_listswitches = floodlight+’/wm/core/controller/switches/json’

  # Do the GET in HTTP and return the Floodlight returned values
return requests.get(fl_listswitches)

 

backoff_timer = 10 #seconds
threshold_packets = 1000 #packets/sec

groups = {‘external’:['1.1.1.0/24'],’internal’:['2.2.2.0/24']} # Define the interesting FLOW in this case IP-SA and IP-DA
flows = {‘keys’:'ipsource,ipdestination’,'value’:'frames’,'filter’:'group:ipsource:ddos=external&group:ipdestination:ddos=internal’}
threshold = {‘metric’:'ddos’,'value’:threshold_packets} # Name of threshold and value to raise an event

# Let’s program sFlow-RT with the interesting FLOW
r = requests.put(sflow_rt + ‘/group/ddos/json’,data=json.dumps(groups))
r = requests.put(sflow_rt + ‘/flow/ddos/json’,data=json.dumps(flows))
r = requests.put(sflow_rt + ‘/threshold/ddos/json’,data=json.dumps(threshold))

# Let’s check for events… bring up to 10 events, and wait up to 60 seconds if no event
eventurl = sflow_rt + ‘/events/json?maxEvents=10&timeout=60′
eventID = -1
while 1 == 1:

  # Let’s check for events… bring up to 10 events, and wait up to 60 seconds if no event
r = requests.get(eventurl + “&eventID=” + str(eventID))

if r.status_code != 200: break #No events, so break the loop and go up again

    # Format the JSON returned values
events = r.json()
#print json.dumps(events,indent=4, separators=(‘,’,':’))

if len(events) == 0: continue
eventID = events[0]["eventID"]
events.reverse()
for e in events: #Let’s move through the events searching for “ddos”, as may be many events, not only those generated by “ddos”
thresholdID = e['thresholdID']
if “ddos” == thresholdID:
#Event found, let’s get Event information
r = requests.get(sflow_rt + ‘/metric/’ + e['agent'] + ‘/’ + e['dataSource'] + ‘.’ + e['metric'] + ‘/json’)
metrics = r.json()
#print json.dumps(metrics,indent=4, separators=(‘,’,':’))
if len(metrics) > 0:
evtMetric = metrics[0]
evtKeys = evtMetric.get(‘topKeys’,None)
if(evtKeys and len(evtKeys) > 0):
topKey = evtKeys[0]
key = topKey.get(‘key’, None)
value = topKey.get(‘value’,None)

              # “key” contains the IP-SA and IP-DA of the attacking flow. Format “1.1.1.100,2.2.2.100″
attacker_ip,dest_ip = key.split(“,”)
# print “attacker_ip:”,attacker_ip
# print “dest_ip:”,dest_ip

print “******************** Event received!!!! ***************”
print “Flow:”,e['metric']
print “sFlow Agent IP:”,e['agent']
print “IP Source:”,attacker_ip
print “IP Destination:”,dest_ip
print “Packets/sec:”,str(value)

              # The switch raising the event is e['agent']
s_raiser = e['agent']

              # Get the list of OF switches from Controller and search for s_raiser
# Need to find out the switch’s DPID that raised the Event, only know
# the IP address now…
r = listofswitches()
of_switches = r.json()
if len(of_switches) == 0: continue
for of_switch in of_switches:
# SDN controller returns the IP as: ‘/69.69.69.10:48097′
# so need to remove “/” and the port “:48097″
s_ip = of_switch['inetAddress']
of_switch_ip = s_ip[1:s_ip.find(":")]
if of_switch_ip == s_raiser:
# switch that raised the event found !!!

#print of_switch['dpid']

                    # Let’s block the ddos flow
# 1) Define the flow to block
flow = {
“switch”:of_switch['dpid'],
“name”:”flow-mod-1″,
“cookie”:”0″,
“priority”:”500″,
“ether-type”:”0×0800″,
“src-ip”:attacker_ip,
“dst-ip”:dest_ip,
“active”:”true”,
“actions”:”"
}
# 2) Call the function to block the flow
r = pushflow(flow)
data = r.json()
print “——–>”
print “Command SDN controller to block traffic from “+attacker_ip+” to “+dest_ip
print “<——–”
print data['status']

#print json.dumps(data,indent=4, separators=(‘,’,':’))

                    # 3) Wait for the attack to subside
time.sleep(backoff_timer)
# 4) Clear the block and back to the top
flow = {
“name”:”flow-mod-1″,
}
r = deleteflow(flow)
data = r.json()
print “——–>”
print “Command SDN controller to release flow >”+flow['name']+”<”
print “<——–”
print data['status']
#print json.dumps(data,indent=4, separators=(‘,’,':’))

#End of script

There are some “print” statements along the script (print json.dump) that can be uncommented for your testing, to see what is returned in each JSON action.

Before running the script, it’s needed to load the python modules from Internet, using the Python Module Manager (pip). Open a Terminal:

sudo pip install requests
sudo pip install simplejson

Download the script ddos_os6900.tar

It’s a tar file, so need to untar it and get ddos_os6900.py:

cd
cd Downloads
tar -xpvf ddos_os6900.tar
cd
mkdir sdn-app
cp Downloads/ddos_os6900.py /sdn-app/.

Now everything is ready to start The Test !!

The Test

Well, let’s summarize: OS6900 is a sFlow-RT agent, it’s a registered vswitch in Floodlight as well. The “ddos_os6900.py” python script have been downloaded to the SDN-APP VM.

Let’s start:

  • Start with a clean environment: restart sFlow-RT and Floodlight services (not the VM!!). Stop the ping from PC1 to PC2.
  • The OS6900 must be present in both sFlow-RT and Floolight.
  • In the SDN-App VM, move to the right directoty:

cd

cd sdn-app

  • start the sdn-app:

python ddos_os6900.py

  •  In sFlow-RT, the new “ddos” flow have been defined (click on “Flows”):

Select the “ddos” flow, and no values are present:

  • Start a regular ping from PC1 to PC2:

  • Now, in sFlow-RT, the ddos programed flow, shows both IP addresses:

  • And in the “Metrics” tab, select the “ddos” flow:

  • The value shows, an average of 1 packets/sec
  •  Floodlight shows no flows configured, but the traffic is passing… Remember we’re using the Hybrid mode:

  • Go to PC1 and start a ping flooding. Only “root” has the privileges to run “ping” with timers lower than 200ms (flooding), so in a NEW Terminal (leave the regular ping running):

sudo su -

ping -f 2.2.2.100

 

  •  Move to SDN-APP, and check that the DDoS have been detected, and our App, has commanded Floodlight to block the traffic:

  • Floodlight shows that the switch has now 1 flow configured:

  • And the traffic metric in sFlow, clearly shows that once the flooding raises the 1000 packets, the traffic is blocked:

The overall traffic pattern, considering NO limitation in the DDoS attack, and then applying the SDN-App is:

Without any DDoS control, the flooded traffic reaches more than 4000 packets/sec… and will impact the performance of the Service.

Once our SDN-Application is activated, traffic is limited up to 1000 packets/sec, if that limit is passed, traffic is blocked.

There is a back-off timer, waiting for the flooding traffic to stop. The flow is blocked, and when back-off timer expires, it’s released. As flooding persists, the traffic is blocked again.

Once flooding stops, the traffic is allowed again, but the SDN-App continues monitoring the traffic.

Regarding OS6900, the provides information about the number of active flows (during attack, there is only 1 pushed flow):

Some Tricks

If while running the Test, and the flow have been pushed to the OS6900, the script is stopped (Crtl-C), there is no way to release the flow… as the SDN-App is no longer running.

In such case, the flow must be removed using this script (it’s a tar file): floodlight_clean_flows_json.py

Remember to adjust the script to your setup (Floodlight IP address)

In order to help  you in your learning path, I’m attaching here some easy, short, Python scripts that will help you in your Labs (it’s a tar file): Python_scripts.tar

In that “tar” file (tar -xpvf Python_scripts.tar) next scripts are packaged:

  • floodlight_clean_flows_json.py -> Cleans ALL flows of ALL vswitches in Floodlight
  • floodlight_delete_flow_json.py -> Delete a specific flow in a specific vswitch (DPID)
  • floodlight_list_flows_json.py -> List ALL flows
  • floodlight_push_flow_json.py -> Push a single flow in a specific vswitch

Obviously, these scripts must be adapted to your setup: IP addresses, DPID, flow-names, etc.

Conclusion

This Lab is finished… I’m working in a extended edition, with SPBm, using more OF1.0 functions, using the REST-JSON interface of OS6900 to push configuration, etc.

There is a lot of hype around SDN, and now you may have a clear understanding of the building blocks.

In my opinion, SDN is just a new tool. I always say that SDN should NOT be a NEW tool for doing OLD things… That is, just get informed about SDN, investigate, and learn; but when going to the real world, think about THE PROBLEM you have. There are a lot of tools to solve it, and maybe SDN could be the right one, or maybe just some CLI lines in your traditional switch.

Hope you enjoyed this, and in someway were helpful for you…

Jorge

About the author