SDN大作業
1.小組成員
組名:bzzb銀河戰艦
031702627 李至恆(組長)
031702623 蔡嘉懿
031702625 楊藍宇
031702632 林華偉
031702634 徐祖豪
2.應用背景
本次實驗屬於流量分類課題中的惡意流量識別小專題(主要針對DDOS攻擊)
SDN環境下的DDoS攻擊檢測,檢測主機是否遭到了DDoS攻擊。
3.環境搭建
以下代碼完整部分均已上傳至github
拓撲圖
from mininet.topo import Topo
class MyTopo(Topo):
def __init__(self):
# initilaize topology
Topo.__init__(self)
# add hosts and switches
h1 = self.addHost('h1',ip='10.1.1.1')
h2 = self.addHost('h2',ip='10.1.1.2')
h3 = self.addHost('h3',ip='10.1.1.3')
h4 = self.addHost('h4',ip='10.1.2.1')
h5 = self.addHost('h5',ip='10.1.2.2')
h6 = self.addHost('h6',ip='10.1.2.3')
h7 = self.addHost('h7',ip='10.10.10.1')
h8 = self.addHost('h8',ip='10.10.10.2')
h9 = self.addHost('h9',ip='10.10.10.3')
h10 = self.addHost('h10',ip='10.10.20.1')
h11 = self.addHost('h11',ip='10.10.20.2')
h12 = self.addHost('h12',ip='10.10.20.3')
s1 = self.addSwitch('s1')
s11 = self.addSwitch('s11')
s12 = self.addSwitch('s12')
s2 = self.addSwitch('s2')
s21 = self.addSwitch('s21')
s22 = self.addSwitch('s22')
# add links
self.addLink(s1,s2,3,1)
self.addLink(s1,s11,1,3)
self.addLink(s1,s12,2,3)
self.addLink(s11,h1,1,1)
self.addLink(s11,h2,2,1)
self.addLink(s11,h3,4,1)
self.addLink(s12,h4,1,1)
self.addLink(s12,h5,2,1)
self.addLink(s12,h6,4,1)
self.addLink(s2,s21,2,3)
self.addLink(s2,s22,3,3)
self.addLink(s21,h7,1,1)
self.addLink(s21,h8,2,1)
self.addLink(s21,h9,4,1)
self.addLink(s22,h10,1,1)
self.addLink(s22,h11,2,1)
self.addLink(s22,h12,4,1)
topos = {'mytopo': (lambda: MyTopo())}
拓撲代碼
def cal_PPS(flow_set):
# 數據包速率
length = len(flow_set)
PPS = float(length / 2)
return PPS
def cal_FER(flow_set, fnum):
# 流表項生成率
for i in flow_set:
flows.update({i[3], i[4]})
length = len(flows)
new_num = length - fnum # 新增流表項數目
FER = float(new_num / 2)
fnum = length # 總流表項數據數目
return FER, fnum, new_num # FER 流表項數目 新增數目
def cal_APPF(flow_set):
# 流表項的平均數據包數目
temp_flows = set()
for i in flow_set:
temp_flows.update({i[3], i[4]})
num = len(flows)
APPF = len(flow_set) / num
return APPF
def cal_SFP(flow_set):
# 單流表項的數目
temp_flows = set()
setL = set()
setR = set()
for i in flow_set:
temp = {(i[3], i[4])}
temp_flows.update(temp)
# print(temp_flows)
num = len(temp_flows)
for i in temp_flows:
# print(i)
setL.add(i[0])
setR.add(i[1])
setR = setL - setR
single_num = len(setR)
SEP = (float(single_num) / float(num))
return SEP
def cal_PS(flow_set):
k = 0
type = ["eth:ethertype:ip:tcp", "eth:ethertype:ip:udp"]
pro = [0.0, 0.0]
for i in flow_set:
for j in type:
if i[2][0:20] == j:
pro[k] = pro[k] + 1
break
k = k + 1
k = 0
M = len(flow_set)
if pro[0] != 0 and pro[1] != 0:
PS = -(((pro[0] / M) * math.log(pro[0] / M)) + ((pro[1] / M) * math.log(pro[1] / M)))
return PS
if pro[0] == 0 and pro[1] != 0:
PS = -(pro[1] / M) * math.log(pro[1] / M)
return PS
if pro[0] != 0 and pro[1] == 0:
PS = -(pro[0] / M) * math.log(pro[0] / M)
return PS
else:
return 0
def cal_h_sIP_dIP(flow_set):
print("cal_h_sIP_dIP")
h = 0
sIP = 0
dIP = 0
temp_flows = set()
srcIP = set()
dstIP = set()
dstPort = set()
for i in flow_set:
# print(i)
temp = {(i[3], i[4], i[6])}
temp_flows.update(temp)
for i in temp_flows:
srcIP.add(i[0])
dstIP.add(i[1])
dstPort.add(i[2])
srcList = list(srcIP)
dstList = list(dstIP)
PortList = list(dstPort)
# 計算H(srcIP|dstIP)
A = [[] for i in range(len(dstList))]
B = [[[] for i in range(len(dstList))] for i in range(len(srcList))]
# Init
for i in range(len(dstList)):
A[i] = 0
for i in range(len(srcList)):
for j in range(len(dstList)):
B[i][j] = 0
# print(srcList)
# print(dstList)
flag = 0
for k in flow_set: # 每一個數據包
for i in range(len(srcList)):
for j in range(len(dstList)):
# print(k[3],k[4])
if srcList[i] == k[3] and dstList[j] == k[4]:
B[i][j] += 1
A[j] += 1
flag = 1
break
if flag == 1:
flag = 0
break
for j in range(len(dstList)):
tempj = (float(A[j]) / float(len(flow_set)))
tempi = 0
for i in range(len(srcList)):
if B[i][j] != 0 and A[j] != 0:
tempi += ((float(B[i][j]) / float(A[j]))) * (math.log(float(B[i][j]) / float(A[j])))
h += tempj * tempi
h = -h
# 計算H(dstPort|dstIP)
C = [[[] for i in range(len(dstList))] for i in range(len(PortList))]
# Init
for i in range(len(PortList)):
for j in range(len(dstList)):
C[i][j] = 0
for k in flow_set: # 每一個數據包
for i in range(len(PortList)):
for j in range(len(dstList)):
if PortList[i] == k[6] and dstList[j] == k[4]:
C[i][j] += 1
for j in range(len(dstList)):
tempj = (float(A[j]) / float(len(flow_set)))
tempi = 0
for i in range(len(PortList)):
if C[i][j] != 0 and A[j] != 0:
tempi += (float(C[i][j]) / float(A[j])) * (math.log(float(C[i][j]) / float(A[j])))
dIP += tempj * tempi
dIP = -dIP
# 計算H(srcIP|dstPort)
D = [[] for i in range(len(PortList))]
E = [[[] for i in range(len(PortList))] for i in range(len(srcList))]
# Init
for i in range(len(PortList)):
D[i] = 0
for i in range(len(srcList)):
for j in range(len(PortList)):
E[i][j] = 0
for k in flow_set: # 每一個數據包
for i in range(len(srcList)):
for j in range(len(PortList)):
if srcList[i] == k[3] and PortList[j] == k[6]:
E[i][j] += 1
D[j] += 1
for j in range(len(PortList)):
tempj = float(D[j]) / float(len(flow_set))
tempi = 0
for i in range(len(srcList)):
if E[i][j] != 0 and D[j] != 0:
tempi += (float(E[i][j]) / float(D[j])) * (math.log(float(E[i][j]) / float(D[j])))
sIP += tempj * tempi
sIP = -sIP
return h, sIP, dIP
讀取數據集(數據集來自UNB ISCX 2012 intrusion detection evaluation dataset)
def zc_read_csv(m):
zc_dataframe = pd.read_csv("./data.csv", sep=",")
x = np.array([[0,0,0,0,0,0,0,0,0,0]])
y = np.array([[0,0]])
listy = [0,0]
flag = 0
for i in zc_dataframe.index:
zc_row = zc_dataframe.loc[i]
private = np.array([(zc_row)],float)
listy[0] = zc_row[8]
listy[1] = zc_row[9]
private_y = np.array([(listy)],float)
x = np.concatenate((x,private),axis=0)
y = np.concatenate((y,private_y),axis=0)
flag += 1
if(flag ==m):
break;
y=y[1:,:]
x=x[1:,:-2]
return (x,y)
def RNN(X, weights, biases):
X_in = tf.matmul(X, weights['in'] + biases['in'])
X_in = tf.reshape(X_in, [-1, n_steps, n_hidden_units])
lstm_cell = tf.nn.rnn_cell.BasicLSTMCell(n_hidden_units, forget_bias=1.0, state_is_tuple=True)
_init_state = lstm_cell.zero_state(batch_size, dtype=tf.float32)
outputs, states = tf.nn.dynamic_rnn(lstm_cell, X_in, initial_state=_init_state, time_major=False)
results = tf.matmul(states[1], weights['out']) + biases['out']
return results
機器學習
4.演示視頻(視頻時長6分鍾,可以跳躍觀看)
https://www.bilibili.com/video/av82387501/
5.實驗思路說明
前期准備:網絡上下載數據集 ==> 數據集初步處理 ==> 特征向量提取 ==>生成訓練集和測試集 ==>構建LSTM模型 ==>訓練模型 ==> 保存模型
實驗過程(視頻):POX控制器開啟 ==> 拓撲搭建 ==> 全網互通 ==> 攻擊模擬 ==> 運行腳本(腳本內容放置在github上) ==> 返回結果
腳本流程:捕獲這2秒內網絡環境中的數據包 ==>生成初步處理數據集 ==>特征向量提取 ==>載入模型 ==>模型給出判斷
如果需要的話:
循環取值訓練,模型在訓練集(來自網絡)上的准確率曲線
隨機取值訓練,模型在訓練集(來自網絡)上的准確率曲線
(但是因為測試集和環境中模型表現很差,最終是重新自己針對實驗制作了數據集訓練了模型,可以完美符合這個小實驗的要求......很遺憾因為知識不足無法更好地改進模型以匹配真實網絡環境中的攻擊)
6.github鏈接
https://github.com/SilentSamsara/DDos-attack-detection/
7.分工和比例
學號 | 姓名 | 分工 | 比例 |
---|---|---|---|
031702627 | 李至恆 | 模型搭建和模型訓練 | 20% |
031702623 | 蔡嘉懿 | 數據集的獲取和特征向量提取的部分函數 | 20% |
031702625 | 楊藍宇 | 部分模型工作和運行腳本和演示工作 | 20% |
031702632 | 林華偉 | 拓撲環境搭建和pox控制器學習 | 20% |
031702634 | 徐祖豪 | 特征向量提取代碼主編 | 20% |
因為這次實驗大家一起在活動室坐了2天,難以量化數據,故取平均值
8.實驗感想
-
林華偉:這次實驗由於時間比較趕,和同學一起在活動室肝了兩天,期間大家一起分工並討論問題,我在這幾天學習了如何使用pox控制器連接拓撲,如何用hping3模擬DDos攻擊,如何編寫shell腳本執行tcpdump自動抓包並將pcap文件轉換為csv文件等等,這段時間通過實踐學到了很多東西,受益匪淺。
-
蔡嘉懿:這次大作業我們做的是深度學習檢測DDoS攻擊,選擇課題的難度較大,所以所有組員一起合作分工做了很久才完成。通過這個大作業感受到了研究課題的難度和學習的艱辛,但同時感受到更多的是收獲的知識以及團隊協同的精神。大家都很努力的在完成這次作業,看到最后的成果,真的是滿足在心中!
-
徐祖豪:SDN作為一門創新創業的課程的確是有其新穎性,通過這一學期的學習,從一開始的一竅不通到如今的掌握了很多新的概念,學習的過程還是很順利的。但是mininet作為核心工具卻只能運行在linux環境下,在這樣一個新的環境下編寫程序運行程序花了很多時間去試錯,但也正是在不停的實踐和試錯中才會有更深刻的理解。然后就是大作業的選題是報告時的惡意流量檢測,題目很新穎,但是大家都沒有機器學習中的分類問題的開發經驗,在數據集的選擇上一頭霧水,對於訓練集數據的采集也不夠具有代表性,訓練出來的模型的正確率不是很理想,剛好最近又有考試,也不能allin,的確有遺憾,下次努力吧
-
楊藍宇:大作業有點復雜,搞得我做得內心極其復雜,不是代碼有多難寫,而是Ubuntu和內部的條件太難懂了,但是我們團隊的人沒有放棄,嘗試了很多次Ubuntu的腳本結合python,有了一些起色,進行了很多次試驗,最后成功檢測感覺付出沒有白費。
-
李至恆:這次實驗真的讓人感覺頭很大,之前從來都沒有做過機器學習,從頭開始去看,映像最深的是第一天坐在活動室一整天都搭不出個模型,基礎實在太差了。模型做完以后本來以為基本完事了,結果訓練的時候又出現了問題,准確率不管怎么樣都上不去,而且原因太多了,排查成本也很大(訓練集問題啊,模型問題啊),最后是一切從簡,既然網絡中的DDOS攻擊檢測因為數據集的提取或者模型的選擇有問題無法很好擬合,那我們就針對這次實驗訓練模型(說白了就是測試集當訓練集的做法,哈哈),所以最終的模型的訓練集用的是自己提取的訓練集......但是不能說沒有意義,我們的模型無法契合現實,但是借用的思想未必是錯的,想想問題還是在於知識的匱乏,沒法很好的調整和選擇模型。我們在一起學習了很多,我們從數據集獲取,處理,導入模型,訓練模型,部署模型,拓撲搭建,攻擊模擬,結果展示,和隊友們一步一步走過來,完成了整個流程,我個人覺得還是很有意義的,感謝隊友們一路一起走來,想說的話真的太多太多。