Network Function Virtualization --- Firewall and Rate Limit

[Description]

 

http://csie.nqu.edu.tw/smallko/sdn/nfv_monitor.files/image002.png

 

When a sender talks to a receiver, the packets go through different network elements, such as IDS, IPS, or firewall. However, different kinds of packets may have different policies. Some packets can go directly to the receiver, and some packets may need to go through firewall or IDP(IPS) to do deep packet inspection (DPI). In order to provide more flexible services to customers, SDN + NFV would be one of solutions. We can implement different network functions, such as IDP, IPS, firewall in VM or docker. Then use openflow to dynamically change the routing path for different packets to those network elements, and finally reach the destination.

 

In the first lab, the packets from h1 to h3 will be diverted h2 for policy checking. We will use iptables to block icmp while allowing other kinds of traffic.

In the second lab, the traffic flow from h1 to h3 will be limited to 5Mbps at maximum.

 

[test_iptables.py]

import urllib2 

import json 

 

def get_all_switches(): 

    url = "http://127.0.0.1:8080/v1.0/topology/switches" 

    req = urllib2.Request(url) 

    res_data = urllib2.urlopen(req) 

    res = res_data.read() 

    res = json.loads(res) 

    return res 

 

def get_all_links(): 

    url = "http://127.0.0.1:8080/v1.0/topology/links" 

    req = urllib2.Request(url) 

    res_data = urllib2.urlopen(req) 

    res = res_data.read() 

    res = json.loads(res) 

    return res 

def get_switch(dpid): 

    url = "http://127.0.0.1:8080/v1.0/topology/switches/" + dpid 

    req = urllib2.Request(url) 

    res_data = urllib2.urlopen(req) 

    res = res_data.read() 

    res = json.loads(res) 

    return res 

 

def get_flow_entries(dpid): 

    url = "http://127.0.0.1:8080/stats/flow/" + dpid 

    req = urllib2.Request(url) 

    res_data = urllib2.urlopen(req) 

    res = res_data.read() 

    res = json.loads(res) 

    return res 

 

def add_flow_entry(dpid,match,priority,actions): 

    url = "http://127.0.0.1:8080/stats/flowentry/add" 

    post_data = "{'dpid':%s,'match':%s,'priority':%s,'actions':%s}" % (dpid,str(match),priority,str(actions)) 

    req = urllib2.Request(url,post_data) 

    res = urllib2.urlopen(req) 

    return res.getcode() 

 

def delete_flow_entry(dpid, match=None, priority=None, actions=None): 

    url = "http://127.0.0.1:8080/stats/flowentry/delete" 

    post_data = "{'dpid':%s" % dpid 

    if match is not None: 

        post_data += ",'match':%s" % str(match) 

    if priority is not None: 

        post_data += ",'priority':%s" % priority 

    if actions is not None: 

        post_data += ",'actions':%s" % str(actions) 

    post_data += "}" 

 

    req = urllib2.Request(url,post_data) 

    res = urllib2.urlopen(req) 

    return res.getcode()

 

 

#h1----s1----h3

#      |

#      h2

# h1 talks to h3

 

 

print "add_flow_entry(dpid,match,priority,actions)"

 

print add_flow_entry('0000000000000001',{"dl_type": 2054},1,[{"type":"OUTPUT","port":"FLOOD"}])

 

print add_flow_entry('0000000000000001',{"in_port":00000001,"dl_type":2048,"nw_proto":1},1,[{"type":"OUTPUT","port":00000003}])

 

print add_flow_entry('0000000000000001',{"in_port":00000003,"dl_type":2048,"nw_proto":1},1,[{"type":"OUTPUT","port":00000001}])

 

print add_flow_entry('0000000000000001',{"in_port":00000001,"dl_dst": "00:00:00:00:00:03","dl_type":2048},20,[{"type": "SET_DL_DST", "dl_dst": "00:00:00:00:00:02"},{"type":"OUTPUT","port":00000002}])

 

print add_flow_entry('0000000000000001',{"in_port":00000002,"dl_dst": "00:00:00:00:00:03","dl_type":2048},20,[{"type":"OUTPUT","port":00000003}])

 

print add_flow_entry('0000000000000001',{"in_port":00000003,"dl_dst": "00:00:00:00:00:01","dl_type":2048},20,[{"type": "SET_DL_DST", "dl_dst": "00:00:00:00:00:02"},{"type":"OUTPUT","port":00000002}])

 

print add_flow_entry('0000000000000001',{"in_port":00000002,"dl_dst": "00:00:00:00:00:01","dl_type":2048},20,[{"type":"OUTPUT","port":00000001}])

 

[Execution]

1.     Firewall

Open three terminals. In first terminal.

http://csie.nqu.edu.tw/smallko/sdn/nfv_monitor.files/image004.png

 

In the second terminal

http://csie.nqu.edu.tw/smallko/sdn/nfv_monitor.files/image011.jpg

 

In the third terminal to run the script.

 

In the second terminal, we can try to ping from h1 to h3.

 

In h2, use the iptables to set the blocking rule for ICMP packet sent from h1.

 

Now h1 cannot ping h3.

 

Here we enable http server on h3. Try the connection between h1 and h3. (In the second terminal)

 

H1 can use curl to get the webpage from H3 because http traffic is allowed except ICMP.

 

2.      Rate Limit

Before applying the rate limit function on h2. (Open terminal for h1 and h3 for traffic measurement)

 

Apply rate limit function on h2. (set 5Mbps at maximum to destination 10.0.0.3)

 

We can see the throughput at h3 is not larger than 5Mbps.

 

 

[References]

1.      https://wiki.archlinux.org/index.php/Advanced_traffic_control#Hierarchical_Token_Bucket_.28HTB.29

2.      http://lartc.org/lartc.html

 

 

Dr. Chih-Heng Ke

Department of Computer Science and Information Engineering, National Quemoy University, Kinmen, Taiwan

Email: smallko@gmail.com / smallko@nqu.edu.tw