Firewall with OpenFlow

For the firewall function demonstration, we will use the existing ryu/app/rest_firewall.py application and combine the knowledge we gained in this chapter about the REST API and flow modification. This is a simplified version of the Ryu book firewall example, https://osrg.github.io/ryu-book/en/html/rest_firewall.html. Besides firewall operations, the Ryu firewall example in the link provided illustrates the usage of multi-tenancy with VLAN. The example covered in this section will focus on the correlation between the firewall application and OpenFlow for learning purposes. This section and the linked example would be good complements of each other.
If you take a look at the rest_firewall.py code, you will notice a lot of similarities with ofctl_rest.py. In fact, most of the rest_* applications have similar functions when it comes to callback functions and URL dispatch. This is great news for us, since we only have to learn the pattern once and can apply it to multiple applications.
To begin with, we will launch a two-host, single-switch topology in Mininet:

$ sudo mn --topo single,2 --mac --switch ovsk --controller remote

We can launch the firewall application:

$ ryu-manager --verbose ryu/app/rest_firewall.py

We can perform a quick flow dump and see that the initial state of the flow includes a drop action at the top:

$ sudo ovs-ofctl dump-flows s1
NXST_FLOW reply (xid=0x4):
cookie=0x0, duration=5.849s, table=0, n_packets=0, n_bytes=0, idle_age=5, priority=65535 actions=drop
cookie=0x0, duration=5.848s, table=0, n_packets=0, n_bytes=0, idle_age=5, priority=0 actions=CONTROLLER:128
cookie=0x0, duration=5.848s, table=0, n_packets=0, n_bytes=0, idle_age=5, priority=65534,arp actions=NORMAL

We can enable the firewall via the API under /firewall/module/enable/<dpid>, which we will do now:

$ curl -X PUT http://localhost:8080/firewall/module/enable/0000000000000001
[{"switch_id": "0000000000000001", "command_result": {"result": "success", "details": "firewall running."}}]

If we perform the flow dump again, we will see the drop action is gone:

$ sudo ovs-ofctl dump-flows s1
NXST_FLOW reply (xid=0x4):
cookie=0x0, duration=964.894s, table=0, n_packets=0, n_bytes=0, idle_age=964, priority=65534,arp actions=NORMAL
cookie=0x0, duration=964.894s, table=0, n_packets=0, n_bytes=0, idle_age=964, priority=0 actions=CONTROLLER:128adfa

But there is still no flow from h1 to h2, so the ping packet will be blocked and dropped:

mininet> h1 ping -c 1 h2
PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.

--- 10.0.0.2 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms

# On Ryu console
EVENT ofp_event->RestFirewallAPI EventOFPPacketIn
[FW][INFO] dpid=0000000000000001: Blocked packet = ethernet(dst='00:00:00:00:00:02',ethertype=2048,src='00:00:00:00:00:01'), ipv4(csum=56630,dst='10.0.0.2',flags=2,header_length=5,identification=18800,offset=0,option=None,proto=1,src='10.0.0.1',tos=0,total_length=84,ttl=64,version=4), icmp(code=0,csum=37249,data=echo(data='Vjxe8Xx00x00x00x00xfe8tx00x00x00x00x00x10x11x12x13x14x15x16x17x18x19x1ax1bx1cx1dx1ex1f !"#$%&'()*+,-./01234567',id=25006,seq=1),type=8)

So let's add the rules for allowing ICMP packets--remember that this needs to be done bidirectionally, so we need to add two rules:

$ curl -X POST -d '{"nw_src": "10.0.0.1/32", "nw_dst": "10.0.0.2/32", "nw_proto": "ICMP"}' http://localhost:8080/firewall/rules/0000000000000001
$ curl -X POST -d '{"nw_src": "10.0.0.2/32", "nw_dst": "10.0.0.1/32", "nw_proto": "ICMP"}' http://localhost:8080/firewall/rules/0000000000000001

If we perform a flow dump again, we will see the flow installed:

$ sudo ovs-ofctl dump-flows s1
NXST_FLOW reply (xid=0x4):
cookie=0x0, duration=1143.144s, table=0, n_packets=2, n_bytes=84, idle_age=101, priority=65534,arp actions=NORMAL
cookie=0x1, duration=16.060s, table=0, n_packets=0, n_bytes=0, idle_age=16, priority=1,icmp,nw_src=10.0.0.1,nw_dst=10.0.0.2 actions=NORMAL
cookie=0x2, duration=3.662s, table=0, n_packets=0, n_bytes=0, idle_age=3, priority=1,icmp,nw_src=10.0.0.2,nw_dst=10.0.0.1 actions=NORMAL
cookie=0x0, duration=1143.144s, table=0, n_packets=1, n_bytes=98, idle_age=101, priority=0 actions=CONTROLLER:128

As expected, the ping packet from h1 to h2 now succeeds:

mininet> h1 ping -c 1 h2
PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=0.423 ms

--- 10.0.0.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.423/0.423/0.423/0.000 ms

But since the flow is implemented specifically for ICMP, other traffic will still be blocked:

mininet> h2 python -m SimpleHTTPServer &
mininet> h1 curl http://10.0.0.2:8000

# Ryu console
[FW][INFO] dpid=0000000000000001: Blocked packet = ethernet(dst='00:00:00:00:00:02',ethertype=2048,src='00:00:00:00:00:01'), ipv4(csum=49315,dst='10.0.0.2',flags=2,header_length=5,identification=26134,offset=0,option=None,proto=6,src='10.0.0.1',tos=0,total_length=60,ttl=64,version=4), tcp(ack=0,bits=2,csum=6514,dst_port=8000,offset=10,option=[TCPOptionMaximumSegmentSize(kind=2,length=4,max_seg_size=1460), TCPOptionSACKPermitted(kind=4,length=2), TCPOptionTimestamps(kind=8,length=10,ts_ecr=0,ts_val=34384732), TCPOptionNoOperation(kind=1,length=1), TCPOptionWindowScale(kind=3,length=3,shift_cnt=9)],seq=677247676,src_port=47286,urgent=0,window_size=29200)

As you can see, the firewall application is a way to use SDN to implement a traditional network function based on packet characteristics and implement it as flows to the network device. In this example, we implemented what is traditionally a layer 4 firewall rule in terms of SDN, Ryu, and OpenFlow.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.176.194