Skip to content
This repository was archived by the owner on Jun 27, 2018. It is now read-only.

Commit bd52573

Browse files
committed
Another example controller: port knocking, a kind of stateful firewall.
1 parent 1a00064 commit bd52573

File tree

1 file changed

+86
-0
lines changed

1 file changed

+86
-0
lines changed

pyretic/modules/port_knocking.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
################################################################################
2+
# The Pyretic Project #
3+
# frenetic-lang.org/pyretic #
4+
# author: Michael Greenberg ([email protected]) #
5+
################################################################################
6+
# Licensed to the Pyretic Project by one or more contributors. See the #
7+
# NOTICES file distributed with this work for additional information #
8+
# regarding copyright and ownership. The Pyretic Project licenses this #
9+
# file to you under the following license. #
10+
# #
11+
# Redistribution and use in source and binary forms, with or without #
12+
# modification, are permitted provided the following conditions are met: #
13+
# - Redistributions of source code must retain the above copyright #
14+
# notice, this list of conditions and the following disclaimer. #
15+
# - Redistributions in binary form must reproduce the above copyright #
16+
# notice, this list of conditions and the following disclaimer in #
17+
# the documentation or other materials provided with the distribution. #
18+
# - The names of the copyright holds and contributors may not be used to #
19+
# endorse or promote products derived from this work without specific #
20+
# prior written permission. #
21+
# #
22+
# Unless required by applicable law or agreed to in writing, software #
23+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT #
24+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the #
25+
# LICENSE file distributed with this work for specific language governing #
26+
# permissions and limitations under the License. #
27+
################################################################################
28+
29+
################################################################################
30+
# SETUP #
31+
# ------------------------------------------------------------------- #
32+
# mininet: mininet.sh #
33+
# test: pingall # everything should work #
34+
# h2 python -m SimpleHTTPServer 80 & #
35+
# h2 wget -O - h2 # should work #
36+
# h1 wget -O - -t 1 --timeout=2 h2 # should timeout #
37+
# h1 echo open sesame | nc -w 1 -u h2 1234 #
38+
# h1 wget -O - h2 # should work #
39+
################################################################################
40+
41+
from pyretic.lib.corelib import *
42+
from pyretic.lib.std import *
43+
from pyretic.lib.query import *
44+
45+
class port_knocking(DynamicPolicy):
46+
def __init__(self,knock_port,open_port):
47+
super(port_knocking,self).__init__()
48+
self.knock_port = knock_port
49+
self.open_port = open_port
50+
self.set_initial_state()
51+
52+
def set_initial_state(self):
53+
# the basic switching behavior
54+
self.switch = (match(inport=1)>>fwd(2)) + (match(inport=2)>>fwd(1))
55+
56+
# always forward ARP and ICMP
57+
forwardARP = match(ethtype=0x0806) >> self.switch
58+
forwardICMP = match(ethtype=0x0800,protocol=1) >> self.switch
59+
self.forward = forwardARP + forwardICMP
60+
61+
# but capture packets on the knocking port
62+
knock_knock = packets(1,['srcmac'])
63+
knock_knock.register_callback(self.whos_there)
64+
self.query = match(dstport=self.knock_port) >> knock_knock
65+
66+
# combine the forwarding and the knock query
67+
self.update_policy()
68+
69+
def update_policy(self):
70+
self.policy = self.forward + self.query
71+
72+
def set_network(self,network):
73+
self.set_initial_state()
74+
75+
def whos_there(self,pkt):
76+
mac = pkt['srcmac']
77+
self.forward = if_(match(srcmac=mac,dstport=self.open_port),
78+
self.switch, # open up port for incoming...
79+
if_(match(dstmac=mac,srcport=self.open_port),
80+
self.switch, # and allow return traffic
81+
self.forward))
82+
self.update_policy()
83+
84+
85+
def main():
86+
return port_knocking(1234,80)

0 commit comments

Comments
 (0)