From 631d7bf10485d5b31c76abd86c855110c59f836d Mon Sep 17 00:00:00 2001 From: 9nehS Date: Tue, 26 Sep 2017 16:13:25 +0800 Subject: [PATCH 001/156] Added FlowSet With Template ID 260 --- rb_netflow/rb_netflow.py | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/rb_netflow/rb_netflow.py b/rb_netflow/rb_netflow.py index 8473a14..250b02d 100644 --- a/rb_netflow/rb_netflow.py +++ b/rb_netflow/rb_netflow.py @@ -283,3 +283,40 @@ class Flow_v9(Packet): bind_layers( NetFlowTemplatev10Field, NetFlowTemplatev10FieldPEN, version=5) #bind_layers( NetflowHeaderV5, NetflowRecordV5 ) #bind_layers( NetflowRecordV5, NetflowRecordV5 ) + + +# FlowSet With Template ID 260 + +class Flow_260_v9(Packet): + name = "Element flow (v9) for template id 260" + fields_desc = [ + IntField('Packets', 1), + IntField('Octets', 1000), + IPField('SrcAddr', '11.11.11.11'), + IPField('DstAddr', '22.22.22.22'), + IntField('InputInt', 100), + IntField('OutputInt', 101), + IntField('EndTime', 3569615), + IntField('StartTime', 3569614), + ShortField("SrcPort", 8888), + ShortField("DstPort", 80), + IntField('SrcAS', 0), + IntField('DstAS', 0), + IPField('BGPNextHop', '0.0.0.0'), + ByteField("SrcMask", 24), + ByteField("DstMask", 24), + ByteField("Protocol", 6), + XByteField("TCPFlags", 0x10), + XByteField("IPToS", 0x00), + ByteField("Direction", 0), + XByteField("ForwardingStatus", 0x40), + ShortField("SamplerID", 2), + XIntField("IngressVRFID", 0x60000000), + XIntField("EgressVRFID", 0x60000000) + ] + + +bind_layers( NetFlowTemplatev10Field, NetFlowTemplatev10FieldPEN, version=5) +#bind_layers( NetflowHeaderV5, NetflowRecordV5 ) +#bind_layers( NetflowRecordV5, NetflowRecordV5 ) + From a959942b55aeebba3d33993364163dac55de1896 Mon Sep 17 00:00:00 2001 From: 9nehS Date: Tue, 26 Sep 2017 16:21:22 +0800 Subject: [PATCH 002/156] Rewrite pygennf_v9 to make it more powerful to use --- src/pygennf_v9.py | 227 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 177 insertions(+), 50 deletions(-) diff --git a/src/pygennf_v9.py b/src/pygennf_v9.py index fd5e9b3..0809936 100644 --- a/src/pygennf_v9.py +++ b/src/pygennf_v9.py @@ -1,7 +1,7 @@ -#!/usr/bin/env python2 +#!/bin/env python # # pygennf: UDP packets producer with scapy. -# Copyright (C) 2015-2016 Ana Rey +# Copyright (C) 2016-2017 Sheng Zhao # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -55,6 +55,8 @@ def main(): help='Port dst') parser.add_argument('-t', '--time-interval', dest='time_interval', help='Time interval to wait to send other messages.') + parser.add_argument('-c', '--pkt-count', dest='pkt_count', + help='Packets count before producer stops.') args = parser.parse_args() @@ -84,71 +86,196 @@ def main(): if args.time_interval: TIME_INTERVAL = args.time_interval else: - TIME_INTERVAL = 0 + TIME_INTERVAL = 1 + + if args.pkt_count: + PKT_COUNT = int(args.pkt_count) + else: + # 0xFFFFFFFF - 1 + PKT_COUNT = 4294967294 signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler) - header_v9 = rbnf.Netflow_Headerv9(version=9, count= 2, SysUptime=0x000069d7, Timestamp=1392292623, FlowSequence= 0,SourceId= 243) + flow_sequence = 1 + + gen_send_pkt('tmpl', flow_sequence=flow_sequence) - flowSet_header_v9 = rbnf.FlowSet_Header_v9(FlowSet_id= 0, FlowSet_length=80) + while TIME_INTERVAL is not 0: + if signal_received == 1: + print "\nSignal received. %s packets have been sent. Stopping and Exiting..." % flow_sequence + sys.exit(0) + time.sleep(float(TIME_INTERVAL)) - flowset_id_v9 = rbnf.FlowTemplate_ID_v9(template_id=258,count=18) + flow_sequence = flow_sequence + 1 + if flow_sequence > PKT_COUNT: + print "\nPackets count[%s] reached. Stopping and Exitting..." % PKT_COUNT + sys.exit(0) + if flow_sequence % 100 == 0: + gen_send_pkt('tmpl', flow_sequence=flow_sequence) + continue + gen_send_pkt('data', flow_sequence) + + +def gen_send_pkt(pkt_type='data', flow_sequence=1): + timestamp = int(time.time()) + if pkt_type == 'tmpl': + pkt_netflow_tmpl = gen_pkt_netflow_tmpl(timestamp=timestamp, flow_sequence=flow_sequence) + wrpcap('v9_test_tmpl.pcap', pkt_netflow_tmpl) + send(pkt_netflow_tmpl) + elif pkt_type == 'data': + sys_uptime = 3600 * 1000 + pkt_netflow_data = gen_pkt_netflow_data(timestamp=timestamp, sys_uptime=sys_uptime, flow_sequence=flow_sequence) + wrpcap('v9_test_data.pcap', pkt_netflow_data) + send(pkt_netflow_data) + + +def gen_pkt_netflow_data(timestamp=1503652676, flow_sequence=1, sys_uptime=3600000, src_ip='121.41.5.67', dst_ip='121.41.5.68', sport=2056, dport=2055): + header_v9 = rbnf.Netflow_Headerv9(version=9, count=1, SysUptime=0x000069d7, Timestamp=timestamp, + FlowSequence=flow_sequence, SourceId=2177) + flowset_flow_header_v9 = rbnf.FlowSet_Header_v9(FlowSet_id=260, FlowSet_length=72) + + # List for SrcAddr and DstAddr in netflow data + src_dst_addr_list = [] + src_dst_addr_list.append(['69.31.102.10', '209.81.108.20']) + src_dst_addr_list.append(['70.32.103.11', '210.81.108.21']) + src_dst_addr_list.append(['70.32.103.12', '210.81.108.22']) + src_dst_addr_list.append(['70.32.103.13', '210.81.108.23']) + src_dst_addr_list.append(['70.32.103.14', '210.81.108.24']) + src_dst_addr_list.append(['70.32.103.15', '210.81.108.25']) + src_dst_addr_list.append(['70.32.103.16', '210.81.108.26']) + src_dst_addr_list.append(['70.32.103.17', '210.81.108.27']) + src_dst_addr_list.append(['70.32.103.18', '210.81.108.28']) + src_dst_addr_list.append(['70.32.103.19', '210.81.108.29']) + src_dst_addr_list.append(['70.32.103.20', '210.81.108.30']) + src_dst_addr_list.append(['70.32.103.21', '210.81.108.31']) + src_dst_addr_list.append(['70.32.103.22', '210.81.108.32']) + src_dst_addr_list.append(['70.32.103.23', '210.81.108.33']) + src_dst_addr_list.append(['70.32.103.24', '210.81.108.34']) + src_dst_addr_list.append(['70.32.103.25', '210.81.108.35']) + src_dst_addr_list.append(['70.32.103.26', '210.81.108.36']) + src_dst_addr_list.append(['70.32.103.27', '210.81.108.37']) + src_dst_addr_list.append(['70.32.103.28', '210.81.108.38']) + src_dst_addr_list.append(['70.32.103.29', '210.81.108.39']) + src_dst_addr_list.append(['70.32.103.30', '210.81.108.40']) + src_dst_port_list = [] + src_dst_port_list.append([12345, 80]) + + # List for flows in one packet + flows = [] + for src_dst_addr in src_dst_addr_list: + #end_time = sys_uptime + 3600 * 1000 + end_time = timestamp + start_time = end_time - 1000 # Duration 1s + flows.append(rbnf.Flow_260_v9( + Packets=1, Octets=1024, SrcAddr=src_dst_addr[0], DstAddr=src_dst_addr[1], InputInt=145, OutputInt=142, + EndTime=end_time, StartTime=start_time, SrcPort=src_dst_port_list[0][0], DstPort=src_dst_port_list[0][1], + SrcAS=0, DstAS=0, BGPNextHop='0.0.0.0', SrcMask=17, DstMask=28, Protocol=6, TCPFlags=0x10, IPToS=0x00, + Direction=0, ForwardingStatus=0x40, SamplerID=2, IngressVRFID=0x60000000, EgressVRFID=0x60000000 + )) + + # Calculate the length of netflow data before padding + len_netflow = 0 + len_netflow = calc_netflow_len(header_v9, flowset_flow_header_v9, flows) + pad_len = 0 + pad = None + print 'len_netflow:', len_netflow + len_after_padding = 0 + + # Padding to make sure that FlowSet starts at a 4-byte aligned boundary -- rfc3954.txt + if len_netflow % 4 != 0: + len_after_padding = ((len_netflow / 4) + 1) * 4 + pad_len = len_after_padding - len_netflow + print 'pad_len:', pad_len + else: + len_after_padding = len_netflow - template = [ - rbnf.NetFlowTemplatev9Field(type_template=1, length= 4), + header_v9.setfieldval('count', len(flows)) + flowset_flow_header_v9.setfieldval('FlowSet_length', len_after_padding - 20) + pkt_netflow_data = IP(src=src_ip, dst=dst_ip, len=len_after_padding + 28) / UDP(sport=sport, dport=dport, + len=len_after_padding + 8) + pkt_netflow_data /= header_v9 / flowset_flow_header_v9 + for flow in flows: + pkt_netflow_data /= flow + + if pad_len > 0: + pad = Padding() + pad.load = '\x00' * pad_len + pkt_netflow_data = pkt_netflow_data / pad + + return pkt_netflow_data + + +def calc_netflow_len(header, flowset_flow_header, flows): + len_netflow = 0 + len_netflow = len(header) + len(flowset_flow_header) + for flow in flows: + len_netflow = len_netflow + len(flow) + + return len_netflow + + +def gen_pkt_netflow_tmpl(timestamp=1503652676, flow_sequence=1, source_id=2177, template_id=260, src_ip='121.41.5.67', dst_ip='121.41.5.68', sport=2056, dport=2055): + header_v9 = rbnf.Netflow_Headerv9(version=9, count=1, SysUptime=0x000069d7, Timestamp=timestamp, FlowSequence=flow_sequence,SourceId=source_id) + flowset_tmpl_header_v9 = rbnf.FlowSet_Header_v9(FlowSet_id=0, FlowSet_length=100) + flowset_tmpl_data_header_v9 = rbnf.FlowTemplate_ID_v9(template_id=template_id,count=23) + flowset_tmpl_data_260_v9 = [ + # Field (1/23): PKTS, Type: 2, Length: 4 rbnf.NetFlowTemplatev9Field(type_template=2, length= 4), - rbnf.NetFlowTemplatev9Field(type_template=4, length= 1), - rbnf.NetFlowTemplatev9Field(type_template=5, length= 1), - rbnf.NetFlowTemplatev9Field(type_template=6, length= 1), + # Field (2/23): BYTES, Type: 1, Length: 4 + rbnf.NetFlowTemplatev9Field(type_template=1, length= 4), + # Field (3/23): IP_SRC_ADDR, Type: 8, Length: 4 + rbnf.NetFlowTemplatev9Field(type_template=8, length= 4), + # Field (4/23): IP_DST_ADDR, Type: 12, Length: 4 + rbnf.NetFlowTemplatev9Field(type_template=12, length= 4), + # Field (5/23): INPUT_SNMP, Type: 10, Length: 4 + rbnf.NetFlowTemplatev9Field(type_template=10, length= 4), + # Field (6/23): OUTPUT_SNMP, Type: 14, Length: 4 + rbnf.NetFlowTemplatev9Field(type_template=14, length= 4), + # Field (7/23): LAST_SWITCHED, Type: 21, Length: 4 + rbnf.NetFlowTemplatev9Field(type_template=21, length= 4), + # Field (8/23): FIRST_SWITCHED, Type: 22, Length: 4 + rbnf.NetFlowTemplatev9Field(type_template=22, length= 4), + # Field (9/23): L4_SRC_PORT, Type: 7, Length: 2 rbnf.NetFlowTemplatev9Field(type_template=7, length= 2), - rbnf.NetFlowTemplatev9Field(type_template=10, length= 2), + # Field (10/23): L4_DST_PORT, Type: 11, Length: 2 rbnf.NetFlowTemplatev9Field(type_template=11, length= 2), - rbnf.NetFlowTemplatev9Field(type_template=14, length= 2), + # Field (11/23): SRC_AS, Type: 16, Length: 4 rbnf.NetFlowTemplatev9Field(type_template=16, length= 4), + # Field (12/23): DST_AS, Type: 17, Length: 4 rbnf.NetFlowTemplatev9Field(type_template=17, length= 4), - rbnf.NetFlowTemplatev9Field(type_template=21, length= 4), - rbnf.NetFlowTemplatev9Field(type_template=22, length= 4), - rbnf.NetFlowTemplatev9Field(type_template=27, length= 16), - rbnf.NetFlowTemplatev9Field(type_template=28, length= 16), - rbnf.NetFlowTemplatev9Field(type_template=29, length= 1), - rbnf.NetFlowTemplatev9Field(type_template=30, length= 1), - rbnf.NetFlowTemplatev9Field(type_template=62, length= 16) - ] - - flowSet_2_header = rbnf.FlowSet_Header_v9(FlowSet_id= 258, FlowSet_length=92) - - - flows = [ - rbnf.Flow_v9(\ - Packets=826, Protocol=17, IP_ToS=0x00, TCP_Flags=0x00, Octets=113162,\ - SrcPort=2416, InputInt=0, DstPort=53, OutputInt=0, SrcAS=0, DstAS=0,\ - StartTime=0x000069b5, EndTime=0x00000002,\ - SrcAddr="3ffe:507:0:1:200:86ff:fe05:80da",\ - DstAddr="3ffe:501:4819::42", SrcMask=0, DstMask=0, NextHop="::", - Padding=3) + # Field (13/23): BGP_NEXT_HOP, Type: 18, Length: 4 + rbnf.NetFlowTemplatev9Field(type_template=18, length= 4), + # Field (14/23): SRC_MASK, Type: 9, Length: 1 + rbnf.NetFlowTemplatev9Field(type_template=9, length= 1), + # Field (15/23): DST_MASK, Type: 13, Length: 1 + rbnf.NetFlowTemplatev9Field(type_template=13, length= 1), + # Field (16/23): PROTOCOL, Type: 4, Length: 1 + rbnf.NetFlowTemplatev9Field(type_template=4, length= 1), + # Field (17/23): TCP_FLAGS, Type: 6, Length: 1 + rbnf.NetFlowTemplatev9Field(type_template=6, length= 1), + # Field (18/23): IP_TOS, Type: 5, Length: 1 + rbnf.NetFlowTemplatev9Field(type_template=5, length= 1), + # Field (19/23): DIRECTION, Type: 61, Length: 1 + rbnf.NetFlowTemplatev9Field(type_template=61, length=1), + # Field (20/23): FORWARDING_STATUS, Type: 89, Length: 1 + rbnf.NetFlowTemplatev9Field(type_template=89, length=1), + # Field (21/23): FLOW_SAMPLER_ID, Type: 48, Length: 2 + rbnf.NetFlowTemplatev9Field(type_template=48, length=2), + # Field (22/23): ingressVRFID, Type: 234, Length: 4 + rbnf.NetFlowTemplatev9Field(type_template=234, length=4), + # Field (23/23): egressVRFID, Type: 235, Length: 4 + rbnf.NetFlowTemplatev9Field(type_template=235, length=4) ] - data = IP(src=IP_SRC,dst=IP_DST)/UDP(sport=PORT_SRC,dport=PORT_DST) - data/=header_v9/flowSet_header_v9/flowset_id_v9 - - for t in template: - data/=t - - data/=flowSet_2_header + pkt_netflow_tmpl = IP(src=src_ip,dst=dst_ip)/UDP(sport=sport,dport=dport) + pkt_netflow_tmpl/=header_v9/flowset_tmpl_header_v9/flowset_tmpl_data_header_v9 - for f in flows: - data/=f + for t in flowset_tmpl_data_260_v9: + pkt_netflow_tmpl/=t - wrpcap('v9.pcap', data) - send(data) + return pkt_netflow_tmpl - while TIME_INTERVAL is not 0: - if signal_received == 1: - print "\nSignal received. Stopping and Exitting..." - sys.exit(0) - time.sleep(float(TIME_INTERVAL)) - send(data) if __name__ == '__main__': main() From b7753e98dad72c06c2e6df70ca597dae7f600d0f Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 26 Sep 2017 16:30:24 +0800 Subject: [PATCH 003/156] Update setup personal message --- setup.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/setup.py b/setup.py index 8871f01..3b6aeae 100644 --- a/setup.py +++ b/setup.py @@ -1,11 +1,11 @@ from setuptools import setup setup(name="pygennf", - version="0.1", + version="0.11", description="UDP packets producer with scapy", - author="Ana Rey", - author_email="anarey@redborder.com", - url="https://github.com/redBorder/", + author="Sheng Zhao", + author_email="sheng.zhao@calix.com", + url="https://github.com/9nehS/", license="AGPL", scripts=["src/pygennf_v5.py", "src/pygennf_v9.py", "src/pygennf_v10.py" ], packages=['rb_netflow'], From aab9e061863ec0fd8f2283a5b98f42cf62ff3685 Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 26 Sep 2017 16:52:56 +0800 Subject: [PATCH 004/156] Add sport and dport for gen_send_pkt() --- src/pygennf_v9.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/pygennf_v9.py b/src/pygennf_v9.py index 0809936..1f2fe8c 100644 --- a/src/pygennf_v9.py +++ b/src/pygennf_v9.py @@ -99,7 +99,7 @@ def main(): flow_sequence = 1 - gen_send_pkt('tmpl', flow_sequence=flow_sequence) + gen_send_pkt('tmpl', flow_sequence=flow_sequence, sport=PORT_SRC, dport=PORT_DST) while TIME_INTERVAL is not 0: if signal_received == 1: @@ -112,12 +112,12 @@ def main(): print "\nPackets count[%s] reached. Stopping and Exitting..." % PKT_COUNT sys.exit(0) if flow_sequence % 100 == 0: - gen_send_pkt('tmpl', flow_sequence=flow_sequence) + gen_send_pkt('tmpl', flow_sequence=flow_sequence, sport=PORT_SRC, dport=PORT_DST) continue - gen_send_pkt('data', flow_sequence) + gen_send_pkt('data', flow_sequence, sport=PORT_SRC, dport=PORT_DST) -def gen_send_pkt(pkt_type='data', flow_sequence=1): +def gen_send_pkt(pkt_type='data', flow_sequence=1, sport=2056, dport=2055): timestamp = int(time.time()) if pkt_type == 'tmpl': pkt_netflow_tmpl = gen_pkt_netflow_tmpl(timestamp=timestamp, flow_sequence=flow_sequence) @@ -125,7 +125,8 @@ def gen_send_pkt(pkt_type='data', flow_sequence=1): send(pkt_netflow_tmpl) elif pkt_type == 'data': sys_uptime = 3600 * 1000 - pkt_netflow_data = gen_pkt_netflow_data(timestamp=timestamp, sys_uptime=sys_uptime, flow_sequence=flow_sequence) + pkt_netflow_data = gen_pkt_netflow_data(timestamp=timestamp, sys_uptime=sys_uptime, flow_sequence=flow_sequence, + sport=sport, dport=dport) wrpcap('v9_test_data.pcap', pkt_netflow_data) send(pkt_netflow_data) From 00d3ff31e1c28c9c0fbefb305aeb43b312560c99 Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 26 Sep 2017 17:04:05 +0800 Subject: [PATCH 005/156] Add src_ip and dst_ip for gen_send_pkt() --- src/pygennf_v9.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/pygennf_v9.py b/src/pygennf_v9.py index 1f2fe8c..3fa0b63 100644 --- a/src/pygennf_v9.py +++ b/src/pygennf_v9.py @@ -99,7 +99,7 @@ def main(): flow_sequence = 1 - gen_send_pkt('tmpl', flow_sequence=flow_sequence, sport=PORT_SRC, dport=PORT_DST) + gen_send_pkt('tmpl', flow_sequence=flow_sequence, src_ip=IP_SRC, dst_ip=IP_DST, sport=PORT_SRC, dport=PORT_DST) while TIME_INTERVAL is not 0: if signal_received == 1: @@ -112,21 +112,23 @@ def main(): print "\nPackets count[%s] reached. Stopping and Exitting..." % PKT_COUNT sys.exit(0) if flow_sequence % 100 == 0: - gen_send_pkt('tmpl', flow_sequence=flow_sequence, sport=PORT_SRC, dport=PORT_DST) + gen_send_pkt('tmpl', flow_sequence=flow_sequence, src_ip=IP_SRC, dst_ip=IP_DST, + sport=PORT_SRC, dport=PORT_DST) continue - gen_send_pkt('data', flow_sequence, sport=PORT_SRC, dport=PORT_DST) + gen_send_pkt('data', flow_sequence, src_ip=IP_SRC, dst_ip=IP_DST, sport=PORT_SRC, dport=PORT_DST) -def gen_send_pkt(pkt_type='data', flow_sequence=1, sport=2056, dport=2055): +def gen_send_pkt(pkt_type='data', flow_sequence=1, src_ip='1.1.1.1', dst_ip = '2.2.2.2', sport=2056, dport=2055): timestamp = int(time.time()) if pkt_type == 'tmpl': - pkt_netflow_tmpl = gen_pkt_netflow_tmpl(timestamp=timestamp, flow_sequence=flow_sequence) + pkt_netflow_tmpl = gen_pkt_netflow_tmpl(timestamp=timestamp, flow_sequence=flow_sequence, + src_ip=src_ip, dst_ip =dst_ip, sport=sport, dport=dport) wrpcap('v9_test_tmpl.pcap', pkt_netflow_tmpl) send(pkt_netflow_tmpl) elif pkt_type == 'data': sys_uptime = 3600 * 1000 pkt_netflow_data = gen_pkt_netflow_data(timestamp=timestamp, sys_uptime=sys_uptime, flow_sequence=flow_sequence, - sport=sport, dport=dport) + src_ip=src_ip, dst_ip=dst_ip, sport=sport, dport=dport) wrpcap('v9_test_data.pcap', pkt_netflow_data) send(pkt_netflow_data) From 5b0782626488c8b53a1d060b4672cc0a1159c1e6 Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 26 Sep 2017 17:32:21 +0800 Subject: [PATCH 006/156] Set verbose=0 in send() --- src/pygennf_v9.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pygennf_v9.py b/src/pygennf_v9.py index 3fa0b63..cfc8be2 100644 --- a/src/pygennf_v9.py +++ b/src/pygennf_v9.py @@ -124,13 +124,13 @@ def gen_send_pkt(pkt_type='data', flow_sequence=1, src_ip='1.1.1.1', dst_ip = '2 pkt_netflow_tmpl = gen_pkt_netflow_tmpl(timestamp=timestamp, flow_sequence=flow_sequence, src_ip=src_ip, dst_ip =dst_ip, sport=sport, dport=dport) wrpcap('v9_test_tmpl.pcap', pkt_netflow_tmpl) - send(pkt_netflow_tmpl) + send(pkt_netflow_tmpl, verbose=0) elif pkt_type == 'data': sys_uptime = 3600 * 1000 pkt_netflow_data = gen_pkt_netflow_data(timestamp=timestamp, sys_uptime=sys_uptime, flow_sequence=flow_sequence, src_ip=src_ip, dst_ip=dst_ip, sport=sport, dport=dport) wrpcap('v9_test_data.pcap', pkt_netflow_data) - send(pkt_netflow_data) + send(pkt_netflow_data, verbose=0) def gen_pkt_netflow_data(timestamp=1503652676, flow_sequence=1, sys_uptime=3600000, src_ip='121.41.5.67', dst_ip='121.41.5.68', sport=2056, dport=2055): From 0d57b0517ccb084e273a20abf5a612c2fc3e7c1b Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 26 Sep 2017 17:39:59 +0800 Subject: [PATCH 007/156] Added stdout.write() in gen_send_pkt() --- src/pygennf_v9.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pygennf_v9.py b/src/pygennf_v9.py index cfc8be2..7e3acaf 100644 --- a/src/pygennf_v9.py +++ b/src/pygennf_v9.py @@ -124,12 +124,14 @@ def gen_send_pkt(pkt_type='data', flow_sequence=1, src_ip='1.1.1.1', dst_ip = '2 pkt_netflow_tmpl = gen_pkt_netflow_tmpl(timestamp=timestamp, flow_sequence=flow_sequence, src_ip=src_ip, dst_ip =dst_ip, sport=sport, dport=dport) wrpcap('v9_test_tmpl.pcap', pkt_netflow_tmpl) + sys.stdout.write("Sending packet: %d" % (flow_sequence)) send(pkt_netflow_tmpl, verbose=0) elif pkt_type == 'data': sys_uptime = 3600 * 1000 pkt_netflow_data = gen_pkt_netflow_data(timestamp=timestamp, sys_uptime=sys_uptime, flow_sequence=flow_sequence, src_ip=src_ip, dst_ip=dst_ip, sport=sport, dport=dport) wrpcap('v9_test_data.pcap', pkt_netflow_data) + sys.stdout.write("Sending packet: %d" % (flow_sequence)) send(pkt_netflow_data, verbose=0) From f5be354d07706a307d81cea2a068f5d022332092 Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 26 Sep 2017 17:43:50 +0800 Subject: [PATCH 008/156] Replace print with sys.stdout.write() --- src/pygennf_v9.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/pygennf_v9.py b/src/pygennf_v9.py index 7e3acaf..e54de15 100644 --- a/src/pygennf_v9.py +++ b/src/pygennf_v9.py @@ -124,15 +124,17 @@ def gen_send_pkt(pkt_type='data', flow_sequence=1, src_ip='1.1.1.1', dst_ip = '2 pkt_netflow_tmpl = gen_pkt_netflow_tmpl(timestamp=timestamp, flow_sequence=flow_sequence, src_ip=src_ip, dst_ip =dst_ip, sport=sport, dport=dport) wrpcap('v9_test_tmpl.pcap', pkt_netflow_tmpl) - sys.stdout.write("Sending packet: %d" % (flow_sequence)) + sys.stdout.write("Sending packet: %d\n" % (flow_sequence)) send(pkt_netflow_tmpl, verbose=0) + sys.stdout.flush() elif pkt_type == 'data': sys_uptime = 3600 * 1000 pkt_netflow_data = gen_pkt_netflow_data(timestamp=timestamp, sys_uptime=sys_uptime, flow_sequence=flow_sequence, src_ip=src_ip, dst_ip=dst_ip, sport=sport, dport=dport) wrpcap('v9_test_data.pcap', pkt_netflow_data) - sys.stdout.write("Sending packet: %d" % (flow_sequence)) + sys.stdout.write("Sending packet: %d\n" % (flow_sequence)) send(pkt_netflow_data, verbose=0) + sys.stdout.flush() def gen_pkt_netflow_data(timestamp=1503652676, flow_sequence=1, sys_uptime=3600000, src_ip='121.41.5.67', dst_ip='121.41.5.68', sport=2056, dport=2055): @@ -184,14 +186,16 @@ def gen_pkt_netflow_data(timestamp=1503652676, flow_sequence=1, sys_uptime=36000 len_netflow = calc_netflow_len(header_v9, flowset_flow_header_v9, flows) pad_len = 0 pad = None - print 'len_netflow:', len_netflow + #print 'len_netflow:', len_netflow + sys.stdout.write("len_netflow: %d\n" % (len_netflow)) len_after_padding = 0 # Padding to make sure that FlowSet starts at a 4-byte aligned boundary -- rfc3954.txt if len_netflow % 4 != 0: len_after_padding = ((len_netflow / 4) + 1) * 4 pad_len = len_after_padding - len_netflow - print 'pad_len:', pad_len + #print 'pad_len:', pad_len + sys.stdout.write("pad_len: %d\n" % (pad_len)) else: len_after_padding = len_netflow From 804b1f4ad7b05b63ab4b33b815f34edf1fd09ae1 Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 26 Sep 2017 17:48:30 +0800 Subject: [PATCH 009/156] Added '\r\n' in sys.stdout.write() in gen_send_pkt() --- src/pygennf_v9.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pygennf_v9.py b/src/pygennf_v9.py index e54de15..07b169f 100644 --- a/src/pygennf_v9.py +++ b/src/pygennf_v9.py @@ -124,7 +124,7 @@ def gen_send_pkt(pkt_type='data', flow_sequence=1, src_ip='1.1.1.1', dst_ip = '2 pkt_netflow_tmpl = gen_pkt_netflow_tmpl(timestamp=timestamp, flow_sequence=flow_sequence, src_ip=src_ip, dst_ip =dst_ip, sport=sport, dport=dport) wrpcap('v9_test_tmpl.pcap', pkt_netflow_tmpl) - sys.stdout.write("Sending packet: %d\n" % (flow_sequence)) + sys.stdout.write("Sending packet: %d \r\n" % (flow_sequence)) send(pkt_netflow_tmpl, verbose=0) sys.stdout.flush() elif pkt_type == 'data': @@ -132,7 +132,7 @@ def gen_send_pkt(pkt_type='data', flow_sequence=1, src_ip='1.1.1.1', dst_ip = '2 pkt_netflow_data = gen_pkt_netflow_data(timestamp=timestamp, sys_uptime=sys_uptime, flow_sequence=flow_sequence, src_ip=src_ip, dst_ip=dst_ip, sport=sport, dport=dport) wrpcap('v9_test_data.pcap', pkt_netflow_data) - sys.stdout.write("Sending packet: %d\n" % (flow_sequence)) + sys.stdout.write("Sending packet: %d \r\n" % (flow_sequence)) send(pkt_netflow_data, verbose=0) sys.stdout.flush() From 15f000cdd3cc1abd2c1d423f33f35d888830a6dd Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 26 Sep 2017 17:54:03 +0800 Subject: [PATCH 010/156] Not to display len_flow and len_padding --- src/pygennf_v9.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pygennf_v9.py b/src/pygennf_v9.py index 07b169f..b30bd73 100644 --- a/src/pygennf_v9.py +++ b/src/pygennf_v9.py @@ -124,7 +124,7 @@ def gen_send_pkt(pkt_type='data', flow_sequence=1, src_ip='1.1.1.1', dst_ip = '2 pkt_netflow_tmpl = gen_pkt_netflow_tmpl(timestamp=timestamp, flow_sequence=flow_sequence, src_ip=src_ip, dst_ip =dst_ip, sport=sport, dport=dport) wrpcap('v9_test_tmpl.pcap', pkt_netflow_tmpl) - sys.stdout.write("Sending packet: %d \r\n" % (flow_sequence)) + sys.stdout.write("Sending packet: %d \r" % (flow_sequence)) send(pkt_netflow_tmpl, verbose=0) sys.stdout.flush() elif pkt_type == 'data': @@ -132,7 +132,7 @@ def gen_send_pkt(pkt_type='data', flow_sequence=1, src_ip='1.1.1.1', dst_ip = '2 pkt_netflow_data = gen_pkt_netflow_data(timestamp=timestamp, sys_uptime=sys_uptime, flow_sequence=flow_sequence, src_ip=src_ip, dst_ip=dst_ip, sport=sport, dport=dport) wrpcap('v9_test_data.pcap', pkt_netflow_data) - sys.stdout.write("Sending packet: %d \r\n" % (flow_sequence)) + sys.stdout.write("Sending packet: %d \r" % (flow_sequence)) send(pkt_netflow_data, verbose=0) sys.stdout.flush() @@ -187,7 +187,7 @@ def gen_pkt_netflow_data(timestamp=1503652676, flow_sequence=1, sys_uptime=36000 pad_len = 0 pad = None #print 'len_netflow:', len_netflow - sys.stdout.write("len_netflow: %d\n" % (len_netflow)) + #sys.stdout.write("len_netflow: %d\n" % (len_netflow)) len_after_padding = 0 # Padding to make sure that FlowSet starts at a 4-byte aligned boundary -- rfc3954.txt @@ -195,7 +195,7 @@ def gen_pkt_netflow_data(timestamp=1503652676, flow_sequence=1, sys_uptime=36000 len_after_padding = ((len_netflow / 4) + 1) * 4 pad_len = len_after_padding - len_netflow #print 'pad_len:', pad_len - sys.stdout.write("pad_len: %d\n" % (pad_len)) + #sys.stdout.write("pad_len: %d\n" % (pad_len)) else: len_after_padding = len_netflow From 58751bb3a35802f8b943891691baf26600de0ea6 Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 26 Sep 2017 18:48:36 +0800 Subject: [PATCH 011/156] Add info message in main() --- src/pygennf_v9.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/pygennf_v9.py b/src/pygennf_v9.py index b30bd73..4e335fc 100644 --- a/src/pygennf_v9.py +++ b/src/pygennf_v9.py @@ -40,6 +40,14 @@ def signal_handler(signal, frame): # Netflow9 def main(): + + print "\n****************************" + print "* Flow Generator Ver. 0.11 *" + print "* Modified by Sheng Zhao *" + print "* Calix Cloud SIT *" + print "* sheng.zhao@calix.com *" + print "****************************\n\n" + if os.getuid() != 0: print "You need to be root to run this, sorry." return From bba99fe2884d24640b7b57448fb955e73925d11b Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 27 Sep 2017 09:54:08 +0800 Subject: [PATCH 012/156] Update install part --- README.md | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 4e8c6d7..d205e5f 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,10 @@ # pygennf -Netflow packets generator with Scape library - -* Download it! [https://github.com/redBorder/pygennf/tree/master/download] - - > rpm: (python2.6) wget https://github.com/redBorder/pygennf/raw/master/download/pygennf-0.1-1.noarch.rpm - - > tar.gz: wget https://github.com/redBorder/pygennf/raw/master/download/pygennf-0.1.tar.gz +Netflow packets generator with Scapy library * How to install: -python setup.py install - -* How to install the rpm packege: -rpm -vUh pygennf-0.1-1.noarch.rpm +> git clone https://github.com/9nehS/pygennf.git +> python setup.py install # Usage (without installation): From 2f1376ffb26e5cd7a2e8f4e17867060f62933ba7 Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 27 Sep 2017 09:56:21 +0800 Subject: [PATCH 013/156] Update install part --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d205e5f..ca9b3b5 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ Netflow packets generator with Scapy library * How to install: > git clone https://github.com/9nehS/pygennf.git +> > python setup.py install # Usage (without installation): From 45dbfc61fd953e1a3216adf0927627379a89bc00 Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 27 Sep 2017 09:57:43 +0800 Subject: [PATCH 014/156] Delete .rpm and .tar.gz --- pygennf-0.1-1.noarch.rpm | Bin 15692 -> 0 bytes pygennf-0.1.tar.gz | Bin 5571 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 pygennf-0.1-1.noarch.rpm delete mode 100644 pygennf-0.1.tar.gz diff --git a/pygennf-0.1-1.noarch.rpm b/pygennf-0.1-1.noarch.rpm deleted file mode 100644 index 400c8f6a2457e9eacd80f53b796df3e101dc92ec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15692 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 A?EnA( diff --git a/pygennf-0.1.tar.gz b/pygennf-0.1.tar.gz deleted file mode 100644 index 89e82bc8061d3bae60128418944c0371a4336fc7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5571 zcmV;!6+G%6iwFqnKL%F<|72-%bT4puXJu|~W-Tx-F)nmrascf;`*Yhi()qRgD{%7M zSZZYo03Q-H$MzD(X+7848avJPCe3JQk+OM_DIQ5V_V?F+3-ATfltf8>-Vy24BC!jC zi+zF%z`wh6Ja2k{Wzu`|NCiXbYa0IxrTmxwCbW-A zZ-V(eS_QYRzWj2pr1--4hfcKc<;nE&5yoFv)#c;gS4!ir>bU;~;b#0Fy?k~qFUPJo zoqv%c>vDXtaA!6$5x=ml$bsLOUxYW_IB;&<(4Bkyru3#MufK@$e{H$m*qa)%fA{e6 zuXFh)eGQ9$S<(6=m4BjXI+K4**R>~>f6KE1XT^K3tAC~PzxS8kA`E&LuGe$C8|2?b zS96a_l6&pXg9ur{rEdkHlidg>mVYNrgZXv*Q?_O^l+=BnK?N6M&xxk9`8PTLiL4MR zys0GZp_BNQAxXUX05nSaDEV!0xwv+`XvAyUwi8YQ*N;H&nESuKA0gkGe08D_`N7;? zOaS+r8(qb{+3zIn$(C)8t)!v${z16kMf(Q_;d~KHoCDW~OK3MT_rqW^W|tDGC|AzR zH}{W6D8^gfx?gCXk)ZH^_{NGyj2O}EFk1QqJAMFwh@FSa-8*mldE14av(`81xde@d zFp$Y(_#gJ5unl$Ylnrnw$MhcZ7LP~c^RvTv=+hd>nT1ZNx<#;zWr`JBYOKy&BLe-@56alnvw&pCe_+t84zz)(q34iJs+_2olS@k?6K zPVcxjYYC;7GsnA(uFL^Wn+rKisi}|7wLb$NV|@IcwH2k8&=}PQ-T3Xu0NO~a0Q)ni zTS^+SnH%GS>&)zSbmu$c6vHH4l=KFvo$iLnbQfebM7- zov_uNu=QQWn)G*Kv)!0=f3ti{fUvlk76a80D`7wo6 zR(}S~)L&6?F*w%1pP6AD#XgNWpumQsU>?mU^BLzVuw5VL=UlCWLO&dhKg_JlFu6XR zL=1}%g}~e7&7B7mW|&Q?GPXYU{6%yOx)dnC5UA$7=+_d8?3MyI|Q8` zxRdRWnPf9H>0LX&WFQ=|XJ)3bch5NX3ib`gdmf+&xgJUxEw=P=JCT$$Smv@AZ_4m^ zdm<8e%+j~O2M4#ke*@7O{9sNR)ODoL@$7c|bLaSP^pBqpj!! z@Xh?sQC3$dmbXFL3O4^8gsXC%s)j%oz;PThBsg&RueS;9OhoY>48x`|kjM z!QmOU^s75@Jn*5>+n-0jO7HUs5xRBqkCW4Xo=77QJrJqu{7y63vqt{&P`&ry^1s>q zzXq4h{QonK|9I?rZZsZ0$W-8(`9Dk*nv6eI!C`rW!B2qdX8!Lf=KuEg(8nt`L{oR> zAo%NpuZQN-O!+f_bH`b!!#Pl*zR};RH1>~D_8_nomw|Q7pS8G{x#5*#qlL#jZKlo9 zEY|Ifx_(ai7bb9b*8qb5S0VpYA({&EuTu>?K@C$T|Ef+J`F|SuuNMDv?!yVP52F9= z+c!CMCbn}U&x6Yz2=c$3Nfh?DzlT`-ay<{A6_5E{7IVi!*23Z3zYE;Us|d9ZJ7{#} z&RpMj&^xHNUGz5}Zu~uOmT8K$io!ymDQ;+{EB3N43h0xDENC9UY;1UEJ3(`;5Y7A<#KE*HJtl(n{u%A$BGm9wzVAFI=N%RF4}%WTO@;-|Q2q z^KLLY>tB!0Aj8YyPW2~@V=sja)A{pS&c^wxk**&G6L?UIeeHmMt!16e5$rJ91i^D|AxQIUport)@`egUe$GZgE`ti

alqYfBe3#BwN@13^*8i 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 RDgUG8{{glAadrU6008gD22}t6 From 067260c1132db326b1f31686f057cef4cdcfc22c Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 27 Sep 2017 10:28:15 +0800 Subject: [PATCH 015/156] Add args.protocol in order to specify protocol --- src/pygennf_v9.py | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/pygennf_v9.py b/src/pygennf_v9.py index 4e335fc..0ceff47 100644 --- a/src/pygennf_v9.py +++ b/src/pygennf_v9.py @@ -28,6 +28,7 @@ signal_received = 0 +dic_protocol_num = {'tcp': 6, 'udp': 17} def preexec(): os.setpgrp() # Don't forward signals @@ -65,6 +66,8 @@ def main(): help='Time interval to wait to send other messages.') parser.add_argument('-c', '--pkt-count', dest='pkt_count', help='Packets count before producer stops.') + parser.add_argument('-p', '--protocol', dest='protocol', + help='Protocols included in netflow data part.') args = parser.parse_args() @@ -102,6 +105,15 @@ def main(): # 0xFFFFFFFF - 1 PKT_COUNT = 4294967294 + if args.protocol: + try: + PROTOCOL_NUM = dic_protocol_num[args.protocol] + except KeyError: + print "'%s' cannot be mapped to existing protocols, use TCP[6] as default" % (args.protocol) + PROTOCOL_NUM = 6 + else: + PROTOCOL_NUM = 6 # TCP by default + signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler) @@ -121,12 +133,14 @@ def main(): sys.exit(0) if flow_sequence % 100 == 0: gen_send_pkt('tmpl', flow_sequence=flow_sequence, src_ip=IP_SRC, dst_ip=IP_DST, - sport=PORT_SRC, dport=PORT_DST) + sport=PORT_SRC, dport=PORT_DST, protocol_num=PROTOCOL_NUM) continue - gen_send_pkt('data', flow_sequence, src_ip=IP_SRC, dst_ip=IP_DST, sport=PORT_SRC, dport=PORT_DST) + gen_send_pkt('data', flow_sequence, src_ip=IP_SRC, dst_ip=IP_DST, sport=PORT_SRC, dport=PORT_DST, + protocol_num=PROTOCOL_NUM) -def gen_send_pkt(pkt_type='data', flow_sequence=1, src_ip='1.1.1.1', dst_ip = '2.2.2.2', sport=2056, dport=2055): +def gen_send_pkt(pkt_type='data', flow_sequence=1, src_ip='1.1.1.1', dst_ip = '2.2.2.2', sport=2056, dport=2055, + protocol_num=6): timestamp = int(time.time()) if pkt_type == 'tmpl': pkt_netflow_tmpl = gen_pkt_netflow_tmpl(timestamp=timestamp, flow_sequence=flow_sequence, @@ -138,14 +152,16 @@ def gen_send_pkt(pkt_type='data', flow_sequence=1, src_ip='1.1.1.1', dst_ip = '2 elif pkt_type == 'data': sys_uptime = 3600 * 1000 pkt_netflow_data = gen_pkt_netflow_data(timestamp=timestamp, sys_uptime=sys_uptime, flow_sequence=flow_sequence, - src_ip=src_ip, dst_ip=dst_ip, sport=sport, dport=dport) + src_ip=src_ip, dst_ip=dst_ip, sport=sport, dport=dport, + protocol_num=protocol_num) wrpcap('v9_test_data.pcap', pkt_netflow_data) sys.stdout.write("Sending packet: %d \r" % (flow_sequence)) send(pkt_netflow_data, verbose=0) sys.stdout.flush() -def gen_pkt_netflow_data(timestamp=1503652676, flow_sequence=1, sys_uptime=3600000, src_ip='121.41.5.67', dst_ip='121.41.5.68', sport=2056, dport=2055): +def gen_pkt_netflow_data(timestamp=1503652676, flow_sequence=1, sys_uptime=3600000, src_ip='121.41.5.67', + dst_ip='121.41.5.68', sport=2056, dport=2055, protocol_num=6): header_v9 = rbnf.Netflow_Headerv9(version=9, count=1, SysUptime=0x000069d7, Timestamp=timestamp, FlowSequence=flow_sequence, SourceId=2177) flowset_flow_header_v9 = rbnf.FlowSet_Header_v9(FlowSet_id=260, FlowSet_length=72) @@ -185,7 +201,7 @@ def gen_pkt_netflow_data(timestamp=1503652676, flow_sequence=1, sys_uptime=36000 flows.append(rbnf.Flow_260_v9( Packets=1, Octets=1024, SrcAddr=src_dst_addr[0], DstAddr=src_dst_addr[1], InputInt=145, OutputInt=142, EndTime=end_time, StartTime=start_time, SrcPort=src_dst_port_list[0][0], DstPort=src_dst_port_list[0][1], - SrcAS=0, DstAS=0, BGPNextHop='0.0.0.0', SrcMask=17, DstMask=28, Protocol=6, TCPFlags=0x10, IPToS=0x00, + SrcAS=0, DstAS=0, BGPNextHop='0.0.0.0', SrcMask=17, DstMask=28, Protocol=protocol_num, TCPFlags=0x10, IPToS=0x00, Direction=0, ForwardingStatus=0x40, SamplerID=2, IngressVRFID=0x60000000, EgressVRFID=0x60000000 )) @@ -232,7 +248,8 @@ def calc_netflow_len(header, flowset_flow_header, flows): return len_netflow -def gen_pkt_netflow_tmpl(timestamp=1503652676, flow_sequence=1, source_id=2177, template_id=260, src_ip='121.41.5.67', dst_ip='121.41.5.68', sport=2056, dport=2055): +def gen_pkt_netflow_tmpl(timestamp=1503652676, flow_sequence=1, source_id=2177, template_id=260, src_ip='121.41.5.67', + dst_ip='121.41.5.68', sport=2056, dport=2055): header_v9 = rbnf.Netflow_Headerv9(version=9, count=1, SysUptime=0x000069d7, Timestamp=timestamp, FlowSequence=flow_sequence,SourceId=source_id) flowset_tmpl_header_v9 = rbnf.FlowSet_Header_v9(FlowSet_id=0, FlowSet_length=100) flowset_tmpl_data_header_v9 = rbnf.FlowTemplate_ID_v9(template_id=template_id,count=23) From 7c6d5c4ade3617a661c2ab6c1ddd75721dce134c Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 27 Sep 2017 16:44:24 +0800 Subject: [PATCH 016/156] Add args.bytes in order to specify bytes(octets) in netflow data --- src/pygennf_v9.py | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/src/pygennf_v9.py b/src/pygennf_v9.py index 0ceff47..5b16416 100644 --- a/src/pygennf_v9.py +++ b/src/pygennf_v9.py @@ -68,6 +68,8 @@ def main(): help='Packets count before producer stops.') parser.add_argument('-p', '--protocol', dest='protocol', help='Protocols included in netflow data part.') + parser.add_argument('-b', '--bytes', dest='bytes', + help='Bytes(octets) in single flow.') args = parser.parse_args() @@ -109,11 +111,23 @@ def main(): try: PROTOCOL_NUM = dic_protocol_num[args.protocol] except KeyError: - print "'%s' cannot be mapped to existing protocols, use TCP[6] as default" % (args.protocol) + print "Protocol '%s' cannot be mapped to existing protocols, use TCP[6] as default" % (args.protocol) PROTOCOL_NUM = 6 else: PROTOCOL_NUM = 6 # TCP by default + if args.bytes: + try: + BYTES = int(args.bytes) + if BYTES < 1 or BYTES > 4096: + raise ValueError + except ValueError: + print "Bytes '%s' should be integer between 1 and 4096, use 1024 as default" % (args.bytes) + BYTES = 1024 + else: + BYTES = 1024 + + signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler) @@ -133,14 +147,14 @@ def main(): sys.exit(0) if flow_sequence % 100 == 0: gen_send_pkt('tmpl', flow_sequence=flow_sequence, src_ip=IP_SRC, dst_ip=IP_DST, - sport=PORT_SRC, dport=PORT_DST, protocol_num=PROTOCOL_NUM) + sport=PORT_SRC, dport=PORT_DST, protocol_num=PROTOCOL_NUM, octets=BYTES) continue gen_send_pkt('data', flow_sequence, src_ip=IP_SRC, dst_ip=IP_DST, sport=PORT_SRC, dport=PORT_DST, - protocol_num=PROTOCOL_NUM) + protocol_num=PROTOCOL_NUM, octets=BYTES) def gen_send_pkt(pkt_type='data', flow_sequence=1, src_ip='1.1.1.1', dst_ip = '2.2.2.2', sport=2056, dport=2055, - protocol_num=6): + protocol_num=6, octets=1024): timestamp = int(time.time()) if pkt_type == 'tmpl': pkt_netflow_tmpl = gen_pkt_netflow_tmpl(timestamp=timestamp, flow_sequence=flow_sequence, @@ -153,7 +167,7 @@ def gen_send_pkt(pkt_type='data', flow_sequence=1, src_ip='1.1.1.1', dst_ip = '2 sys_uptime = 3600 * 1000 pkt_netflow_data = gen_pkt_netflow_data(timestamp=timestamp, sys_uptime=sys_uptime, flow_sequence=flow_sequence, src_ip=src_ip, dst_ip=dst_ip, sport=sport, dport=dport, - protocol_num=protocol_num) + protocol_num=protocol_num, octets=octets) wrpcap('v9_test_data.pcap', pkt_netflow_data) sys.stdout.write("Sending packet: %d \r" % (flow_sequence)) send(pkt_netflow_data, verbose=0) @@ -161,7 +175,7 @@ def gen_send_pkt(pkt_type='data', flow_sequence=1, src_ip='1.1.1.1', dst_ip = '2 def gen_pkt_netflow_data(timestamp=1503652676, flow_sequence=1, sys_uptime=3600000, src_ip='121.41.5.67', - dst_ip='121.41.5.68', sport=2056, dport=2055, protocol_num=6): + dst_ip='121.41.5.68', sport=2056, dport=2055, protocol_num=6, octets=1024): header_v9 = rbnf.Netflow_Headerv9(version=9, count=1, SysUptime=0x000069d7, Timestamp=timestamp, FlowSequence=flow_sequence, SourceId=2177) flowset_flow_header_v9 = rbnf.FlowSet_Header_v9(FlowSet_id=260, FlowSet_length=72) @@ -199,7 +213,7 @@ def gen_pkt_netflow_data(timestamp=1503652676, flow_sequence=1, sys_uptime=36000 end_time = timestamp start_time = end_time - 1000 # Duration 1s flows.append(rbnf.Flow_260_v9( - Packets=1, Octets=1024, SrcAddr=src_dst_addr[0], DstAddr=src_dst_addr[1], InputInt=145, OutputInt=142, + Packets=1, Octets=octets, SrcAddr=src_dst_addr[0], DstAddr=src_dst_addr[1], InputInt=145, OutputInt=142, EndTime=end_time, StartTime=start_time, SrcPort=src_dst_port_list[0][0], DstPort=src_dst_port_list[0][1], SrcAS=0, DstAS=0, BGPNextHop='0.0.0.0', SrcMask=17, DstMask=28, Protocol=protocol_num, TCPFlags=0x10, IPToS=0x00, Direction=0, ForwardingStatus=0x40, SamplerID=2, IngressVRFID=0x60000000, EgressVRFID=0x60000000 From e89b8bc77f5304b2d524b6edea116fdff1b8c02e Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 27 Sep 2017 17:11:26 +0800 Subject: [PATCH 017/156] Update help info --- src/pygennf_v9.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/pygennf_v9.py b/src/pygennf_v9.py index 5b16416..bfa3828 100644 --- a/src/pygennf_v9.py +++ b/src/pygennf_v9.py @@ -55,21 +55,21 @@ def main(): parser = argparse.ArgumentParser(description='UDP packets producer with scapy') parser.add_argument('-s', '--source-ip', dest='src_ip', - help='IP source') + help='Source IP of netflow packet(s).') parser.add_argument('-sp', '--source-port', dest='src_port', - help='Port dst') + help='Source port of netflow packet(s).') parser.add_argument('-d', '--dst-ip', dest='dst_ip', - help='IP source') + help='Destination IP of netflow packet(s).') parser.add_argument('-dp', '--dst-port', dest='dst_port', - help='Port dst') + help='Destination port of netflow packet(s).') parser.add_argument('-t', '--time-interval', dest='time_interval', - help='Time interval to wait to send other messages.') + help='Time interval to wait before sending each netflow packet.') parser.add_argument('-c', '--pkt-count', dest='pkt_count', - help='Packets count before producer stops.') + help='Packets count to be sent before this generator stopping.') parser.add_argument('-p', '--protocol', dest='protocol', - help='Protocols included in netflow data part.') + help='Protocols included in netflow data part, e.g. tcp(6) or udp(17).') parser.add_argument('-b', '--bytes', dest='bytes', - help='Bytes(octets) in single flow.') + help='Bytes(octets) in single flow, e.g. 1024.') args = parser.parse_args() From 9acebd0d88e1c76fc65c9ed79617c810c80636b2 Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 27 Sep 2017 17:18:01 +0800 Subject: [PATCH 018/156] Update README --- README.md | 49 ++++++++++++++++++++++--------------------------- 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index ca9b3b5..b3ef6fa 100644 --- a/README.md +++ b/README.md @@ -7,42 +7,37 @@ Netflow packets generator with Scapy library > > python setup.py install -# Usage (without installation): +# Usage: - * You need to install the scapy library: - pip install scapy + * pygennf_v9.py --help - * python ./pygennf_v5.py --help - -> usage: pygennf_v5.py [-h] [-s SRC_IP] [-sp SRC_PORT] [-d DST_IP] -> [-dp DST_PORT] [-t TIME_INTERVAL] -> -> UDP packets producer with scapy -> -> optional arguments: +>usage: pygennf_v9.py [-h] [-s SRC_IP] [-sp SRC_PORT] [-d DST_IP] +> [-dp DST_PORT] [-t TIME_INTERVAL] [-c PKT_COUNT] +> [-p PROTOCOL] [-b BYTES] +> +>UDP packets producer with scapy +> +>optional arguments: > -h, --help show this help message and exit - > -s SRC_IP, --source-ip SRC_IP -> IP source - +> Source IP of netflow packet(s). > -sp SRC_PORT, --source-port SRC_PORT -> Port dst - +> Source port of netflow packet(s). > -d DST_IP, --dst-ip DST_IP -> IP source - +> Destination IP of netflow packet(s). > -dp DST_PORT, --dst-port DST_PORT -> Port dst - +> Destination port of netflow packet(s). > -t TIME_INTERVAL, --time-interval TIME_INTERVAL - Time interval to wait to send other messages. +> Time interval to wait before sending each netflow packet. +> -c PKT_COUNT, --pkt-count PKT_COUNT +> Packets count to be sent before this generator stopping. +> -p PROTOCOL, --protocol PROTOCOL +> Protocols included in netflow data part, e.g. tcp(6) or udp(17). +> -b BYTES, --bytes BYTES +> Bytes(octets) in single flow, e.g. 1024. + # Example of use: - * Netflow 5: -> sudo python src/pygennf_v5.py -s 10.0.203.2 -d 10.0.30.89 -t 2 * Netflow 9: -> sudo python src/pygennf_v9.py -s 10.0.203.2 -d 10.0.30.89 -t 2 - * Netflow 10: -> sudo python src/pygennf_v10.py -s 10.0.203.2 -d 10.0.30.89 -t 2 - +> pygennf_v9.py --source-ip 10.19.5.54 --dst-ip 10.19.5.118 --dst-port 2062 -t 1 -c 3600 -p tcp -b 1024 From 2e50f214432229f8e78331dde55c37164185fcda Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 27 Sep 2017 17:21:00 +0800 Subject: [PATCH 019/156] Update README --- README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/README.md b/README.md index b3ef6fa..8e21178 100644 --- a/README.md +++ b/README.md @@ -12,29 +12,49 @@ Netflow packets generator with Scapy library * pygennf_v9.py --help >usage: pygennf_v9.py [-h] [-s SRC_IP] [-sp SRC_PORT] [-d DST_IP] +> > [-dp DST_PORT] [-t TIME_INTERVAL] [-c PKT_COUNT] +> > [-p PROTOCOL] [-b BYTES] > >UDP packets producer with scapy > >optional arguments: +> > -h, --help show this help message and exit +> > -s SRC_IP, --source-ip SRC_IP +> > Source IP of netflow packet(s). +> > -sp SRC_PORT, --source-port SRC_PORT +> > Source port of netflow packet(s). +> > -d DST_IP, --dst-ip DST_IP +> > Destination IP of netflow packet(s). +> > -dp DST_PORT, --dst-port DST_PORT +> > Destination port of netflow packet(s). +> > -t TIME_INTERVAL, --time-interval TIME_INTERVAL +> > Time interval to wait before sending each netflow packet. +> > -c PKT_COUNT, --pkt-count PKT_COUNT +> > Packets count to be sent before this generator stopping. +> > -p PROTOCOL, --protocol PROTOCOL +> > Protocols included in netflow data part, e.g. tcp(6) or udp(17). +> > -b BYTES, --bytes BYTES +> > Bytes(octets) in single flow, e.g. 1024. +> # Example of use: From 98313f4ad5e2acf77ceae943087611e3907792a5 Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 27 Sep 2017 17:22:06 +0800 Subject: [PATCH 020/156] Update README --- README.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/README.md b/README.md index 8e21178..5ef5506 100644 --- a/README.md +++ b/README.md @@ -24,35 +24,27 @@ Netflow packets generator with Scapy library > -h, --help show this help message and exit > > -s SRC_IP, --source-ip SRC_IP -> > Source IP of netflow packet(s). > > -sp SRC_PORT, --source-port SRC_PORT -> > Source port of netflow packet(s). > > -d DST_IP, --dst-ip DST_IP -> > Destination IP of netflow packet(s). > > -dp DST_PORT, --dst-port DST_PORT -> > Destination port of netflow packet(s). > > -t TIME_INTERVAL, --time-interval TIME_INTERVAL -> > Time interval to wait before sending each netflow packet. > > -c PKT_COUNT, --pkt-count PKT_COUNT -> > Packets count to be sent before this generator stopping. > > -p PROTOCOL, --protocol PROTOCOL -> > Protocols included in netflow data part, e.g. tcp(6) or udp(17). > > -b BYTES, --bytes BYTES -> > Bytes(octets) in single flow, e.g. 1024. > From 152b1290adbec52552d7e7f98a4a57dbdeaf3b2c Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 27 Sep 2017 17:22:54 +0800 Subject: [PATCH 021/156] Update README --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 5ef5506..92f5e8f 100644 --- a/README.md +++ b/README.md @@ -12,9 +12,7 @@ Netflow packets generator with Scapy library * pygennf_v9.py --help >usage: pygennf_v9.py [-h] [-s SRC_IP] [-sp SRC_PORT] [-d DST_IP] -> > [-dp DST_PORT] [-t TIME_INTERVAL] [-c PKT_COUNT] -> > [-p PROTOCOL] [-b BYTES] > >UDP packets producer with scapy From 924bf48504fe77517a3ea4da5453d649331b083a Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 27 Sep 2017 17:35:06 +0800 Subject: [PATCH 022/156] Remove files not needed --- README | 44 ------------------------------ download/pygennf-0.1-1.noarch.rpm | Bin 10388 -> 0 bytes download/pygennf-0.1.tar.gz | Bin 6966 -> 0 bytes 3 files changed, 44 deletions(-) delete mode 100644 README delete mode 100644 download/pygennf-0.1-1.noarch.rpm delete mode 100644 download/pygennf-0.1.tar.gz diff --git a/README b/README deleted file mode 100644 index 07588b3..0000000 --- a/README +++ /dev/null @@ -1,44 +0,0 @@ -# pygennf - -Netflow packets generator with Scape library - -* How to install: -python setup.py install - -* How to install the rpm packege: -rpm -vUh pygennf-0.1-1.noarch.rpm - -# Usage (without installation): - - * You need to install the scapy library: - pip install scapy - - * python ./pygennf_v5.py --help - -usage: pygennf_v5.py [-h] [-s SRC_IP] [-sp SRC_PORT] [-d DST_IP] - [-dp DST_PORT] [-t TIME_INTERVAL] - -UDP packets producer with scapy - -optional arguments: - -h, --help show this help message and exit - -s SRC_IP, --source-ip SRC_IP - IP source - -sp SRC_PORT, --source-port SRC_PORT - Port dst - -d DST_IP, --dst-ip DST_IP - IP source - -dp DST_PORT, --dst-port DST_PORT - Port dst - -t TIME_INTERVAL, --time-interval TIME_INTERVAL - Time interval to wait to send other messages. - -# Example of use: - - * Netflow 5: - sudo python src/pygennf_v5.py -s 10.0.203.2 -d 10.0.30.89 -t 2 - * Netflow 9: - sudo python src/pygennf_v9.py -s 10.0.203.2 -d 10.0.30.89 -t 2 - * Netflow 10: - sudo python src/pygennf_v10.py -s 10.0.203.2 -d 10.0.30.89 -t 2 - diff --git a/download/pygennf-0.1-1.noarch.rpm b/download/pygennf-0.1-1.noarch.rpm deleted file mode 100644 index de7e3d993453de11f276e22e5240f3fb47a312fe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10388 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 diff --git a/download/pygennf-0.1.tar.gz b/download/pygennf-0.1.tar.gz deleted file mode 100644 index 99d15c88ab214dc450f616fbc89f958010b55c62..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6966 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 Date: Wed, 27 Sep 2017 17:36:01 +0800 Subject: [PATCH 023/156] Add snapshots --- resources/2017-09-27_console_snapshot_01.png | Bin 0 -> 4354 bytes resources/2017-09-27_web_snapshot_01.png | Bin 0 -> 32099 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 resources/2017-09-27_console_snapshot_01.png create mode 100644 resources/2017-09-27_web_snapshot_01.png diff --git a/resources/2017-09-27_console_snapshot_01.png b/resources/2017-09-27_console_snapshot_01.png new file mode 100644 index 0000000000000000000000000000000000000000..2d36af310290323f584c046fcf2f52d92d0c5f64 GIT binary patch literal 4354 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 mf40|1{oOCO(iL;Z9h|74H)LH>`M%;Kg Date: Wed, 27 Sep 2017 17:38:48 +0800 Subject: [PATCH 024/156] Update - added links to snapshots --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 92f5e8f..49e2e7a 100644 --- a/README.md +++ b/README.md @@ -51,3 +51,7 @@ Netflow packets generator with Scapy library * Netflow 9: > pygennf_v9.py --source-ip 10.19.5.54 --dst-ip 10.19.5.118 --dst-port 2062 -t 1 -c 3600 -p tcp -b 1024 +> +> ![2017-09-27_console_snapshot_01.png](https://github.com/9nehS/pygennf/blob/master/resources/2017-09-27_console_snapshot_01.png) +> +> ![2017-09-27_web_snapshot_01.png](https://github.com/9nehS/pygennf/blob/master/resources/2017-09-27_web_snapshot_01.png) \ No newline at end of file From f564a9bc3e6112ab8360d93c644f37f9bf415e78 Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 27 Sep 2017 17:41:01 +0800 Subject: [PATCH 025/156] Remove udpnf.py --- src/udpnf.py | 56 ---------------------------------------------------- 1 file changed, 56 deletions(-) delete mode 100755 src/udpnf.py diff --git a/src/udpnf.py b/src/udpnf.py deleted file mode 100755 index e8fa963..0000000 --- a/src/udpnf.py +++ /dev/null @@ -1,56 +0,0 @@ -import argparse -import json -from types import * - - -def print_use(): - print "Usage: udpnf.py [-h] path/to/file.t [destination_site]" - print "UDP packets producer with Scapy" - print " Positional arguments:" - print " path/to/file.t Config json file of the UPD packet" - print " destination site destination site." - print " Optional arguments:" - print " -h, --help show this help message and exit" - - -def generate_udp(conf_dic): - pass - - -def send_packet_udp_to(udp_packet, destination): - pass - - -def main(): - parser = argparse.ArgumentParser(description='UDP packets producer with scapy') - parser.add_argument('filename_conf', nargs='?', - metavar='path/to/file.t', - help='Config json file of the UPD packet') - parser.add_argument('destination', nargs='?', - metavar='destination site', - help='destination site.') - args = parser.parse_args() - - if args.filename_conf and args.destination: - try: - template_file = open(args.filename_conf) - except EOFError: - print "Cannot open json config file %s" % (args.filename_conf) - return - else: - print_use() - return - - print "Destination site: %s" % (args.destination) - - json_dic = {} - json_dic = json.load(template_file) - template_file.close() - - udp_packet = generate_udp(json_dic) - - # send the packet to 'destination site' - send_packet_udp_to(udp_packet, args.destination) - -if __name__ == '__main__': - main() From be5444fa9494fced2888c9858f22905ce3996b47 Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 27 Sep 2017 17:45:11 +0800 Subject: [PATCH 026/156] Remove .egg --- pygennf-0.1-py2.7.egg | Bin 10824 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 pygennf-0.1-py2.7.egg diff --git a/pygennf-0.1-py2.7.egg b/pygennf-0.1-py2.7.egg deleted file mode 100644 index 2f1c4b545b9f9c62a4c78fd2e0d2be3c228a227b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10824 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 T0wBJ Date: Wed, 27 Sep 2017 17:50:07 +0800 Subject: [PATCH 027/156] Update - comment wrpcap() --- src/pygennf_v9.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pygennf_v9.py b/src/pygennf_v9.py index bfa3828..e3360c1 100644 --- a/src/pygennf_v9.py +++ b/src/pygennf_v9.py @@ -159,7 +159,7 @@ def gen_send_pkt(pkt_type='data', flow_sequence=1, src_ip='1.1.1.1', dst_ip = '2 if pkt_type == 'tmpl': pkt_netflow_tmpl = gen_pkt_netflow_tmpl(timestamp=timestamp, flow_sequence=flow_sequence, src_ip=src_ip, dst_ip =dst_ip, sport=sport, dport=dport) - wrpcap('v9_test_tmpl.pcap', pkt_netflow_tmpl) + #wrpcap('v9_test_tmpl.pcap', pkt_netflow_tmpl) sys.stdout.write("Sending packet: %d \r" % (flow_sequence)) send(pkt_netflow_tmpl, verbose=0) sys.stdout.flush() @@ -168,7 +168,7 @@ def gen_send_pkt(pkt_type='data', flow_sequence=1, src_ip='1.1.1.1', dst_ip = '2 pkt_netflow_data = gen_pkt_netflow_data(timestamp=timestamp, sys_uptime=sys_uptime, flow_sequence=flow_sequence, src_ip=src_ip, dst_ip=dst_ip, sport=sport, dport=dport, protocol_num=protocol_num, octets=octets) - wrpcap('v9_test_data.pcap', pkt_netflow_data) + #wrpcap('v9_test_data.pcap', pkt_netflow_data) sys.stdout.write("Sending packet: %d \r" % (flow_sequence)) send(pkt_netflow_data, verbose=0) sys.stdout.flush() From 0243deeb2ff1c1c738399bd3972236607fc29a69 Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 27 Sep 2017 17:54:00 +0800 Subject: [PATCH 028/156] Update - only keep v9 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 3b6aeae..776b263 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ author_email="sheng.zhao@calix.com", url="https://github.com/9nehS/", license="AGPL", - scripts=["src/pygennf_v5.py", "src/pygennf_v9.py", "src/pygennf_v10.py" ], + scripts=["src/pygennf_v9.py"], packages=['rb_netflow'], install_requires=[ 'scapy', From 4eeedd2b97531320379c2595a719586527cb92fc Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 27 Sep 2017 18:05:17 +0800 Subject: [PATCH 029/156] Update - modify help info --- src/pygennf_v9.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pygennf_v9.py b/src/pygennf_v9.py index e3360c1..2564fc3 100644 --- a/src/pygennf_v9.py +++ b/src/pygennf_v9.py @@ -53,7 +53,7 @@ def main(): print "You need to be root to run this, sorry." return - parser = argparse.ArgumentParser(description='UDP packets producer with scapy') + parser = argparse.ArgumentParser(description='Netflow packets generator with scapy') parser.add_argument('-s', '--source-ip', dest='src_ip', help='Source IP of netflow packet(s).') parser.add_argument('-sp', '--source-port', dest='src_port', From 5efc9f47e3cdc0321f4c95a91840d08581d602d1 Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 27 Sep 2017 18:05:52 +0800 Subject: [PATCH 030/156] Update - modify description --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 776b263..b87d6ae 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ setup(name="pygennf", version="0.11", - description="UDP packets producer with scapy", + description="Netflow packets generator with scapy", author="Sheng Zhao", author_email="sheng.zhao@calix.com", url="https://github.com/9nehS/", From 4e04d07b01c8118d9f6d2512ed65243452e42e20 Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 28 Sep 2017 15:26:27 +0800 Subject: [PATCH 031/156] Update - Change name --- src/pygennf_v5.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pygennf_v5.py b/src/pygennf_v5.py index e35b6c9..0b9c6a1 100644 --- a/src/pygennf_v5.py +++ b/src/pygennf_v5.py @@ -26,14 +26,14 @@ import rb_netflow.rb_netflow as rbnf -signal_received = 0 +SIGNAL_RECEIVED = 0 def preexec(): os.setpgrp() # Don't forward signals def signal_handler(signal, frame): - global signal_received - signal_received = 1 + global SIGNAL_RECEIVED + SIGNAL_RECEIVED = 1 def main(): if os.getuid() != 0: @@ -323,7 +323,7 @@ def main(): send(data) while TIME_INTERVAL is not 0: - if signal_received == 1: + if SIGNAL_RECEIVED == 1: print "\nSignal received. Stopping and Exitting..." sys.exit(0) time.sleep(float(TIME_INTERVAL)) From 0043312aa57280b3e380af20def33017de526923 Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 28 Sep 2017 15:27:06 +0800 Subject: [PATCH 032/156] Update - Change name --- src/pygennf_v10.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pygennf_v10.py b/src/pygennf_v10.py index b3f8f7f..b1b155e 100644 --- a/src/pygennf_v10.py +++ b/src/pygennf_v10.py @@ -26,14 +26,14 @@ import rb_netflow.rb_netflow as rbnf -signal_received = 0 +SIGNAL_RECEIVED = 0 def preexec(): os.setpgrp() # Don't forward signals def signal_handler(signal, frame): - global signal_received - signal_received = 1 + global SIGNAL_RECEIVED + SIGNAL_RECEIVED = 1 def main(): if os.getuid() != 0: @@ -188,7 +188,7 @@ def main(): send(data) while TIME_INTERVAL is not 0: - if signal_received == 1: + if SIGNAL_RECEIVED == 1: print "\nSignal received. Stopping and Exitting..." sys.exit(0) time.sleep(float(TIME_INTERVAL)) From 610c6203f667248bbfaa4112ba6f804474659c5c Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 28 Sep 2017 15:28:56 +0800 Subject: [PATCH 033/156] Added args.flows_data --- src/pygennf_v9.py | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/src/pygennf_v9.py b/src/pygennf_v9.py index 2564fc3..dcecf21 100644 --- a/src/pygennf_v9.py +++ b/src/pygennf_v9.py @@ -19,24 +19,37 @@ import argparse import time import signal - +import re import scapy from scapy.all import * import rb_netflow.rb_netflow as rbnf -signal_received = 0 +SIGNAL_RECEIVED = 0 + +DIC_PROTOCOL_NUM = {'tcp': 6, 'udp': 17} +DIC_DIRECTION_NUM = {'ingress': 0, 'egress': 1} -dic_protocol_num = {'tcp': 6, 'udp': 17} +# ip1/mask:port1:ip2/mask:port2:protocol:direction:bytes +# e.g. 11.11.11.11/32:1001:11.11.11.22/32:1002:tcp:ingress:1024 +FLOW_DATA_PATTERN = r'^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d{1,2}:\d{1,4}:){2}\w+:(ingress|egress):\d{1,4}$' def preexec(): os.setpgrp() # Don't forward signals def signal_handler(signal, frame): - global signal_received - signal_received = 1 + global SIGNAL_RECEIVED + SIGNAL_RECEIVED = 1 + + +def valid_flow_data(flow_data_str=''): + global FLOW_DATA_PATTERN + m = re.match(FLOW_DATA_PATTERN, flow_data_str) + if m is not None: + return True + return False # Netflow9 @@ -70,9 +83,10 @@ def main(): help='Protocols included in netflow data part, e.g. tcp(6) or udp(17).') parser.add_argument('-b', '--bytes', dest='bytes', help='Bytes(octets) in single flow, e.g. 1024.') + parser.add_argument('-fd', '--flows-data', dest='flows_data', + help='Contents in flows data, e.g. ip1/mask:port1:ip2/mask:port2:protocol:direction:bytes.') args = parser.parse_args() - if args.src_ip: IP_SRC = args.src_ip else: @@ -109,7 +123,7 @@ def main(): if args.protocol: try: - PROTOCOL_NUM = dic_protocol_num[args.protocol] + PROTOCOL_NUM = DIC_PROTOCOL_NUM[args.protocol] except KeyError: print "Protocol '%s' cannot be mapped to existing protocols, use TCP[6] as default" % (args.protocol) PROTOCOL_NUM = 6 @@ -127,6 +141,13 @@ def main(): else: BYTES = 1024 + if args.flows_data: + FLOW_DATA_LIST = args.flows_data.split(',') + FLOW_DATA_LIST = map(str.strip, FLOW_DATA_LIST) + FLOW_DATA_LIST = filter(valid_flow_data, FLOW_DATA_LIST) + print FLOW_DATA_LIST + else: + pass signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler) @@ -136,14 +157,14 @@ def main(): gen_send_pkt('tmpl', flow_sequence=flow_sequence, src_ip=IP_SRC, dst_ip=IP_DST, sport=PORT_SRC, dport=PORT_DST) while TIME_INTERVAL is not 0: - if signal_received == 1: + if SIGNAL_RECEIVED == 1: print "\nSignal received. %s packets have been sent. Stopping and Exiting..." % flow_sequence sys.exit(0) time.sleep(float(TIME_INTERVAL)) flow_sequence = flow_sequence + 1 if flow_sequence > PKT_COUNT: - print "\nPackets count[%s] reached. Stopping and Exitting..." % PKT_COUNT + print "\nPackets count[%s] reached. Stopping and Exiting..." % PKT_COUNT sys.exit(0) if flow_sequence % 100 == 0: gen_send_pkt('tmpl', flow_sequence=flow_sequence, src_ip=IP_SRC, dst_ip=IP_DST, From 352090e0597c0a006b622e921a6e57064f6f9ced Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 28 Sep 2017 16:25:21 +0800 Subject: [PATCH 034/156] Update gen_pkt_netflow_data() to process flow_data_list --- src/pygennf_v9.py | 98 ++++++++++++++++++++++++++++++----------------- 1 file changed, 62 insertions(+), 36 deletions(-) diff --git a/src/pygennf_v9.py b/src/pygennf_v9.py index dcecf21..25a8cc5 100644 --- a/src/pygennf_v9.py +++ b/src/pygennf_v9.py @@ -34,6 +34,7 @@ # ip1/mask:port1:ip2/mask:port2:protocol:direction:bytes # e.g. 11.11.11.11/32:1001:11.11.11.22/32:1002:tcp:ingress:1024 FLOW_DATA_PATTERN = r'^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d{1,2}:\d{1,4}:){2}\w+:(ingress|egress):\d{1,4}$' +DEFAULT_FLOW_DATA = '11.11.11.11/32:1001:11.11.11.22/32:80:tcp:ingress:1024' def preexec(): os.setpgrp() # Don't forward signals @@ -147,7 +148,10 @@ def main(): FLOW_DATA_LIST = filter(valid_flow_data, FLOW_DATA_LIST) print FLOW_DATA_LIST else: - pass + print "'%s' is empty, default flow data list will be used: " % (args.flows_data) + print "Default flow data: %s" % (DEFAULT_FLOW_DATA) + FLOW_DATA_LIST = [] + FLOW_DATA_LIST.append(DEFAULT_FLOW_DATA) signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler) @@ -171,11 +175,11 @@ def main(): sport=PORT_SRC, dport=PORT_DST, protocol_num=PROTOCOL_NUM, octets=BYTES) continue gen_send_pkt('data', flow_sequence, src_ip=IP_SRC, dst_ip=IP_DST, sport=PORT_SRC, dport=PORT_DST, - protocol_num=PROTOCOL_NUM, octets=BYTES) + protocol_num=PROTOCOL_NUM, octets=BYTES, flow_data_list=FLOW_DATA_LIST) def gen_send_pkt(pkt_type='data', flow_sequence=1, src_ip='1.1.1.1', dst_ip = '2.2.2.2', sport=2056, dport=2055, - protocol_num=6, octets=1024): + protocol_num=6, octets=1024, flow_data_list=[]): timestamp = int(time.time()) if pkt_type == 'tmpl': pkt_netflow_tmpl = gen_pkt_netflow_tmpl(timestamp=timestamp, flow_sequence=flow_sequence, @@ -188,7 +192,7 @@ def gen_send_pkt(pkt_type='data', flow_sequence=1, src_ip='1.1.1.1', dst_ip = '2 sys_uptime = 3600 * 1000 pkt_netflow_data = gen_pkt_netflow_data(timestamp=timestamp, sys_uptime=sys_uptime, flow_sequence=flow_sequence, src_ip=src_ip, dst_ip=dst_ip, sport=sport, dport=dport, - protocol_num=protocol_num, octets=octets) + protocol_num=protocol_num, octets=octets, flow_data_list=flow_data_list) #wrpcap('v9_test_data.pcap', pkt_netflow_data) sys.stdout.write("Sending packet: %d \r" % (flow_sequence)) send(pkt_netflow_data, verbose=0) @@ -196,48 +200,70 @@ def gen_send_pkt(pkt_type='data', flow_sequence=1, src_ip='1.1.1.1', dst_ip = '2 def gen_pkt_netflow_data(timestamp=1503652676, flow_sequence=1, sys_uptime=3600000, src_ip='121.41.5.67', - dst_ip='121.41.5.68', sport=2056, dport=2055, protocol_num=6, octets=1024): + dst_ip='121.41.5.68', sport=2056, dport=2055, protocol_num=6, octets=1024, flow_data_list=[]): header_v9 = rbnf.Netflow_Headerv9(version=9, count=1, SysUptime=0x000069d7, Timestamp=timestamp, FlowSequence=flow_sequence, SourceId=2177) flowset_flow_header_v9 = rbnf.FlowSet_Header_v9(FlowSet_id=260, FlowSet_length=72) # List for SrcAddr and DstAddr in netflow data - src_dst_addr_list = [] - src_dst_addr_list.append(['69.31.102.10', '209.81.108.20']) - src_dst_addr_list.append(['70.32.103.11', '210.81.108.21']) - src_dst_addr_list.append(['70.32.103.12', '210.81.108.22']) - src_dst_addr_list.append(['70.32.103.13', '210.81.108.23']) - src_dst_addr_list.append(['70.32.103.14', '210.81.108.24']) - src_dst_addr_list.append(['70.32.103.15', '210.81.108.25']) - src_dst_addr_list.append(['70.32.103.16', '210.81.108.26']) - src_dst_addr_list.append(['70.32.103.17', '210.81.108.27']) - src_dst_addr_list.append(['70.32.103.18', '210.81.108.28']) - src_dst_addr_list.append(['70.32.103.19', '210.81.108.29']) - src_dst_addr_list.append(['70.32.103.20', '210.81.108.30']) - src_dst_addr_list.append(['70.32.103.21', '210.81.108.31']) - src_dst_addr_list.append(['70.32.103.22', '210.81.108.32']) - src_dst_addr_list.append(['70.32.103.23', '210.81.108.33']) - src_dst_addr_list.append(['70.32.103.24', '210.81.108.34']) - src_dst_addr_list.append(['70.32.103.25', '210.81.108.35']) - src_dst_addr_list.append(['70.32.103.26', '210.81.108.36']) - src_dst_addr_list.append(['70.32.103.27', '210.81.108.37']) - src_dst_addr_list.append(['70.32.103.28', '210.81.108.38']) - src_dst_addr_list.append(['70.32.103.29', '210.81.108.39']) - src_dst_addr_list.append(['70.32.103.30', '210.81.108.40']) - src_dst_port_list = [] - src_dst_port_list.append([12345, 80]) + # src_dst_addr_list = [] + # src_dst_addr_list.append(['69.31.102.10', '209.81.108.20']) + # src_dst_addr_list.append(['70.32.103.11', '210.81.108.21']) + # src_dst_addr_list.append(['70.32.103.12', '210.81.108.22']) + # src_dst_addr_list.append(['70.32.103.13', '210.81.108.23']) + # src_dst_addr_list.append(['70.32.103.14', '210.81.108.24']) + # src_dst_addr_list.append(['70.32.103.15', '210.81.108.25']) + # src_dst_addr_list.append(['70.32.103.16', '210.81.108.26']) + # src_dst_addr_list.append(['70.32.103.17', '210.81.108.27']) + # src_dst_addr_list.append(['70.32.103.18', '210.81.108.28']) + # src_dst_addr_list.append(['70.32.103.19', '210.81.108.29']) + # src_dst_addr_list.append(['70.32.103.20', '210.81.108.30']) + # src_dst_addr_list.append(['70.32.103.21', '210.81.108.31']) + # src_dst_addr_list.append(['70.32.103.22', '210.81.108.32']) + # src_dst_addr_list.append(['70.32.103.23', '210.81.108.33']) + # src_dst_addr_list.append(['70.32.103.24', '210.81.108.34']) + # src_dst_addr_list.append(['70.32.103.25', '210.81.108.35']) + # src_dst_addr_list.append(['70.32.103.26', '210.81.108.36']) + # src_dst_addr_list.append(['70.32.103.27', '210.81.108.37']) + # src_dst_addr_list.append(['70.32.103.28', '210.81.108.38']) + # src_dst_addr_list.append(['70.32.103.29', '210.81.108.39']) + # src_dst_addr_list.append(['70.32.103.30', '210.81.108.40']) + # src_dst_port_list = [] + # src_dst_port_list.append([12345, 80]) # List for flows in one packet flows = [] - for src_dst_addr in src_dst_addr_list: - #end_time = sys_uptime + 3600 * 1000 + # for src_dst_addr in src_dst_addr_list: + # #end_time = sys_uptime + 3600 * 1000 + # end_time = timestamp + # start_time = end_time - 1000 # Duration 1s + # flows.append(rbnf.Flow_260_v9( + # Packets=1, Octets=octets, SrcAddr=src_dst_addr[0], DstAddr=src_dst_addr[1], InputInt=145, OutputInt=142, + # EndTime=end_time, StartTime=start_time, SrcPort=src_dst_port_list[0][0], DstPort=src_dst_port_list[0][1], + # SrcAS=0, DstAS=0, BGPNextHop='0.0.0.0', SrcMask=17, DstMask=28, Protocol=protocol_num, TCPFlags=0x10, IPToS=0x00, + # Direction=0, ForwardingStatus=0x40, SamplerID=2, IngressVRFID=0x60000000, EgressVRFID=0x60000000 + # )) + + # To process flow_data_list + for flow_data in flow_data_list: + data_item_list = flow_data.split(':') + src_addr = data_item_list[0].split('/')[0] + src_mask = int(data_item_list[0].split('/')[1]) + src_port = int(data_item_list[1]) + dst_addr = data_item_list[2].split('/')[0] + dst_mask = int(data_item_list[2].split('/')[1]) + dst_port = int(data_item_list[3]) + protocol_num = DIC_PROTOCOL_NUM[data_item_list[4]] + direction = DIC_DIRECTION_NUM[data_item_list[5]] + bytes = int(data_item_list[6]) end_time = timestamp - start_time = end_time - 1000 # Duration 1s + start_time = end_time - 1000 # Duration 1s flows.append(rbnf.Flow_260_v9( - Packets=1, Octets=octets, SrcAddr=src_dst_addr[0], DstAddr=src_dst_addr[1], InputInt=145, OutputInt=142, - EndTime=end_time, StartTime=start_time, SrcPort=src_dst_port_list[0][0], DstPort=src_dst_port_list[0][1], - SrcAS=0, DstAS=0, BGPNextHop='0.0.0.0', SrcMask=17, DstMask=28, Protocol=protocol_num, TCPFlags=0x10, IPToS=0x00, - Direction=0, ForwardingStatus=0x40, SamplerID=2, IngressVRFID=0x60000000, EgressVRFID=0x60000000 + Packets=1, Octets=bytes, SrcAddr=src_addr, DstAddr=dst_addr, InputInt=145, OutputInt=142, + EndTime=end_time, StartTime=start_time, SrcPort=src_port, DstPort=dst_port, + SrcAS=0, DstAS=0, BGPNextHop='0.0.0.0', SrcMask=src_mask, DstMask=dst_mask, Protocol=protocol_num, + TCPFlags=0x10, IPToS=0x00, Direction=direction, ForwardingStatus=0x40, SamplerID=2, IngressVRFID=0x60000000, + EgressVRFID=0x60000000 )) # Calculate the length of netflow data before padding From f6bff358874209ade39c0bd7db47d374ae7b5451 Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 28 Sep 2017 16:27:45 +0800 Subject: [PATCH 035/156] Update gen_pkt_netflow_data() to process flow_data_list --- src/pygennf_v9.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pygennf_v9.py b/src/pygennf_v9.py index 25a8cc5..a22e5d6 100644 --- a/src/pygennf_v9.py +++ b/src/pygennf_v9.py @@ -148,7 +148,7 @@ def main(): FLOW_DATA_LIST = filter(valid_flow_data, FLOW_DATA_LIST) print FLOW_DATA_LIST else: - print "'%s' is empty, default flow data list will be used: " % (args.flows_data) + print "'args.flows_data' is empty, default flow data list will be used: " print "Default flow data: %s" % (DEFAULT_FLOW_DATA) FLOW_DATA_LIST = [] FLOW_DATA_LIST.append(DEFAULT_FLOW_DATA) From c8b80f7340f1fd12c305dc50dedc25899f2eb618 Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 28 Sep 2017 16:29:06 +0800 Subject: [PATCH 036/156] Update gen_pkt_netflow_data() to process flow_data_list --- src/pygennf_v9.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pygennf_v9.py b/src/pygennf_v9.py index a22e5d6..fe93af8 100644 --- a/src/pygennf_v9.py +++ b/src/pygennf_v9.py @@ -148,7 +148,7 @@ def main(): FLOW_DATA_LIST = filter(valid_flow_data, FLOW_DATA_LIST) print FLOW_DATA_LIST else: - print "'args.flows_data' is empty, default flow data list will be used: " + print "'args.flows_data' is empty, default flow data list will be used..." print "Default flow data: %s" % (DEFAULT_FLOW_DATA) FLOW_DATA_LIST = [] FLOW_DATA_LIST.append(DEFAULT_FLOW_DATA) From ab6a861b4dcb07140ec71aa7a58c2bb0b1dee395 Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 28 Sep 2017 16:34:29 +0800 Subject: [PATCH 037/156] Update gen_pkt_netflow_data() to process flow_data_list --- src/pygennf_v9.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pygennf_v9.py b/src/pygennf_v9.py index fe93af8..c0b5631 100644 --- a/src/pygennf_v9.py +++ b/src/pygennf_v9.py @@ -146,7 +146,7 @@ def main(): FLOW_DATA_LIST = args.flows_data.split(',') FLOW_DATA_LIST = map(str.strip, FLOW_DATA_LIST) FLOW_DATA_LIST = filter(valid_flow_data, FLOW_DATA_LIST) - print FLOW_DATA_LIST + print 'FLOW_DATA_LIST: ' % FLOW_DATA_LIST else: print "'args.flows_data' is empty, default flow data list will be used..." print "Default flow data: %s" % (DEFAULT_FLOW_DATA) From d7daee7fbe9f3f8cef2b2a5657ed44ce5cbbe8e7 Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 28 Sep 2017 16:35:24 +0800 Subject: [PATCH 038/156] Update gen_pkt_netflow_data() to process flow_data_list --- src/pygennf_v9.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pygennf_v9.py b/src/pygennf_v9.py index c0b5631..954e347 100644 --- a/src/pygennf_v9.py +++ b/src/pygennf_v9.py @@ -144,9 +144,10 @@ def main(): if args.flows_data: FLOW_DATA_LIST = args.flows_data.split(',') + print 'FLOW_DATA_LIST before pre-processing: ' % FLOW_DATA_LIST FLOW_DATA_LIST = map(str.strip, FLOW_DATA_LIST) FLOW_DATA_LIST = filter(valid_flow_data, FLOW_DATA_LIST) - print 'FLOW_DATA_LIST: ' % FLOW_DATA_LIST + print 'FLOW_DATA_LIST after pre-processing: ' % FLOW_DATA_LIST else: print "'args.flows_data' is empty, default flow data list will be used..." print "Default flow data: %s" % (DEFAULT_FLOW_DATA) From 6dbd9bbb813027ffa8ef999e17ee841dfa6e3db6 Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 28 Sep 2017 16:37:03 +0800 Subject: [PATCH 039/156] Update gen_pkt_netflow_data() to process flow_data_list --- src/pygennf_v9.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pygennf_v9.py b/src/pygennf_v9.py index 954e347..694574f 100644 --- a/src/pygennf_v9.py +++ b/src/pygennf_v9.py @@ -143,6 +143,7 @@ def main(): BYTES = 1024 if args.flows_data: + print 'args.flows_data: ' % args.flows_data FLOW_DATA_LIST = args.flows_data.split(',') print 'FLOW_DATA_LIST before pre-processing: ' % FLOW_DATA_LIST FLOW_DATA_LIST = map(str.strip, FLOW_DATA_LIST) From 4d600f5fc2d142da36bab22cca14100acb19c3e6 Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 28 Sep 2017 16:40:10 +0800 Subject: [PATCH 040/156] Update gen_pkt_netflow_data() to process flow_data_list --- src/pygennf_v9.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pygennf_v9.py b/src/pygennf_v9.py index 694574f..7bf7954 100644 --- a/src/pygennf_v9.py +++ b/src/pygennf_v9.py @@ -143,7 +143,7 @@ def main(): BYTES = 1024 if args.flows_data: - print 'args.flows_data: ' % args.flows_data + print 'args.flows_data: %s' % (args.flows_data) FLOW_DATA_LIST = args.flows_data.split(',') print 'FLOW_DATA_LIST before pre-processing: ' % FLOW_DATA_LIST FLOW_DATA_LIST = map(str.strip, FLOW_DATA_LIST) From cf4dfc6ab2cfa99bf5deec4b92d40db5a211063d Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 28 Sep 2017 16:43:04 +0800 Subject: [PATCH 041/156] Update gen_pkt_netflow_data() to process flow_data_list --- src/pygennf_v9.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/pygennf_v9.py b/src/pygennf_v9.py index 7bf7954..6cb5969 100644 --- a/src/pygennf_v9.py +++ b/src/pygennf_v9.py @@ -145,10 +145,12 @@ def main(): if args.flows_data: print 'args.flows_data: %s' % (args.flows_data) FLOW_DATA_LIST = args.flows_data.split(',') - print 'FLOW_DATA_LIST before pre-processing: ' % FLOW_DATA_LIST + print 'FLOW_DATA_LIST before pre-processing: ' + print FLOW_DATA_LIST FLOW_DATA_LIST = map(str.strip, FLOW_DATA_LIST) FLOW_DATA_LIST = filter(valid_flow_data, FLOW_DATA_LIST) - print 'FLOW_DATA_LIST after pre-processing: ' % FLOW_DATA_LIST + print 'FLOW_DATA_LIST after pre-processing: ' + print FLOW_DATA_LIST else: print "'args.flows_data' is empty, default flow data list will be used..." print "Default flow data: %s" % (DEFAULT_FLOW_DATA) From 0c6c3642ebd9bb38bfaf82ac2ba0a2b26e8ab1db Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 28 Sep 2017 16:44:57 +0800 Subject: [PATCH 042/156] Update gen_pkt_netflow_data() to process flow_data_list --- src/pygennf_v9.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pygennf_v9.py b/src/pygennf_v9.py index 6cb5969..b732a32 100644 --- a/src/pygennf_v9.py +++ b/src/pygennf_v9.py @@ -148,8 +148,10 @@ def main(): print 'FLOW_DATA_LIST before pre-processing: ' print FLOW_DATA_LIST FLOW_DATA_LIST = map(str.strip, FLOW_DATA_LIST) + print 'FLOW_DATA_LIST after map:' + print FLOW_DATA_LIST FLOW_DATA_LIST = filter(valid_flow_data, FLOW_DATA_LIST) - print 'FLOW_DATA_LIST after pre-processing: ' + print 'FLOW_DATA_LIST after filter: ' print FLOW_DATA_LIST else: print "'args.flows_data' is empty, default flow data list will be used..." From d5c2d0b544f4fe157c087654b13d9cd60322edfd Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 28 Sep 2017 16:59:08 +0800 Subject: [PATCH 043/156] Update gen_pkt_netflow_data() to process flow_data_list --- src/pygennf_v9.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pygennf_v9.py b/src/pygennf_v9.py index b732a32..38b6977 100644 --- a/src/pygennf_v9.py +++ b/src/pygennf_v9.py @@ -33,7 +33,7 @@ # ip1/mask:port1:ip2/mask:port2:protocol:direction:bytes # e.g. 11.11.11.11/32:1001:11.11.11.22/32:1002:tcp:ingress:1024 -FLOW_DATA_PATTERN = r'^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d{1,2}:\d{1,4}:){2}\w+:(ingress|egress):\d{1,4}$' +FLOW_DATA_PATTERN = r'^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d{1,2}:\d{1,5}:){2}\w+:(ingress|egress):\d{1,4}$' DEFAULT_FLOW_DATA = '11.11.11.11/32:1001:11.11.11.22/32:80:tcp:ingress:1024' def preexec(): From 1a604cb756c77e6a9d72ac373c8ddcc0fec9bb88 Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 28 Sep 2017 17:08:21 +0800 Subject: [PATCH 044/156] Update the logic to process args.flows_data --- src/pygennf_v9.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/pygennf_v9.py b/src/pygennf_v9.py index 38b6977..8f2a2f3 100644 --- a/src/pygennf_v9.py +++ b/src/pygennf_v9.py @@ -143,16 +143,13 @@ def main(): BYTES = 1024 if args.flows_data: - print 'args.flows_data: %s' % (args.flows_data) FLOW_DATA_LIST = args.flows_data.split(',') - print 'FLOW_DATA_LIST before pre-processing: ' - print FLOW_DATA_LIST FLOW_DATA_LIST = map(str.strip, FLOW_DATA_LIST) - print 'FLOW_DATA_LIST after map:' - print FLOW_DATA_LIST FLOW_DATA_LIST = filter(valid_flow_data, FLOW_DATA_LIST) - print 'FLOW_DATA_LIST after filter: ' - print FLOW_DATA_LIST + if len(FLOW_DATA_LIST) == 0: + print 'No valid flow data list, default flow data list will be used...' + print "Default flow data: %s" % (DEFAULT_FLOW_DATA) + FLOW_DATA_LIST.append(DEFAULT_FLOW_DATA) else: print "'args.flows_data' is empty, default flow data list will be used..." print "Default flow data: %s" % (DEFAULT_FLOW_DATA) From de224d6b1879b26c11bc38023c88f4c14dcd9262 Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 28 Sep 2017 17:18:34 +0800 Subject: [PATCH 045/156] Update the logic to process args.flows_data --- src/pygennf_v9.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/pygennf_v9.py b/src/pygennf_v9.py index 8f2a2f3..a781639 100644 --- a/src/pygennf_v9.py +++ b/src/pygennf_v9.py @@ -247,8 +247,11 @@ def gen_pkt_netflow_data(timestamp=1503652676, flow_sequence=1, sys_uptime=36000 # Direction=0, ForwardingStatus=0x40, SamplerID=2, IngressVRFID=0x60000000, EgressVRFID=0x60000000 # )) + print 'Flows to be sent:\n' + # To process flow_data_list for flow_data in flow_data_list: + print flow_data data_item_list = flow_data.split(':') src_addr = data_item_list[0].split('/')[0] src_mask = int(data_item_list[0].split('/')[1]) From 11e2e21a2da75a228c715a9046cc1539c422d209 Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 28 Sep 2017 17:22:38 +0800 Subject: [PATCH 046/156] Update the logic to process args.flows_data --- src/pygennf_v9.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pygennf_v9.py b/src/pygennf_v9.py index a781639..6601aed 100644 --- a/src/pygennf_v9.py +++ b/src/pygennf_v9.py @@ -163,6 +163,8 @@ def main(): gen_send_pkt('tmpl', flow_sequence=flow_sequence, src_ip=IP_SRC, dst_ip=IP_DST, sport=PORT_SRC, dport=PORT_DST) + print 'Flows to be sent: ' % FLOW_DATA_LIST + while TIME_INTERVAL is not 0: if SIGNAL_RECEIVED == 1: print "\nSignal received. %s packets have been sent. Stopping and Exiting..." % flow_sequence @@ -247,11 +249,9 @@ def gen_pkt_netflow_data(timestamp=1503652676, flow_sequence=1, sys_uptime=36000 # Direction=0, ForwardingStatus=0x40, SamplerID=2, IngressVRFID=0x60000000, EgressVRFID=0x60000000 # )) - print 'Flows to be sent:\n' # To process flow_data_list for flow_data in flow_data_list: - print flow_data data_item_list = flow_data.split(':') src_addr = data_item_list[0].split('/')[0] src_mask = int(data_item_list[0].split('/')[1]) From ede62390c7c29374bd18699eb09b80a4719fa1a0 Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 28 Sep 2017 17:23:57 +0800 Subject: [PATCH 047/156] Update the logic to process args.flows_data --- src/pygennf_v9.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pygennf_v9.py b/src/pygennf_v9.py index 6601aed..320583c 100644 --- a/src/pygennf_v9.py +++ b/src/pygennf_v9.py @@ -163,7 +163,8 @@ def main(): gen_send_pkt('tmpl', flow_sequence=flow_sequence, src_ip=IP_SRC, dst_ip=IP_DST, sport=PORT_SRC, dport=PORT_DST) - print 'Flows to be sent: ' % FLOW_DATA_LIST + print 'Flows to be sent: ' + print FLOW_DATA_LIST while TIME_INTERVAL is not 0: if SIGNAL_RECEIVED == 1: From af317ca08d208140e4c0b89ce377b48d1b484927 Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 28 Sep 2017 17:25:12 +0800 Subject: [PATCH 048/156] Update the logic to process args.flows_data --- src/pygennf_v9.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pygennf_v9.py b/src/pygennf_v9.py index 320583c..40ac009 100644 --- a/src/pygennf_v9.py +++ b/src/pygennf_v9.py @@ -191,7 +191,7 @@ def gen_send_pkt(pkt_type='data', flow_sequence=1, src_ip='1.1.1.1', dst_ip = '2 pkt_netflow_tmpl = gen_pkt_netflow_tmpl(timestamp=timestamp, flow_sequence=flow_sequence, src_ip=src_ip, dst_ip =dst_ip, sport=sport, dport=dport) #wrpcap('v9_test_tmpl.pcap', pkt_netflow_tmpl) - sys.stdout.write("Sending packet: %d \r" % (flow_sequence)) + sys.stdout.write("Sending packets: %d \r" % (flow_sequence)) send(pkt_netflow_tmpl, verbose=0) sys.stdout.flush() elif pkt_type == 'data': @@ -200,7 +200,7 @@ def gen_send_pkt(pkt_type='data', flow_sequence=1, src_ip='1.1.1.1', dst_ip = '2 src_ip=src_ip, dst_ip=dst_ip, sport=sport, dport=dport, protocol_num=protocol_num, octets=octets, flow_data_list=flow_data_list) #wrpcap('v9_test_data.pcap', pkt_netflow_data) - sys.stdout.write("Sending packet: %d \r" % (flow_sequence)) + sys.stdout.write("Sending packets: %d \r" % (flow_sequence)) send(pkt_netflow_data, verbose=0) sys.stdout.flush() From 13276b87a6512228eb6c4093519447c171b18a6c Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 28 Sep 2017 17:33:06 +0800 Subject: [PATCH 049/156] Remove args.protocol and args.bytes --- src/pygennf_v9.py | 52 +++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/pygennf_v9.py b/src/pygennf_v9.py index 40ac009..253a1cc 100644 --- a/src/pygennf_v9.py +++ b/src/pygennf_v9.py @@ -80,10 +80,10 @@ def main(): help='Time interval to wait before sending each netflow packet.') parser.add_argument('-c', '--pkt-count', dest='pkt_count', help='Packets count to be sent before this generator stopping.') - parser.add_argument('-p', '--protocol', dest='protocol', - help='Protocols included in netflow data part, e.g. tcp(6) or udp(17).') - parser.add_argument('-b', '--bytes', dest='bytes', - help='Bytes(octets) in single flow, e.g. 1024.') + # parser.add_argument('-p', '--protocol', dest='protocol', + # help='Protocols included in netflow data part, e.g. tcp(6) or udp(17).') + # parser.add_argument('-b', '--bytes', dest='bytes', + # help='Bytes(octets) in single flow, e.g. 1024.') parser.add_argument('-fd', '--flows-data', dest='flows_data', help='Contents in flows data, e.g. ip1/mask:port1:ip2/mask:port2:protocol:direction:bytes.') @@ -122,25 +122,25 @@ def main(): # 0xFFFFFFFF - 1 PKT_COUNT = 4294967294 - if args.protocol: - try: - PROTOCOL_NUM = DIC_PROTOCOL_NUM[args.protocol] - except KeyError: - print "Protocol '%s' cannot be mapped to existing protocols, use TCP[6] as default" % (args.protocol) - PROTOCOL_NUM = 6 - else: - PROTOCOL_NUM = 6 # TCP by default - - if args.bytes: - try: - BYTES = int(args.bytes) - if BYTES < 1 or BYTES > 4096: - raise ValueError - except ValueError: - print "Bytes '%s' should be integer between 1 and 4096, use 1024 as default" % (args.bytes) - BYTES = 1024 - else: - BYTES = 1024 + # if args.protocol: + # try: + # PROTOCOL_NUM = DIC_PROTOCOL_NUM[args.protocol] + # except KeyError: + # print "Protocol '%s' cannot be mapped to existing protocols, use TCP[6] as default" % (args.protocol) + # PROTOCOL_NUM = 6 + # else: + # PROTOCOL_NUM = 6 # TCP by default + # + # if args.bytes: + # try: + # BYTES = int(args.bytes) + # if BYTES < 1 or BYTES > 4096: + # raise ValueError + # except ValueError: + # print "Bytes '%s' should be integer between 1 and 4096, use 1024 as default" % (args.bytes) + # BYTES = 1024 + # else: + # BYTES = 1024 if args.flows_data: FLOW_DATA_LIST = args.flows_data.split(',') @@ -178,14 +178,14 @@ def main(): sys.exit(0) if flow_sequence % 100 == 0: gen_send_pkt('tmpl', flow_sequence=flow_sequence, src_ip=IP_SRC, dst_ip=IP_DST, - sport=PORT_SRC, dport=PORT_DST, protocol_num=PROTOCOL_NUM, octets=BYTES) + sport=PORT_SRC, dport=PORT_DST) continue gen_send_pkt('data', flow_sequence, src_ip=IP_SRC, dst_ip=IP_DST, sport=PORT_SRC, dport=PORT_DST, - protocol_num=PROTOCOL_NUM, octets=BYTES, flow_data_list=FLOW_DATA_LIST) + flow_data_list=FLOW_DATA_LIST) def gen_send_pkt(pkt_type='data', flow_sequence=1, src_ip='1.1.1.1', dst_ip = '2.2.2.2', sport=2056, dport=2055, - protocol_num=6, octets=1024, flow_data_list=[]): + flow_data_list=[]): timestamp = int(time.time()) if pkt_type == 'tmpl': pkt_netflow_tmpl = gen_pkt_netflow_tmpl(timestamp=timestamp, flow_sequence=flow_sequence, From 3bd857defcb1025e2268d9118084b84989e9947d Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 28 Sep 2017 17:35:09 +0800 Subject: [PATCH 050/156] Remove args.protocol and args.bytes --- src/pygennf_v9.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pygennf_v9.py b/src/pygennf_v9.py index 253a1cc..68add24 100644 --- a/src/pygennf_v9.py +++ b/src/pygennf_v9.py @@ -198,7 +198,7 @@ def gen_send_pkt(pkt_type='data', flow_sequence=1, src_ip='1.1.1.1', dst_ip = '2 sys_uptime = 3600 * 1000 pkt_netflow_data = gen_pkt_netflow_data(timestamp=timestamp, sys_uptime=sys_uptime, flow_sequence=flow_sequence, src_ip=src_ip, dst_ip=dst_ip, sport=sport, dport=dport, - protocol_num=protocol_num, octets=octets, flow_data_list=flow_data_list) + flow_data_list=flow_data_list) #wrpcap('v9_test_data.pcap', pkt_netflow_data) sys.stdout.write("Sending packets: %d \r" % (flow_sequence)) send(pkt_netflow_data, verbose=0) @@ -206,7 +206,7 @@ def gen_send_pkt(pkt_type='data', flow_sequence=1, src_ip='1.1.1.1', dst_ip = '2 def gen_pkt_netflow_data(timestamp=1503652676, flow_sequence=1, sys_uptime=3600000, src_ip='121.41.5.67', - dst_ip='121.41.5.68', sport=2056, dport=2055, protocol_num=6, octets=1024, flow_data_list=[]): + dst_ip='121.41.5.68', sport=2056, dport=2055, flow_data_list=[]): header_v9 = rbnf.Netflow_Headerv9(version=9, count=1, SysUptime=0x000069d7, Timestamp=timestamp, FlowSequence=flow_sequence, SourceId=2177) flowset_flow_header_v9 = rbnf.FlowSet_Header_v9(FlowSet_id=260, FlowSet_length=72) From d410a159840e15d0544d06a9a98b1d86aff63624 Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 28 Sep 2017 17:42:40 +0800 Subject: [PATCH 051/156] Add console snapshot --- resources/2017-09-28_console_snapshot_02.png | Bin 0 -> 7218 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 resources/2017-09-28_console_snapshot_02.png diff --git a/resources/2017-09-28_console_snapshot_02.png b/resources/2017-09-28_console_snapshot_02.png new file mode 100644 index 0000000000000000000000000000000000000000..a93cdc2bf1da7067fd6163dd650fdc0ffaf0405d GIT binary patch literal 7218 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 Date: Thu, 28 Sep 2017 17:46:23 +0800 Subject: [PATCH 052/156] Update README --- README.md | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 49e2e7a..817baa7 100644 --- a/README.md +++ b/README.md @@ -13,9 +13,9 @@ Netflow packets generator with Scapy library >usage: pygennf_v9.py [-h] [-s SRC_IP] [-sp SRC_PORT] [-d DST_IP] > [-dp DST_PORT] [-t TIME_INTERVAL] [-c PKT_COUNT] -> [-p PROTOCOL] [-b BYTES] +> [-fd FLOWS_DATA] > ->UDP packets producer with scapy +>Netflow packets generator with scapy > >optional arguments: > @@ -39,19 +39,16 @@ Netflow packets generator with Scapy library > -c PKT_COUNT, --pkt-count PKT_COUNT > Packets count to be sent before this generator stopping. > -> -p PROTOCOL, --protocol PROTOCOL -> Protocols included in netflow data part, e.g. tcp(6) or udp(17). -> -> -b BYTES, --bytes BYTES -> Bytes(octets) in single flow, e.g. 1024. +> -fd FLOWS_DATA, --flows-data FLOWS_DATA +> Contents in flows data, e.g. ip1/mask:port1:ip2/mask:port2:protocol:direction:bytes. > # Example of use: * Netflow 9: -> pygennf_v9.py --source-ip 10.19.5.54 --dst-ip 10.19.5.118 --dst-port 2062 -t 1 -c 3600 -p tcp -b 1024 +> pygennf_v9.py --source-ip 10.9.255.54 --dst-ip 10.9.255.118 --dst-port 2062 -t 1 -c 3600 -fd '69.31.102.10/32:12345:209.81.108.20/32:80:tcp:ingress:1024, 70.32.103.11/32:54321:210.81.108.21/32:21:udp:ingress:1024' > -> ![2017-09-27_console_snapshot_01.png](https://github.com/9nehS/pygennf/blob/master/resources/2017-09-27_console_snapshot_01.png) +> ![2017-09-28_console_snapshot_02.png](https://github.com/9nehS/pygennf/blob/master/resources/2017-09-28_console_snapshot_02.png) > > ![2017-09-27_web_snapshot_01.png](https://github.com/9nehS/pygennf/blob/master/resources/2017-09-27_web_snapshot_01.png) \ No newline at end of file From 3f886adc8d62a58effde80908dff5da5440bb441 Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 28 Sep 2017 17:48:53 +0800 Subject: [PATCH 053/156] Add WEB snapshot --- resources/2017-09-28_web_snapshot_01.png | Bin 0 -> 48594 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 resources/2017-09-28_web_snapshot_01.png diff --git a/resources/2017-09-28_web_snapshot_01.png b/resources/2017-09-28_web_snapshot_01.png new file mode 100644 index 0000000000000000000000000000000000000000..454650e4126c13ec9fe6d61efe4d7ba283f4707a GIT binary patch literal 48594 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%0DYVHGKUO4pKb+F4iHymRT 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 z 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⋘LLN@n&wx+3qiIt3pt6N#DSr_w}o2<={o2EVF z&Zt}HaXxw~&dwMc;cv6>^6IEwcH0|7$rBVXn>YN+G|m^f3Uqq)oz<(?Y?sGT|%N7VWZwoE5_XXa}!-Wj^D7Bc$L%osXG^zq~u zWsz#7HcQ>J@mGvXyUb&T18tMGse;Bd-lQ>2ZKMe~>4!KL&zbg7uqwsm4cj(hg`m+0 zJ1S?CCOXH_w$sgd}_R0%=Eh_ac)DH+sitd5vj{&WF_~X@XcmR^g^JC z;2Y$6<-F=xT&;>qj?Vp_#{Xr=+wwdkmxv_0TGt1BKdQF%)+WdIug&PHE+loV2;~*` zN_V*yt-UKQZ=1wvoU=2efrUTuUGQpK@(JO^xq~?CM`i?43(|`Sab=b7a#jP_?&cVIq1FE62AXVvX zxd0W=DhW=ZOgFTLMD_4OS=`I9On$@Ht$jkHDRX2Rm!`xFkUa}o1#ZTj;{J<}K6I&F z#l<`4Nkqxc#TAIb*Bhg<_^EqiaqQNg;h#j+Zk=~Vsh|h4!k!gTujWw0aDv|=`CFke z!x%zWCv`e7*fpJNpEZrc&l1kpY*Q@`#_)urz3EzkRCOe1+v+!m*<6qu;WH4C(a$&v z-tFPxXO{WH?Pjf=EBv_Ssnnv!=bTa3(PpW!LsfM38Yvy?4dMy!CK+CRjWc#{@p@?a z9X*ymIgqn>d5A+)^{P{upAwH6^ttaxeV2Jh}SW zWRK1rYU&R(b`w1*nD`v*YXh Date: Thu, 28 Sep 2017 17:50:09 +0800 Subject: [PATCH 054/156] Update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 817baa7..98feb24 100644 --- a/README.md +++ b/README.md @@ -51,4 +51,4 @@ Netflow packets generator with Scapy library > > ![2017-09-28_console_snapshot_02.png](https://github.com/9nehS/pygennf/blob/master/resources/2017-09-28_console_snapshot_02.png) > -> ![2017-09-27_web_snapshot_01.png](https://github.com/9nehS/pygennf/blob/master/resources/2017-09-27_web_snapshot_01.png) \ No newline at end of file +> ![2017-09-28_web_snapshot_01.png](https://github.com/9nehS/pygennf/blob/master/resources/2017-09-28_web_snapshot_01.png) \ No newline at end of file From 932493683cccbd2ee10af80689116c7011ad87e5 Mon Sep 17 00:00:00 2001 From: szhao Date: Fri, 29 Sep 2017 09:41:35 +0800 Subject: [PATCH 055/156] Remove old snapshots --- resources/2017-09-27_console_snapshot_01.png | Bin 4354 -> 0 bytes resources/2017-09-27_web_snapshot_01.png | Bin 32099 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 resources/2017-09-27_console_snapshot_01.png delete mode 100644 resources/2017-09-27_web_snapshot_01.png diff --git a/resources/2017-09-27_console_snapshot_01.png b/resources/2017-09-27_console_snapshot_01.png deleted file mode 100644 index 2d36af310290323f584c046fcf2f52d92d0c5f64..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4354 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 mf40|1{oOCO(iL;Z9h|74H)LH>`M%;Kg Date: Sat, 30 Sep 2017 13:51:21 +0800 Subject: [PATCH 056/156] Update comments --- rb_netflow/rb_netflow.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rb_netflow/rb_netflow.py b/rb_netflow/rb_netflow.py index 250b02d..caa040a 100644 --- a/rb_netflow/rb_netflow.py +++ b/rb_netflow/rb_netflow.py @@ -3,9 +3,10 @@ ## Copyright (C) Philippe Biondi ## This program is published under a GPLv2 license ## Netflow V5 appended by spaceB0x and Guillaume Valadon +## Netflow v9 with template ID 260 appended by Sheng """ -Cisco NetFlow protocol v1 and v5 +Cisco NetFlow protocol v1, v5, v9 and v10 """ From de542952e5c4979c871ef0a4056875b1abc5908c Mon Sep 17 00:00:00 2001 From: szhao Date: Sat, 30 Sep 2017 14:12:18 +0800 Subject: [PATCH 057/156] Update banner with ascii art --- src/pygennf_v9.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/pygennf_v9.py b/src/pygennf_v9.py index 68add24..2e272f4 100644 --- a/src/pygennf_v9.py +++ b/src/pygennf_v9.py @@ -56,12 +56,19 @@ def valid_flow_data(flow_data_str=''): # Netflow9 def main(): - print "\n****************************" - print "* Flow Generator Ver. 0.11 *" - print "* Modified by Sheng Zhao *" - print "* Calix Cloud SIT *" - print "* sheng.zhao@calix.com *" - print "****************************\n\n" + print "\n**************************************************************************" + print "* ______ _ _____ _ *" + print "* | ___| | | __ \ | | *" + print "* | |_ | | _____ __ | | \/ ___ _ __ ___ _ __ __ _| |_ ___ _ __ *" + print "* | _| | |/ _ \ \ /\ / / | | __ / _ \ '_ \ / _ \ '__/ _` | __/ _ \| '__| *" + print "* | | | | (_) \ V V / | |_\ \ __/ | | | __/ | | (_| | || (_) | | *" + print "* \_| |_|\___/ \_/\_/ \____/\___|_| |_|\___|_| \__,_|\__\___/|_| *" + print "* *" + print "* Flow Generator Ver. 0.11 *" + print "* Modified by Sheng Zhao *" + print "* Calix Cloud SIT *" + print "* sheng.zhao@calix.com *" + print "***************************************************************************\n\n" if os.getuid() != 0: print "You need to be root to run this, sorry." From 8ecb962ca063fb481339a38bea8482973ab4f233 Mon Sep 17 00:00:00 2001 From: szhao Date: Sat, 30 Sep 2017 14:15:53 +0800 Subject: [PATCH 058/156] Update banner with ascii art --- src/pygennf_v9.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pygennf_v9.py b/src/pygennf_v9.py index 2e272f4..42b595a 100644 --- a/src/pygennf_v9.py +++ b/src/pygennf_v9.py @@ -56,7 +56,7 @@ def valid_flow_data(flow_data_str=''): # Netflow9 def main(): - print "\n**************************************************************************" + print "\n***************************************************************************" print "* ______ _ _____ _ *" print "* | ___| | | __ \ | | *" print "* | |_ | | _____ __ | | \/ ___ _ __ ___ _ __ __ _| |_ ___ _ __ *" From 20c01fceb17a83b27db93dfbb8948c333f4e728d Mon Sep 17 00:00:00 2001 From: szhao Date: Sat, 30 Sep 2017 14:20:40 +0800 Subject: [PATCH 059/156] Remove legacy and added latest console snapshot --- resources/2017-09-28_console_snapshot_02.png | Bin 7218 -> 0 bytes resources/2017-09-30_console_snapshot_01.png | Bin 0 -> 11012 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 resources/2017-09-28_console_snapshot_02.png create mode 100644 resources/2017-09-30_console_snapshot_01.png diff --git a/resources/2017-09-28_console_snapshot_02.png b/resources/2017-09-28_console_snapshot_02.png deleted file mode 100644 index a93cdc2bf1da7067fd6163dd650fdc0ffaf0405d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7218 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 Date: Sat, 30 Sep 2017 14:21:31 +0800 Subject: [PATCH 060/156] Update snapshot link in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 98feb24..116051d 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,6 @@ Netflow packets generator with Scapy library * Netflow 9: > pygennf_v9.py --source-ip 10.9.255.54 --dst-ip 10.9.255.118 --dst-port 2062 -t 1 -c 3600 -fd '69.31.102.10/32:12345:209.81.108.20/32:80:tcp:ingress:1024, 70.32.103.11/32:54321:210.81.108.21/32:21:udp:ingress:1024' > -> ![2017-09-28_console_snapshot_02.png](https://github.com/9nehS/pygennf/blob/master/resources/2017-09-28_console_snapshot_02.png) +> ![2017-09-30_console_snapshot_01](https://github.com/9nehS/pygennf/blob/master/resources/2017-09-30_console_snapshot_01) > > ![2017-09-28_web_snapshot_01.png](https://github.com/9nehS/pygennf/blob/master/resources/2017-09-28_web_snapshot_01.png) \ No newline at end of file From eb07fd4cc6182b6e6a3aa0ba765ca854f822c198 Mon Sep 17 00:00:00 2001 From: szhao Date: Sat, 30 Sep 2017 14:23:01 +0800 Subject: [PATCH 061/156] Update snapshot link in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 116051d..e68ae1d 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,6 @@ Netflow packets generator with Scapy library * Netflow 9: > pygennf_v9.py --source-ip 10.9.255.54 --dst-ip 10.9.255.118 --dst-port 2062 -t 1 -c 3600 -fd '69.31.102.10/32:12345:209.81.108.20/32:80:tcp:ingress:1024, 70.32.103.11/32:54321:210.81.108.21/32:21:udp:ingress:1024' > -> ![2017-09-30_console_snapshot_01](https://github.com/9nehS/pygennf/blob/master/resources/2017-09-30_console_snapshot_01) +> ![2017-09-30_console_snapshot_01.png](https://github.com/9nehS/pygennf/blob/master/resources/2017-09-30_console_snapshot_01.png) > > ![2017-09-28_web_snapshot_01.png](https://github.com/9nehS/pygennf/blob/master/resources/2017-09-28_web_snapshot_01.png) \ No newline at end of file From 00589169f6fc9a67a3e88ac00181c3774fed9d50 Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 31 Oct 2017 16:24:58 +0800 Subject: [PATCH 062/156] To add multi threads capability --- src/pygennf_v9_multi_threads.py | 391 ++++++++++++++++++++++++++++++++ 1 file changed, 391 insertions(+) create mode 100644 src/pygennf_v9_multi_threads.py diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py new file mode 100644 index 0000000..42b595a --- /dev/null +++ b/src/pygennf_v9_multi_threads.py @@ -0,0 +1,391 @@ +#!/bin/env python +# +# pygennf: UDP packets producer with scapy. +# Copyright (C) 2016-2017 Sheng Zhao +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +import argparse +import time +import signal +import re + +import scapy +from scapy.all import * + +import rb_netflow.rb_netflow as rbnf + +SIGNAL_RECEIVED = 0 + +DIC_PROTOCOL_NUM = {'tcp': 6, 'udp': 17} +DIC_DIRECTION_NUM = {'ingress': 0, 'egress': 1} + +# ip1/mask:port1:ip2/mask:port2:protocol:direction:bytes +# e.g. 11.11.11.11/32:1001:11.11.11.22/32:1002:tcp:ingress:1024 +FLOW_DATA_PATTERN = r'^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d{1,2}:\d{1,5}:){2}\w+:(ingress|egress):\d{1,4}$' +DEFAULT_FLOW_DATA = '11.11.11.11/32:1001:11.11.11.22/32:80:tcp:ingress:1024' + +def preexec(): + os.setpgrp() # Don't forward signals + + +def signal_handler(signal, frame): + global SIGNAL_RECEIVED + SIGNAL_RECEIVED = 1 + + +def valid_flow_data(flow_data_str=''): + global FLOW_DATA_PATTERN + m = re.match(FLOW_DATA_PATTERN, flow_data_str) + if m is not None: + return True + return False + + +# Netflow9 +def main(): + + print "\n***************************************************************************" + print "* ______ _ _____ _ *" + print "* | ___| | | __ \ | | *" + print "* | |_ | | _____ __ | | \/ ___ _ __ ___ _ __ __ _| |_ ___ _ __ *" + print "* | _| | |/ _ \ \ /\ / / | | __ / _ \ '_ \ / _ \ '__/ _` | __/ _ \| '__| *" + print "* | | | | (_) \ V V / | |_\ \ __/ | | | __/ | | (_| | || (_) | | *" + print "* \_| |_|\___/ \_/\_/ \____/\___|_| |_|\___|_| \__,_|\__\___/|_| *" + print "* *" + print "* Flow Generator Ver. 0.11 *" + print "* Modified by Sheng Zhao *" + print "* Calix Cloud SIT *" + print "* sheng.zhao@calix.com *" + print "***************************************************************************\n\n" + + if os.getuid() != 0: + print "You need to be root to run this, sorry." + return + + parser = argparse.ArgumentParser(description='Netflow packets generator with scapy') + parser.add_argument('-s', '--source-ip', dest='src_ip', + help='Source IP of netflow packet(s).') + parser.add_argument('-sp', '--source-port', dest='src_port', + help='Source port of netflow packet(s).') + parser.add_argument('-d', '--dst-ip', dest='dst_ip', + help='Destination IP of netflow packet(s).') + parser.add_argument('-dp', '--dst-port', dest='dst_port', + help='Destination port of netflow packet(s).') + parser.add_argument('-t', '--time-interval', dest='time_interval', + help='Time interval to wait before sending each netflow packet.') + parser.add_argument('-c', '--pkt-count', dest='pkt_count', + help='Packets count to be sent before this generator stopping.') + # parser.add_argument('-p', '--protocol', dest='protocol', + # help='Protocols included in netflow data part, e.g. tcp(6) or udp(17).') + # parser.add_argument('-b', '--bytes', dest='bytes', + # help='Bytes(octets) in single flow, e.g. 1024.') + parser.add_argument('-fd', '--flows-data', dest='flows_data', + help='Contents in flows data, e.g. ip1/mask:port1:ip2/mask:port2:protocol:direction:bytes.') + + args = parser.parse_args() + if args.src_ip: + IP_SRC = args.src_ip + else: + IP_SRC = "10.0.203.2" + + if args.dst_ip: + IP_DST = args.dst_ip + else: + IP_DST = "10.0.30.89" + + if IP_DST == "127.0.0.1": + conf.L3socket=L3RawSocket + + if args.src_port: + PORT_SRC = int(args.src_port) + else: + PORT_SRC = int(2056) + + if args.dst_port: + PORT_DST = int(args.dst_port) + else: + PORT_DST = int(2055) + + if args.time_interval: + TIME_INTERVAL = args.time_interval + else: + TIME_INTERVAL = 1 + + if args.pkt_count: + PKT_COUNT = int(args.pkt_count) + else: + # 0xFFFFFFFF - 1 + PKT_COUNT = 4294967294 + + # if args.protocol: + # try: + # PROTOCOL_NUM = DIC_PROTOCOL_NUM[args.protocol] + # except KeyError: + # print "Protocol '%s' cannot be mapped to existing protocols, use TCP[6] as default" % (args.protocol) + # PROTOCOL_NUM = 6 + # else: + # PROTOCOL_NUM = 6 # TCP by default + # + # if args.bytes: + # try: + # BYTES = int(args.bytes) + # if BYTES < 1 or BYTES > 4096: + # raise ValueError + # except ValueError: + # print "Bytes '%s' should be integer between 1 and 4096, use 1024 as default" % (args.bytes) + # BYTES = 1024 + # else: + # BYTES = 1024 + + if args.flows_data: + FLOW_DATA_LIST = args.flows_data.split(',') + FLOW_DATA_LIST = map(str.strip, FLOW_DATA_LIST) + FLOW_DATA_LIST = filter(valid_flow_data, FLOW_DATA_LIST) + if len(FLOW_DATA_LIST) == 0: + print 'No valid flow data list, default flow data list will be used...' + print "Default flow data: %s" % (DEFAULT_FLOW_DATA) + FLOW_DATA_LIST.append(DEFAULT_FLOW_DATA) + else: + print "'args.flows_data' is empty, default flow data list will be used..." + print "Default flow data: %s" % (DEFAULT_FLOW_DATA) + FLOW_DATA_LIST = [] + FLOW_DATA_LIST.append(DEFAULT_FLOW_DATA) + + signal.signal(signal.SIGINT, signal_handler) + signal.signal(signal.SIGTERM, signal_handler) + + flow_sequence = 1 + + gen_send_pkt('tmpl', flow_sequence=flow_sequence, src_ip=IP_SRC, dst_ip=IP_DST, sport=PORT_SRC, dport=PORT_DST) + + print 'Flows to be sent: ' + print FLOW_DATA_LIST + + while TIME_INTERVAL is not 0: + if SIGNAL_RECEIVED == 1: + print "\nSignal received. %s packets have been sent. Stopping and Exiting..." % flow_sequence + sys.exit(0) + time.sleep(float(TIME_INTERVAL)) + + flow_sequence = flow_sequence + 1 + if flow_sequence > PKT_COUNT: + print "\nPackets count[%s] reached. Stopping and Exiting..." % PKT_COUNT + sys.exit(0) + if flow_sequence % 100 == 0: + gen_send_pkt('tmpl', flow_sequence=flow_sequence, src_ip=IP_SRC, dst_ip=IP_DST, + sport=PORT_SRC, dport=PORT_DST) + continue + gen_send_pkt('data', flow_sequence, src_ip=IP_SRC, dst_ip=IP_DST, sport=PORT_SRC, dport=PORT_DST, + flow_data_list=FLOW_DATA_LIST) + + +def gen_send_pkt(pkt_type='data', flow_sequence=1, src_ip='1.1.1.1', dst_ip = '2.2.2.2', sport=2056, dport=2055, + flow_data_list=[]): + timestamp = int(time.time()) + if pkt_type == 'tmpl': + pkt_netflow_tmpl = gen_pkt_netflow_tmpl(timestamp=timestamp, flow_sequence=flow_sequence, + src_ip=src_ip, dst_ip =dst_ip, sport=sport, dport=dport) + #wrpcap('v9_test_tmpl.pcap', pkt_netflow_tmpl) + sys.stdout.write("Sending packets: %d \r" % (flow_sequence)) + send(pkt_netflow_tmpl, verbose=0) + sys.stdout.flush() + elif pkt_type == 'data': + sys_uptime = 3600 * 1000 + pkt_netflow_data = gen_pkt_netflow_data(timestamp=timestamp, sys_uptime=sys_uptime, flow_sequence=flow_sequence, + src_ip=src_ip, dst_ip=dst_ip, sport=sport, dport=dport, + flow_data_list=flow_data_list) + #wrpcap('v9_test_data.pcap', pkt_netflow_data) + sys.stdout.write("Sending packets: %d \r" % (flow_sequence)) + send(pkt_netflow_data, verbose=0) + sys.stdout.flush() + + +def gen_pkt_netflow_data(timestamp=1503652676, flow_sequence=1, sys_uptime=3600000, src_ip='121.41.5.67', + dst_ip='121.41.5.68', sport=2056, dport=2055, flow_data_list=[]): + header_v9 = rbnf.Netflow_Headerv9(version=9, count=1, SysUptime=0x000069d7, Timestamp=timestamp, + FlowSequence=flow_sequence, SourceId=2177) + flowset_flow_header_v9 = rbnf.FlowSet_Header_v9(FlowSet_id=260, FlowSet_length=72) + + # List for SrcAddr and DstAddr in netflow data + # src_dst_addr_list = [] + # src_dst_addr_list.append(['69.31.102.10', '209.81.108.20']) + # src_dst_addr_list.append(['70.32.103.11', '210.81.108.21']) + # src_dst_addr_list.append(['70.32.103.12', '210.81.108.22']) + # src_dst_addr_list.append(['70.32.103.13', '210.81.108.23']) + # src_dst_addr_list.append(['70.32.103.14', '210.81.108.24']) + # src_dst_addr_list.append(['70.32.103.15', '210.81.108.25']) + # src_dst_addr_list.append(['70.32.103.16', '210.81.108.26']) + # src_dst_addr_list.append(['70.32.103.17', '210.81.108.27']) + # src_dst_addr_list.append(['70.32.103.18', '210.81.108.28']) + # src_dst_addr_list.append(['70.32.103.19', '210.81.108.29']) + # src_dst_addr_list.append(['70.32.103.20', '210.81.108.30']) + # src_dst_addr_list.append(['70.32.103.21', '210.81.108.31']) + # src_dst_addr_list.append(['70.32.103.22', '210.81.108.32']) + # src_dst_addr_list.append(['70.32.103.23', '210.81.108.33']) + # src_dst_addr_list.append(['70.32.103.24', '210.81.108.34']) + # src_dst_addr_list.append(['70.32.103.25', '210.81.108.35']) + # src_dst_addr_list.append(['70.32.103.26', '210.81.108.36']) + # src_dst_addr_list.append(['70.32.103.27', '210.81.108.37']) + # src_dst_addr_list.append(['70.32.103.28', '210.81.108.38']) + # src_dst_addr_list.append(['70.32.103.29', '210.81.108.39']) + # src_dst_addr_list.append(['70.32.103.30', '210.81.108.40']) + # src_dst_port_list = [] + # src_dst_port_list.append([12345, 80]) + + # List for flows in one packet + flows = [] + # for src_dst_addr in src_dst_addr_list: + # #end_time = sys_uptime + 3600 * 1000 + # end_time = timestamp + # start_time = end_time - 1000 # Duration 1s + # flows.append(rbnf.Flow_260_v9( + # Packets=1, Octets=octets, SrcAddr=src_dst_addr[0], DstAddr=src_dst_addr[1], InputInt=145, OutputInt=142, + # EndTime=end_time, StartTime=start_time, SrcPort=src_dst_port_list[0][0], DstPort=src_dst_port_list[0][1], + # SrcAS=0, DstAS=0, BGPNextHop='0.0.0.0', SrcMask=17, DstMask=28, Protocol=protocol_num, TCPFlags=0x10, IPToS=0x00, + # Direction=0, ForwardingStatus=0x40, SamplerID=2, IngressVRFID=0x60000000, EgressVRFID=0x60000000 + # )) + + + # To process flow_data_list + for flow_data in flow_data_list: + data_item_list = flow_data.split(':') + src_addr = data_item_list[0].split('/')[0] + src_mask = int(data_item_list[0].split('/')[1]) + src_port = int(data_item_list[1]) + dst_addr = data_item_list[2].split('/')[0] + dst_mask = int(data_item_list[2].split('/')[1]) + dst_port = int(data_item_list[3]) + protocol_num = DIC_PROTOCOL_NUM[data_item_list[4]] + direction = DIC_DIRECTION_NUM[data_item_list[5]] + bytes = int(data_item_list[6]) + end_time = timestamp + start_time = end_time - 1000 # Duration 1s + flows.append(rbnf.Flow_260_v9( + Packets=1, Octets=bytes, SrcAddr=src_addr, DstAddr=dst_addr, InputInt=145, OutputInt=142, + EndTime=end_time, StartTime=start_time, SrcPort=src_port, DstPort=dst_port, + SrcAS=0, DstAS=0, BGPNextHop='0.0.0.0', SrcMask=src_mask, DstMask=dst_mask, Protocol=protocol_num, + TCPFlags=0x10, IPToS=0x00, Direction=direction, ForwardingStatus=0x40, SamplerID=2, IngressVRFID=0x60000000, + EgressVRFID=0x60000000 + )) + + # Calculate the length of netflow data before padding + len_netflow = 0 + len_netflow = calc_netflow_len(header_v9, flowset_flow_header_v9, flows) + pad_len = 0 + pad = None + #print 'len_netflow:', len_netflow + #sys.stdout.write("len_netflow: %d\n" % (len_netflow)) + len_after_padding = 0 + + # Padding to make sure that FlowSet starts at a 4-byte aligned boundary -- rfc3954.txt + if len_netflow % 4 != 0: + len_after_padding = ((len_netflow / 4) + 1) * 4 + pad_len = len_after_padding - len_netflow + #print 'pad_len:', pad_len + #sys.stdout.write("pad_len: %d\n" % (pad_len)) + else: + len_after_padding = len_netflow + + header_v9.setfieldval('count', len(flows)) + flowset_flow_header_v9.setfieldval('FlowSet_length', len_after_padding - 20) + pkt_netflow_data = IP(src=src_ip, dst=dst_ip, len=len_after_padding + 28) / UDP(sport=sport, dport=dport, + len=len_after_padding + 8) + pkt_netflow_data /= header_v9 / flowset_flow_header_v9 + for flow in flows: + pkt_netflow_data /= flow + + if pad_len > 0: + pad = Padding() + pad.load = '\x00' * pad_len + pkt_netflow_data = pkt_netflow_data / pad + + return pkt_netflow_data + + +def calc_netflow_len(header, flowset_flow_header, flows): + len_netflow = 0 + len_netflow = len(header) + len(flowset_flow_header) + for flow in flows: + len_netflow = len_netflow + len(flow) + + return len_netflow + + +def gen_pkt_netflow_tmpl(timestamp=1503652676, flow_sequence=1, source_id=2177, template_id=260, src_ip='121.41.5.67', + dst_ip='121.41.5.68', sport=2056, dport=2055): + header_v9 = rbnf.Netflow_Headerv9(version=9, count=1, SysUptime=0x000069d7, Timestamp=timestamp, FlowSequence=flow_sequence,SourceId=source_id) + flowset_tmpl_header_v9 = rbnf.FlowSet_Header_v9(FlowSet_id=0, FlowSet_length=100) + flowset_tmpl_data_header_v9 = rbnf.FlowTemplate_ID_v9(template_id=template_id,count=23) + flowset_tmpl_data_260_v9 = [ + # Field (1/23): PKTS, Type: 2, Length: 4 + rbnf.NetFlowTemplatev9Field(type_template=2, length= 4), + # Field (2/23): BYTES, Type: 1, Length: 4 + rbnf.NetFlowTemplatev9Field(type_template=1, length= 4), + # Field (3/23): IP_SRC_ADDR, Type: 8, Length: 4 + rbnf.NetFlowTemplatev9Field(type_template=8, length= 4), + # Field (4/23): IP_DST_ADDR, Type: 12, Length: 4 + rbnf.NetFlowTemplatev9Field(type_template=12, length= 4), + # Field (5/23): INPUT_SNMP, Type: 10, Length: 4 + rbnf.NetFlowTemplatev9Field(type_template=10, length= 4), + # Field (6/23): OUTPUT_SNMP, Type: 14, Length: 4 + rbnf.NetFlowTemplatev9Field(type_template=14, length= 4), + # Field (7/23): LAST_SWITCHED, Type: 21, Length: 4 + rbnf.NetFlowTemplatev9Field(type_template=21, length= 4), + # Field (8/23): FIRST_SWITCHED, Type: 22, Length: 4 + rbnf.NetFlowTemplatev9Field(type_template=22, length= 4), + # Field (9/23): L4_SRC_PORT, Type: 7, Length: 2 + rbnf.NetFlowTemplatev9Field(type_template=7, length= 2), + # Field (10/23): L4_DST_PORT, Type: 11, Length: 2 + rbnf.NetFlowTemplatev9Field(type_template=11, length= 2), + # Field (11/23): SRC_AS, Type: 16, Length: 4 + rbnf.NetFlowTemplatev9Field(type_template=16, length= 4), + # Field (12/23): DST_AS, Type: 17, Length: 4 + rbnf.NetFlowTemplatev9Field(type_template=17, length= 4), + # Field (13/23): BGP_NEXT_HOP, Type: 18, Length: 4 + rbnf.NetFlowTemplatev9Field(type_template=18, length= 4), + # Field (14/23): SRC_MASK, Type: 9, Length: 1 + rbnf.NetFlowTemplatev9Field(type_template=9, length= 1), + # Field (15/23): DST_MASK, Type: 13, Length: 1 + rbnf.NetFlowTemplatev9Field(type_template=13, length= 1), + # Field (16/23): PROTOCOL, Type: 4, Length: 1 + rbnf.NetFlowTemplatev9Field(type_template=4, length= 1), + # Field (17/23): TCP_FLAGS, Type: 6, Length: 1 + rbnf.NetFlowTemplatev9Field(type_template=6, length= 1), + # Field (18/23): IP_TOS, Type: 5, Length: 1 + rbnf.NetFlowTemplatev9Field(type_template=5, length= 1), + # Field (19/23): DIRECTION, Type: 61, Length: 1 + rbnf.NetFlowTemplatev9Field(type_template=61, length=1), + # Field (20/23): FORWARDING_STATUS, Type: 89, Length: 1 + rbnf.NetFlowTemplatev9Field(type_template=89, length=1), + # Field (21/23): FLOW_SAMPLER_ID, Type: 48, Length: 2 + rbnf.NetFlowTemplatev9Field(type_template=48, length=2), + # Field (22/23): ingressVRFID, Type: 234, Length: 4 + rbnf.NetFlowTemplatev9Field(type_template=234, length=4), + # Field (23/23): egressVRFID, Type: 235, Length: 4 + rbnf.NetFlowTemplatev9Field(type_template=235, length=4) + ] + + pkt_netflow_tmpl = IP(src=src_ip,dst=dst_ip)/UDP(sport=sport,dport=dport) + pkt_netflow_tmpl/=header_v9/flowset_tmpl_header_v9/flowset_tmpl_data_header_v9 + + for t in flowset_tmpl_data_260_v9: + pkt_netflow_tmpl/=t + + return pkt_netflow_tmpl + + +if __name__ == '__main__': + main() + From dcddb62119a87ecfdd27091770a249cd02e25533 Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 31 Oct 2017 17:10:55 +0800 Subject: [PATCH 063/156] To add multi threads capability in main() --- src/pygennf_v9_multi_threads.py | 36 ++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index 42b595a..7ad07e3 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -20,6 +20,7 @@ import time import signal import re +import threading import scapy from scapy.all import * @@ -166,29 +167,40 @@ def main(): signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler) - flow_sequence = 1 + #start_send(IP_SRC, IP_DST, PORT_SRC, PORT_DST, FLOW_DATA_LIST, PKT_COUNT, TIME_INTERVAL) - gen_send_pkt('tmpl', flow_sequence=flow_sequence, src_ip=IP_SRC, dst_ip=IP_DST, sport=PORT_SRC, dport=PORT_DST) + print 'Thread %s is running...' % threading.current_thread().name + t = threading.Thread(target=start_send, name='SendingThread', args=(IP_SRC, IP_DST, PORT_SRC, PORT_DST, + FLOW_DATA_LIST, PKT_COUNT, TIME_INTERVAL)) + t.start() + t.join() + print 'Thread %s ended.' % threading.current_thread().name - print 'Flows to be sent: ' - print FLOW_DATA_LIST - while TIME_INTERVAL is not 0: +def start_send(ip_src, ip_dst, port_src, port_dst, flow_data_list, pkt_count, time_interval): + print 'Thread %s is running...' % threading.current_thread().name + flow_sequence = 1 + gen_send_pkt('tmpl', flow_sequence=flow_sequence, src_ip=ip_src, dst_ip=ip_dst, sport=port_src, dport=port_dst) + print 'Flows to be sent: ' + print flow_data_list + while time_interval is not 0: if SIGNAL_RECEIVED == 1: print "\nSignal received. %s packets have been sent. Stopping and Exiting..." % flow_sequence sys.exit(0) - time.sleep(float(TIME_INTERVAL)) + time.sleep(float(time_interval)) flow_sequence = flow_sequence + 1 - if flow_sequence > PKT_COUNT: - print "\nPackets count[%s] reached. Stopping and Exiting..." % PKT_COUNT + if flow_sequence > pkt_count: + print "\nPackets count[%s] reached. Stopping and Exiting..." % pkt_count sys.exit(0) if flow_sequence % 100 == 0: - gen_send_pkt('tmpl', flow_sequence=flow_sequence, src_ip=IP_SRC, dst_ip=IP_DST, - sport=PORT_SRC, dport=PORT_DST) + gen_send_pkt('tmpl', flow_sequence=flow_sequence, src_ip=ip_src, dst_ip=ip_dst, + sport=port_src, dport=port_dst) continue - gen_send_pkt('data', flow_sequence, src_ip=IP_SRC, dst_ip=IP_DST, sport=PORT_SRC, dport=PORT_DST, - flow_data_list=FLOW_DATA_LIST) + gen_send_pkt('data', flow_sequence, src_ip=ip_src, dst_ip=ip_dst, sport=port_src, dport=port_dst, + flow_data_list=flow_data_list) + + print 'Thread %s ended.' % threading.current_thread().name def gen_send_pkt(pkt_type='data', flow_sequence=1, src_ip='1.1.1.1', dst_ip = '2.2.2.2', sport=2056, dport=2055, From f901dd76989a96b04a8ae4ae4ae90a1f34315cb2 Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 31 Oct 2017 17:11:54 +0800 Subject: [PATCH 064/156] To include the multi threads file --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index b87d6ae..2caf0ce 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ author_email="sheng.zhao@calix.com", url="https://github.com/9nehS/", license="AGPL", - scripts=["src/pygennf_v9.py"], + scripts=["src/pygennf_v9.py", "src/pygennf_v9_multi_threads.py"], packages=['rb_netflow'], install_requires=[ 'scapy', From 39e174b3e65256ef82c0b5cc45cfdc6fb6abf899 Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 31 Oct 2017 17:31:15 +0800 Subject: [PATCH 065/156] To include the multi threads file --- src/pygennf_v9_multi_threads.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index 7ad07e3..599eda9 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -192,7 +192,8 @@ def start_send(ip_src, ip_dst, port_src, port_dst, flow_data_list, pkt_count, ti flow_sequence = flow_sequence + 1 if flow_sequence > pkt_count: print "\nPackets count[%s] reached. Stopping and Exiting..." % pkt_count - sys.exit(0) + #sys.exit(0) + break if flow_sequence % 100 == 0: gen_send_pkt('tmpl', flow_sequence=flow_sequence, src_ip=ip_src, dst_ip=ip_dst, sport=port_src, dport=port_dst) From 8129715f91502676aa008e89b41eaf836a5680d7 Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 31 Oct 2017 17:50:24 +0800 Subject: [PATCH 066/156] To include the multi threads file --- src/pygennf_v9_multi_threads.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index 599eda9..e877376 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -44,6 +44,7 @@ def preexec(): def signal_handler(signal, frame): global SIGNAL_RECEIVED SIGNAL_RECEIVED = 1 + print 'signal_handler invoked...' def valid_flow_data(flow_data_str=''): @@ -172,6 +173,7 @@ def main(): print 'Thread %s is running...' % threading.current_thread().name t = threading.Thread(target=start_send, name='SendingThread', args=(IP_SRC, IP_DST, PORT_SRC, PORT_DST, FLOW_DATA_LIST, PKT_COUNT, TIME_INTERVAL)) + t.do_run = True t.start() t.join() print 'Thread %s ended.' % threading.current_thread().name From c39bb0b03823f7c185e39eb28f7af4f2030b9577 Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 31 Oct 2017 17:52:59 +0800 Subject: [PATCH 067/156] To include the multi threads file --- src/pygennf_v9_multi_threads.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index e877376..9820eab 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -180,6 +180,8 @@ def main(): def start_send(ip_src, ip_dst, port_src, port_dst, flow_data_list, pkt_count, time_interval): + signal.signal(signal.SIGINT, signal_handler) + signal.signal(signal.SIGTERM, signal_handler) print 'Thread %s is running...' % threading.current_thread().name flow_sequence = 1 gen_send_pkt('tmpl', flow_sequence=flow_sequence, src_ip=ip_src, dst_ip=ip_dst, sport=port_src, dport=port_dst) From da73ccf2d43f8e12ecb96b51e7a3141fbed9978d Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 31 Oct 2017 17:56:28 +0800 Subject: [PATCH 068/156] To include the multi threads file --- src/pygennf_v9_multi_threads.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index 9820eab..e877376 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -180,8 +180,6 @@ def main(): def start_send(ip_src, ip_dst, port_src, port_dst, flow_data_list, pkt_count, time_interval): - signal.signal(signal.SIGINT, signal_handler) - signal.signal(signal.SIGTERM, signal_handler) print 'Thread %s is running...' % threading.current_thread().name flow_sequence = 1 gen_send_pkt('tmpl', flow_sequence=flow_sequence, src_ip=ip_src, dst_ip=ip_dst, sport=port_src, dport=port_dst) From ce4583bc154dbc2f86c70050beadf71ed2b54f6d Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 31 Oct 2017 18:01:40 +0800 Subject: [PATCH 069/156] To include the multi threads file --- src/pygennf_v9_multi_threads.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index e877376..d5ff4f2 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -174,6 +174,7 @@ def main(): t = threading.Thread(target=start_send, name='SendingThread', args=(IP_SRC, IP_DST, PORT_SRC, PORT_DST, FLOW_DATA_LIST, PKT_COUNT, TIME_INTERVAL)) t.do_run = True + t.setDaemon(True) t.start() t.join() print 'Thread %s ended.' % threading.current_thread().name From bab4a56dd0e029927b536ba7069fed12ef88ee76 Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 31 Oct 2017 18:58:58 +0800 Subject: [PATCH 070/156] To include the multi threads file --- src/pygennf_v9_multi_threads.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index d5ff4f2..a3958f5 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -174,9 +174,11 @@ def main(): t = threading.Thread(target=start_send, name='SendingThread', args=(IP_SRC, IP_DST, PORT_SRC, PORT_DST, FLOW_DATA_LIST, PKT_COUNT, TIME_INTERVAL)) t.do_run = True - t.setDaemon(True) + #t.setDaemon(True) t.start() - t.join() + while True: + t.join(5) + print 'Thread %s ended.' % threading.current_thread().name @@ -189,7 +191,8 @@ def start_send(ip_src, ip_dst, port_src, port_dst, flow_data_list, pkt_count, ti while time_interval is not 0: if SIGNAL_RECEIVED == 1: print "\nSignal received. %s packets have been sent. Stopping and Exiting..." % flow_sequence - sys.exit(0) + #sys.exit(0) + break time.sleep(float(time_interval)) flow_sequence = flow_sequence + 1 From a6289b0ea5e073390c6b94a2962c54ee11187b79 Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 31 Oct 2017 19:00:42 +0800 Subject: [PATCH 071/156] To include the multi threads file --- src/pygennf_v9_multi_threads.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index a3958f5..a5630b6 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -174,7 +174,7 @@ def main(): t = threading.Thread(target=start_send, name='SendingThread', args=(IP_SRC, IP_DST, PORT_SRC, PORT_DST, FLOW_DATA_LIST, PKT_COUNT, TIME_INTERVAL)) t.do_run = True - #t.setDaemon(True) + t.setDaemon(True) t.start() while True: t.join(5) From 842167c605c3b914168d6a2f9695dd84daa1f664 Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 31 Oct 2017 19:02:56 +0800 Subject: [PATCH 072/156] To include the multi threads file --- src/pygennf_v9_multi_threads.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index a5630b6..116683b 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -191,8 +191,8 @@ def start_send(ip_src, ip_dst, port_src, port_dst, flow_data_list, pkt_count, ti while time_interval is not 0: if SIGNAL_RECEIVED == 1: print "\nSignal received. %s packets have been sent. Stopping and Exiting..." % flow_sequence - #sys.exit(0) - break + sys.exit(0) + #break time.sleep(float(time_interval)) flow_sequence = flow_sequence + 1 From e6163b2900d479b225c195e9858d6dd7c5a88346 Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 31 Oct 2017 19:07:30 +0800 Subject: [PATCH 073/156] To include the multi threads file --- src/pygennf_v9_multi_threads.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index 116683b..4367d88 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -178,6 +178,8 @@ def main(): t.start() while True: t.join(5) + if not t.isAlive(): + break print 'Thread %s ended.' % threading.current_thread().name @@ -191,8 +193,8 @@ def start_send(ip_src, ip_dst, port_src, port_dst, flow_data_list, pkt_count, ti while time_interval is not 0: if SIGNAL_RECEIVED == 1: print "\nSignal received. %s packets have been sent. Stopping and Exiting..." % flow_sequence - sys.exit(0) - #break + #sys.exit(0) + break time.sleep(float(time_interval)) flow_sequence = flow_sequence + 1 From 4b2778418a79b426149a9af23d2284b79194d6cb Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 1 Nov 2017 19:28:49 +0800 Subject: [PATCH 074/156] To include the multi threads file --- src/pygennf_v9_multi_threads.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index 4367d88..bb81292 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -173,8 +173,8 @@ def main(): print 'Thread %s is running...' % threading.current_thread().name t = threading.Thread(target=start_send, name='SendingThread', args=(IP_SRC, IP_DST, PORT_SRC, PORT_DST, FLOW_DATA_LIST, PKT_COUNT, TIME_INTERVAL)) - t.do_run = True - t.setDaemon(True) + #t.do_run = True + #t.setDaemon(True) t.start() while True: t.join(5) From 8aa88228c27e22428f4abbfcbc4b77a9ee29d4d0 Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 12 Dec 2017 17:00:28 +0800 Subject: [PATCH 075/156] Add web_api.py --- src/web_api/__init__.py | 0 src/web_api/web_api.py | 21 +++++++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 src/web_api/__init__.py create mode 100644 src/web_api/web_api.py diff --git a/src/web_api/__init__.py b/src/web_api/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/web_api/web_api.py b/src/web_api/web_api.py new file mode 100644 index 0000000..cb417cf --- /dev/null +++ b/src/web_api/web_api.py @@ -0,0 +1,21 @@ +from flask import Flask, request, jsonify +from flask import Response + +app = Flask(__name__) + +@app.route('/') +def help(): + return jsonify( + # 'API (application/json)': 'PATH, notes ?org-id= currently required', + {'Cache clean': '/marketing/cache/clean?org-ids=', + 'Cache clean and rebuild': '/marketing/cache/clean-rebuild?org-ids=&rebuild-table=true', + 'Cache status': '/marketing/cache/status', + 'On board': '/marketing/onboard?org-ids=', + 'On board status': '/marketing/onboard/status', + 'Delayed scheduled rebuild task': 'add:/marketing/cache/rebuild/operation?opt=add&org-ids= ' + 'delete:/marketing/cache/rebuild/operation?opt=delete&org-ids=', + 'Delayed task status': '/marketing/cache/rebuild/status?org-id=' + }) + +def start(): + app.run(host='0.0.0.0') \ No newline at end of file From 4d27eb7d335609785a30879642b61f71f0c9e99c Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 12 Dec 2017 17:01:29 +0800 Subject: [PATCH 076/156] Add __init__.py --- src/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/__init__.py diff --git a/src/__init__.py b/src/__init__.py new file mode 100644 index 0000000..e69de29 From 6a1ef44e98cf36918f99dc37749689d1a1f4647c Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 12 Dec 2017 17:02:11 +0800 Subject: [PATCH 077/156] Add __init__.py --- src/pygennf_v9_multi_threads.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index bb81292..3a8133a 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -17,15 +17,13 @@ # along with this program. If not, see . import argparse -import time import signal -import re import threading -import scapy from scapy.all import * import rb_netflow.rb_netflow as rbnf +from web_api import web_api SIGNAL_RECEIVED = 0 @@ -95,8 +93,15 @@ def main(): # help='Bytes(octets) in single flow, e.g. 1024.') parser.add_argument('-fd', '--flows-data', dest='flows_data', help='Contents in flows data, e.g. ip1/mask:port1:ip2/mask:port2:protocol:direction:bytes.') + parser.add_argument('-r', '--remote', dest='remote', + help='Listen on TCP port 9080 as API server. All other parameters will be ignored.') args = parser.parse_args() + + if args.remote: + web_api.start() + sys.exit(0) + if args.src_ip: IP_SRC = args.src_ip else: From baa615ed38462aea22d16786fc6036dd9c164cd2 Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 12 Dec 2017 17:08:03 +0800 Subject: [PATCH 078/156] Add web_api.py in setup.py --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 2caf0ce..b7846ac 100644 --- a/setup.py +++ b/setup.py @@ -7,9 +7,9 @@ author_email="sheng.zhao@calix.com", url="https://github.com/9nehS/", license="AGPL", - scripts=["src/pygennf_v9.py", "src/pygennf_v9_multi_threads.py"], + scripts=["src/pygennf_v9.py", "src/pygennf_v9_multi_threads.py", "src/web_api/web_api.py"], packages=['rb_netflow'], install_requires=[ 'scapy', ] -) + ) From f31019b960f6ab39e719f266058ad4b68022a424 Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 12 Dec 2017 17:16:07 +0800 Subject: [PATCH 079/156] Change the location for web_api dir --- {src/web_api => web_api}/__init__.py | 0 {src/web_api => web_api}/web_api.py | 3 +-- 2 files changed, 1 insertion(+), 2 deletions(-) rename {src/web_api => web_api}/__init__.py (100%) rename {src/web_api => web_api}/web_api.py (92%) diff --git a/src/web_api/__init__.py b/web_api/__init__.py similarity index 100% rename from src/web_api/__init__.py rename to web_api/__init__.py diff --git a/src/web_api/web_api.py b/web_api/web_api.py similarity index 92% rename from src/web_api/web_api.py rename to web_api/web_api.py index cb417cf..a5cf244 100644 --- a/src/web_api/web_api.py +++ b/web_api/web_api.py @@ -1,5 +1,4 @@ -from flask import Flask, request, jsonify -from flask import Response +from flask import Flask, jsonify app = Flask(__name__) From c99e4229fb0ffb93a1ede9cdc68582cdfc1bebe6 Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 12 Dec 2017 17:17:00 +0800 Subject: [PATCH 080/156] Add web_api for packages --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index b7846ac..adee228 100644 --- a/setup.py +++ b/setup.py @@ -7,8 +7,8 @@ author_email="sheng.zhao@calix.com", url="https://github.com/9nehS/", license="AGPL", - scripts=["src/pygennf_v9.py", "src/pygennf_v9_multi_threads.py", "src/web_api/web_api.py"], - packages=['rb_netflow'], + scripts=["src/pygennf_v9.py", "src/pygennf_v9_multi_threads.py"], + packages=['rb_netflow', 'web_api'], install_requires=[ 'scapy', ] From 7cfa99a41c069d3b48a3042ed337294e5d24d234 Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 12 Dec 2017 17:21:52 +0800 Subject: [PATCH 081/156] Change import statement --- src/pygennf_v9_multi_threads.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index 3a8133a..3a2cb1a 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -23,7 +23,7 @@ from scapy.all import * import rb_netflow.rb_netflow as rbnf -from web_api import web_api +import web_api.web_api as api SIGNAL_RECEIVED = 0 @@ -99,7 +99,7 @@ def main(): args = parser.parse_args() if args.remote: - web_api.start() + api.start() sys.exit(0) if args.src_ip: From 912a7e3ab8a760faae5a672e9d306eb399bbe015 Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 12 Dec 2017 19:10:28 +0800 Subject: [PATCH 082/156] Add find_packages() --- setup.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index adee228..1491790 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,4 @@ -from setuptools import setup +from setuptools import setup, find_packages setup(name="pygennf", version="0.11", @@ -8,8 +8,10 @@ url="https://github.com/9nehS/", license="AGPL", scripts=["src/pygennf_v9.py", "src/pygennf_v9_multi_threads.py"], - packages=['rb_netflow', 'web_api'], + # packages=['rb_netflow', 'web_api'], + packages=find_packages(), install_requires=[ 'scapy', + 'flask' ] ) From 6272b9cbaddf99ea387b1609c615cd544d6ddb65 Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 12 Dec 2017 19:30:53 +0800 Subject: [PATCH 083/156] Update import for web_api --- src/pygennf_v9_multi_threads.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index 3a2cb1a..3a8133a 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -23,7 +23,7 @@ from scapy.all import * import rb_netflow.rb_netflow as rbnf -import web_api.web_api as api +from web_api import web_api SIGNAL_RECEIVED = 0 @@ -99,7 +99,7 @@ def main(): args = parser.parse_args() if args.remote: - api.start() + web_api.start() sys.exit(0) if args.src_ip: From 131e9d32be15846ad82f034682d30b68f6a4ae6d Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 13 Dec 2017 15:22:11 +0800 Subject: [PATCH 084/156] Update import for web_api --- src/pygennf_v9_multi_threads.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index 3a8133a..3a2cb1a 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -23,7 +23,7 @@ from scapy.all import * import rb_netflow.rb_netflow as rbnf -from web_api import web_api +import web_api.web_api as api SIGNAL_RECEIVED = 0 @@ -99,7 +99,7 @@ def main(): args = parser.parse_args() if args.remote: - web_api.start() + api.start() sys.exit(0) if args.src_ip: From 6c3d8f0b1c661cc3baaf4a604d36e379828692ed Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 13 Dec 2017 15:27:16 +0800 Subject: [PATCH 085/156] Update packages --- setup.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index 1491790..b561bd2 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,4 @@ -from setuptools import setup, find_packages +from setuptools import setup setup(name="pygennf", version="0.11", @@ -8,8 +8,8 @@ url="https://github.com/9nehS/", license="AGPL", scripts=["src/pygennf_v9.py", "src/pygennf_v9_multi_threads.py"], - # packages=['rb_netflow', 'web_api'], - packages=find_packages(), + packages=['rb_netflow', 'web_api'], + # packages=find_packages(), install_requires=[ 'scapy', 'flask' From 7b52ff979880426e3eb6234cce3e20ced4ddb6d2 Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 13 Dec 2017 15:43:12 +0800 Subject: [PATCH 086/156] Update argument '-r' --- src/pygennf_v9_multi_threads.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index 3a2cb1a..017b4ed 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -93,7 +93,7 @@ def main(): # help='Bytes(octets) in single flow, e.g. 1024.') parser.add_argument('-fd', '--flows-data', dest='flows_data', help='Contents in flows data, e.g. ip1/mask:port1:ip2/mask:port2:protocol:direction:bytes.') - parser.add_argument('-r', '--remote', dest='remote', + parser.add_argument('-r', '--remote', dest='remote', action="store_true", help='Listen on TCP port 9080 as API server. All other parameters will be ignored.') args = parser.parse_args() From 22ca83a877591001d9d926b735689b75cc48d6da Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 13 Dec 2017 15:45:51 +0800 Subject: [PATCH 087/156] Add port=9080 --- web_api/web_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web_api/web_api.py b/web_api/web_api.py index a5cf244..e7e620f 100644 --- a/web_api/web_api.py +++ b/web_api/web_api.py @@ -17,4 +17,4 @@ def help(): }) def start(): - app.run(host='0.0.0.0') \ No newline at end of file + app.run(host='0.0.0.0', port=9080) From 2d4cd418e1ead90c7d94d02518fdf1c197aed7c7 Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 13 Dec 2017 16:30:18 +0800 Subject: [PATCH 088/156] Refactor some variables --- src/pygennf_v9_multi_threads.py | 61 ++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 24 deletions(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index 017b4ed..76d288f 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -103,38 +103,38 @@ def main(): sys.exit(0) if args.src_ip: - IP_SRC = args.src_ip + ip_src = args.src_ip else: - IP_SRC = "10.0.203.2" + ip_src = "10.0.203.2" if args.dst_ip: - IP_DST = args.dst_ip + ip_dst = args.dst_ip else: - IP_DST = "10.0.30.89" + ip_dst = "10.0.30.89" - if IP_DST == "127.0.0.1": + if ip_dst == "127.0.0.1": conf.L3socket=L3RawSocket if args.src_port: - PORT_SRC = int(args.src_port) + port_src = int(args.src_port) else: - PORT_SRC = int(2056) + port_src = int(2056) if args.dst_port: - PORT_DST = int(args.dst_port) + port_dst = int(args.dst_port) else: - PORT_DST = int(2055) + port_dst = int(2055) if args.time_interval: - TIME_INTERVAL = args.time_interval + time_interval = args.time_interval else: - TIME_INTERVAL = 1 + time_interval = 1 if args.pkt_count: - PKT_COUNT = int(args.pkt_count) + pkt_count = int(args.pkt_count) else: # 0xFFFFFFFF - 1 - PKT_COUNT = 4294967294 + pkt_count = 4294967294 # if args.protocol: # try: @@ -157,18 +157,19 @@ def main(): # BYTES = 1024 if args.flows_data: - FLOW_DATA_LIST = args.flows_data.split(',') - FLOW_DATA_LIST = map(str.strip, FLOW_DATA_LIST) - FLOW_DATA_LIST = filter(valid_flow_data, FLOW_DATA_LIST) - if len(FLOW_DATA_LIST) == 0: - print 'No valid flow data list, default flow data list will be used...' - print "Default flow data: %s" % (DEFAULT_FLOW_DATA) - FLOW_DATA_LIST.append(DEFAULT_FLOW_DATA) + # FLOW_DATA_LIST = args.flows_data.split(',') + # FLOW_DATA_LIST = map(str.strip, FLOW_DATA_LIST) + # FLOW_DATA_LIST = filter(valid_flow_data, FLOW_DATA_LIST) + # if len(FLOW_DATA_LIST) == 0: + # print 'No valid flow data list, default flow data list will be used...' + # print "Default flow data: %s" % (DEFAULT_FLOW_DATA) + # FLOW_DATA_LIST.append(DEFAULT_FLOW_DATA) + flow_data_list = get_flow_data_list(args.flows_data, DEFAULT_FLOW_DATA) else: print "'args.flows_data' is empty, default flow data list will be used..." print "Default flow data: %s" % (DEFAULT_FLOW_DATA) - FLOW_DATA_LIST = [] - FLOW_DATA_LIST.append(DEFAULT_FLOW_DATA) + flow_data_list = [] + flow_data_list.append(DEFAULT_FLOW_DATA) signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler) @@ -176,8 +177,8 @@ def main(): #start_send(IP_SRC, IP_DST, PORT_SRC, PORT_DST, FLOW_DATA_LIST, PKT_COUNT, TIME_INTERVAL) print 'Thread %s is running...' % threading.current_thread().name - t = threading.Thread(target=start_send, name='SendingThread', args=(IP_SRC, IP_DST, PORT_SRC, PORT_DST, - FLOW_DATA_LIST, PKT_COUNT, TIME_INTERVAL)) + t = threading.Thread(target=start_send, name='SendingThread', args=(ip_src, ip_dst, port_src, port_dst, + flow_data_list, pkt_count, time_interval)) #t.do_run = True #t.setDaemon(True) t.start() @@ -189,6 +190,18 @@ def main(): print 'Thread %s ended.' % threading.current_thread().name +def get_flow_data_list(args_flows_data, default_flow_data): + flow_data_list = args_flows_data.split(',') + flow_data_list = map(str.strip, flow_data_list) + flow_data_list = filter(valid_flow_data, flow_data_list) + if len(flow_data_list) == 0: + print 'No valid flow data list, default flow data list will be used...' + print "Default flow data: %s" % (default_flow_data) + flow_data_list.append(default_flow_data) + return flow_data_list + + + def start_send(ip_src, ip_dst, port_src, port_dst, flow_data_list, pkt_count, time_interval): print 'Thread %s is running...' % threading.current_thread().name flow_sequence = 1 From 6bcb93d997ae782f222ae19cbbd2b051317e7fbc Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 13 Dec 2017 16:30:52 +0800 Subject: [PATCH 089/156] Add method send() --- web_api/web_api.py | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/web_api/web_api.py b/web_api/web_api.py index e7e620f..591b006 100644 --- a/web_api/web_api.py +++ b/web_api/web_api.py @@ -1,4 +1,6 @@ -from flask import Flask, jsonify +import threading + +from flask import Flask, jsonify, request, abort app = Flask(__name__) @@ -16,5 +18,36 @@ def help(): 'Delayed task status': '/marketing/cache/rebuild/status?org-id=' }) + +@app.route('/pygennf/send', methods=['POST']) +def send(): + if not request.json: + abort(404) + ip_src = request.json['ip_src'] + ip_dst = request.json['ip_dst'] + port_src = int(request.json['port_src']) + port_dst = int(request.json['port_dst']) + flow_data_list = get_flow_data_list(request.json['flows-data'], DEFAULT_FLOW_DATA) + pkt_count = int(request.json['pkt_count']) + time_interval = request.json['time_interval'] + print 'Thread %s is running...' % threading.current_thread().name + t = threading.Thread(target=start_send, name='SendingThread', args=(ip_src, ip_dst, port_src, port_dst, + flow_data_list, pkt_count, time_interval)) + # t.do_run = True + # t.setDaemon(True) + t.start() + while True: + t.join(5) + if not t.isAlive(): + break + + print 'Thread %s ended.' % threading.current_thread().name + + +@app.route('/pygennf/status') +def status(): + pass + + def start(): app.run(host='0.0.0.0', port=9080) From d10b79d39e792eae2bdaae8ad167a605785afac6 Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 13 Dec 2017 16:40:08 +0800 Subject: [PATCH 090/156] Add method send() --- web_api/web_api.py | 1 + 1 file changed, 1 insertion(+) diff --git a/web_api/web_api.py b/web_api/web_api.py index 591b006..2b6e5cc 100644 --- a/web_api/web_api.py +++ b/web_api/web_api.py @@ -21,6 +21,7 @@ def help(): @app.route('/pygennf/send', methods=['POST']) def send(): + print "send() invoked..." if not request.json: abort(404) ip_src = request.json['ip_src'] From 069a3ed60f2cfe0780eac9e18f368d9bcfc2dced Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 13 Dec 2017 16:45:35 +0800 Subject: [PATCH 091/156] Add method send() --- web_api/web_api.py | 1 + 1 file changed, 1 insertion(+) diff --git a/web_api/web_api.py b/web_api/web_api.py index 2b6e5cc..67f8a14 100644 --- a/web_api/web_api.py +++ b/web_api/web_api.py @@ -24,6 +24,7 @@ def send(): print "send() invoked..." if not request.json: abort(404) + print request.json ip_src = request.json['ip_src'] ip_dst = request.json['ip_dst'] port_src = int(request.json['port_src']) From 52ce3f1a4037675d7beae3969c0fca689578e106 Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 13 Dec 2017 16:47:35 +0800 Subject: [PATCH 092/156] Add method send() --- web_api/web_api.py | 1 + 1 file changed, 1 insertion(+) diff --git a/web_api/web_api.py b/web_api/web_api.py index 67f8a14..8f3e7c5 100644 --- a/web_api/web_api.py +++ b/web_api/web_api.py @@ -26,6 +26,7 @@ def send(): abort(404) print request.json ip_src = request.json['ip_src'] + print 'ip_src: %s' % ip_src ip_dst = request.json['ip_dst'] port_src = int(request.json['port_src']) port_dst = int(request.json['port_dst']) From 1416dba3a194cadc706cf51cf5633f23d77562fa Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 13 Dec 2017 16:50:01 +0800 Subject: [PATCH 093/156] Add method send() --- web_api/web_api.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/web_api/web_api.py b/web_api/web_api.py index 8f3e7c5..d6793b1 100644 --- a/web_api/web_api.py +++ b/web_api/web_api.py @@ -28,9 +28,13 @@ def send(): ip_src = request.json['ip_src'] print 'ip_src: %s' % ip_src ip_dst = request.json['ip_dst'] + print 'ip_dst: %s' % ip_dst port_src = int(request.json['port_src']) + print 'port_src: ', port_src port_dst = int(request.json['port_dst']) + print 'port_dst: ', port_dst flow_data_list = get_flow_data_list(request.json['flows-data'], DEFAULT_FLOW_DATA) + print 'flow_data_list: %s' % flow_data_list pkt_count = int(request.json['pkt_count']) time_interval = request.json['time_interval'] print 'Thread %s is running...' % threading.current_thread().name From 2edec447c31ebc336a883a326f53d216992241cd Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 13 Dec 2017 17:00:50 +0800 Subject: [PATCH 094/156] Add debug print --- src/pygennf_v9_multi_threads.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index 76d288f..af18807 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -191,6 +191,7 @@ def main(): def get_flow_data_list(args_flows_data, default_flow_data): + print 'get_flow_data_list() start...' flow_data_list = args_flows_data.split(',') flow_data_list = map(str.strip, flow_data_list) flow_data_list = filter(valid_flow_data, flow_data_list) From 3952c1eb7300ad5abfa01127c6043cacf68ed219 Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 13 Dec 2017 17:01:42 +0800 Subject: [PATCH 095/156] Add debug print --- web_api/web_api.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/web_api/web_api.py b/web_api/web_api.py index d6793b1..d9211d9 100644 --- a/web_api/web_api.py +++ b/web_api/web_api.py @@ -36,7 +36,9 @@ def send(): flow_data_list = get_flow_data_list(request.json['flows-data'], DEFAULT_FLOW_DATA) print 'flow_data_list: %s' % flow_data_list pkt_count = int(request.json['pkt_count']) + print 'pkt_count:', pkt_count time_interval = request.json['time_interval'] + print 'time_interval: %s' % time_interval print 'Thread %s is running...' % threading.current_thread().name t = threading.Thread(target=start_send, name='SendingThread', args=(ip_src, ip_dst, port_src, port_dst, flow_data_list, pkt_count, time_interval)) From 828c3eb031bb9f24619708cb8611c3a4391c147f Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 13 Dec 2017 17:04:05 +0800 Subject: [PATCH 096/156] Add import --- web_api/web_api.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/web_api/web_api.py b/web_api/web_api.py index d9211d9..3c5dbd2 100644 --- a/web_api/web_api.py +++ b/web_api/web_api.py @@ -2,6 +2,8 @@ from flask import Flask, jsonify, request, abort +from src.pygennf_v9_multi_threads import get_flow_data_list, DEFAULT_FLOW_DATA, start_send + app = Flask(__name__) @app.route('/') From b7170ec649ff336c1ca2dc7d7df68cdb044e0582 Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 13 Dec 2017 17:06:24 +0800 Subject: [PATCH 097/156] Update packages --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index b561bd2..35445b3 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ url="https://github.com/9nehS/", license="AGPL", scripts=["src/pygennf_v9.py", "src/pygennf_v9_multi_threads.py"], - packages=['rb_netflow', 'web_api'], + packages=['rb_netflow', 'web_api', 'src'], # packages=find_packages(), install_requires=[ 'scapy', From b5686bfcad9dd2efa52131f54f4a70aa13242e7b Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 13 Dec 2017 17:07:45 +0800 Subject: [PATCH 098/156] Update packages --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 35445b3..b561bd2 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ url="https://github.com/9nehS/", license="AGPL", scripts=["src/pygennf_v9.py", "src/pygennf_v9_multi_threads.py"], - packages=['rb_netflow', 'web_api', 'src'], + packages=['rb_netflow', 'web_api'], # packages=find_packages(), install_requires=[ 'scapy', From 788ec9494f345be9456249fe2655328e3072a776 Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 13 Dec 2017 17:08:25 +0800 Subject: [PATCH 099/156] Update import --- web_api/web_api.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/web_api/web_api.py b/web_api/web_api.py index 3c5dbd2..d9211d9 100644 --- a/web_api/web_api.py +++ b/web_api/web_api.py @@ -2,8 +2,6 @@ from flask import Flask, jsonify, request, abort -from src.pygennf_v9_multi_threads import get_flow_data_list, DEFAULT_FLOW_DATA, start_send - app = Flask(__name__) @app.route('/') From f83a860557a7aaa992c7db364d5ce093199690c2 Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 13 Dec 2017 17:35:42 +0800 Subject: [PATCH 100/156] Update packages --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index b561bd2..98674ef 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ url="https://github.com/9nehS/", license="AGPL", scripts=["src/pygennf_v9.py", "src/pygennf_v9_multi_threads.py"], - packages=['rb_netflow', 'web_api'], + packages=['rb_netflow'], # packages=find_packages(), install_requires=[ 'scapy', From 48c9c2a76c681bd58566baa50c619ce2da8b02ec Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 13 Dec 2017 17:37:24 +0800 Subject: [PATCH 101/156] Merge web_api --- src/pygennf_v9_multi_threads.py | 58 +++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 3 deletions(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index af18807..31937cb 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -20,13 +20,12 @@ import signal import threading +from flask import Flask, jsonify, request, abort from scapy.all import * import rb_netflow.rb_netflow as rbnf -import web_api.web_api as api SIGNAL_RECEIVED = 0 - DIC_PROTOCOL_NUM = {'tcp': 6, 'udp': 17} DIC_DIRECTION_NUM = {'ingress': 0, 'egress': 1} @@ -35,6 +34,58 @@ FLOW_DATA_PATTERN = r'^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d{1,2}:\d{1,5}:){2}\w+:(ingress|egress):\d{1,4}$' DEFAULT_FLOW_DATA = '11.11.11.11/32:1001:11.11.11.22/32:80:tcp:ingress:1024' +app = Flask(__name__) + + +@app.route('/') +def help(): + return jsonify( + # 'API (application/json)': 'PATH, notes ?org-id= currently required', + {'Cache clean': '/marketing/cache/clean?org-ids=', + 'Cache clean and rebuild': '/marketing/cache/clean-rebuild?org-ids=&rebuild-table=true', + 'Cache status': '/marketing/cache/status', + 'On board': '/marketing/onboard?org-ids=', + 'On board status': '/marketing/onboard/status', + 'Delayed scheduled rebuild task': 'add:/marketing/cache/rebuild/operation?opt=add&org-ids= ' + 'delete:/marketing/cache/rebuild/operation?opt=delete&org-ids=', + 'Delayed task status': '/marketing/cache/rebuild/status?org-id=' + }) + + +@app.route('/pygennf/send', methods=['POST']) +def send(): + print "send() invoked..." + if not request.json: + abort(404) + print request.json + ip_src = request.json['ip_src'] + print 'ip_src: %s' % ip_src + ip_dst = request.json['ip_dst'] + print 'ip_dst: %s' % ip_dst + port_src = int(request.json['port_src']) + print 'port_src: ', port_src + port_dst = int(request.json['port_dst']) + print 'port_dst: ', port_dst + flow_data_list = get_flow_data_list(request.json['flows-data'], DEFAULT_FLOW_DATA) + print 'flow_data_list: %s' % flow_data_list + pkt_count = int(request.json['pkt_count']) + print 'pkt_count:', pkt_count + time_interval = request.json['time_interval'] + print 'time_interval: %s' % time_interval + print 'Thread %s is running...' % threading.current_thread().name + t = threading.Thread(target=start_send, name='SendingThread', args=(ip_src, ip_dst, port_src, port_dst, + flow_data_list, pkt_count, time_interval)) + # t.do_run = True + # t.setDaemon(True) + t.start() + while True: + t.join(5) + if not t.isAlive(): + break + + print 'Thread %s ended.' % threading.current_thread().name + + def preexec(): os.setpgrp() # Don't forward signals @@ -99,7 +150,8 @@ def main(): args = parser.parse_args() if args.remote: - api.start() + # api.start() + app.run(host='0.0.0.0', port=9080) sys.exit(0) if args.src_ip: From 3cb8473a38800eafa8b3f91b8dbaafedf05dd7e1 Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 13 Dec 2017 17:41:34 +0800 Subject: [PATCH 102/156] Add debug print --- src/pygennf_v9_multi_threads.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index 31937cb..9732ad2 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -251,6 +251,7 @@ def get_flow_data_list(args_flows_data, default_flow_data): print 'No valid flow data list, default flow data list will be used...' print "Default flow data: %s" % (default_flow_data) flow_data_list.append(default_flow_data) + print 'flow_data_list before return:', flow_data_list return flow_data_list From 0afe91dfb3a670624dce9f04b16782294f1a18ca Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 13 Dec 2017 17:43:10 +0800 Subject: [PATCH 103/156] Add debug print --- src/pygennf_v9_multi_threads.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index 9732ad2..274bf10 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -244,6 +244,8 @@ def main(): def get_flow_data_list(args_flows_data, default_flow_data): print 'get_flow_data_list() start...' + print 'type(args_flows_data):', type(args_flows_data) + print 'args_flows_data: %s' % args_flows_data flow_data_list = args_flows_data.split(',') flow_data_list = map(str.strip, flow_data_list) flow_data_list = filter(valid_flow_data, flow_data_list) From e99daa01472e01de7bf096047c850531abe7d8f0 Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 13 Dec 2017 19:19:58 +0800 Subject: [PATCH 104/156] Add unicode conversion --- src/pygennf_v9_multi_threads.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index 274bf10..be107f3 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -58,19 +58,19 @@ def send(): if not request.json: abort(404) print request.json - ip_src = request.json['ip_src'] + ip_src = request.json['ip_src'].encode("ascii") print 'ip_src: %s' % ip_src - ip_dst = request.json['ip_dst'] + ip_dst = request.json['ip_dst'].encode("ascii") print 'ip_dst: %s' % ip_dst port_src = int(request.json['port_src']) print 'port_src: ', port_src port_dst = int(request.json['port_dst']) print 'port_dst: ', port_dst - flow_data_list = get_flow_data_list(request.json['flows-data'], DEFAULT_FLOW_DATA) + flow_data_list = get_flow_data_list(request.json['flows-data'].encode("ascii"), DEFAULT_FLOW_DATA) print 'flow_data_list: %s' % flow_data_list pkt_count = int(request.json['pkt_count']) print 'pkt_count:', pkt_count - time_interval = request.json['time_interval'] + time_interval = request.json['time_interval'].encode("ascii") print 'time_interval: %s' % time_interval print 'Thread %s is running...' % threading.current_thread().name t = threading.Thread(target=start_send, name='SendingThread', args=(ip_src, ip_dst, port_src, port_dst, From 67fa2571d27401ca513b402bdddde500f3082c02 Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 13 Dec 2017 19:34:32 +0800 Subject: [PATCH 105/156] Change URL --- src/pygennf_v9_multi_threads.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index be107f3..a9d353b 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -52,9 +52,9 @@ def help(): }) -@app.route('/pygennf/send', methods=['POST']) -def send(): - print "send() invoked..." +@app.route('/pygennf/tasks/create', methods=['POST']) +def create(): + print "create() invoked..." if not request.json: abort(404) print request.json From bfbbca4972c74451f295d29701edf0853d0cfc1e Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 13 Dec 2017 19:36:37 +0800 Subject: [PATCH 106/156] Change thread behavior --- src/pygennf_v9_multi_threads.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index a9d353b..c854790 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -78,12 +78,12 @@ def create(): # t.do_run = True # t.setDaemon(True) t.start() - while True: - t.join(5) - if not t.isAlive(): - break - - print 'Thread %s ended.' % threading.current_thread().name + # while True: + # t.join(5) + # if not t.isAlive(): + # break + # + # print 'Thread %s ended.' % threading.current_thread().name def preexec(): From adaa506214d3a3a8681fe7b2e057357215ea4fa3 Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 13 Dec 2017 19:40:35 +0800 Subject: [PATCH 107/156] Add return content for create() --- src/pygennf_v9_multi_threads.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index c854790..19cf86e 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -78,6 +78,10 @@ def create(): # t.do_run = True # t.setDaemon(True) t.start() + return jsonify( + {'Status': 'Sending task created successfully', + 'TaskName': 'This is task name' + }) # while True: # t.join(5) # if not t.isAlive(): From e386f1d478a7850ae5b8e7bbc69b310475916134 Mon Sep 17 00:00:00 2001 From: szhao Date: Wed, 13 Dec 2017 19:45:37 +0800 Subject: [PATCH 108/156] Remove some comments --- src/pygennf_v9_multi_threads.py | 47 +-------------------------------- 1 file changed, 1 insertion(+), 46 deletions(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index 19cf86e..3b82231 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -213,13 +213,6 @@ def main(): # BYTES = 1024 if args.flows_data: - # FLOW_DATA_LIST = args.flows_data.split(',') - # FLOW_DATA_LIST = map(str.strip, FLOW_DATA_LIST) - # FLOW_DATA_LIST = filter(valid_flow_data, FLOW_DATA_LIST) - # if len(FLOW_DATA_LIST) == 0: - # print 'No valid flow data list, default flow data list will be used...' - # print "Default flow data: %s" % (DEFAULT_FLOW_DATA) - # FLOW_DATA_LIST.append(DEFAULT_FLOW_DATA) flow_data_list = get_flow_data_list(args.flows_data, DEFAULT_FLOW_DATA) else: print "'args.flows_data' is empty, default flow data list will be used..." @@ -317,45 +310,8 @@ def gen_pkt_netflow_data(timestamp=1503652676, flow_sequence=1, sys_uptime=36000 FlowSequence=flow_sequence, SourceId=2177) flowset_flow_header_v9 = rbnf.FlowSet_Header_v9(FlowSet_id=260, FlowSet_length=72) - # List for SrcAddr and DstAddr in netflow data - # src_dst_addr_list = [] - # src_dst_addr_list.append(['69.31.102.10', '209.81.108.20']) - # src_dst_addr_list.append(['70.32.103.11', '210.81.108.21']) - # src_dst_addr_list.append(['70.32.103.12', '210.81.108.22']) - # src_dst_addr_list.append(['70.32.103.13', '210.81.108.23']) - # src_dst_addr_list.append(['70.32.103.14', '210.81.108.24']) - # src_dst_addr_list.append(['70.32.103.15', '210.81.108.25']) - # src_dst_addr_list.append(['70.32.103.16', '210.81.108.26']) - # src_dst_addr_list.append(['70.32.103.17', '210.81.108.27']) - # src_dst_addr_list.append(['70.32.103.18', '210.81.108.28']) - # src_dst_addr_list.append(['70.32.103.19', '210.81.108.29']) - # src_dst_addr_list.append(['70.32.103.20', '210.81.108.30']) - # src_dst_addr_list.append(['70.32.103.21', '210.81.108.31']) - # src_dst_addr_list.append(['70.32.103.22', '210.81.108.32']) - # src_dst_addr_list.append(['70.32.103.23', '210.81.108.33']) - # src_dst_addr_list.append(['70.32.103.24', '210.81.108.34']) - # src_dst_addr_list.append(['70.32.103.25', '210.81.108.35']) - # src_dst_addr_list.append(['70.32.103.26', '210.81.108.36']) - # src_dst_addr_list.append(['70.32.103.27', '210.81.108.37']) - # src_dst_addr_list.append(['70.32.103.28', '210.81.108.38']) - # src_dst_addr_list.append(['70.32.103.29', '210.81.108.39']) - # src_dst_addr_list.append(['70.32.103.30', '210.81.108.40']) - # src_dst_port_list = [] - # src_dst_port_list.append([12345, 80]) - # List for flows in one packet flows = [] - # for src_dst_addr in src_dst_addr_list: - # #end_time = sys_uptime + 3600 * 1000 - # end_time = timestamp - # start_time = end_time - 1000 # Duration 1s - # flows.append(rbnf.Flow_260_v9( - # Packets=1, Octets=octets, SrcAddr=src_dst_addr[0], DstAddr=src_dst_addr[1], InputInt=145, OutputInt=142, - # EndTime=end_time, StartTime=start_time, SrcPort=src_dst_port_list[0][0], DstPort=src_dst_port_list[0][1], - # SrcAS=0, DstAS=0, BGPNextHop='0.0.0.0', SrcMask=17, DstMask=28, Protocol=protocol_num, TCPFlags=0x10, IPToS=0x00, - # Direction=0, ForwardingStatus=0x40, SamplerID=2, IngressVRFID=0x60000000, EgressVRFID=0x60000000 - # )) - # To process flow_data_list for flow_data in flow_data_list: @@ -486,5 +442,4 @@ def gen_pkt_netflow_tmpl(timestamp=1503652676, flow_sequence=1, source_id=2177, if __name__ == '__main__': - main() - + main() \ No newline at end of file From 99ae7c242373ee2e99e38c972008f44588077441 Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 14 Dec 2017 14:49:00 +0800 Subject: [PATCH 109/156] Add logger --- utils/__init__.py | 0 utils/logger.py | 16 ++++++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 utils/__init__.py create mode 100644 utils/logger.py diff --git a/utils/__init__.py b/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/utils/logger.py b/utils/logger.py new file mode 100644 index 0000000..450a471 --- /dev/null +++ b/utils/logger.py @@ -0,0 +1,16 @@ +import logging + +DEFAULT_LOGGER_LEVEL = logging.INFO +DEFAULT_LOG_FORMAT = '%(asctime)s[%(levelname)s][%(name)s][%(filename)s]:%(lineno)s - %(message)s' +LOGGER_LEVEL_MAP = {'info': logging.INFO, 'debug': logging.DEBUG} + + +def get_logger(logger_name, logger_level=DEFAULT_LOGGER_LEVEL, logger_stream=sys.stdout): + logger = logging.getLogger(logger_name) + logger.basicConfig(format=DEFAULT_LOG_FORMAT, stream=logger_stream) + logger.setLevel(logger_level or DEFAULT_LOGGER_LEVEL) + return logger + + +def set_logger_level(logger, logger_level='info'): + logger.setLevel(LOGGER_LEVEL_MAP[logger_level.lower()]) From 68603fc0fa48aca3b3ba9198f04740dfe7c9ced9 Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 14 Dec 2017 14:50:44 +0800 Subject: [PATCH 110/156] Add logger print --- src/pygennf_v9_multi_threads.py | 87 +++++++++++++++++++-------------- 1 file changed, 50 insertions(+), 37 deletions(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index 3b82231..2d1abf5 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -24,6 +24,7 @@ from scapy.all import * import rb_netflow.rb_netflow as rbnf +from utils.logger import get_logger, set_logger_level SIGNAL_RECEIVED = 0 DIC_PROTOCOL_NUM = {'tcp': 6, 'udp': 17} @@ -34,8 +35,9 @@ FLOW_DATA_PATTERN = r'^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d{1,2}:\d{1,5}:){2}\w+:(ingress|egress):\d{1,4}$' DEFAULT_FLOW_DATA = '11.11.11.11/32:1001:11.11.11.22/32:80:tcp:ingress:1024' -app = Flask(__name__) +app = Flask(__name__) +logger = get_logger('pygennf') @app.route('/') def help(): @@ -54,25 +56,33 @@ def help(): @app.route('/pygennf/tasks/create', methods=['POST']) def create(): - print "create() invoked..." + # print "create() invoked..." if not request.json: abort(404) - print request.json + # print request.json ip_src = request.json['ip_src'].encode("ascii") - print 'ip_src: %s' % ip_src + # print 'ip_src: %s' % ip_src + logger.debug('ip_src: %s' % ip_src) ip_dst = request.json['ip_dst'].encode("ascii") - print 'ip_dst: %s' % ip_dst + # print 'ip_dst: %s' % ip_dst + logger.debug('ip_dst: %s' % ip_dst) port_src = int(request.json['port_src']) - print 'port_src: ', port_src + # print 'port_src:', port_src + logger.debug('port_src:', port_src) port_dst = int(request.json['port_dst']) - print 'port_dst: ', port_dst + # print 'port_dst:', port_dst + logger.debug('port_dst:', port_dst) flow_data_list = get_flow_data_list(request.json['flows-data'].encode("ascii"), DEFAULT_FLOW_DATA) - print 'flow_data_list: %s' % flow_data_list + # print 'flow_data_list: %s' % flow_data_list + logger.debug('flow_data_list: %s' % flow_data_list) pkt_count = int(request.json['pkt_count']) - print 'pkt_count:', pkt_count + # print 'pkt_count:', pkt_count + logger.debug('pkt_count:', pkt_count) time_interval = request.json['time_interval'].encode("ascii") - print 'time_interval: %s' % time_interval - print 'Thread %s is running...' % threading.current_thread().name + # print 'time_interval: %s' % time_interval + logger.debug('time_interval: %s' % time_interval) + # print 'Thread %s is running...' % threading.current_thread().name + logger.info('Thread %s is running...' % threading.current_thread().name) t = threading.Thread(target=start_send, name='SendingThread', args=(ip_src, ip_dst, port_src, port_dst, flow_data_list, pkt_count, time_interval)) # t.do_run = True @@ -90,10 +100,6 @@ def create(): # print 'Thread %s ended.' % threading.current_thread().name -def preexec(): - os.setpgrp() # Don't forward signals - - def signal_handler(signal, frame): global SIGNAL_RECEIVED SIGNAL_RECEIVED = 1 @@ -108,27 +114,7 @@ def valid_flow_data(flow_data_str=''): return False -# Netflow9 -def main(): - - print "\n***************************************************************************" - print "* ______ _ _____ _ *" - print "* | ___| | | __ \ | | *" - print "* | |_ | | _____ __ | | \/ ___ _ __ ___ _ __ __ _| |_ ___ _ __ *" - print "* | _| | |/ _ \ \ /\ / / | | __ / _ \ '_ \ / _ \ '__/ _` | __/ _ \| '__| *" - print "* | | | | (_) \ V V / | |_\ \ __/ | | | __/ | | (_| | || (_) | | *" - print "* \_| |_|\___/ \_/\_/ \____/\___|_| |_|\___|_| \__,_|\__\___/|_| *" - print "* *" - print "* Flow Generator Ver. 0.11 *" - print "* Modified by Sheng Zhao *" - print "* Calix Cloud SIT *" - print "* sheng.zhao@calix.com *" - print "***************************************************************************\n\n" - - if os.getuid() != 0: - print "You need to be root to run this, sorry." - return - +def get_parser(): parser = argparse.ArgumentParser(description='Netflow packets generator with scapy') parser.add_argument('-s', '--source-ip', dest='src_ip', help='Source IP of netflow packet(s).') @@ -150,8 +136,35 @@ def main(): help='Contents in flows data, e.g. ip1/mask:port1:ip2/mask:port2:protocol:direction:bytes.') parser.add_argument('-r', '--remote', dest='remote', action="store_true", help='Listen on TCP port 9080 as API server. All other parameters will be ignored.') + parser.add_argument('-ll', '--log-level', dest='log_level', type=str, choices=['info', 'debug'], + help='Log level, default log level is info') + return parser.parse_args() + + +# Netflow9 +def main(): + print "\n***************************************************************************" + print "* ______ _ _____ _ *" + print "* | ___| | | __ \ | | *" + print "* | |_ | | _____ __ | | \/ ___ _ __ ___ _ __ __ _| |_ ___ _ __ *" + print "* | _| | |/ _ \ \ /\ / / | | __ / _ \ '_ \ / _ \ '__/ _` | __/ _ \| '__| *" + print "* | | | | (_) \ V V / | |_\ \ __/ | | | __/ | | (_| | || (_) | | *" + print "* \_| |_|\___/ \_/\_/ \____/\___|_| |_|\___|_| \__,_|\__\___/|_| *" + print "* *" + print "* Flow Generator Ver. 0.11 *" + print "* Modified by Sheng Zhao *" + print "* Calix Cloud SIT *" + print "* sheng.zhao@calix.com *" + print "***************************************************************************\n\n" + + if os.getuid() != 0: + print "You need to be root to run this, sorry." + return + + args = get_parser() - args = parser.parse_args() + if args.log_level: + set_logger_level(logger, args.log_level) if args.remote: # api.start() From c0571e80bc0bd73f57649f49f5d2558452a07457 Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 14 Dec 2017 14:51:14 +0800 Subject: [PATCH 111/156] Add module utils --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 98674ef..e9c85cf 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ url="https://github.com/9nehS/", license="AGPL", scripts=["src/pygennf_v9.py", "src/pygennf_v9_multi_threads.py"], - packages=['rb_netflow'], + packages=['rb_netflow', 'utils'], # packages=find_packages(), install_requires=[ 'scapy', From 967eb3b2e8cba89ba4a797f3a263bddfaaa0eb2e Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 14 Dec 2017 14:53:02 +0800 Subject: [PATCH 112/156] Add sys in import --- utils/logger.py | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/logger.py b/utils/logger.py index 450a471..f975d64 100644 --- a/utils/logger.py +++ b/utils/logger.py @@ -1,4 +1,5 @@ import logging +import sys DEFAULT_LOGGER_LEVEL = logging.INFO DEFAULT_LOG_FORMAT = '%(asctime)s[%(levelname)s][%(name)s][%(filename)s]:%(lineno)s - %(message)s' From 27e0dc734022723dff4e5445de2938182471b729 Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 14 Dec 2017 14:59:22 +0800 Subject: [PATCH 113/156] Updated naming error for logger --- utils/{logger.py => logger_util.py} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename utils/{logger.py => logger_util.py} (88%) diff --git a/utils/logger.py b/utils/logger_util.py similarity index 88% rename from utils/logger.py rename to utils/logger_util.py index f975d64..a9f8ef0 100644 --- a/utils/logger.py +++ b/utils/logger_util.py @@ -8,7 +8,7 @@ def get_logger(logger_name, logger_level=DEFAULT_LOGGER_LEVEL, logger_stream=sys.stdout): logger = logging.getLogger(logger_name) - logger.basicConfig(format=DEFAULT_LOG_FORMAT, stream=logger_stream) + logging.basicConfig(format=DEFAULT_LOG_FORMAT, stream=logger_stream) logger.setLevel(logger_level or DEFAULT_LOGGER_LEVEL) return logger From db68cf077003566512116bd09b5f51a18c911a60 Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 14 Dec 2017 15:00:15 +0800 Subject: [PATCH 114/156] Updated import for logger --- src/pygennf_v9_multi_threads.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index 2d1abf5..d3c60be 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -24,7 +24,7 @@ from scapy.all import * import rb_netflow.rb_netflow as rbnf -from utils.logger import get_logger, set_logger_level +from utils.logger_util import get_logger, set_logger_level SIGNAL_RECEIVED = 0 DIC_PROTOCOL_NUM = {'tcp': 6, 'udp': 17} From 5bb87996aa23ba9ae89fd3a4a0f22de57019e521 Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 14 Dec 2017 15:05:11 +0800 Subject: [PATCH 115/156] Updated logger output in create() --- src/pygennf_v9_multi_threads.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index d3c60be..4df6d98 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -68,16 +68,16 @@ def create(): logger.debug('ip_dst: %s' % ip_dst) port_src = int(request.json['port_src']) # print 'port_src:', port_src - logger.debug('port_src:', port_src) + logger.debug('port_src: %s' % port_src) port_dst = int(request.json['port_dst']) # print 'port_dst:', port_dst - logger.debug('port_dst:', port_dst) + logger.debug('port_dst: %s' % port_dst) flow_data_list = get_flow_data_list(request.json['flows-data'].encode("ascii"), DEFAULT_FLOW_DATA) # print 'flow_data_list: %s' % flow_data_list logger.debug('flow_data_list: %s' % flow_data_list) pkt_count = int(request.json['pkt_count']) # print 'pkt_count:', pkt_count - logger.debug('pkt_count:', pkt_count) + logger.debug('pkt_count: %s' % pkt_count) time_interval = request.json['time_interval'].encode("ascii") # print 'time_interval: %s' % time_interval logger.debug('time_interval: %s' % time_interval) From 8fac6367b85f76eb18b4008dd59e6a6932f35bba Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 14 Dec 2017 15:09:31 +0800 Subject: [PATCH 116/156] Updated logger output in get_flow_data_list() --- src/pygennf_v9_multi_threads.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index 4df6d98..67496b3 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -253,17 +253,21 @@ def main(): def get_flow_data_list(args_flows_data, default_flow_data): - print 'get_flow_data_list() start...' - print 'type(args_flows_data):', type(args_flows_data) - print 'args_flows_data: %s' % args_flows_data + # print 'get_flow_data_list() start...' + logger.debug('Enter get_flow_data_list()...') + # print 'type(args_flows_data):', type(args_flows_data) + # print 'args_flows_data: %s' % args_flows_data flow_data_list = args_flows_data.split(',') flow_data_list = map(str.strip, flow_data_list) flow_data_list = filter(valid_flow_data, flow_data_list) if len(flow_data_list) == 0: - print 'No valid flow data list, default flow data list will be used...' - print "Default flow data: %s" % (default_flow_data) + # print 'No valid flow data list, default flow data list will be used...' + logger.warn('No valid flow data list, default flow data list will be used...') + # print "Default flow data: %s" % (default_flow_data) + logger.info('Default flow data: %s' % (default_flow_data)) flow_data_list.append(default_flow_data) - print 'flow_data_list before return:', flow_data_list + # print 'flow_data_list before return:', flow_data_list + logger.debug('flow_data_list before return: %s' % flow_data_list) return flow_data_list From d7ea6f5add3c997cc42f7da4075ed0f04e7ccb16 Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 14 Dec 2017 15:14:51 +0800 Subject: [PATCH 117/156] Updated logger output --- src/pygennf_v9_multi_threads.py | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index 67496b3..5174e84 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -56,33 +56,34 @@ def help(): @app.route('/pygennf/tasks/create', methods=['POST']) def create(): + prefix_logger = '[Method][create]' # print "create() invoked..." if not request.json: abort(404) # print request.json ip_src = request.json['ip_src'].encode("ascii") # print 'ip_src: %s' % ip_src - logger.debug('ip_src: %s' % ip_src) + logger.debug(prefix_logger + 'ip_src: %s' % ip_src) ip_dst = request.json['ip_dst'].encode("ascii") # print 'ip_dst: %s' % ip_dst - logger.debug('ip_dst: %s' % ip_dst) + logger.debug(prefix_logger + 'ip_dst: %s' % ip_dst) port_src = int(request.json['port_src']) # print 'port_src:', port_src - logger.debug('port_src: %s' % port_src) + logger.debug(prefix_logger + 'port_src: %s' % port_src) port_dst = int(request.json['port_dst']) # print 'port_dst:', port_dst - logger.debug('port_dst: %s' % port_dst) + logger.debug(prefix_logger + 'port_dst: %s' % port_dst) flow_data_list = get_flow_data_list(request.json['flows-data'].encode("ascii"), DEFAULT_FLOW_DATA) # print 'flow_data_list: %s' % flow_data_list - logger.debug('flow_data_list: %s' % flow_data_list) + logger.debug(prefix_logger + 'flow_data_list: %s' % flow_data_list) pkt_count = int(request.json['pkt_count']) # print 'pkt_count:', pkt_count - logger.debug('pkt_count: %s' % pkt_count) + logger.debug(prefix_logger + 'pkt_count: %s' % pkt_count) time_interval = request.json['time_interval'].encode("ascii") # print 'time_interval: %s' % time_interval - logger.debug('time_interval: %s' % time_interval) + logger.debug(prefix_logger + 'time_interval: %s' % time_interval) # print 'Thread %s is running...' % threading.current_thread().name - logger.info('Thread %s is running...' % threading.current_thread().name) + logger.info(prefix_logger + 'Thread %s is running...' % threading.current_thread().name) t = threading.Thread(target=start_send, name='SendingThread', args=(ip_src, ip_dst, port_src, port_dst, flow_data_list, pkt_count, time_interval)) # t.do_run = True @@ -253,8 +254,9 @@ def main(): def get_flow_data_list(args_flows_data, default_flow_data): + prefix_logger = '[Method][get_flow_data_list]' # print 'get_flow_data_list() start...' - logger.debug('Enter get_flow_data_list()...') + logger.debug(prefix_logger + 'Entering...') # print 'type(args_flows_data):', type(args_flows_data) # print 'args_flows_data: %s' % args_flows_data flow_data_list = args_flows_data.split(',') @@ -262,12 +264,13 @@ def get_flow_data_list(args_flows_data, default_flow_data): flow_data_list = filter(valid_flow_data, flow_data_list) if len(flow_data_list) == 0: # print 'No valid flow data list, default flow data list will be used...' - logger.warn('No valid flow data list, default flow data list will be used...') + logger.warn(prefix_logger + 'No valid flow data list, default flow data list will be used...') # print "Default flow data: %s" % (default_flow_data) - logger.info('Default flow data: %s' % (default_flow_data)) + logger.info(prefix_logger + 'Default flow data: %s' % (default_flow_data)) flow_data_list.append(default_flow_data) # print 'flow_data_list before return:', flow_data_list - logger.debug('flow_data_list before return: %s' % flow_data_list) + logger.debug(prefix_logger + 'flow_data_list before return: %s' % flow_data_list) + logger.debug(prefix_logger + '...') return flow_data_list From 9fca4318ffa145223d047739c7d834652b2dcec7 Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 14 Dec 2017 15:17:14 +0800 Subject: [PATCH 118/156] Updated logger output --- src/pygennf_v9_multi_threads.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index 5174e84..571f214 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -270,7 +270,7 @@ def get_flow_data_list(args_flows_data, default_flow_data): flow_data_list.append(default_flow_data) # print 'flow_data_list before return:', flow_data_list logger.debug(prefix_logger + 'flow_data_list before return: %s' % flow_data_list) - logger.debug(prefix_logger + '...') + logger.debug(prefix_logger + 'Leaving...') return flow_data_list From 40227944fb5f9b6e73f0c25f8273ac76a60917ce Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 14 Dec 2017 15:18:33 +0800 Subject: [PATCH 119/156] Remove package web_api --- web_api/__init__.py | 0 web_api/web_api.py | 62 --------------------------------------------- 2 files changed, 62 deletions(-) delete mode 100644 web_api/__init__.py delete mode 100644 web_api/web_api.py diff --git a/web_api/__init__.py b/web_api/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/web_api/web_api.py b/web_api/web_api.py deleted file mode 100644 index d9211d9..0000000 --- a/web_api/web_api.py +++ /dev/null @@ -1,62 +0,0 @@ -import threading - -from flask import Flask, jsonify, request, abort - -app = Flask(__name__) - -@app.route('/') -def help(): - return jsonify( - # 'API (application/json)': 'PATH, notes ?org-id= currently required', - {'Cache clean': '/marketing/cache/clean?org-ids=', - 'Cache clean and rebuild': '/marketing/cache/clean-rebuild?org-ids=&rebuild-table=true', - 'Cache status': '/marketing/cache/status', - 'On board': '/marketing/onboard?org-ids=', - 'On board status': '/marketing/onboard/status', - 'Delayed scheduled rebuild task': 'add:/marketing/cache/rebuild/operation?opt=add&org-ids= ' - 'delete:/marketing/cache/rebuild/operation?opt=delete&org-ids=', - 'Delayed task status': '/marketing/cache/rebuild/status?org-id=' - }) - - -@app.route('/pygennf/send', methods=['POST']) -def send(): - print "send() invoked..." - if not request.json: - abort(404) - print request.json - ip_src = request.json['ip_src'] - print 'ip_src: %s' % ip_src - ip_dst = request.json['ip_dst'] - print 'ip_dst: %s' % ip_dst - port_src = int(request.json['port_src']) - print 'port_src: ', port_src - port_dst = int(request.json['port_dst']) - print 'port_dst: ', port_dst - flow_data_list = get_flow_data_list(request.json['flows-data'], DEFAULT_FLOW_DATA) - print 'flow_data_list: %s' % flow_data_list - pkt_count = int(request.json['pkt_count']) - print 'pkt_count:', pkt_count - time_interval = request.json['time_interval'] - print 'time_interval: %s' % time_interval - print 'Thread %s is running...' % threading.current_thread().name - t = threading.Thread(target=start_send, name='SendingThread', args=(ip_src, ip_dst, port_src, port_dst, - flow_data_list, pkt_count, time_interval)) - # t.do_run = True - # t.setDaemon(True) - t.start() - while True: - t.join(5) - if not t.isAlive(): - break - - print 'Thread %s ended.' % threading.current_thread().name - - -@app.route('/pygennf/status') -def status(): - pass - - -def start(): - app.run(host='0.0.0.0', port=9080) From 5b1dadb3e8a9c8474853ad751255efeca726ada0 Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 14 Dec 2017 16:23:46 +0800 Subject: [PATCH 120/156] Added util for uuid --- utils/uuid_util.py | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 utils/uuid_util.py diff --git a/utils/uuid_util.py b/utils/uuid_util.py new file mode 100644 index 0000000..5c24dbc --- /dev/null +++ b/utils/uuid_util.py @@ -0,0 +1,5 @@ +import uuid + + +def get_uuid(): + return str(uuid.uuid1()) From c9bb20dc23b71ac970a073935a66a8ce1b9f2e90 Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 14 Dec 2017 16:24:35 +0800 Subject: [PATCH 121/156] Added thread list --- src/pygennf_v9_multi_threads.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index 571f214..df9e278 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -25,6 +25,7 @@ import rb_netflow.rb_netflow as rbnf from utils.logger_util import get_logger, set_logger_level +from utils.uuid_util import get_uuid SIGNAL_RECEIVED = 0 DIC_PROTOCOL_NUM = {'tcp': 6, 'udp': 17} @@ -38,6 +39,7 @@ app = Flask(__name__) logger = get_logger('pygennf') +threads_dict = collections.OrderedDict() @app.route('/') def help(): @@ -88,6 +90,8 @@ def create(): flow_data_list, pkt_count, time_interval)) # t.do_run = True # t.setDaemon(True) + threads_dict[str(get_uuid())] = [time.time(), t] + logger.debug(prefix_logger + 'threads_dict: %s' % threads_dict) t.start() return jsonify( {'Status': 'Sending task created successfully', From e471f41c0b75197e05b19068de9fc0c17820b315 Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 14 Dec 2017 16:32:43 +0800 Subject: [PATCH 122/156] Added /pygennf/help and /pygennf/tasks/status --- src/pygennf_v9_multi_threads.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index df9e278..d9fab11 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -41,21 +41,21 @@ logger = get_logger('pygennf') threads_dict = collections.OrderedDict() -@app.route('/') + +@app.route('/pygennf/help') def help(): return jsonify( # 'API (application/json)': 'PATH, notes ?org-id= currently required', - {'Cache clean': '/marketing/cache/clean?org-ids=', - 'Cache clean and rebuild': '/marketing/cache/clean-rebuild?org-ids=&rebuild-table=true', - 'Cache status': '/marketing/cache/status', - 'On board': '/marketing/onboard?org-ids=', - 'On board status': '/marketing/onboard/status', - 'Delayed scheduled rebuild task': 'add:/marketing/cache/rebuild/operation?opt=add&org-ids= ' - 'delete:/marketing/cache/rebuild/operation?opt=delete&org-ids=', - 'Delayed task status': '/marketing/cache/rebuild/status?org-id=' + {'Create sending task': '/pygennf/tasks/create', + 'Check tasks status': '/pygennf/tasks/status' }) +@app.route('/pygennf/tasks/status', methods=['GET']) +def status(): + return jsonify(threads_dict) + + @app.route('/pygennf/tasks/create', methods=['POST']) def create(): prefix_logger = '[Method][create]' From 04aba6586731e18269127663c310f7cae95e9c9f Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 14 Dec 2017 16:40:35 +0800 Subject: [PATCH 123/156] Updated return value in status() --- src/pygennf_v9_multi_threads.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index d9fab11..445da60 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -17,6 +17,7 @@ # along with this program. If not, see . import argparse +import json import signal import threading @@ -53,7 +54,8 @@ def help(): @app.route('/pygennf/tasks/status', methods=['GET']) def status(): - return jsonify(threads_dict) + status_info = json.dumps(threads_dict) + return jsonify(status_info) @app.route('/pygennf/tasks/create', methods=['POST']) From 172f6fb68dc42bbda0968cb9e4efdb727ca87c4d Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 14 Dec 2017 16:51:24 +0800 Subject: [PATCH 124/156] Updated returned dict in status() --- src/pygennf_v9_multi_threads.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index 445da60..c74f617 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -20,6 +20,7 @@ import json import signal import threading +from datetime import datetime from flask import Flask, jsonify, request, abort from scapy.all import * @@ -54,7 +55,10 @@ def help(): @app.route('/pygennf/tasks/status', methods=['GET']) def status(): - status_info = json.dumps(threads_dict) + status_info_dict = {} + for k, v in threads_dict.items(): + status_info_dict[k] = [v[0], v[1].__repr__()] + status_info = json.dumps(status_info_dict) return jsonify(status_info) @@ -92,7 +96,7 @@ def create(): flow_data_list, pkt_count, time_interval)) # t.do_run = True # t.setDaemon(True) - threads_dict[str(get_uuid())] = [time.time(), t] + threads_dict[str(get_uuid())] = [datetime.now().isoformat(), t] logger.debug(prefix_logger + 'threads_dict: %s' % threads_dict) t.start() return jsonify( From c78fd6d0adb5a413e7bfc637857b20b7bcfcda8f Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 14 Dec 2017 16:53:09 +0800 Subject: [PATCH 125/156] Updated returned dict in status() --- src/pygennf_v9_multi_threads.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index c74f617..57cedc1 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -17,10 +17,8 @@ # along with this program. If not, see . import argparse -import json import signal import threading -from datetime import datetime from flask import Flask, jsonify, request, abort from scapy.all import * @@ -58,8 +56,8 @@ def status(): status_info_dict = {} for k, v in threads_dict.items(): status_info_dict[k] = [v[0], v[1].__repr__()] - status_info = json.dumps(status_info_dict) - return jsonify(status_info) + # status_info = json.dumps(status_info_dict) + return jsonify(status_info_dict) @app.route('/pygennf/tasks/create', methods=['POST']) From 6ed4391f127c02bc29ab0ba702e72ca9a51d30f5 Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 14 Dec 2017 17:08:27 +0800 Subject: [PATCH 126/156] Updated return info in create() --- src/pygennf_v9_multi_threads.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index 57cedc1..0b50c2a 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -47,7 +47,8 @@ def help(): return jsonify( # 'API (application/json)': 'PATH, notes ?org-id= currently required', {'Create sending task': '/pygennf/tasks/create', - 'Check tasks status': '/pygennf/tasks/status' + 'Check tasks status': '/pygennf/tasks/status', + 'Print help info': '/pygennf/help' }) @@ -94,12 +95,14 @@ def create(): flow_data_list, pkt_count, time_interval)) # t.do_run = True # t.setDaemon(True) - threads_dict[str(get_uuid())] = [datetime.now().isoformat(), t] + task_uuid = get_uuid() + threads_dict[task_uuid] = [datetime.now().isoformat(), t] logger.debug(prefix_logger + 'threads_dict: %s' % threads_dict) t.start() return jsonify( - {'Status': 'Sending task created successfully', - 'TaskName': 'This is task name' + {'status': 'Sending task created and started successfully', + 'task_uuid': task_uuid, + 'task_info': t.__repr__() }) # while True: # t.join(5) From e52ea91c0bd6d74c52910281d0f5fba2a0949134 Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 14 Dec 2017 17:26:31 +0800 Subject: [PATCH 127/156] Changed thread name to uuid in create() --- src/pygennf_v9_multi_threads.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index 0b50c2a..0eeb76a 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -91,11 +91,13 @@ def create(): logger.debug(prefix_logger + 'time_interval: %s' % time_interval) # print 'Thread %s is running...' % threading.current_thread().name logger.info(prefix_logger + 'Thread %s is running...' % threading.current_thread().name) - t = threading.Thread(target=start_send, name='SendingThread', args=(ip_src, ip_dst, port_src, port_dst, + + task_uuid = get_uuid() + t = threading.Thread(target=start_send, name=task_uuid, args=(ip_src, ip_dst, port_src, port_dst, flow_data_list, pkt_count, time_interval)) # t.do_run = True # t.setDaemon(True) - task_uuid = get_uuid() + threads_dict[task_uuid] = [datetime.now().isoformat(), t] logger.debug(prefix_logger + 'threads_dict: %s' % threads_dict) t.start() From 6f45add2abbb58831c7bae083f358952bc249cbf Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 14 Dec 2017 17:34:08 +0800 Subject: [PATCH 128/156] Changed threads_dict in create() --- src/pygennf_v9_multi_threads.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index 0eeb76a..dabe5ab 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -56,7 +56,7 @@ def help(): def status(): status_info_dict = {} for k, v in threads_dict.items(): - status_info_dict[k] = [v[0], v[1].__repr__()] + status_info_dict[k] = [v['start_time'], v['thread'].__repr__()] # status_info = json.dumps(status_info_dict) return jsonify(status_info_dict) @@ -98,7 +98,7 @@ def create(): # t.do_run = True # t.setDaemon(True) - threads_dict[task_uuid] = [datetime.now().isoformat(), t] + threads_dict[task_uuid] = {"start_time": datetime.now().isoformat(), "thread": t} logger.debug(prefix_logger + 'threads_dict: %s' % threads_dict) t.start() return jsonify( From d5c44e2af73e135fdbef9b173b5924a38c0182f4 Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 14 Dec 2017 18:20:40 +0800 Subject: [PATCH 129/156] Add pkt_sent in threads_dict --- src/pygennf_v9_multi_threads.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index dabe5ab..3c3bc2a 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -56,7 +56,7 @@ def help(): def status(): status_info_dict = {} for k, v in threads_dict.items(): - status_info_dict[k] = [v['start_time'], v['thread'].__repr__()] + status_info_dict[k] = [v['start_time'], v['thread'].__repr__(), v['pkt_sent']] # status_info = json.dumps(status_info_dict) return jsonify(status_info_dict) @@ -98,7 +98,7 @@ def create(): # t.do_run = True # t.setDaemon(True) - threads_dict[task_uuid] = {"start_time": datetime.now().isoformat(), "thread": t} + threads_dict[task_uuid] = {"start_time": datetime.now().isoformat(), "thread": t, "pkt_sent": 0} logger.debug(prefix_logger + 'threads_dict: %s' % threads_dict) t.start() return jsonify( From 2701b37b7e2263c864d6440a3edab702e12c7729 Mon Sep 17 00:00:00 2001 From: szhao Date: Thu, 14 Dec 2017 18:23:05 +0800 Subject: [PATCH 130/156] Changed the status_info_dict in status() --- src/pygennf_v9_multi_threads.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index 3c3bc2a..f37b6f9 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -56,7 +56,8 @@ def help(): def status(): status_info_dict = {} for k, v in threads_dict.items(): - status_info_dict[k] = [v['start_time'], v['thread'].__repr__(), v['pkt_sent']] + status_info_dict[k] = {'start_time': v['start_time'], 'task_info': v['thread'].__repr__(), + 'pkt_sent': v['pkt_sent']} # status_info = json.dumps(status_info_dict) return jsonify(status_info_dict) From b9508f12fb9878f5c92ce5f0614d0bc757c522de Mon Sep 17 00:00:00 2001 From: szhao Date: Mon, 18 Dec 2017 16:28:28 +0800 Subject: [PATCH 131/156] Add parameter 'remote' in gen_send_pkt() --- src/pygennf_v9_multi_threads.py | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index f37b6f9..be58b45 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -95,7 +95,7 @@ def create(): task_uuid = get_uuid() t = threading.Thread(target=start_send, name=task_uuid, args=(ip_src, ip_dst, port_src, port_dst, - flow_data_list, pkt_count, time_interval)) + flow_data_list, pkt_count, time_interval, True)) # t.do_run = True # t.setDaemon(True) @@ -288,11 +288,12 @@ def get_flow_data_list(args_flows_data, default_flow_data): return flow_data_list - -def start_send(ip_src, ip_dst, port_src, port_dst, flow_data_list, pkt_count, time_interval): - print 'Thread %s is running...' % threading.current_thread().name +def start_send(ip_src, ip_dst, port_src, port_dst, flow_data_list, pkt_count, time_interval, remote=False): + current_thread_name = threading.current_thread().name + print 'Thread %s is running...' % current_thread_name flow_sequence = 1 - gen_send_pkt('tmpl', flow_sequence=flow_sequence, src_ip=ip_src, dst_ip=ip_dst, sport=port_src, dport=port_dst) + gen_send_pkt('tmpl', flow_sequence=flow_sequence, src_ip=ip_src, dst_ip=ip_dst, sport=port_src, dport=port_dst, + remote=remote) print 'Flows to be sent: ' print flow_data_list while time_interval is not 0: @@ -308,17 +309,18 @@ def start_send(ip_src, ip_dst, port_src, port_dst, flow_data_list, pkt_count, ti #sys.exit(0) break if flow_sequence % 100 == 0: - gen_send_pkt('tmpl', flow_sequence=flow_sequence, src_ip=ip_src, dst_ip=ip_dst, - sport=port_src, dport=port_dst) + gen_send_pkt('tmpl', flow_sequence=flow_sequence, src_ip=ip_src, dst_ip=ip_dst, sport=port_src, + dport=port_dst, remote=remote) continue gen_send_pkt('data', flow_sequence, src_ip=ip_src, dst_ip=ip_dst, sport=port_src, dport=port_dst, - flow_data_list=flow_data_list) + flow_data_list=flow_data_list, remote=remote) print 'Thread %s ended.' % threading.current_thread().name -def gen_send_pkt(pkt_type='data', flow_sequence=1, src_ip='1.1.1.1', dst_ip = '2.2.2.2', sport=2056, dport=2055, - flow_data_list=[]): +def gen_send_pkt(pkt_type='data', flow_sequence=1, src_ip='1.1.1.1', dst_ip='2.2.2.2', sport=2056, dport=2055, + flow_data_list=[], remote=False): + current_thread_name = threading.current_thread().name timestamp = int(time.time()) if pkt_type == 'tmpl': pkt_netflow_tmpl = gen_pkt_netflow_tmpl(timestamp=timestamp, flow_sequence=flow_sequence, @@ -337,6 +339,12 @@ def gen_send_pkt(pkt_type='data', flow_sequence=1, src_ip='1.1.1.1', dst_ip = '2 send(pkt_netflow_data, verbose=0) sys.stdout.flush() + if remote: + try: + threads_dict[current_thread_name]['pkt_sent'] = flow_sequence + except KeyError: + logger.warn("pkt_sent cannot be assigned to thread '%s' in thread_dict" % current_thread_name) + def gen_pkt_netflow_data(timestamp=1503652676, flow_sequence=1, sys_uptime=3600000, src_ip='121.41.5.67', dst_ip='121.41.5.68', sport=2056, dport=2055, flow_data_list=[]): From d16fd87c693c764b1e799cdc9a6fb6e0d1354a08 Mon Sep 17 00:00:00 2001 From: szhao Date: Mon, 18 Dec 2017 16:56:51 +0800 Subject: [PATCH 132/156] Modify default app port --- src/pygennf_v9_multi_threads.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index be58b45..370813c 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -35,6 +35,8 @@ # e.g. 11.11.11.11/32:1001:11.11.11.22/32:1002:tcp:ingress:1024 FLOW_DATA_PATTERN = r'^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d{1,2}:\d{1,5}:){2}\w+:(ingress|egress):\d{1,4}$' DEFAULT_FLOW_DATA = '11.11.11.11/32:1001:11.11.11.22/32:80:tcp:ingress:1024' +DEFAULT_APP_HOST = '0.0.0.0' +DEFAULT_APP_PORT = 15000 app = Flask(__name__) @@ -150,7 +152,7 @@ def get_parser(): parser.add_argument('-fd', '--flows-data', dest='flows_data', help='Contents in flows data, e.g. ip1/mask:port1:ip2/mask:port2:protocol:direction:bytes.') parser.add_argument('-r', '--remote', dest='remote', action="store_true", - help='Listen on TCP port 9080 as API server. All other parameters will be ignored.') + help='Listen on TCP port 15000 as API server. All other parameters will be ignored.') parser.add_argument('-ll', '--log-level', dest='log_level', type=str, choices=['info', 'debug'], help='Log level, default log level is info') return parser.parse_args() @@ -183,7 +185,8 @@ def main(): if args.remote: # api.start() - app.run(host='0.0.0.0', port=9080) + logger.info("Flow Generator starting to listen on '%s':'%s'" % (DEFAULT_APP_HOST, str(DEFAULT_APP_PORT))) + app.run(host=DEFAULT_APP_HOST, port=DEFAULT_APP_PORT) sys.exit(0) if args.src_ip: @@ -326,7 +329,7 @@ def gen_send_pkt(pkt_type='data', flow_sequence=1, src_ip='1.1.1.1', dst_ip='2.2 pkt_netflow_tmpl = gen_pkt_netflow_tmpl(timestamp=timestamp, flow_sequence=flow_sequence, src_ip=src_ip, dst_ip =dst_ip, sport=sport, dport=dport) #wrpcap('v9_test_tmpl.pcap', pkt_netflow_tmpl) - sys.stdout.write("Sending packets: %d \r" % (flow_sequence)) + sys.stdout.write("Sending packets: %d \r" % flow_sequence) send(pkt_netflow_tmpl, verbose=0) sys.stdout.flush() elif pkt_type == 'data': @@ -335,7 +338,7 @@ def gen_send_pkt(pkt_type='data', flow_sequence=1, src_ip='1.1.1.1', dst_ip='2.2 src_ip=src_ip, dst_ip=dst_ip, sport=sport, dport=dport, flow_data_list=flow_data_list) #wrpcap('v9_test_data.pcap', pkt_netflow_data) - sys.stdout.write("Sending packets: %d \r" % (flow_sequence)) + sys.stdout.write("Sending packets: %d \r" % flow_sequence) send(pkt_netflow_data, verbose=0) sys.stdout.flush() From 1511fe2a70130817de4025597bffb0a1259aae12 Mon Sep 17 00:00:00 2001 From: szhao Date: Mon, 18 Dec 2017 17:09:27 +0800 Subject: [PATCH 133/156] Add end_time in threads_dict --- src/pygennf_v9_multi_threads.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index 370813c..1b46cd0 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -101,7 +101,7 @@ def create(): # t.do_run = True # t.setDaemon(True) - threads_dict[task_uuid] = {"start_time": datetime.now().isoformat(), "thread": t, "pkt_sent": 0} + threads_dict[task_uuid] = {"start_time": datetime.now().isoformat(), "end_time": "", "thread": t, "pkt_sent": 0} logger.debug(prefix_logger + 'threads_dict: %s' % threads_dict) t.start() return jsonify( @@ -319,6 +319,11 @@ def start_send(ip_src, ip_dst, port_src, port_dst, flow_data_list, pkt_count, ti flow_data_list=flow_data_list, remote=remote) print 'Thread %s ended.' % threading.current_thread().name + if remote: + try: + threads_dict[current_thread_name]['end_time'] = datetime.now().isoformat() + except KeyError: + logger.warn("end_time set failed in threads_dict") def gen_send_pkt(pkt_type='data', flow_sequence=1, src_ip='1.1.1.1', dst_ip='2.2.2.2', sport=2056, dport=2055, From 4622de97ac45bacce580c4dde70c269f870e287e Mon Sep 17 00:00:00 2001 From: szhao Date: Mon, 18 Dec 2017 17:22:50 +0800 Subject: [PATCH 134/156] Add debug log in start_send --- src/pygennf_v9_multi_threads.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index 1b46cd0..f8829df 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -321,7 +321,10 @@ def start_send(ip_src, ip_dst, port_src, port_dst, flow_data_list, pkt_count, ti print 'Thread %s ended.' % threading.current_thread().name if remote: try: - threads_dict[current_thread_name]['end_time'] = datetime.now().isoformat() + current_time = datetime.now().isoformat() + threads_dict[current_thread_name]['end_time'] = current_time + logger.debug( + "current_time '%s' has been set to threads_dict for thread '%s'" % (current_time, current_thread_name)) except KeyError: logger.warn("end_time set failed in threads_dict") From 5479bcffa73c6e76b2d1a8da18ae0c35c54fadae Mon Sep 17 00:00:00 2001 From: szhao Date: Mon, 18 Dec 2017 17:25:25 +0800 Subject: [PATCH 135/156] Update output in status() --- src/pygennf_v9_multi_threads.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index f8829df..ffafb60 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -58,7 +58,8 @@ def help(): def status(): status_info_dict = {} for k, v in threads_dict.items(): - status_info_dict[k] = {'start_time': v['start_time'], 'task_info': v['thread'].__repr__(), + status_info_dict[k] = {'start_time': v['start_time'], 'end_time': v['end_time'], + 'task_info': v['thread'].__repr__(), 'pkt_sent': v['pkt_sent']} # status_info = json.dumps(status_info_dict) return jsonify(status_info_dict) @@ -324,7 +325,7 @@ def start_send(ip_src, ip_dst, port_src, port_dst, flow_data_list, pkt_count, ti current_time = datetime.now().isoformat() threads_dict[current_thread_name]['end_time'] = current_time logger.debug( - "current_time '%s' has been set to threads_dict for thread '%s'" % (current_time, current_thread_name)) + "end_time '%s' has been set to threads_dict for thread '%s'" % (current_time, current_thread_name)) except KeyError: logger.warn("end_time set failed in threads_dict") From c53d1172f2fcfa01c13766acba9666400294f84a Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 19 Dec 2017 15:20:55 +0800 Subject: [PATCH 136/156] Add API to support query for specific task --- src/pygennf_v9_multi_threads.py | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index ffafb60..53eae65 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -54,8 +54,9 @@ def help(): }) +# Get the status of all threads @app.route('/pygennf/tasks/status', methods=['GET']) -def status(): +def status_all(): status_info_dict = {} for k, v in threads_dict.items(): status_info_dict[k] = {'start_time': v['start_time'], 'end_time': v['end_time'], @@ -65,11 +66,25 @@ def status(): return jsonify(status_info_dict) +# Get the status of specific thread +@app.route('/pygennf/tasks/status/', methods=['GET']) +def status_specific(task_id): + if task_id not in threads_dict: + return jsonify( + {'status': 'Error', + 'desc': 'The task_id cannot be found in task list', + 'task_uuid': task_id, + 'task_info': '' + }) + + +# Create the thread to send packets @app.route('/pygennf/tasks/create', methods=['POST']) def create(): prefix_logger = '[Method][create]' # print "create() invoked..." if not request.json: + logger.debug(prefix_logger + "Json body is expected in POST message!!") abort(404) # print request.json ip_src = request.json['ip_src'].encode("ascii") @@ -106,7 +121,8 @@ def create(): logger.debug(prefix_logger + 'threads_dict: %s' % threads_dict) t.start() return jsonify( - {'status': 'Sending task created and started successfully', + {'status': 'Success', + 'desc': 'Packets sending task created and started successfully', 'task_uuid': task_uuid, 'task_info': t.__repr__() }) @@ -127,9 +143,7 @@ def signal_handler(signal, frame): def valid_flow_data(flow_data_str=''): global FLOW_DATA_PATTERN m = re.match(FLOW_DATA_PATTERN, flow_data_str) - if m is not None: - return True - return False + return True if m is not None else False def get_parser(): @@ -185,7 +199,6 @@ def main(): set_logger_level(logger, args.log_level) if args.remote: - # api.start() logger.info("Flow Generator starting to listen on '%s':'%s'" % (DEFAULT_APP_HOST, str(DEFAULT_APP_PORT))) app.run(host=DEFAULT_APP_HOST, port=DEFAULT_APP_PORT) sys.exit(0) @@ -255,8 +268,6 @@ def main(): signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler) - #start_send(IP_SRC, IP_DST, PORT_SRC, PORT_DST, FLOW_DATA_LIST, PKT_COUNT, TIME_INTERVAL) - print 'Thread %s is running...' % threading.current_thread().name t = threading.Thread(target=start_send, name='SendingThread', args=(ip_src, ip_dst, port_src, port_dst, flow_data_list, pkt_count, time_interval)) @@ -282,7 +293,7 @@ def get_flow_data_list(args_flows_data, default_flow_data): flow_data_list = filter(valid_flow_data, flow_data_list) if len(flow_data_list) == 0: # print 'No valid flow data list, default flow data list will be used...' - logger.warn(prefix_logger + 'No valid flow data list, default flow data list will be used...') + logger.info(prefix_logger + 'No valid flow data list, default flow data list will be used...') # print "Default flow data: %s" % (default_flow_data) logger.info(prefix_logger + 'Default flow data: %s' % (default_flow_data)) flow_data_list.append(default_flow_data) @@ -327,7 +338,7 @@ def start_send(ip_src, ip_dst, port_src, port_dst, flow_data_list, pkt_count, ti logger.debug( "end_time '%s' has been set to threads_dict for thread '%s'" % (current_time, current_thread_name)) except KeyError: - logger.warn("end_time set failed in threads_dict") + logger.info("end_time set failed in threads_dict") def gen_send_pkt(pkt_type='data', flow_sequence=1, src_ip='1.1.1.1', dst_ip='2.2.2.2', sport=2056, dport=2055, @@ -355,7 +366,7 @@ def gen_send_pkt(pkt_type='data', flow_sequence=1, src_ip='1.1.1.1', dst_ip='2.2 try: threads_dict[current_thread_name]['pkt_sent'] = flow_sequence except KeyError: - logger.warn("pkt_sent cannot be assigned to thread '%s' in thread_dict" % current_thread_name) + logger.info("pkt_sent cannot be assigned to thread '%s' in thread_dict" % current_thread_name) def gen_pkt_netflow_data(timestamp=1503652676, flow_sequence=1, sys_uptime=3600000, src_ip='121.41.5.67', From d00cf246960af5c9b1bc09bc79971fd5c8628803 Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 19 Dec 2017 15:23:12 +0800 Subject: [PATCH 137/156] Add API to support query for specific task --- src/pygennf_v9_multi_threads.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index 53eae65..b1528d4 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -76,6 +76,8 @@ def status_specific(task_id): 'task_uuid': task_id, 'task_info': '' }) + else: + logger.debug("Task_id '%s' was found in task list" % task_id) # Create the thread to send packets From bfbe4aa5ba4e0dd23be336fab80275a4d49d12e5 Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 19 Dec 2017 15:29:08 +0800 Subject: [PATCH 138/156] Add API to support query for specific task --- src/pygennf_v9_multi_threads.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index b1528d4..ec4ecbc 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -77,7 +77,12 @@ def status_specific(task_id): 'task_info': '' }) else: - logger.debug("Task_id '%s' was found in task list" % task_id) + status_info_dict = {} + status_info_dict[task_id] = {'start_time': threads_dict[task_id]['start_time'], + 'end_time': threads_dict[task_id]['end_time'], + 'task_info': threads_dict[task_id]['thread'].__repr__(), + 'pkt_sent': threads_dict[task_id]['pkt_sent']} + return jsonify(status_info_dict) # Create the thread to send packets From 37332ec8d189f8d2c519409775f0112a9c939b55 Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 19 Dec 2017 15:42:13 +0800 Subject: [PATCH 139/156] Add status in task info returned --- src/pygennf_v9_multi_threads.py | 40 +++++---------------------------- 1 file changed, 6 insertions(+), 34 deletions(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index ec4ecbc..1f75beb 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -124,21 +124,18 @@ def create(): # t.do_run = True # t.setDaemon(True) - threads_dict[task_uuid] = {"start_time": datetime.now().isoformat(), "end_time": "", "thread": t, "pkt_sent": 0} + threads_dict[task_uuid] = {"start_time": "", "end_time": "", "thread": t, "pkt_sent": 0, "status": "not started"} logger.debug(prefix_logger + 'threads_dict: %s' % threads_dict) t.start() + threads_dict[task_uuid]['start_time'] = datetime.now().isoformat() + threads_dict[task_uuid]['status'] = 'started' + return jsonify( {'status': 'Success', 'desc': 'Packets sending task created and started successfully', 'task_uuid': task_uuid, 'task_info': t.__repr__() }) - # while True: - # t.join(5) - # if not t.isAlive(): - # break - # - # print 'Thread %s ended.' % threading.current_thread().name def signal_handler(signal, frame): @@ -167,10 +164,6 @@ def get_parser(): help='Time interval to wait before sending each netflow packet.') parser.add_argument('-c', '--pkt-count', dest='pkt_count', help='Packets count to be sent before this generator stopping.') - # parser.add_argument('-p', '--protocol', dest='protocol', - # help='Protocols included in netflow data part, e.g. tcp(6) or udp(17).') - # parser.add_argument('-b', '--bytes', dest='bytes', - # help='Bytes(octets) in single flow, e.g. 1024.') parser.add_argument('-fd', '--flows-data', dest='flows_data', help='Contents in flows data, e.g. ip1/mask:port1:ip2/mask:port2:protocol:direction:bytes.') parser.add_argument('-r', '--remote', dest='remote', action="store_true", @@ -244,26 +237,6 @@ def main(): # 0xFFFFFFFF - 1 pkt_count = 4294967294 - # if args.protocol: - # try: - # PROTOCOL_NUM = DIC_PROTOCOL_NUM[args.protocol] - # except KeyError: - # print "Protocol '%s' cannot be mapped to existing protocols, use TCP[6] as default" % (args.protocol) - # PROTOCOL_NUM = 6 - # else: - # PROTOCOL_NUM = 6 # TCP by default - # - # if args.bytes: - # try: - # BYTES = int(args.bytes) - # if BYTES < 1 or BYTES > 4096: - # raise ValueError - # except ValueError: - # print "Bytes '%s' should be integer between 1 and 4096, use 1024 as default" % (args.bytes) - # BYTES = 1024 - # else: - # BYTES = 1024 - if args.flows_data: flow_data_list = get_flow_data_list(args.flows_data, DEFAULT_FLOW_DATA) else: @@ -291,10 +264,8 @@ def main(): def get_flow_data_list(args_flows_data, default_flow_data): prefix_logger = '[Method][get_flow_data_list]' - # print 'get_flow_data_list() start...' logger.debug(prefix_logger + 'Entering...') - # print 'type(args_flows_data):', type(args_flows_data) - # print 'args_flows_data: %s' % args_flows_data + flow_data_list = args_flows_data.split(',') flow_data_list = map(str.strip, flow_data_list) flow_data_list = filter(valid_flow_data, flow_data_list) @@ -344,6 +315,7 @@ def start_send(ip_src, ip_dst, port_src, port_dst, flow_data_list, pkt_count, ti threads_dict[current_thread_name]['end_time'] = current_time logger.debug( "end_time '%s' has been set to threads_dict for thread '%s'" % (current_time, current_thread_name)) + threads_dict[current_thread_name]['status'] = "completed" except KeyError: logger.info("end_time set failed in threads_dict") From c38bb35ed153160186651cd79caa303d9b3a907b Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 19 Dec 2017 15:44:11 +0800 Subject: [PATCH 140/156] Add status in task info returned --- src/pygennf_v9_multi_threads.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index 1f75beb..a12579d 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -61,7 +61,8 @@ def status_all(): for k, v in threads_dict.items(): status_info_dict[k] = {'start_time': v['start_time'], 'end_time': v['end_time'], 'task_info': v['thread'].__repr__(), - 'pkt_sent': v['pkt_sent']} + 'pkt_sent': v['pkt_sent'], + 'status': v['status']} # status_info = json.dumps(status_info_dict) return jsonify(status_info_dict) @@ -81,7 +82,8 @@ def status_specific(task_id): status_info_dict[task_id] = {'start_time': threads_dict[task_id]['start_time'], 'end_time': threads_dict[task_id]['end_time'], 'task_info': threads_dict[task_id]['thread'].__repr__(), - 'pkt_sent': threads_dict[task_id]['pkt_sent']} + 'pkt_sent': threads_dict[task_id]['pkt_sent'], + 'status': threads_dict[task_id]['status']} return jsonify(status_info_dict) From 47b7121720f378e8ea9fd170a289112bbc08cdd5 Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 19 Dec 2017 16:33:48 +0800 Subject: [PATCH 141/156] Add method for task killing --- src/pygennf_v9_multi_threads.py | 63 +++++++++++++++++++++++++++++---- 1 file changed, 57 insertions(+), 6 deletions(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index a12579d..2826b15 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -87,6 +87,45 @@ def status_specific(task_id): return jsonify(status_info_dict) +# Kill the specific thread +@app.route('/pygennf/tasks/kill/', methods=['GET']) +def kill_specific(task_id): + if task_id not in threads_dict: + return jsonify( + {'status': 'Error', + 'desc': 'The task_id cannot be found in task list', + 'task_uuid': task_id, + 'task_info': '' + }) + else: + if 'completed' == threads_dict[task_id]['status']: + return jsonify( + {'status': 'Success', + 'desc': 'The task with this task_id is already completed, no need to be killed', + 'task_uuid': task_id, + 'task_info': '' + }) + else: + logger.debug("Task with task_id '%s' is running now, will be stopped" % task_id) + task_thread = threads_dict[task_id]['thread'] + if task_thread.isAlive(): + threads_dict[task_id]['stop_flag'] = 'true' + return jsonify( + {'status': 'Success', + 'desc': 'The stop_flag for this task_id is set, it will be completed soon', + 'task_uuid': task_id, + 'task_info': '' + }) + else: + return jsonify( + {'status': 'Success', + 'desc': 'The task with this task_id is already completed, no need to be killed', + 'task_uuid': task_id, + 'task_info': '' + }) + + + # Create the thread to send packets @app.route('/pygennf/tasks/create', methods=['POST']) def create(): @@ -298,6 +337,14 @@ def start_send(ip_src, ip_dst, port_src, port_dst, flow_data_list, pkt_count, ti break time.sleep(float(time_interval)) + if remote: + try: + if 'true' == threads_dict[current_thread_name]['stop_flag']: + logger.info("Detected stop_flag for task '%s', task will be completed" % current_thread_name) + break + except KeyError: + pass + flow_sequence = flow_sequence + 1 if flow_sequence > pkt_count: print "\nPackets count[%s] reached. Stopping and Exiting..." % pkt_count @@ -312,14 +359,18 @@ def start_send(ip_src, ip_dst, port_src, port_dst, flow_data_list, pkt_count, ti print 'Thread %s ended.' % threading.current_thread().name if remote: + current_time = datetime.now().isoformat() + threads_dict[current_thread_name]['end_time'] = current_time + logger.debug( + "end_time '%s' has been set to threads_dict for thread '%s'" % (current_time, current_thread_name)) + try: - current_time = datetime.now().isoformat() - threads_dict[current_thread_name]['end_time'] = current_time - logger.debug( - "end_time '%s' has been set to threads_dict for thread '%s'" % (current_time, current_thread_name)) - threads_dict[current_thread_name]['status'] = "completed" + if 'true' == threads_dict[current_thread_name]['stop_flag']: + threads_dict[current_thread_name]['status'] = "user stopped" + else: + threads_dict[current_thread_name]['status'] = "completed" except KeyError: - logger.info("end_time set failed in threads_dict") + threads_dict[current_thread_name]['status'] = "completed" def gen_send_pkt(pkt_type='data', flow_sequence=1, src_ip='1.1.1.1', dst_ip='2.2.2.2', sport=2056, dport=2055, From 5aa69560f0e291c34b24bb5f48f7acdf957d58e0 Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 19 Dec 2017 16:50:31 +0800 Subject: [PATCH 142/156] Add method for task killing --- src/pygennf_v9_multi_threads.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index 2826b15..f04ed52 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -98,7 +98,7 @@ def kill_specific(task_id): 'task_info': '' }) else: - if 'completed' == threads_dict[task_id]['status']: + if threads_dict[task_id]['status'] in ('completed', 'user stopped'): return jsonify( {'status': 'Success', 'desc': 'The task with this task_id is already completed, no need to be killed', @@ -106,7 +106,7 @@ def kill_specific(task_id): 'task_info': '' }) else: - logger.debug("Task with task_id '%s' is running now, will be stopped" % task_id) + logger.debug("Task with task_id '%s' will be stopped now" % task_id) task_thread = threads_dict[task_id]['thread'] if task_thread.isAlive(): threads_dict[task_id]['stop_flag'] = 'true' From 9d38432731316e4a52ee337ac8a19a1fb052dddd Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 19 Dec 2017 17:03:14 +0800 Subject: [PATCH 143/156] Add method for all tasks stopping --- src/pygennf_v9_multi_threads.py | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index f04ed52..761c221 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -87,9 +87,9 @@ def status_specific(task_id): return jsonify(status_info_dict) -# Kill the specific thread -@app.route('/pygennf/tasks/kill/', methods=['GET']) -def kill_specific(task_id): +# Stop the specific thread +@app.route('/pygennf/tasks/stop/', methods=['GET']) +def stop_specific(task_id): if task_id not in threads_dict: return jsonify( {'status': 'Error', @@ -101,7 +101,7 @@ def kill_specific(task_id): if threads_dict[task_id]['status'] in ('completed', 'user stopped'): return jsonify( {'status': 'Success', - 'desc': 'The task with this task_id is already completed, no need to be killed', + 'desc': 'The task with this task_id is already completed, no need to be stopped', 'task_uuid': task_id, 'task_info': '' }) @@ -119,12 +119,28 @@ def kill_specific(task_id): else: return jsonify( {'status': 'Success', - 'desc': 'The task with this task_id is already completed, no need to be killed', + 'desc': 'The task with this task_id is already completed, no need to be stopped', 'task_uuid': task_id, 'task_info': '' }) +# Stop all the running threads +@app.route('/pygennf/tasks/stop', methods=['GET']) +def stop_all(): + thread_name_list = [] + for task_id in threads_dict.keys(): + threads_dict[task_id]['stop_flag'] = 'true' + thread_name_list.append(task_id) + + return jsonify( + {'status': 'Success', + 'desc': 'The stop_flag for all the tasks have been set, those tasks will be completed soon', + 'task_uuid': thread_name_list, + 'task_info': '' + }) + + # Create the thread to send packets @app.route('/pygennf/tasks/create', methods=['POST']) From a83a17353894d5eb7020673522b3bcf2dcfe56df Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 19 Dec 2017 17:19:14 +0800 Subject: [PATCH 144/156] Change from uuid1 to uuid4 --- utils/uuid_util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/uuid_util.py b/utils/uuid_util.py index 5c24dbc..137d398 100644 --- a/utils/uuid_util.py +++ b/utils/uuid_util.py @@ -2,4 +2,4 @@ def get_uuid(): - return str(uuid.uuid1()) + return str(uuid.uuid4()) From 51945eed5f0251802c779ac2cff9a29e50b36c7b Mon Sep 17 00:00:00 2001 From: szhao Date: Mon, 15 Jan 2018 16:04:15 +0800 Subject: [PATCH 145/156] Add detail_all() to return all tasks details --- src/pygennf_v9_multi_threads.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index 761c221..394eae7 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -87,6 +87,16 @@ def status_specific(task_id): return jsonify(status_info_dict) +# Get the detail of all threads +@app.route('/pygennf/tasks/detail', methods=['GET']) +def detail_all(): + detail_info_dict = {} + for k, v in threads_dict.items(): + detail_info_dict[k] = {'task_detail': v['task_detail']} + + return jsonify(detail_info_dict) + + # Stop the specific thread @app.route('/pygennf/tasks/stop/', methods=['GET']) def stop_specific(task_id): @@ -181,7 +191,11 @@ def create(): # t.do_run = True # t.setDaemon(True) - threads_dict[task_uuid] = {"start_time": "", "end_time": "", "thread": t, "pkt_sent": 0, "status": "not started"} + threads_dict[task_uuid] = {"start_time": "", "end_time": "", "thread": t, "pkt_sent": 0, "status": "not started", + "task_detail": {"ip_src": ip_src, "ip_dst": ip_dst, "port_src": port_src, + "port_dst": port_dst, "flow_data_list": flow_data_list, + "pkt_count": pkt_count, "time_interval": time_interval} + } logger.debug(prefix_logger + 'threads_dict: %s' % threads_dict) t.start() threads_dict[task_uuid]['start_time'] = datetime.now().isoformat() From 566023bee7d27d6905ceeb92d72d316bd1adba8d Mon Sep 17 00:00:00 2001 From: szhao Date: Mon, 15 Jan 2018 16:11:39 +0800 Subject: [PATCH 146/156] Add detail_specific() to return specific task detail --- src/pygennf_v9_multi_threads.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index 394eae7..ee65036 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -97,6 +97,22 @@ def detail_all(): return jsonify(detail_info_dict) +# Get the detail of specific thread +@app.route('/pygennf/tasks/detail/', methods=['GET']) +def detail_specific(task_id): + if task_id not in threads_dict: + return jsonify( + {'status': 'Error', + 'desc': 'The task_id cannot be found in task list', + 'task_uuid': task_id, + 'task_info': '' + }) + else: + detail_info_dict = {} + detail_info_dict[task_id] = {'task_detail': threads_dict[task_id]['task_detail']} + return jsonify(detail_info_dict) + + # Stop the specific thread @app.route('/pygennf/tasks/stop/', methods=['GET']) def stop_specific(task_id): From 8e017d3442120257cee914d4a29d486c6034fb67 Mon Sep 17 00:00:00 2001 From: szhao Date: Mon, 15 Jan 2018 16:29:52 +0800 Subject: [PATCH 147/156] Add clear() to clear task list --- src/pygennf_v9_multi_threads.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index ee65036..cd44221 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -167,6 +167,34 @@ def stop_all(): }) +# Clear specific task +@app.route('/pygennf/tasks/clear/', methods=['GET']) +def clear(task_id): + if task_id not in threads_dict: + return jsonify( + {'status': 'Error', + 'desc': 'The task_id cannot be found in task list', + 'task_uuid': task_id, + 'task_info': '' + }) + else: + if threads_dict[task_id]['status'] not in ('completed', 'user stopped'): + return jsonify( + {'status': 'Error', + 'desc': 'The task with this task_id is still running, it should be completed or stopped first', + 'task_uuid': task_id, + 'task_info': '' + }) + else: + logger.debug("Task with task_id '%s' will be cleared from threads_dict now" % task_id) + del threads_dict[task_id] + return jsonify( + {'status': 'Success', + 'desc': 'Task has been cleared', + 'task_uuid': task_id, + 'task_info': '' + }) + # Create the thread to send packets @app.route('/pygennf/tasks/create', methods=['POST']) From 71e1e852c85cf3c00abaee533384f1f40775ed8b Mon Sep 17 00:00:00 2001 From: szhao Date: Mon, 5 Feb 2018 15:43:24 +0800 Subject: [PATCH 148/156] Rename remote to is_remote --- src/pygennf_v9_multi_threads.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_multi_threads.py index cd44221..ffdd43b 100644 --- a/src/pygennf_v9_multi_threads.py +++ b/src/pygennf_v9_multi_threads.py @@ -396,12 +396,12 @@ def get_flow_data_list(args_flows_data, default_flow_data): return flow_data_list -def start_send(ip_src, ip_dst, port_src, port_dst, flow_data_list, pkt_count, time_interval, remote=False): +def start_send(ip_src, ip_dst, port_src, port_dst, flow_data_list, pkt_count, time_interval, is_remote=False): current_thread_name = threading.current_thread().name print 'Thread %s is running...' % current_thread_name flow_sequence = 1 gen_send_pkt('tmpl', flow_sequence=flow_sequence, src_ip=ip_src, dst_ip=ip_dst, sport=port_src, dport=port_dst, - remote=remote) + is_remote=is_remote) print 'Flows to be sent: ' print flow_data_list while time_interval is not 0: @@ -411,7 +411,7 @@ def start_send(ip_src, ip_dst, port_src, port_dst, flow_data_list, pkt_count, ti break time.sleep(float(time_interval)) - if remote: + if is_remote: try: if 'true' == threads_dict[current_thread_name]['stop_flag']: logger.info("Detected stop_flag for task '%s', task will be completed" % current_thread_name) @@ -426,13 +426,13 @@ def start_send(ip_src, ip_dst, port_src, port_dst, flow_data_list, pkt_count, ti break if flow_sequence % 100 == 0: gen_send_pkt('tmpl', flow_sequence=flow_sequence, src_ip=ip_src, dst_ip=ip_dst, sport=port_src, - dport=port_dst, remote=remote) + dport=port_dst, is_remote=is_remote) continue gen_send_pkt('data', flow_sequence, src_ip=ip_src, dst_ip=ip_dst, sport=port_src, dport=port_dst, - flow_data_list=flow_data_list, remote=remote) + flow_data_list=flow_data_list, is_remote=is_remote) print 'Thread %s ended.' % threading.current_thread().name - if remote: + if is_remote: current_time = datetime.now().isoformat() threads_dict[current_thread_name]['end_time'] = current_time logger.debug( @@ -448,7 +448,7 @@ def start_send(ip_src, ip_dst, port_src, port_dst, flow_data_list, pkt_count, ti def gen_send_pkt(pkt_type='data', flow_sequence=1, src_ip='1.1.1.1', dst_ip='2.2.2.2', sport=2056, dport=2055, - flow_data_list=[], remote=False): + flow_data_list=[], is_remote=False): current_thread_name = threading.current_thread().name timestamp = int(time.time()) if pkt_type == 'tmpl': @@ -468,7 +468,7 @@ def gen_send_pkt(pkt_type='data', flow_sequence=1, src_ip='1.1.1.1', dst_ip='2.2 send(pkt_netflow_data, verbose=0) sys.stdout.flush() - if remote: + if is_remote: try: threads_dict[current_thread_name]['pkt_sent'] = flow_sequence except KeyError: From b03e9725cabee9a374cbbe9e13942a98eb61a8e3 Mon Sep 17 00:00:00 2001 From: szhao Date: Mon, 5 Feb 2018 16:08:55 +0800 Subject: [PATCH 149/156] Update README --- README.md | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index e68ae1d..fab099d 100644 --- a/README.md +++ b/README.md @@ -9,11 +9,12 @@ Netflow packets generator with Scapy library # Usage: - * pygennf_v9.py --help + * pygennf_v9_multi_threads.py --help ->usage: pygennf_v9.py [-h] [-s SRC_IP] [-sp SRC_PORT] [-d DST_IP] -> [-dp DST_PORT] [-t TIME_INTERVAL] [-c PKT_COUNT] -> [-fd FLOWS_DATA] +>usage: pygennf_v9_multi_threads.py [-h] [-s SRC_IP] [-sp SRC_PORT] [-d DST_IP] +> [-dp DST_PORT] [-t TIME_INTERVAL] +> [-c PKT_COUNT] [-fd FLOWS_DATA] [-r] +> [-ll {info,debug}] > >Netflow packets generator with scapy > @@ -42,13 +43,21 @@ Netflow packets generator with Scapy library > -fd FLOWS_DATA, --flows-data FLOWS_DATA > Contents in flows data, e.g. ip1/mask:port1:ip2/mask:port2:protocol:direction:bytes. > +> -r, --remote +> Listen on TCP port 15000 as API server. All other parameters will be ignored. +> +> -ll {info,debug}, --log-level {info,debug} +> Log level, default log level is info +> # Example of use: - * Netflow 9: -> pygennf_v9.py --source-ip 10.9.255.54 --dst-ip 10.9.255.118 --dst-port 2062 -t 1 -c 3600 -fd '69.31.102.10/32:12345:209.81.108.20/32:80:tcp:ingress:1024, 70.32.103.11/32:54321:210.81.108.21/32:21:udp:ingress:1024' + * Netflow 9 (CLI): +> pygennf_v9_multi_threads.py --source-ip 10.9.255.54 --dst-ip 10.9.255.118 --dst-port 2062 -t 1 -c 3600 -fd '69.31.102.10/32:12345:209.81.108.20/32:80:tcp:ingress:1024, 70.32.103.11/32:54321:210.81.108.21/32:21:udp:ingress:1024' > > ![2017-09-30_console_snapshot_01.png](https://github.com/9nehS/pygennf/blob/master/resources/2017-09-30_console_snapshot_01.png) > -> ![2017-09-28_web_snapshot_01.png](https://github.com/9nehS/pygennf/blob/master/resources/2017-09-28_web_snapshot_01.png) \ No newline at end of file +> ![2017-09-28_web_snapshot_01.png](https://github.com/9nehS/pygennf/blob/master/resources/2017-09-28_web_snapshot_01.png) +> + * Netflow 9 (WebService): \ No newline at end of file From 536c668a9f06331e3831722175e9ec33631f273c Mon Sep 17 00:00:00 2001 From: szhao Date: Mon, 5 Feb 2018 16:10:57 +0800 Subject: [PATCH 150/156] Update README --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index fab099d..3b8ff58 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,9 @@ Netflow packets generator with Scapy library * How to install: > git clone https://github.com/9nehS/pygennf.git > -> python setup.py install +> git checkout dev_multi_threads +> +> python setup.py install --force # Usage: From 2d51d42be435493a5f70ca4146538ecbb36ab696 Mon Sep 17 00:00:00 2001 From: szhao Date: Mon, 5 Feb 2018 16:13:26 +0800 Subject: [PATCH 151/156] Rename to pygennf_v9_dev.py --- src/{pygennf_v9_multi_threads.py => pygennf_v9_dev.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/{pygennf_v9_multi_threads.py => pygennf_v9_dev.py} (100%) diff --git a/src/pygennf_v9_multi_threads.py b/src/pygennf_v9_dev.py similarity index 100% rename from src/pygennf_v9_multi_threads.py rename to src/pygennf_v9_dev.py From fe176f592fba48d19b9f30a01b47a70b8bdf66aa Mon Sep 17 00:00:00 2001 From: szhao Date: Mon, 5 Feb 2018 16:16:12 +0800 Subject: [PATCH 152/156] Rename to pygennf_v9_dev.py --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index e9c85cf..cbd07e3 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ author_email="sheng.zhao@calix.com", url="https://github.com/9nehS/", license="AGPL", - scripts=["src/pygennf_v9.py", "src/pygennf_v9_multi_threads.py"], + scripts=["src/pygennf_v9.py", "src/pygennf_v9_dev.py"], packages=['rb_netflow', 'utils'], # packages=find_packages(), install_requires=[ From f764a24c313a29d3a6d022b14120e93c36aaf15d Mon Sep 17 00:00:00 2001 From: szhao Date: Mon, 5 Feb 2018 16:20:43 +0800 Subject: [PATCH 153/156] Rename to pygennf_v9_dev.py --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3b8ff58..2981570 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,9 @@ Netflow packets generator with Scapy library # Usage: - * pygennf_v9_multi_threads.py --help + * pygennf_v9_dev.py --help ->usage: pygennf_v9_multi_threads.py [-h] [-s SRC_IP] [-sp SRC_PORT] [-d DST_IP] +>usage: pygennf_v9_dev.py [-h] [-s SRC_IP] [-sp SRC_PORT] [-d DST_IP] > [-dp DST_PORT] [-t TIME_INTERVAL] > [-c PKT_COUNT] [-fd FLOWS_DATA] [-r] > [-ll {info,debug}] @@ -56,7 +56,7 @@ Netflow packets generator with Scapy library # Example of use: * Netflow 9 (CLI): -> pygennf_v9_multi_threads.py --source-ip 10.9.255.54 --dst-ip 10.9.255.118 --dst-port 2062 -t 1 -c 3600 -fd '69.31.102.10/32:12345:209.81.108.20/32:80:tcp:ingress:1024, 70.32.103.11/32:54321:210.81.108.21/32:21:udp:ingress:1024' +> pygennf_v9_dev.py --source-ip 10.9.255.54 --dst-ip 10.9.255.118 --dst-port 2062 -t 1 -c 3600 -fd '69.31.102.10/32:12345:209.81.108.20/32:80:tcp:ingress:1024, 70.32.103.11/32:54321:210.81.108.21/32:21:udp:ingress:1024' > > ![2017-09-30_console_snapshot_01.png](https://github.com/9nehS/pygennf/blob/master/resources/2017-09-30_console_snapshot_01.png) > From e8b933f5313a3e311719564b80de1f0de31cc590 Mon Sep 17 00:00:00 2001 From: szhao Date: Tue, 6 Feb 2018 10:20:11 +0800 Subject: [PATCH 154/156] Update help info --- src/pygennf_v9_dev.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pygennf_v9_dev.py b/src/pygennf_v9_dev.py index ffdd43b..d944ac1 100644 --- a/src/pygennf_v9_dev.py +++ b/src/pygennf_v9_dev.py @@ -47,9 +47,11 @@ @app.route('/pygennf/help') def help(): return jsonify( - # 'API (application/json)': 'PATH, notes ?org-id= currently required', {'Create sending task': '/pygennf/tasks/create', 'Check tasks status': '/pygennf/tasks/status', + 'List tasks details': '/pygennf/tasks/detail', + 'Stop the running tasks': '/pygennf/tasks/stop', + 'Clear tasks': '/pygennf/tasks/clear', 'Print help info': '/pygennf/help' }) From 25f5815400e781d1d980aebdee78cdebb9955378 Mon Sep 17 00:00:00 2001 From: szhao Date: Fri, 11 May 2018 16:43:26 +0800 Subject: [PATCH 155/156] Add snapshot for remote mode --- resources/2018-05-11_remote.png | Bin 0 -> 12316 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 resources/2018-05-11_remote.png diff --git a/resources/2018-05-11_remote.png b/resources/2018-05-11_remote.png new file mode 100644 index 0000000000000000000000000000000000000000..6006b73f935886372f5240476662cb7bbf04f263 GIT binary patch literal 12316 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 literal 0 HcmV?d00001 From 370e7cf46565ae931971730be9c3a21a49121339 Mon Sep 17 00:00:00 2001 From: szhao Date: Fri, 11 May 2018 16:45:46 +0800 Subject: [PATCH 156/156] Add remote part --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2981570..96167b1 100644 --- a/README.md +++ b/README.md @@ -62,4 +62,7 @@ Netflow packets generator with Scapy library > > ![2017-09-28_web_snapshot_01.png](https://github.com/9nehS/pygennf/blob/master/resources/2017-09-28_web_snapshot_01.png) > - * Netflow 9 (WebService): \ No newline at end of file + * Netflow 9 (WebService): +> pygennf_v9_dev.py --remote +> +> ![2018-05-11_remote.png](https://github.com/9nehS/pygennf/blob/master/resources/2018-05-11_remote.png) \ No newline at end of file