├── kmeans ├── __init__.py ├── default_clf.py └── kmeans_nsl.py ├── docs ├── sections │ ├── abstract.tex │ ├── conclusion.tex │ ├── introduce.tex │ ├── scikit.tex │ ├── flatbuffer.tex │ ├── data-mining.tex │ ├── experiment.tex │ ├── kmeans.tex │ ├── machine-learning.tex │ ├── nsl-kdd.tex │ └── ids.tex ├── cover.pdf ├── main.pdf ├── images │ ├── logo.png │ ├── nids.png │ ├── test1.png │ ├── test2.png │ ├── test3.png │ ├── test4.png │ ├── test5.png │ ├── test6.png │ ├── kmeans.png │ ├── scikit.png │ ├── server1.png │ ├── server2.png │ ├── server3.png │ ├── server4.png │ ├── server5.png │ ├── snort1.png │ ├── snort2.png │ ├── snort3.png │ ├── snort4.png │ ├── snort5.png │ ├── snort6.png │ ├── snort7.png │ ├── table1.png │ ├── table2.png │ ├── table3.png │ ├── table4.png │ ├── table5.png │ ├── table6.png │ ├── table7.png │ ├── table8.png │ ├── table9.png │ ├── workflow.png │ ├── snortver2.png │ ├── snortver3.png │ ├── data_mining.png │ ├── kmeans_detail1.png │ ├── kmeans_detail2.png │ ├── kmeans_detail3.png │ ├── kmeans_detail4.png │ ├── kmeans_detail5.png │ ├── kmeans_detail6.png │ ├── kmeans_detail7.png │ ├── kmeans_2_clusters.png │ └── reinforcement_learning.png └── main.tex ├── .vs └── slnx.sqlite ├── plugin ├── extractor │ ├── Conversation.h │ ├── types.h │ ├── UdpConversation.h │ ├── ReferenceCounter.cpp │ ├── IpReassemblyBufferHoleList.h │ ├── IpDatagram.h │ ├── StatsPerServiceWithSrcPort.h │ ├── IntervalKeeper.h │ ├── StatsEngine.cpp │ ├── StatsWindowTime.h │ ├── StatsWindowCount.h │ ├── TcpConnection.h │ ├── IntervalKeeper.cpp │ ├── IpFragment.h │ ├── IcmpConversation.h │ ├── StatsCollector.h │ ├── IpReassemblyBuffer.h │ ├── ReferenceCounter.h │ ├── StatsEngine.h │ ├── FeatureUpdaterTime.h │ ├── FeatureUpdaterCount.h │ ├── StatsPerService.h │ ├── UdpConversation.cpp │ ├── FeatureUpdater.h │ ├── Timestamp.h │ ├── StatsPerHost.h │ ├── FiveTuple.h │ ├── IcmpConversation.cpp │ ├── IpFragment.cpp │ ├── IpDatagram.cpp │ ├── FeatureUpdaterTime.cpp │ ├── FeatureUpdaterCount.cpp │ ├── StatsWindowCount.cpp │ ├── StatsPerService.cpp │ ├── ConversationReconstructor.h │ ├── StatsWindowTime.cpp │ ├── Packet.h │ ├── IpReassemblyBuffer.cpp │ ├── IpReassembler.h │ ├── StatsPerServiceWithSrcPort.cpp │ ├── FiveTuple.cpp │ ├── StatsPerHost.cpp │ ├── net.cpp │ ├── Timestamp.cpp │ ├── StatsWindow.h │ ├── Config.h │ ├── IpReassemblyBufferHoleList.cpp │ ├── StatsWindow.cpp │ ├── ConversationFeatures.h │ ├── net.h │ ├── IpReassembler.cpp │ ├── Config.cpp │ ├── Packet.cpp │ ├── ConversationReconstructor.cpp │ ├── Conversation.cpp │ └── ConversationFeatures.cpp ├── CMakeLists.txt ├── Dockerfile └── snort.lua ├── Dockerfile ├── docker-compose.yml ├── requirements.txt ├── README.md ├── LICENSE ├── packet.fbs ├── templates └── index.html ├── test_predict.py └── .gitignore /kmeans/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/sections/abstract.tex: -------------------------------------------------------------------------------- 1 | feafea -------------------------------------------------------------------------------- /docs/cover.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/cover.pdf -------------------------------------------------------------------------------- /docs/main.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/main.pdf -------------------------------------------------------------------------------- /.vs/slnx.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/.vs/slnx.sqlite -------------------------------------------------------------------------------- /docs/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/logo.png -------------------------------------------------------------------------------- /docs/images/nids.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/nids.png -------------------------------------------------------------------------------- /docs/images/test1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/test1.png -------------------------------------------------------------------------------- /docs/images/test2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/test2.png -------------------------------------------------------------------------------- /docs/images/test3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/test3.png -------------------------------------------------------------------------------- /docs/images/test4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/test4.png -------------------------------------------------------------------------------- /docs/images/test5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/test5.png -------------------------------------------------------------------------------- /docs/images/test6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/test6.png -------------------------------------------------------------------------------- /docs/images/kmeans.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/kmeans.png -------------------------------------------------------------------------------- /docs/images/scikit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/scikit.png -------------------------------------------------------------------------------- /docs/images/server1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/server1.png -------------------------------------------------------------------------------- /docs/images/server2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/server2.png -------------------------------------------------------------------------------- /docs/images/server3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/server3.png -------------------------------------------------------------------------------- /docs/images/server4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/server4.png -------------------------------------------------------------------------------- /docs/images/server5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/server5.png -------------------------------------------------------------------------------- /docs/images/snort1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/snort1.png -------------------------------------------------------------------------------- /docs/images/snort2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/snort2.png -------------------------------------------------------------------------------- /docs/images/snort3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/snort3.png -------------------------------------------------------------------------------- /docs/images/snort4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/snort4.png -------------------------------------------------------------------------------- /docs/images/snort5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/snort5.png -------------------------------------------------------------------------------- /docs/images/snort6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/snort6.png -------------------------------------------------------------------------------- /docs/images/snort7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/snort7.png -------------------------------------------------------------------------------- /docs/images/table1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/table1.png -------------------------------------------------------------------------------- /docs/images/table2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/table2.png -------------------------------------------------------------------------------- /docs/images/table3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/table3.png -------------------------------------------------------------------------------- /docs/images/table4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/table4.png -------------------------------------------------------------------------------- /docs/images/table5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/table5.png -------------------------------------------------------------------------------- /docs/images/table6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/table6.png -------------------------------------------------------------------------------- /docs/images/table7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/table7.png -------------------------------------------------------------------------------- /docs/images/table8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/table8.png -------------------------------------------------------------------------------- /docs/images/table9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/table9.png -------------------------------------------------------------------------------- /docs/images/workflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/workflow.png -------------------------------------------------------------------------------- /docs/images/snortver2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/snortver2.png -------------------------------------------------------------------------------- /docs/images/snortver3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/snortver3.png -------------------------------------------------------------------------------- /docs/images/data_mining.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/data_mining.png -------------------------------------------------------------------------------- /docs/images/kmeans_detail1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/kmeans_detail1.png -------------------------------------------------------------------------------- /docs/images/kmeans_detail2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/kmeans_detail2.png -------------------------------------------------------------------------------- /docs/images/kmeans_detail3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/kmeans_detail3.png -------------------------------------------------------------------------------- /docs/images/kmeans_detail4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/kmeans_detail4.png -------------------------------------------------------------------------------- /docs/images/kmeans_detail5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/kmeans_detail5.png -------------------------------------------------------------------------------- /docs/images/kmeans_detail6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/kmeans_detail6.png -------------------------------------------------------------------------------- /docs/images/kmeans_detail7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/kmeans_detail7.png -------------------------------------------------------------------------------- /plugin/extractor/Conversation.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/plugin/extractor/Conversation.h -------------------------------------------------------------------------------- /docs/images/kmeans_2_clusters.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/kmeans_2_clusters.png -------------------------------------------------------------------------------- /docs/images/reinforcement_learning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dthongvl/ids-machine-learning/HEAD/docs/images/reinforcement_learning.png -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:2.7 2 | 3 | ADD . /code 4 | WORKDIR code 5 | RUN pip install -r requirements.txt 6 | EXPOSE 5000 7 | CMD ["python", "main.py"] 8 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | predict-server: 4 | image: predict-server 5 | ports: 6 | - "5000:5000" 7 | snort: 8 | image: snort -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | numpy 2 | scipy 3 | scikit-learn 4 | pandas 5 | matplotlib 6 | ipython 7 | jupyter 8 | pandas 9 | sympy 10 | nose 11 | flask 12 | flatbuffers 13 | pytest 14 | Flask-Sockets -------------------------------------------------------------------------------- /plugin/extractor/types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define __STDC_LIMIT_MACROS 4 | #define __STDC_CONSTANT_MACROS 5 | #include 6 | 7 | #define __need_size_t 8 | #define __need_NULL 9 | #if __GNUC__ > 4 || \ 10 | (__GNUC__ == 4 && __GNUC_MINOR__ >= 9) 11 | #include 12 | #endif 13 | #include 14 | 15 | // nullptr is keyword from C++11 16 | #ifndef nullptr 17 | #define nullptr NULL 18 | #endif 19 | -------------------------------------------------------------------------------- /plugin/extractor/UdpConversation.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Conversation.h" 3 | 4 | namespace FeatureExtractor { 5 | 6 | /** 7 | * UDP conversation 8 | * Overrides default state transition behaviour in these points: 9 | * - service name is specific for TCP and dependent od destination port 10 | */ 11 | class UdpConversation : public Conversation 12 | { 13 | public: 14 | UdpConversation(); 15 | UdpConversation(const FiveTuple *tuple); 16 | UdpConversation(const Packet *packet); 17 | ~UdpConversation(); 18 | 19 | service_t get_service() const; 20 | }; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /plugin/extractor/ReferenceCounter.cpp: -------------------------------------------------------------------------------- 1 | #include "ReferenceCounter.h" 2 | #include 3 | 4 | 5 | namespace FeatureExtractor { 6 | ReferenceCounter::ReferenceCounter() 7 | : reference_count(0) 8 | { 9 | } 10 | 11 | 12 | void ReferenceCounter::register_reference() 13 | { 14 | reference_count++; 15 | } 16 | 17 | void ReferenceCounter::deregister_reference() 18 | { 19 | assert(reference_count > 0 && "Deregistering reference failed: no more registered references left!"); 20 | 21 | // If no more references, commit suicide (hahaha) 22 | if (!(reference_count--)) 23 | delete this; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /plugin/extractor/IpReassemblyBufferHoleList.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | 5 | namespace FeatureExtractor { 6 | class IpReassemblyBufferHoleList 7 | { 8 | /* 9 | * Hole descriptor in hole descriptor linked list 10 | */ 11 | class Hole { 12 | public: 13 | size_t start, end; 14 | Hole *next; 15 | Hole(); 16 | Hole(size_t first, size_t last, Hole *next); 17 | }; 18 | 19 | // Pointer to linked list 20 | Hole *first_hole; 21 | 22 | public: 23 | IpReassemblyBufferHoleList(); 24 | ~IpReassemblyBufferHoleList(); 25 | 26 | bool is_empty() const; 27 | void add_fragment(size_t start, size_t end, bool is_last_frag); 28 | }; 29 | 30 | } -------------------------------------------------------------------------------- /plugin/extractor/IpDatagram.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Packet.h" 4 | 5 | namespace FeatureExtractor { 6 | class IpDatagram : 7 | public Packet 8 | { 9 | Timestamp end_ts; 10 | uint16_t frame_count; 11 | public: 12 | IpDatagram(); 13 | IpDatagram(Packet const &packet); 14 | ~IpDatagram(); 15 | 16 | Timestamp get_end_ts() const; 17 | void set_end_ts(Timestamp &end_ts); // override 18 | 19 | uint16_t get_frame_count() const; 20 | void set_frame_count(uint16_t frame_count); 21 | void inc_frame_count(); 22 | 23 | /** 24 | * Output the class values (e.g. for debuging purposes) 25 | * overriden 26 | */ 27 | void print_human() const; 28 | }; 29 | } 30 | -------------------------------------------------------------------------------- /plugin/extractor/StatsPerServiceWithSrcPort.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "StatsPerService.h" 5 | 6 | namespace FeatureExtractor { 7 | using namespace std; 8 | 9 | class StatsPerServiceWithSrcPort : public StatsPerService 10 | { 11 | // 36: Number of conversations per each source port (33 split by source port) 12 | map same_src_port_counts; 13 | 14 | public: 15 | StatsPerServiceWithSrcPort(); 16 | StatsPerServiceWithSrcPort(FeatureUpdater *feature_updater); 17 | ~StatsPerServiceWithSrcPort(); 18 | 19 | void report_conversation_removal(const Conversation *conv); 20 | void report_new_conversation(ConversationFeatures *cf); 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /plugin/extractor/IntervalKeeper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | #include "Timestamp.h" 5 | 6 | namespace FeatureExtractor { 7 | /** 8 | * Interval watcher that is fed by timestamps representing current time 9 | * and "times out" after given interval (in ms) 10 | */ 11 | class IntervalKeeper 12 | { 13 | uint64_t interval; // in usec 14 | Timestamp last_ts; 15 | 16 | public: 17 | IntervalKeeper(); 18 | IntervalKeeper(uint64_t interval_ms); 19 | ~IntervalKeeper(); 20 | 21 | uint64_t get_interval() const; 22 | void set_interval(uint64_t interval_ms); 23 | 24 | void update_time(const Timestamp &ts); 25 | bool is_timedout(const Timestamp &now) const; 26 | }; 27 | } 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ids-machine-learning 2 | #### Create virtual environment 3 | ```bash 4 | pip install virtualenv 5 | virtualenv env 6 | ``` 7 | 8 | #### Active and install packages 9 | ```bash 10 | source env/bin/activate 11 | pip install -r requirements.txt 12 | ``` 13 | 14 | #### Run 15 | Build KMeans cluster and test accuracy 16 | 17 | ```bash 18 | python main.py 19 | ``` 20 | ./flatc --python packet.fbs 21 | #### Install LaTeX to build docs 22 | ```bash 23 | sudo apt install texlive-full 24 | ``` 25 | 26 | Datasets from: https://github.com/defcom17/NSL_KDD 27 | 28 | Code based on: https://github.com/AnomalyIDSBenchmark/KMeansNSL-KDD 29 | 30 | Feature Extractor from: https://github.com/AI-IDS/kdd99_feature_extractor -------------------------------------------------------------------------------- /plugin/extractor/StatsEngine.cpp: -------------------------------------------------------------------------------- 1 | #include "StatsEngine.h" 2 | 3 | 4 | namespace FeatureExtractor { 5 | StatsEngine::StatsEngine(const Config *config) 6 | : time_window(config->get_time_window_size_ms()) 7 | , count_window(config->get_count_window_size()) 8 | { 9 | } 10 | 11 | 12 | StatsEngine::~StatsEngine() 13 | { 14 | } 15 | 16 | ConversationFeatures *StatsEngine::calculate_features(Conversation *conv) 17 | { 18 | ConversationFeatures *cf = new ConversationFeatures(conv); 19 | 20 | // Set time window features & to time window 21 | time_window.add_conversation(cf); 22 | 23 | // Set count window features & to count window 24 | count_window.add_conversation(cf); 25 | 26 | return cf; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /plugin/extractor/StatsWindowTime.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "StatsWindow.h" 3 | 4 | namespace FeatureExtractor { 5 | /** 6 | * Statistics for time window 7 | */ 8 | template 9 | class StatsWindowTime : public StatsWindow 10 | { 11 | unsigned int window_size_ms; 12 | 13 | /** 14 | * Method performing window maintenance. 15 | * 16 | * Keeps the size of queue <= 100. Each time new conversation is added, the 17 | * oldest one is removed from windows. 18 | */ 19 | void perform_window_maintenance(const Conversation *new_conv); 20 | 21 | public: 22 | StatsWindowTime(); 23 | StatsWindowTime(unsigned int window_size_ms); 24 | ~StatsWindowTime(); 25 | }; 26 | } 27 | -------------------------------------------------------------------------------- /plugin/extractor/StatsWindowCount.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "StatsWindow.h" 3 | 4 | namespace FeatureExtractor { 5 | /** 6 | * Statistics window defined by number of connections 7 | */ 8 | template 9 | class StatsWindowCount : public StatsWindow 10 | { 11 | unsigned int window_size; 12 | 13 | /** 14 | * Method performing window maintenance. 15 | * 16 | * Keeps the size of queue <= 100. Each time new conversation is added, the 17 | * oldest one is removed from windows. 18 | */ 19 | void perform_window_maintenance(const Conversation *new_conv); 20 | 21 | public: 22 | StatsWindowCount(); 23 | StatsWindowCount(unsigned int window_size); 24 | ~StatsWindowCount(); 25 | }; 26 | } 27 | -------------------------------------------------------------------------------- /plugin/extractor/TcpConnection.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Conversation.h" 4 | 5 | namespace FeatureExtractor { 6 | /** 7 | * TCP Connection = specific conversation 8 | * Overrides default state transition behaviour in these points: 9 | * - state transition behaviour (employ all states for TCP) 10 | * - evaluates whether connection is finished depending on the state 11 | * - service name is specific for TCP and dependent od destination port 12 | */ 13 | class TcpConnection : public Conversation 14 | { 15 | virtual void update_state(const Packet *packet); 16 | 17 | public: 18 | TcpConnection(); 19 | TcpConnection(const FiveTuple *tuple); 20 | TcpConnection(const Packet *packet); 21 | ~TcpConnection(); 22 | 23 | bool is_in_final_state() const; 24 | service_t get_service() const; 25 | }; 26 | } 27 | 28 | -------------------------------------------------------------------------------- /plugin/extractor/IntervalKeeper.cpp: -------------------------------------------------------------------------------- 1 | #include "IntervalKeeper.h" 2 | 3 | 4 | namespace FeatureExtractor { 5 | IntervalKeeper::IntervalKeeper() 6 | :interval(0), last_ts() 7 | { 8 | } 9 | 10 | IntervalKeeper::IntervalKeeper(uint64_t interval_ms) 11 | : interval(interval_ms * 1000), last_ts() 12 | { 13 | } 14 | 15 | 16 | IntervalKeeper::~IntervalKeeper() 17 | { 18 | } 19 | 20 | 21 | uint64_t IntervalKeeper::get_interval() const 22 | { 23 | return interval / 1000; 24 | } 25 | 26 | void IntervalKeeper::set_interval(uint64_t interval_ms) 27 | { 28 | this->interval = interval_ms * 1000; 29 | } 30 | 31 | void IntervalKeeper::update_time(const Timestamp &ts) 32 | { 33 | last_ts = ts; 34 | } 35 | 36 | bool IntervalKeeper::is_timedout(const Timestamp &now) const 37 | { 38 | return (now >= last_ts + interval); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /plugin/extractor/IpFragment.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Packet.h" 4 | 5 | namespace FeatureExtractor { 6 | class IpFragment : 7 | public Packet 8 | { 9 | uint16_t ip_id; 10 | bool ip_flag_mf; 11 | uint16_t ip_frag_offset; 12 | size_t ip_payload_length; 13 | 14 | public: 15 | IpFragment(); 16 | ~IpFragment(); 17 | 18 | uint16_t get_ip_id() const; 19 | void set_ip_id(uint16_t ip_id); 20 | 21 | bool get_ip_flag_mf() const; 22 | void set_ip_flag_mf(bool ip_flag_mf); 23 | 24 | uint16_t get_ip_frag_offset() const; 25 | void set_ip_frag_offset(uint16_t ip_frag_offset); 26 | 27 | size_t get_ip_payload_length() const; 28 | void set_ip_payload_length(size_t ip_payload_length); 29 | 30 | /** 31 | * Output the class values (e.g. for debuging purposes) 32 | * overriden 33 | */ 34 | void print() const; 35 | }; 36 | } 37 | -------------------------------------------------------------------------------- /plugin/extractor/IcmpConversation.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Conversation.h" 3 | #include "net.h" 4 | 5 | namespace FeatureExtractor { 6 | 7 | /** 8 | * ICMP conversation 9 | * Overrides default state transition behaviour in these points: 10 | * - service name is specific for TCP and dependent on code and type fields in ICMP header 11 | */ 12 | class IcmpConversation : public Conversation 13 | { 14 | icmp_field_type_t icmp_type; 15 | uint8_t icmp_code; 16 | 17 | public: 18 | IcmpConversation(); 19 | IcmpConversation(const FiveTuple *tuple); 20 | IcmpConversation(const Packet *packet); 21 | ~IcmpConversation(); 22 | 23 | icmp_field_type_t get_icmp_type(); 24 | void set_icmp_type(icmp_field_type_t icmp_type); 25 | uint8_t get_icmp_code(); 26 | void get_icmp_code(uint8_t icmp_code); 27 | 28 | service_t get_service() const; 29 | }; 30 | } -------------------------------------------------------------------------------- /plugin/extractor/StatsCollector.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Conversation.h" 4 | #include "ConversationFeatures.h" 5 | 6 | namespace FeatureExtractor { 7 | /** 8 | * General interface for collecting statistics about specific conversations 9 | * (e.g. per host/service in one window) 10 | */ 11 | class StatsCollector 12 | { 13 | public: 14 | virtual ~StatsCollector() { }; 15 | 16 | /** 17 | * Notify statitics about conversation being removed from window 18 | */ 19 | virtual void report_conversation_removal(const Conversation *conv) = 0; 20 | 21 | /** 22 | * Notify statitics about new conversation being added to window 23 | */ 24 | virtual void report_new_conversation(ConversationFeatures *cf) = 0; 25 | 26 | /** 27 | * Checks whether the statistical collection is empty (e.g. count == 0) 28 | */ 29 | virtual bool is_empty() = 0; 30 | }; 31 | } 32 | 33 | -------------------------------------------------------------------------------- /plugin/extractor/IpReassemblyBuffer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "IpReassemblyBufferHoleList.h" 4 | #include "IpFragment.h" 5 | #include "IpDatagram.h" 6 | #include "Timestamp.h" 7 | 8 | namespace FeatureExtractor { 9 | /* 10 | * Reassembly buffer used to reassemble fragments of one original IP datagram. 11 | * Techniques to cope with IP fragmentation based od RFC 815. 12 | */ 13 | class IpReassemblyBuffer 14 | { 15 | // Hole descriptor list - initially one hole from 0 to "infinity" 16 | IpReassemblyBufferHoleList hole_list; 17 | 18 | IpDatagram *datagram; 19 | Timestamp first_frag_ts; 20 | Timestamp last_frag_ts; 21 | uint16_t frame_count; 22 | size_t total_length; 23 | 24 | public: 25 | IpReassemblyBuffer(); 26 | ~IpReassemblyBuffer(); 27 | 28 | Timestamp get_last_fragment_ts() const; 29 | 30 | IpDatagram *add_fragment(const IpFragment *fragment); 31 | }; 32 | } 33 | -------------------------------------------------------------------------------- /docs/sections/conclusion.tex: -------------------------------------------------------------------------------- 1 | \section{Nhận định} 2 | Nhóm vẫn chưa thể triển khai thành công hệ thống phát triển xâm nhập dựa trên kĩ thuật máy học, tuy nhiên 3 | nhóm đã hoàn thành được bộ khung hoạt động. Nhóm đã đút kết được nhiều kiến thức từ quá trình phát triển. 4 | \par 5 | Sử dụng thuật toán KMeans vẫn chưa mang lại độ chính xác cao, chỉ ở mức 74\%. Kèm theo đó, tập dữ liệu NSL-KDD đã cũ 6 | và khó có thể nhận biết được các hình thức tấn công mới. Khả năng hoạt động thực tế khi máy chủ dự đoán dùng Python 7 | vẫn còn khá chậm. 8 | \section{Hướng phát triển} 9 | \begin{itemize} 10 | \item Tăng tốc độ dự đoán và trả lời của máy chủ 11 | \item Cải thiện độ chính xác của mạng bằng các thuật toán khác hoặc kết hợp nhiều thuật toán. 12 | Ví dụ: Kmean kết hợp Random Forest. 13 | \item Sử dụng các tập dữ liệu mới và thực tế hơn. 14 | \item Cải thiện giao diện thống kê và các chức năng cảnh báo. 15 | \end{itemize} 16 | -------------------------------------------------------------------------------- /plugin/extractor/ReferenceCounter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace FeatureExtractor { 4 | /* 5 | * General implementation of reference counting 6 | * 7 | * Every instance can keep the number of references(pointers) to itself.If the this number 8 | * reaches zero after deregistering a reference, the object commits suicide(delete this). 9 | */ 10 | class ReferenceCounter 11 | { 12 | // Number of references (pointers) to this instance 13 | int reference_count; 14 | 15 | public: 16 | ReferenceCounter(); 17 | 18 | /** 19 | * Increment the number of references to this object 20 | */ 21 | void register_reference(); 22 | 23 | /** 24 | * Decrement the number of references to this object 25 | * If the number of references reaches 0, commit suicide (delete this). 26 | * 27 | * The calling object/function should not use reference to this object 28 | * after calling this method. 29 | */ 30 | void deregister_reference(); 31 | }; 32 | } 33 | -------------------------------------------------------------------------------- /plugin/extractor/StatsEngine.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "StatsWindowTime.h" 4 | #include "StatsWindowCount.h" 5 | #include "StatsPerHost.h" 6 | #include "StatsPerService.h" 7 | #include "StatsPerServiceWithSrcPort.h" 8 | #include "Config.h" 9 | 10 | namespace FeatureExtractor { 11 | /** 12 | * Statistical engine for computation of derived features 13 | */ 14 | class StatsEngine 15 | { 16 | StatsWindowTime time_window; 17 | StatsWindowCount count_window; 18 | 19 | public: 20 | StatsEngine(const Config *config); 21 | ~StatsEngine(); 22 | 23 | /** 24 | * Passes new conversation to statistical engine. Features for given 25 | * conversation are returned. 26 | * 27 | * Caller is responsible for deallocation of returned instance. Original 28 | * Conversation object should not be used after returned instance of class 29 | * ConversationFeatures was deallocated. 30 | */ 31 | ConversationFeatures *calculate_features(Conversation *conv); 32 | }; 33 | } 34 | -------------------------------------------------------------------------------- /plugin/extractor/FeatureUpdaterTime.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "FeatureUpdater.h" 3 | 4 | namespace FeatureExtractor { 5 | class FeatureUpdaterTime : public FeatureUpdater 6 | { 7 | public: 8 | virtual void set_count(ConversationFeatures * f, uint32_t count); 9 | virtual void set_srv_count(ConversationFeatures * f, uint32_t srv_count); 10 | virtual void set_serror_rate(ConversationFeatures * f, double serror_rate); 11 | virtual void set_srv_serror_rate(ConversationFeatures * f, double srv_serror_rate); 12 | virtual void set_rerror_rate(ConversationFeatures * f, double rerror_rate); 13 | virtual void set_srv_rerror_rate(ConversationFeatures * f, double srv_rerror_rate); 14 | virtual void set_same_srv_rate(ConversationFeatures * f, double same_srv_rate); 15 | virtual void set_diff_srv_rate(ConversationFeatures * f, double diff_srv_rate); 16 | virtual void set_dst_host_same_src_port_rate(ConversationFeatures * f, double dst_host_same_src_port_rate); 17 | virtual void set_same_srv_count(ConversationFeatures * f, uint32_t same_srv_count); 18 | }; 19 | } 20 | -------------------------------------------------------------------------------- /plugin/extractor/FeatureUpdaterCount.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "FeatureUpdater.h" 3 | 4 | namespace FeatureExtractor { 5 | class FeatureUpdaterCount : public FeatureUpdater 6 | { 7 | public: 8 | virtual void set_count(ConversationFeatures * f, uint32_t count); 9 | virtual void set_srv_count(ConversationFeatures * f, uint32_t srv_count); 10 | virtual void set_serror_rate(ConversationFeatures * f, double serror_rate); 11 | virtual void set_srv_serror_rate(ConversationFeatures * f, double srv_serror_rate); 12 | virtual void set_rerror_rate(ConversationFeatures * f, double rerror_rate); 13 | virtual void set_srv_rerror_rate(ConversationFeatures * f, double srv_rerror_rate); 14 | virtual void set_same_srv_rate(ConversationFeatures * f, double same_srv_rate); 15 | virtual void set_diff_srv_rate(ConversationFeatures * f, double diff_srv_rate); 16 | virtual void set_dst_host_same_src_port_rate(ConversationFeatures * f, double dst_host_same_src_port_rate); 17 | virtual void set_same_srv_count(ConversationFeatures * f, uint32_t same_srv_count); 18 | }; 19 | } 20 | 21 | -------------------------------------------------------------------------------- /plugin/extractor/StatsPerService.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | #include "StatsCollector.h" 5 | #include "FeatureUpdater.h" 6 | 7 | namespace FeatureExtractor { 8 | /** 9 | * Statistics per one service 10 | */ 11 | class StatsPerService : public StatsCollector 12 | { 13 | protected: 14 | FeatureUpdater *feature_updater; // Used to update features in ConversationFeatures object 15 | 16 | // 24/33: Number of conversations to same service 17 | uint32_t srv_count; 18 | 19 | // 26/39: Number of conversations that have activated the flag 20 | // S0, S1, S2 or S3 among conv. srv_in count (24/33s) 21 | uint32_t srv_serror_count; 22 | 23 | // 28/41: Number of conversations that have activated the flag REJ among 24 | // conv. in srv_count (24/33) 25 | uint32_t srv_rerror_count; 26 | 27 | public: 28 | StatsPerService(); 29 | StatsPerService(FeatureUpdater *feature_updater); 30 | virtual ~StatsPerService(); 31 | 32 | void report_conversation_removal(const Conversation *conv); 33 | void report_new_conversation(ConversationFeatures *cf); 34 | bool is_empty(); 35 | }; 36 | } 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 dthongvl 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /plugin/extractor/UdpConversation.cpp: -------------------------------------------------------------------------------- 1 | #include "UdpConversation.h" 2 | 3 | namespace FeatureExtractor { 4 | 5 | UdpConversation::UdpConversation() 6 | { 7 | } 8 | 9 | UdpConversation::UdpConversation(const FiveTuple *tuple) 10 | : Conversation(tuple) 11 | { 12 | } 13 | 14 | UdpConversation::UdpConversation(const Packet *packet) 15 | : Conversation(packet) 16 | { 17 | } 18 | 19 | 20 | UdpConversation::~UdpConversation() 21 | { 22 | } 23 | 24 | 25 | service_t UdpConversation::get_service() const 26 | { 27 | switch (five_tuple.get_dst_port()) 28 | { 29 | case 53: // DNS 30 | return SRV_DOMAIN_U; 31 | break; 32 | 33 | case 69: // TFTP 34 | return SRV_TFTP_U; 35 | break; 36 | 37 | case 123: // NTP 38 | return SRV_NTP_U; 39 | break; 40 | 41 | default: 42 | // Defined by IANA in RFC 6335 section 6: 43 | // the Dynamic Ports, also known as the Private or Ephemeral Ports, 44 | // from 49152 - 65535 (never assigned) 45 | if (five_tuple.get_dst_port() >= 49152) 46 | return SRV_PRIVATE; 47 | else 48 | return SRV_OTHER; 49 | break; 50 | } 51 | 52 | return SRV_OTHER; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /plugin/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required ( VERSION 3.4.3 ) 2 | project ( dpx CXX ) 3 | 4 | set (CMAKE_CXX_STANDARD 11) 5 | set (CMAKE_CXX_STANDARD_REQUIRED ON) 6 | set (CMAKE_CXX_EXTENSIONS OFF) 7 | 8 | if ( APPLE ) 9 | set ( CMAKE_MACOSX_RPATH OFF ) 10 | endif ( APPLE ) 11 | 12 | include ( FindPkgConfig ) 13 | pkg_search_module ( SNORT3 REQUIRED snort>=3 ) 14 | 15 | file(GLOB SOURCES 16 | "extractor/*.h" 17 | "extractor/*.cpp" 18 | ) 19 | 20 | add_library ( 21 | dpx MODULE 22 | dpx.cc 23 | ${SOURCES} 24 | ) 25 | 26 | target_link_libraries(dpx -lcurl) 27 | 28 | if ( APPLE ) 29 | set_target_properties ( 30 | dpx 31 | PROPERTIES 32 | LINK_FLAGS "-undefined dynamic_lookup" 33 | ) 34 | endif ( APPLE ) 35 | 36 | set_target_properties ( 37 | dpx 38 | PROPERTIES 39 | PREFIX "" 40 | ) 41 | 42 | target_include_directories ( 43 | dpx PUBLIC 44 | ${SNORT3_INCLUDE_DIRS} 45 | ) 46 | 47 | install ( 48 | TARGETS dpx 49 | LIBRARY 50 | DESTINATION "${CMAKE_INSTALL_LIBDIR}/${CMAKE_PROJECT_NAME}/inspectors" 51 | ) 52 | -------------------------------------------------------------------------------- /plugin/extractor/FeatureUpdater.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ConversationFeatures.h" 4 | 5 | namespace FeatureExtractor { 6 | /** 7 | * Interface for updating features. There are 2 subclasses for updating 8 | * either time or count window statistics. 9 | */ 10 | class FeatureUpdater 11 | { 12 | public: 13 | virtual void set_count(ConversationFeatures * f, uint32_t count) = 0; 14 | virtual void set_srv_count(ConversationFeatures * f, uint32_t srv_count) = 0; 15 | virtual void set_serror_rate(ConversationFeatures * f, double serror_rate) = 0; 16 | virtual void set_srv_serror_rate(ConversationFeatures * f, double srv_serror_rate) = 0; 17 | virtual void set_rerror_rate(ConversationFeatures * f, double rerror_rate) = 0; 18 | virtual void set_srv_rerror_rate(ConversationFeatures * f, double srv_rerror_rate) = 0; 19 | virtual void set_same_srv_rate(ConversationFeatures * f, double same_srv_rate) = 0; 20 | virtual void set_diff_srv_rate(ConversationFeatures * f, double diff_srv_rate) = 0; 21 | virtual void set_dst_host_same_src_port_rate(ConversationFeatures * f, double dst_host_same_src_port_rate) = 0; 22 | virtual void set_same_srv_count(ConversationFeatures * f, uint32_t same_srv_count) = 0; 23 | }; 24 | } -------------------------------------------------------------------------------- /packet.fbs: -------------------------------------------------------------------------------- 1 | namespace kmeans; 2 | 3 | table Packet { 4 | duration:int; 5 | protocol_type:string; 6 | service:string; 7 | flag:string; 8 | src_bytes:int; 9 | dst_bytes:int; 10 | land:int; 11 | wrong_fragment:int; 12 | urgent:int; 13 | hot:int; 14 | num_failed_logins:int; 15 | logged_in:int; 16 | num_compromised:int; 17 | root_shell:int; 18 | su_attempted:int; 19 | num_root:int; 20 | num_file_creations:int; 21 | num_shells:int; 22 | num_access_files:int; 23 | num_outbound_cmds:int; 24 | is_host_login:int; 25 | is_guest_login:int; 26 | count:int; 27 | srv_count:int; 28 | serror_rate:float; 29 | srv_serror_rate:float; 30 | rerror_rate:float; 31 | srv_rerror_rate:float; 32 | same_srv_rate:float; 33 | diff_srv_rate:float; 34 | srv_diff_host_rate:float; 35 | dst_host_count:int; 36 | dst_host_srv_count:int; 37 | dst_host_same_srv_rate:float; 38 | dst_host_diff_srv_rate:float; 39 | dst_host_same_src_port_rate:float; 40 | dst_host_srv_diff_host_rate:float; 41 | dst_host_serror_rate:float; 42 | dst_host_srv_serror_rate:float; 43 | dst_host_rerror_rate:float; 44 | dst_host_srv_rerror_rate:float; 45 | } 46 | 47 | root_type Packet; -------------------------------------------------------------------------------- /plugin/extractor/Timestamp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | // Bug in win WpdPack_4_1_2: On line 69 of pcap-stdinc.h, 'inline' is re-defined 5 | // http://www.winpcap.org/pipermail/winpcap-bugs/2013-November/001760.html 6 | // Solved by including pcap.h after standard libs 7 | #include 8 | 9 | namespace FeatureExtractor { 10 | /** 11 | * Wrapper class for timeval with aditional operations 12 | */ 13 | class Timestamp 14 | { 15 | struct timeval ts; 16 | 17 | public: 18 | Timestamp(); 19 | Timestamp(const struct timeval &ts); 20 | Timestamp(int64_t usecs); 21 | ~Timestamp(); 22 | 23 | struct timeval get_timeval() const; 24 | int64_t get_secs() const; 25 | int64_t get_usecs() const; 26 | int64_t get_total_usecs() const; 27 | int64_t get_total_msecs() const; 28 | 29 | bool operator==(const Timestamp &b) const; 30 | bool operator!=(const Timestamp &b) const; 31 | bool operator<(const Timestamp &b) const; 32 | bool operator>(const Timestamp &b) const; 33 | bool operator<=(const Timestamp &b) const; 34 | bool operator>=(const Timestamp &b) const; 35 | Timestamp operator+(const Timestamp &b) const; 36 | Timestamp operator-(const Timestamp &b) const; 37 | Timestamp operator+(int64_t b) const; // Add usecs 38 | Timestamp operator-(int64_t b) const; // Substract usecs 39 | }; 40 | } 41 | 42 | -------------------------------------------------------------------------------- /plugin/extractor/StatsPerHost.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | #include "StatsCollector.h" 5 | #include "FeatureUpdater.h" 6 | 7 | namespace FeatureExtractor { 8 | /** 9 | * Statistics per one host (IP address) 10 | */ 11 | class StatsPerHost : public StatsCollector 12 | { 13 | FeatureUpdater *feature_updater; // Used to update features in ConversationFeatures object 14 | 15 | // 23/32: Number of conversations to same destination IP 16 | uint32_t count; 17 | 18 | // 25/38: Number of conversations that have activated the flag 19 | // S0, S1, S2 or S3 among conv. in count (23/32) 20 | uint32_t serror_count; 21 | 22 | // 27/40: Number of conversations that have activated the flag REJ among 23 | // conv. in count (23/32) 24 | uint32_t rerror_count; 25 | 26 | // 29/34 : Number of conversations for each service (23/32 split by service) 27 | // Feature 30 can be derived from this: diff_srv_rate = (1 - same_srv_rate) 28 | // TODO: consider using map to save memory 29 | uint32_t same_srv_counts[NUMBER_OF_SERVICES]; 30 | 31 | public: 32 | StatsPerHost(FeatureUpdater *feature_updater); 33 | ~StatsPerHost(); 34 | 35 | void report_conversation_removal(const Conversation *conv); 36 | void report_new_conversation(ConversationFeatures *cf); 37 | bool is_empty(); 38 | 39 | }; 40 | } 41 | -------------------------------------------------------------------------------- /docs/sections/introduce.tex: -------------------------------------------------------------------------------- 1 | \section{Đề tài} 2 | Thiết kế và triển khai hệ thống phát hiện xâm nhập dựa trên kĩ thuật máy học 3 | \section{Đặt vấn đề} 4 | Ngày nay, mạng máy tính đang trở nên phổ biến hơn và được sử dụng rộng rãi trong hầu hết các lĩnh vực trên toàn thế giới. 5 | Tuy nhiên, đi kèm với sự phát triển và phổ biến của các mạng này là những rủi ro và thách thức liên quan đến chúng, đặc biệt là các vấn đề an ninh mạng và bảo mật dữ liệu. 6 | \par 7 | Theo Mạng lưới Bảo mật Việt Nam (VSEC), 70\% trang web ở Việt Nam có thể xâm nhập và 80\% hệ thống mạng có thể được kiểm soát bởi tin tặc. 8 | Trong văn bản này, sự phát triển của các hệ thống phát hiện xâm nhập (IDS) quan trọng hơn bao giờ hết, phát triển IDS trở nên phổ biến và đóng một vai trò vô cùng quan trọng trong bất kỳ chính sách, an ninh và an toàn nào của bất kỳ hệ thống thông tin nào. 9 | Đối với những điều đã đề cập ở trên, chúng tôi nghiên cứu về phát hiện xâm nhập và thuật toán K-means làm thuật toán phân cụm chính cho việc học máy. 10 | Ngoài thuật toán K-means, NSL-KDD là một tập dữ liệu hiệu quả được phát triển để giúp các nhà nghiên cứu so sánh các phương pháp phát hiện xâm nhập khác nhau. 11 | \section{Mục tiêu} 12 | Hệ thống ứng dụng IDS của chúng tôi được sử dụng làm bộ lọc, lưu lượng mạng được truyền qua bộ lọc của chúng tôi sẽ được phân tích và tính toán. 13 | Kết quả sẽ được báo cáo cho người giám sát nếu có bất thường về dữ liệu trong thời gian nhanh nhất, để giúp người giám sát kịp thời xử lý và ngăn chặn bất kỳ sự xâm nhập nào. 14 | -------------------------------------------------------------------------------- /plugin/extractor/FiveTuple.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "net.h" 4 | 5 | namespace FeatureExtractor { 6 | /** 7 | * 5-tuple identificator for conversation 8 | * 9 | */ 10 | class FiveTuple 11 | { 12 | ip_field_protocol_t ip_proto; 13 | uint32_t src_ip; 14 | uint32_t dst_ip; 15 | uint16_t src_port; 16 | uint16_t dst_port; 17 | 18 | public: 19 | FiveTuple(); 20 | ~FiveTuple(); 21 | 22 | ip_field_protocol_t get_ip_proto() const; 23 | void set_ip_proto(ip_field_protocol_t ip_proto); 24 | 25 | uint32_t get_src_ip() const; 26 | void set_src_ip(uint32_t src_ip); 27 | 28 | uint32_t get_dst_ip() const; 29 | void set_dst_ip(uint32_t dst_ip); 30 | 31 | uint16_t get_src_port() const; 32 | void set_src_port(uint16_t src_port); 33 | 34 | uint16_t get_dst_port() const; 35 | void set_dst_port(uint16_t dst_port); 36 | 37 | /** 38 | * Returns true if source endpoint (IP:port) is the same as destination 39 | */ 40 | bool land() const; 41 | 42 | /** 43 | * Less than operator - can be used for map<> keyoperator 44 | * Operator '<' is applied to field in this order: 45 | * 1. IP protocol 46 | * 2. Source IP 47 | * 3. Destination IP 48 | * 4. Source port 49 | * 5. Destionatio port 50 | */ 51 | bool operator<(const FiveTuple& other) const; 52 | 53 | /** 54 | * Creates 5-tuple with swapped source and destionation (IPs, ports) 55 | */ 56 | FiveTuple get_reversed() const; 57 | 58 | }; 59 | } 60 | -------------------------------------------------------------------------------- /plugin/extractor/IcmpConversation.cpp: -------------------------------------------------------------------------------- 1 | #include "IcmpConversation.h" 2 | 3 | namespace FeatureExtractor { 4 | 5 | IcmpConversation::IcmpConversation() 6 | : Conversation(), icmp_type(ECHOREPLY), icmp_code(0) 7 | { 8 | } 9 | 10 | IcmpConversation::IcmpConversation(const FiveTuple *tuple) 11 | : Conversation(tuple), icmp_type(ECHOREPLY), icmp_code(0) 12 | { 13 | } 14 | 15 | IcmpConversation::IcmpConversation(const Packet *packet) 16 | : Conversation(packet) 17 | , icmp_type(packet->get_icmp_type()) 18 | , icmp_code(packet->get_icmp_code()) 19 | { 20 | } 21 | 22 | 23 | IcmpConversation::~IcmpConversation() 24 | { 25 | } 26 | 27 | 28 | service_t IcmpConversation::get_service() const 29 | { 30 | switch (icmp_type) 31 | { 32 | case ECHOREPLY: 33 | return SRV_ECR_I; // Echo Reply (0) 34 | break; 35 | 36 | case DEST_UNREACH: 37 | if (icmp_code == 0) // Destination network unreachable 38 | return SRV_URP_I; 39 | else if (icmp_code == 1) // Destination host unreachable 40 | return SRV_URH_I; 41 | else 42 | return SRV_OTH_I; // Other ICMP messages; 43 | break; 44 | 45 | case REDIRECT: 46 | return SRV_RED_I; // Redirect message (5) 47 | break; 48 | 49 | case ECHO: 50 | return SRV_ECO_I; // Echo Request (8) 51 | break; 52 | 53 | case TIME_EXCEEDED: // Time Exceeded (11) 54 | return SRV_TIM_I; 55 | break; 56 | 57 | default: 58 | return SRV_OTH_I; // Other ICMP messages; 59 | break; 60 | } 61 | 62 | return SRV_OTH_I; // Other ICMP messages; 63 | } 64 | } -------------------------------------------------------------------------------- /plugin/extractor/IpFragment.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "IpFragment.h" 3 | 4 | namespace FeatureExtractor { 5 | using namespace std; 6 | 7 | IpFragment::IpFragment() 8 | : Packet() 9 | , ip_flag_mf(0), ip_frag_offset(0), ip_payload_length(0) 10 | { 11 | } 12 | 13 | 14 | IpFragment::~IpFragment() 15 | { 16 | 17 | } 18 | 19 | uint16_t IpFragment::get_ip_id() const 20 | { 21 | return ip_id; 22 | } 23 | 24 | void IpFragment::set_ip_id(uint16_t ip_id) 25 | { 26 | this->ip_id = ip_id; 27 | } 28 | 29 | bool IpFragment::get_ip_flag_mf() const 30 | { 31 | return ip_flag_mf; 32 | } 33 | 34 | void IpFragment::set_ip_flag_mf(bool ip_flag_mf) 35 | { 36 | this->ip_flag_mf = ip_flag_mf; 37 | } 38 | 39 | uint16_t IpFragment::get_ip_frag_offset() const 40 | { 41 | return ip_frag_offset; 42 | } 43 | 44 | void IpFragment::set_ip_frag_offset(uint16_t ip_frag_offset) 45 | { 46 | this->ip_frag_offset = ip_frag_offset; 47 | } 48 | 49 | size_t IpFragment::get_ip_payload_length() const 50 | { 51 | return ip_payload_length; 52 | } 53 | 54 | void IpFragment::set_ip_payload_length(size_t ip_payload_length) 55 | { 56 | this->ip_payload_length = ip_payload_length; 57 | } 58 | 59 | void IpFragment::print() const 60 | { 61 | Packet::print_human(); 62 | 63 | if (get_eth_type() == IPV4) { 64 | cout << " ip.flag_mf=" << get_ip_flag_mf() 65 | << ", ip.frag_offset=" << get_ip_frag_offset() 66 | << ", ip.id=0x" << hex << get_ip_id() << dec 67 | << ", payload_length=" << get_ip_payload_length() << endl; 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /plugin/extractor/IpDatagram.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "IpDatagram.h" 3 | 4 | 5 | namespace FeatureExtractor { 6 | using namespace std; 7 | 8 | IpDatagram::IpDatagram() 9 | : Packet(), end_ts(), frame_count(0) 10 | { 11 | } 12 | 13 | IpDatagram::IpDatagram(Packet const &packet) 14 | : Packet(packet), end_ts(), frame_count(0) 15 | { 16 | } 17 | 18 | 19 | IpDatagram::~IpDatagram() 20 | { 21 | } 22 | 23 | 24 | Timestamp IpDatagram::get_end_ts() const 25 | { 26 | return this->end_ts; 27 | } 28 | void IpDatagram::set_end_ts(Timestamp &end_ts) 29 | { 30 | this->end_ts = end_ts; 31 | } 32 | 33 | uint16_t IpDatagram::get_frame_count() const 34 | { 35 | return frame_count; 36 | } 37 | 38 | void IpDatagram::set_frame_count(uint16_t frame_count) 39 | { 40 | this->frame_count = frame_count; 41 | } 42 | 43 | 44 | void IpDatagram::inc_frame_count() 45 | { 46 | this->frame_count++; 47 | } 48 | 49 | // Allow using localtime instead of localtime_s 50 | #ifdef _MSC_VER 51 | #pragma warning(disable:4996) 52 | #endif 53 | void IpDatagram::print_human() const 54 | { 55 | Packet::print_human(); 56 | if (get_eth_type() == IPV4) { 57 | struct tm *ltime; 58 | //struct tm timeinfo; 59 | char timestr[16]; 60 | time_t local_tv_sec; 61 | local_tv_sec = end_ts.get_secs(); 62 | ltime = localtime(&local_tv_sec); 63 | //localtime_s(&timeinfo, &local_tv_sec); 64 | strftime(timestr, sizeof timestr, "%H:%M:%S", ltime); 65 | //strftime(timestr, sizeof timestr, "%H:%M:%S", &timeinfo); 66 | cout << " IP datagram end ts: " << timestr << endl; 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /plugin/extractor/FeatureUpdaterTime.cpp: -------------------------------------------------------------------------------- 1 | #include "FeatureUpdaterTime.h" 2 | 3 | 4 | namespace FeatureExtractor { 5 | void FeatureUpdaterTime::set_count(ConversationFeatures * f, uint32_t count) { 6 | f->set_count(count); 7 | } 8 | 9 | void FeatureUpdaterTime::set_srv_count(ConversationFeatures * f, uint32_t srv_count) { 10 | f->set_srv_count(srv_count); 11 | } 12 | 13 | void FeatureUpdaterTime::set_serror_rate(ConversationFeatures * f, double serror_rate) { 14 | f->set_serror_rate(serror_rate); 15 | } 16 | 17 | void FeatureUpdaterTime::set_srv_serror_rate(ConversationFeatures * f, double srv_serror_rate) { 18 | f->set_srv_serror_rate(srv_serror_rate); 19 | } 20 | 21 | void FeatureUpdaterTime::set_rerror_rate(ConversationFeatures * f, double rerror_rate) { 22 | f->set_rerror_rate(rerror_rate); 23 | } 24 | 25 | void FeatureUpdaterTime::set_srv_rerror_rate(ConversationFeatures * f, double srv_rerror_rate) { 26 | f->set_srv_rerror_rate(srv_rerror_rate); 27 | } 28 | 29 | void FeatureUpdaterTime::set_same_srv_rate(ConversationFeatures * f, double same_srv_rate) { 30 | f->set_same_srv_rate(same_srv_rate); 31 | } 32 | 33 | void FeatureUpdaterTime::set_diff_srv_rate(ConversationFeatures * f, double diff_srv_rate) { 34 | f->set_diff_srv_rate(diff_srv_rate); 35 | } 36 | 37 | void FeatureUpdaterTime::set_dst_host_same_src_port_rate(ConversationFeatures * f, double dst_host_same_src_port_rate) { 38 | // Do nothing - no such feature for time window 39 | } 40 | 41 | void FeatureUpdaterTime::set_same_srv_count(ConversationFeatures * f, uint32_t same_srv_count) { 42 | f->set_same_srv_count(same_srv_count); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /plugin/extractor/FeatureUpdaterCount.cpp: -------------------------------------------------------------------------------- 1 | #include "FeatureUpdaterCount.h" 2 | 3 | 4 | namespace FeatureExtractor { 5 | void FeatureUpdaterCount::set_count(ConversationFeatures * f, uint32_t count) { 6 | f->set_dst_host_count(count); 7 | } 8 | 9 | void FeatureUpdaterCount::set_srv_count(ConversationFeatures * f, uint32_t srv_count) { 10 | f->set_dst_host_srv_count(srv_count); 11 | } 12 | 13 | void FeatureUpdaterCount::set_serror_rate(ConversationFeatures * f, double serror_rate) { 14 | f->set_dst_host_serror_rate(serror_rate); 15 | } 16 | 17 | void FeatureUpdaterCount::set_srv_serror_rate(ConversationFeatures * f, double srv_serror_rate) { 18 | f->set_dst_host_srv_serror_rate(srv_serror_rate); 19 | } 20 | 21 | void FeatureUpdaterCount::set_rerror_rate(ConversationFeatures * f, double rerror_rate) { 22 | f->set_dst_host_rerror_rate(rerror_rate); 23 | } 24 | 25 | void FeatureUpdaterCount::set_srv_rerror_rate(ConversationFeatures * f, double srv_rerror_rate) { 26 | f->set_dst_host_srv_rerror_rate(srv_rerror_rate); 27 | } 28 | 29 | void FeatureUpdaterCount::set_same_srv_rate(ConversationFeatures * f, double same_srv_rate) { 30 | f->set_dst_host_same_srv_rate(same_srv_rate); 31 | } 32 | 33 | void FeatureUpdaterCount::set_diff_srv_rate(ConversationFeatures * f, double diff_srv_rate) { 34 | f->set_dst_host_diff_srv_rate(diff_srv_rate); 35 | } 36 | 37 | void FeatureUpdaterCount::set_dst_host_same_src_port_rate(ConversationFeatures * f, double dst_host_same_src_port_rate) { 38 | f->set_dst_host_same_src_port_rate(dst_host_same_src_port_rate); 39 | } 40 | 41 | void FeatureUpdaterCount::set_same_srv_count(ConversationFeatures * f, uint32_t same_srv_count) { 42 | f->set_dst_host_same_srv_count(same_srv_count); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /plugin/extractor/StatsWindowCount.cpp: -------------------------------------------------------------------------------- 1 | #include "StatsWindowCount.h" 2 | #include "StatsPerHost.h" 3 | #include "StatsPerService.h" 4 | #include "StatsPerServiceWithSrcPort.h" 5 | #include "FeatureUpdaterCount.h" 6 | 7 | 8 | namespace FeatureExtractor { 9 | template 10 | StatsWindowCount::StatsWindowCount() 11 | : StatsWindow(new FeatureUpdaterCount()) 12 | , window_size(100) // Default size = 100 conversations 13 | { 14 | } 15 | 16 | template 17 | StatsWindowCount::StatsWindowCount(unsigned int window_size) 18 | : StatsWindow(new FeatureUpdaterCount()) 19 | , window_size(window_size) 20 | { 21 | } 22 | 23 | template 24 | StatsWindowCount::~StatsWindowCount() 25 | { 26 | } 27 | 28 | 29 | template 30 | void StatsWindowCount::perform_window_maintenance(const Conversation *new_conv) 31 | { 32 | while (this->finished_convs.size() > window_size) { 33 | Conversation *conv = this->finished_convs.front(); 34 | this->finished_convs.pop(); 35 | 36 | // Exclude removed conversation from stats 37 | this->report_conversation_removal(conv); 38 | 39 | // Object commits suicide if no more references to it 40 | conv->deregister_reference(); 41 | } 42 | } 43 | 44 | // Explicit template specialisation 45 | template class StatsWindowCount; 46 | template class StatsWindowCount; 47 | } 48 | -------------------------------------------------------------------------------- /plugin/extractor/StatsPerService.cpp: -------------------------------------------------------------------------------- 1 | #include "StatsPerService.h" 2 | 3 | namespace FeatureExtractor { 4 | StatsPerService::StatsPerService() 5 | : feature_updater(nullptr) 6 | , srv_count(0), srv_serror_count(0), srv_rerror_count(0) 7 | { 8 | } 9 | 10 | StatsPerService::StatsPerService(FeatureUpdater *feature_updater) 11 | : feature_updater(feature_updater) 12 | , srv_count(0), srv_serror_count(0), srv_rerror_count(0) 13 | { 14 | } 15 | 16 | 17 | StatsPerService::~StatsPerService() 18 | { 19 | } 20 | 21 | void StatsPerService::report_conversation_removal(const Conversation *conv) 22 | { 23 | srv_count--; 24 | 25 | // SYN error 26 | if (conv->is_serror()) 27 | srv_serror_count--; 28 | 29 | // REJ error 30 | if (conv->is_rerror()) 31 | srv_rerror_count--; 32 | } 33 | 34 | void StatsPerService::report_new_conversation(ConversationFeatures *cf) 35 | { 36 | const Conversation *conv = cf->get_conversation(); 37 | 38 | /* 39 | * Set derived window features based on previous conversations in window 40 | */ 41 | // Feature 24 42 | feature_updater->set_srv_count(cf, srv_count); 43 | 44 | // Feature 26 45 | double srv_serror_rate = (srv_count == 0) ? 0.0 : (srv_serror_count / (double)srv_count); 46 | feature_updater->set_srv_serror_rate(cf, srv_serror_rate); 47 | 48 | // Feature 28 49 | double srv_rerror_rate = (srv_count == 0) ? 0.0 : (srv_rerror_count / (double)srv_count); 50 | feature_updater->set_srv_rerror_rate(cf, srv_rerror_rate); 51 | 52 | /* 53 | * Include new conversation to stats 54 | */ 55 | srv_count++; 56 | 57 | // SYN error 58 | if (conv->is_serror()) 59 | srv_serror_count++; 60 | 61 | // REJ error 62 | if (conv->is_rerror()) 63 | srv_rerror_count++; 64 | } 65 | 66 | bool StatsPerService::is_empty() 67 | { 68 | return (srv_count == 0); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /docs/sections/scikit.tex: -------------------------------------------------------------------------------- 1 | \subsection{Giới thiệu} 2 | \textbf{Scikit-learn} (viết tắt là \textbf{sklearn}) là một thư viện mã nguồn mở trong ngành machine learning, 3 | rất mạnh mẽ và thông dụng với cộng đồng Python, được thiết kế trên nền NumPy và SciPy. 4 | Scikit-learn chứa hầu hết các thuật toán machine learning hiện đại nhất, 5 | đi kèm với comprehensive documentations. Điểm mạnh của thư viện này là nó được sử dụng phổ biến trong giáo dục và công nghiệp, 6 | do đó nó luôn được cập nhật và có một cộng đồng người dùng đông đảo. 7 | \begin{figure}[!htbp] 8 | \centering 9 | \includegraphics[scale=0.5]{scikit} 10 | \caption{Scikit} 11 | \label{fig:x cubed graph} 12 | \end{figure} 13 | \FloatBarrier 14 | \subsection{Tại sao nên dùng Scikit?} 15 | Hiện nay có nhiều thư viện mã nguồn mở phục vụ cho nghiên cứu machine learning. Bên cạnh Scikit-learn, có 2 thư viện nổi bật khác là 16 | \begin{itemize} 17 | \item \textbf{LibSVM}: Được viết trên C bởi Chih-Chung Chang và Chih-Jen Lin. Như tên gọi của nó, thư viên này chứa các thuật toán SVM (Support Vector Machine), nhóm thuật toán mạnh mẽ hỗ trợ cả các tác vụ regression và classification. 18 | \item \textbf{TensorFlows}: Do các nhà khoa học của viện nghiên cứu Google Brain phát triển. TensorFlows được viết trên Python và là thư viện mở. 19 | \end{itemize} 20 | Trong khi TensorFlows có vẻ ở mức độ tiếp cận thấp hơn hơn thì Scikit-learn cho phép ta sử dụng ngay các thuật toán quan trọng một cách đơn giản và hiệu quả. 21 | Nói vậy không có nghĩa Scikit-learn là một thư viện “nông cạn”, Scikit-learn là nền tảng để xây dựng các ML implementations khác (Nilearn, Pylearn2,…). 22 | Scikit-learn còn là một trong những lựa chọn hàng đầu của các nhà nghiên cứu và phát triển. Đứng sau Scikit-learn là các viện nghiên cứu hàng đầu thế giới, gồm có Inria, Télécom Paristech, Paris-Saclay (Pháp), NYU Moore-Sloan Data Science Environment và Columbia University. -------------------------------------------------------------------------------- /plugin/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:18.04 2 | 3 | # Install dependecies 4 | RUN apt update 5 | RUN apt install -y build-essential autotools-dev libdumbnet-dev libluajit-5.1-dev libpcap-dev libpcre3-dev zlib1g-dev pkg-config libhwloc-dev cmake 6 | RUN apt install -y liblzma-dev openssl libssl-dev cpputest libsqlite3-dev 7 | RUN apt install -y libtool git autoconf 8 | RUN apt install -y bison flex wget libcurl4-openssl-dev 9 | 10 | # Install daq 11 | RUN wget https://www.snort.org/downloads/snortplus/daq-2.2.2.tar.gz 12 | RUN tar -xvzf daq-2.2.2.tar.gz 13 | RUN cd daq-2.2.2 && ./configure && make && make install 14 | 15 | # Install flatbuffer 16 | RUN wget -O flatbuffers.tar.gz https://github.com/google/flatbuffers/archive/master.tar.gz 17 | RUN tar -xzvf flatbuffers.tar.gz 18 | RUN cd flatbuffers-master && cmake -G "Unix Makefiles" && make && make install 19 | 20 | # Install snort 21 | RUN wget -O snort3.tar.gz https://github.com/snort3/snort3/archive/master.tar.gz 22 | RUN tar -xvzf snort3.tar.gz 23 | RUN ldconfig 24 | RUN cd snort3-master && ./configure_cmake.sh --prefix=/opt/snort && cd build && make -j $(nproc) install 25 | RUN ln -s /opt/snort/bin/snort /usr/sbin/snort 26 | 27 | # Install plugin 28 | RUN wget -O snort3_extra.tar.gz https://github.com/snort3/snort3_extra/archive/master.tar.gz 29 | RUN tar -xzvf snort3_extra.tar.gz 30 | ADD extractor snort3_extra-master/src/inspectors/dpx/extractor 31 | ADD CMakeLists.txt dpx.cc packet_generated.h snort3_extra-master/src/inspectors/dpx/ 32 | RUN export PKG_CONFIG_PATH=/opt/snort/lib/pkgconfig/ && cd snort3_extra-master && ./configure_cmake.sh --prefix=/opt/snort && cd build && make && make install 33 | 34 | # Enable plugin 35 | ADD snort.lua /opt/snort/etc/snort/snort.lua 36 | ENV LUA_PATH /opt/snort/include/snort/lua/\?.lua\;\; 37 | ENV SNORT_LUA_PATH /opt/snort/etc/snort 38 | 39 | ENTRYPOINT [ "snort", "-c", "/opt/snort/etc/snort/snort.lua", "--plugin-path", "/opt/snort/lib/snort_extra/", "-i", "eth0" ] -------------------------------------------------------------------------------- /plugin/extractor/ConversationReconstructor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "net.h" 6 | #include "Packet.h" 7 | #include "Conversation.h" 8 | #include "Config.h" 9 | #include "IntervalKeeper.h" 10 | 11 | namespace FeatureExtractor { 12 | using namespace std; 13 | 14 | /** 15 | * Engine for identification and reconstruction of conversations from IP datagrams/packets 16 | */ 17 | class ConversationReconstructor 18 | { 19 | typedef map ConversationMap; 20 | ConversationMap conv_map; 21 | 22 | 23 | // Queue of reconstructed conversations prepared to output 24 | queueoutput_queue; 25 | 26 | // Timeout values & timeout check interval 27 | Config timeouts; 28 | IntervalKeeper timeout_interval; 29 | 30 | /** 31 | * Removes timed out reassembly buffers - "drops incomplete datagrams" 32 | */ 33 | void check_timeouts(const Timestamp &now); 34 | public: 35 | ConversationReconstructor(); 36 | ConversationReconstructor(Config &timeouts); 37 | ~ConversationReconstructor(); 38 | 39 | /** 40 | * Send next packet to conversation reconstruction engine 41 | */ 42 | void add_packet(const Packet *packet); 43 | 44 | /** 45 | * When no new packets, time can be reported to timeout old connections 46 | */ 47 | void report_time(const Timestamp &now); 48 | 49 | /** 50 | * Returns next reconstructed conversation from internal queue of finished conversation. 51 | * 52 | * Conversations are returned in order the ended (sorted by the timestamp 53 | * of their last packet). 54 | * If the queueis empty nullptr is returned. 55 | * Caller must take care of deallocation of returned object. 56 | */ 57 | Conversation *get_next_conversation(); 58 | 59 | /** 60 | * Places timeout on all active conversations 61 | * Can be used to get unfinished conversations when no more traffic available 62 | */ 63 | void finish_all_conversations(); 64 | }; 65 | } 66 | 67 | -------------------------------------------------------------------------------- /plugin/extractor/StatsWindowTime.cpp: -------------------------------------------------------------------------------- 1 | #include "StatsWindowTime.h" 2 | #include "StatsPerHost.h" 3 | #include "StatsPerService.h" 4 | #include "StatsPerServiceWithSrcPort.h" 5 | #include "FeatureUpdaterTime.h" 6 | 7 | 8 | namespace FeatureExtractor { 9 | template 10 | StatsWindowTime::StatsWindowTime() 11 | : StatsWindow(new FeatureUpdaterTime()) 12 | , window_size_ms(2000) // Default size = 2 sec. 13 | { 14 | } 15 | 16 | template 17 | StatsWindowTime::StatsWindowTime(unsigned int window_size_ms) 18 | : StatsWindow(new FeatureUpdaterTime()) 19 | , window_size_ms(window_size_ms) 20 | { 21 | } 22 | 23 | template 24 | StatsWindowTime::~StatsWindowTime() 25 | { 26 | } 27 | 28 | template 29 | void StatsWindowTime::perform_window_maintenance(const Conversation *new_conv) 30 | { 31 | Timestamp now = new_conv->get_last_ts(); 32 | Timestamp max_delete_ts = now - (window_size_ms * 1000); // Substract usecs 33 | 34 | // Delete all conversations with last timestamp <= max_delete_ts 35 | while (!this->finished_convs.empty() && this->finished_convs.front()->get_last_ts() <= max_delete_ts) { 36 | Conversation *conv = this->finished_convs.front(); 37 | this->finished_convs.pop(); 38 | 39 | // Exclude removed conversation from stats 40 | this->report_conversation_removal(conv); 41 | 42 | // Object commits suicide if no more references to it 43 | conv->deregister_reference(); 44 | } 45 | } 46 | 47 | 48 | // Explicit template specialisation 49 | template class StatsWindowTime; 50 | template class StatsWindowTime; 51 | } 52 | -------------------------------------------------------------------------------- /plugin/extractor/Packet.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "net.h" 4 | #include "Timestamp.h" 5 | #include "FiveTuple.h" 6 | 7 | namespace FeatureExtractor { 8 | /** 9 | * Abstract Packet 10 | */ 11 | class Packet 12 | { 13 | Timestamp start_ts; 14 | bool eth2; 15 | eth_field_type_t eth_type; 16 | 17 | // 18 | FiveTuple five_tuple; 19 | 20 | tcp_field_flags_t tcp_flags; 21 | icmp_field_type_t icmp_type; 22 | uint8_t icmp_code; 23 | size_t length; 24 | 25 | public: 26 | Packet(); 27 | virtual ~Packet(); 28 | 29 | Timestamp get_start_ts() const; 30 | void set_start_ts(const Timestamp &start_ts); 31 | virtual Timestamp get_end_ts() const; 32 | 33 | bool is_eth2() const; 34 | void set_eth2(bool is_eth2); 35 | 36 | eth_field_type_t get_eth_type() const; 37 | void set_eth_type(eth_field_type_t eth_type); 38 | 39 | ip_field_protocol_t get_ip_proto() const; 40 | void set_ip_proto(ip_field_protocol_t ip_proto); 41 | 42 | FiveTuple get_five_tuple() const; 43 | void set_five_tuple(const FiveTuple &five_tuple); 44 | 45 | uint32_t get_src_ip() const; 46 | void set_src_ip(uint32_t src_ip); 47 | 48 | uint32_t get_dst_ip() const; 49 | void set_dst_ip(uint32_t dst_ip); 50 | 51 | uint16_t get_src_port() const; 52 | void set_src_port(uint16_t src_port); 53 | 54 | uint16_t get_dst_port() const; 55 | void set_dst_port(uint16_t dst_port); 56 | 57 | tcp_field_flags_t get_tcp_flags() const; 58 | void set_tcp_flags(tcp_field_flags_t tcp_flags); 59 | 60 | icmp_field_type_t get_icmp_type() const; 61 | void set_icmp_type(icmp_field_type_t icmp_type); 62 | 63 | uint8_t get_icmp_code() const; 64 | void set_icmp_code(uint8_t icmp_code); 65 | 66 | virtual size_t get_length() const; 67 | virtual void set_length(size_t length); 68 | 69 | virtual uint16_t get_frame_count() const; 70 | 71 | /** 72 | * Output the class values (e.g. for debuging purposes) 73 | */ 74 | virtual void print_human() const; 75 | 76 | }; 77 | 78 | } -------------------------------------------------------------------------------- /plugin/extractor/IpReassemblyBuffer.cpp: -------------------------------------------------------------------------------- 1 | #include "IpReassemblyBuffer.h" 2 | #include 3 | 4 | namespace FeatureExtractor { 5 | using namespace std; 6 | 7 | IpReassemblyBuffer::IpReassemblyBuffer() 8 | : datagram(nullptr), first_frag_ts(), last_frag_ts() 9 | , frame_count(0), total_length(0) 10 | { 11 | } 12 | 13 | 14 | IpReassemblyBuffer::~IpReassemblyBuffer() 15 | { 16 | // Datagram is returned by calling method add_fragment() or& must be deallocated by caller 17 | } 18 | 19 | Timestamp IpReassemblyBuffer::get_last_fragment_ts() const 20 | { 21 | return last_frag_ts; 22 | } 23 | 24 | IpDatagram *IpReassemblyBuffer::add_fragment(const IpFragment *frag) 25 | { 26 | // If first fragment (by order in datagram) received for the first time, 27 | // create datagram with its values 28 | if (!datagram && frag->get_ip_frag_offset() == 0) { 29 | datagram = new IpDatagram(*frag); 30 | } 31 | 32 | // Timestamps, fragment/frame count & total_length of datagram 33 | if (frame_count == 0) 34 | first_frag_ts = frag->get_start_ts(); 35 | last_frag_ts = frag->get_start_ts(); 36 | frame_count++; 37 | total_length += frag->get_length(); 38 | 39 | // Flag MF = 0 only if last fragment 40 | bool is_last_frag = !frag->get_ip_flag_mf(); 41 | size_t frag_start = frag->get_ip_frag_offset(); 42 | size_t frag_end = frag_start + frag->get_ip_payload_length() - 1; 43 | 44 | // Fill holes with new fragment 45 | hole_list.add_fragment(frag_start, frag_end, is_last_frag); 46 | 47 | // If no hole left IP datagram is reassembled 48 | if (hole_list.is_empty()) { 49 | assert(datagram != nullptr && "IP reassebly failed: NULL datagram"); 50 | 51 | // Update timestamps, frame count & length 52 | datagram->set_start_ts(first_frag_ts); 53 | datagram->set_end_ts(last_frag_ts); 54 | datagram->set_frame_count(frame_count); 55 | datagram->set_length(total_length); 56 | 57 | // Caller should take care of destroying the datagram object 58 | IpDatagram *ret = datagram; 59 | datagram = nullptr; 60 | 61 | return ret; 62 | } 63 | 64 | return nullptr; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /plugin/extractor/IpReassembler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "IpReassemblyBuffer.h" 5 | #include "IpFragment.h" 6 | #include "IntervalKeeper.h" 7 | #include "Config.h" 8 | 9 | namespace FeatureExtractor { 10 | using namespace std; 11 | 12 | /* 13 | * IP Reassembly 14 | * Techniques to cope with IP fragmentation based od RFC 815 15 | */ 16 | class IpReassembler 17 | { 18 | /** 19 | * Reassembly buffer identification (key for map) 20 | * RFC 815 Section 7: 21 | * The correct reassembly buffer is identified by an equality of the following 22 | * fields: the foreign and local internet address, the protocol ID, 23 | * and the identification field. 24 | */ 25 | class IpReassemblyBufferKey { 26 | uint32_t src; 27 | uint32_t dst; 28 | ip_field_protocol_t proto; 29 | uint16_t id; 30 | public: 31 | IpReassemblyBufferKey(); 32 | IpReassemblyBufferKey(const IpFragment *fragment); 33 | bool operator<(const IpReassemblyBufferKey& other) const; // Required for map<> key 34 | }; 35 | 36 | // IP Reassembly buffers 37 | typedef map BufferMap; 38 | BufferMap buffer_map; 39 | 40 | // Timeout values & timeout check interval 41 | Config timeouts; 42 | IntervalKeeper timeout_interval; 43 | 44 | /** 45 | * Forwards fragment of fragmented datagram to correct buffer for reassembly. 46 | * 47 | * If reassembly is completed, datagram is returned. Otherwise the return 48 | * values is nullptr. 49 | */ 50 | IpDatagram *forward_to_buffer(IpFragment *fragment); 51 | 52 | /** 53 | * Removes timed out reassembly buffers - "drops incomplete datagrams" 54 | */ 55 | void check_timeouts(const Timestamp &now); 56 | 57 | public: 58 | IpReassembler(); 59 | IpReassembler(Config &timeouts); 60 | ~IpReassembler(); 61 | 62 | /** 63 | * Pass fragment to IP reassembler. 64 | * 65 | * If new datagram/packet is successfully reassembled, it is returned. 66 | * Otherwise nullpter is returned. 67 | * IpFragment object passed by pointer might be deleted after reassembly, 68 | * thus it must not be used after this call. Caller must take care 69 | * of erasing the returned object. 70 | */ 71 | Packet *reassemble(IpFragment *fragment); 72 | }; 73 | } 74 | 75 | -------------------------------------------------------------------------------- /plugin/extractor/StatsPerServiceWithSrcPort.cpp: -------------------------------------------------------------------------------- 1 | #include "StatsPerServiceWithSrcPort.h" 2 | #include 3 | 4 | namespace FeatureExtractor { 5 | 6 | StatsPerServiceWithSrcPort::StatsPerServiceWithSrcPort() 7 | : StatsPerService() 8 | , same_src_port_counts() // zero-initialize 9 | { 10 | } 11 | 12 | StatsPerServiceWithSrcPort::StatsPerServiceWithSrcPort(FeatureUpdater *feature_updater) 13 | : StatsPerService(feature_updater) 14 | , same_src_port_counts() // zero-initialize 15 | { 16 | } 17 | 18 | 19 | StatsPerServiceWithSrcPort::~StatsPerServiceWithSrcPort() 20 | { 21 | } 22 | 23 | void StatsPerServiceWithSrcPort::report_conversation_removal(const Conversation *conv) 24 | { 25 | StatsPerService::report_conversation_removal(conv); 26 | 27 | uint16_t src_port = conv->get_five_tuple_ptr()->get_src_port(); 28 | 29 | // Find the conversation count for source port number & decrement 30 | map::iterator it = same_src_port_counts.find(src_port); 31 | assert(it != same_src_port_counts.end() && "Stats: reporting removal of non-existing source port"); 32 | it->second--; 33 | 34 | // Remove from list if no conversation for given src port left 35 | if (it->second == 0) { 36 | same_src_port_counts.erase(it); 37 | } 38 | } 39 | 40 | void StatsPerServiceWithSrcPort::report_new_conversation(ConversationFeatures *cf) 41 | { 42 | StatsPerService::report_new_conversation(cf); 43 | 44 | uint16_t src_port = cf->get_conversation()->get_five_tuple_ptr()->get_src_port(); 45 | uint32_t value; 46 | 47 | 48 | // Find or insert conversation count 49 | // with single lookup http://stackoverflow.com/a/101980/3503528 50 | map::iterator it = same_src_port_counts.lower_bound(src_port); 51 | if (it != same_src_port_counts.end() && !(same_src_port_counts.key_comp()(src_port, it->first))) { 52 | // Key already exists, take value, then update (exclude new conversation from stats) 53 | value = it->second; 54 | it->second++; 55 | } 56 | else { 57 | // The key does not exist in the map 58 | // Add it to the map + update iterator to point to new item 59 | same_src_port_counts.insert(it, map::value_type(src_port, 1)); 60 | value = 0; 61 | } 62 | 63 | // Feature 36 64 | double same_src_port_rate = value / (double)srv_count; 65 | feature_updater->set_dst_host_same_src_port_rate(cf, same_src_port_rate); 66 | 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /plugin/extractor/FiveTuple.cpp: -------------------------------------------------------------------------------- 1 | #include "FiveTuple.h" 2 | 3 | namespace FeatureExtractor { 4 | 5 | FiveTuple::FiveTuple() 6 | : ip_proto(PROTO_ZERO), src_ip(0), dst_ip(0), src_port(0), dst_port(0) 7 | { 8 | } 9 | 10 | 11 | FiveTuple::~FiveTuple() 12 | { 13 | } 14 | 15 | ip_field_protocol_t FiveTuple::get_ip_proto() const 16 | { 17 | return ip_proto; 18 | } 19 | 20 | void FiveTuple::set_ip_proto(ip_field_protocol_t ip_proto) 21 | { 22 | this->ip_proto = ip_proto; 23 | } 24 | 25 | uint32_t FiveTuple::get_src_ip() const 26 | { 27 | return src_ip; 28 | } 29 | 30 | void FiveTuple::set_src_ip(uint32_t src_ip) 31 | { 32 | this->src_ip = src_ip; 33 | } 34 | 35 | uint32_t FiveTuple::get_dst_ip() const 36 | { 37 | return dst_ip; 38 | } 39 | 40 | void FiveTuple::set_dst_ip(uint32_t dst_ip) 41 | { 42 | this->dst_ip = dst_ip; 43 | } 44 | 45 | uint16_t FiveTuple::get_src_port() const 46 | { 47 | return src_port; 48 | } 49 | 50 | void FiveTuple::set_src_port(uint16_t src_port) 51 | { 52 | this->src_port = src_port; 53 | } 54 | 55 | uint16_t FiveTuple::get_dst_port() const 56 | { 57 | return dst_port; 58 | } 59 | 60 | void FiveTuple::set_dst_port(uint16_t dst_port) 61 | { 62 | this->dst_port = dst_port; 63 | } 64 | 65 | bool FiveTuple::land() const 66 | { 67 | return (src_ip == dst_ip && src_port == dst_port); 68 | } 69 | 70 | bool FiveTuple::operator<(const FiveTuple& other) const 71 | { 72 | if (ip_proto < other.ip_proto) 73 | return true; 74 | if (ip_proto > other.ip_proto) 75 | return false; 76 | 77 | // IP protocols are same 78 | if (src_ip < other.src_ip) 79 | return true; 80 | if (src_ip > other.src_ip) 81 | return false; 82 | 83 | // src IPs are equal 84 | if (dst_ip < other.dst_ip) 85 | return true; 86 | if (dst_ip > other.dst_ip) 87 | return false; 88 | 89 | // dst IPs are equal 90 | if (src_port < other.src_port) 91 | return true; 92 | if (src_port > other.src_port) 93 | return false; 94 | 95 | // src ports are equal 96 | return (dst_port < other.dst_port); 97 | } 98 | 99 | FiveTuple FiveTuple::get_reversed() const 100 | { 101 | FiveTuple tuple; 102 | tuple.ip_proto = this->ip_proto; 103 | tuple.src_ip = this->dst_ip; 104 | tuple.dst_ip = this->src_ip; 105 | tuple.src_port = this->dst_port; 106 | tuple.dst_port = this->src_port; 107 | 108 | return tuple; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /plugin/extractor/StatsPerHost.cpp: -------------------------------------------------------------------------------- 1 | #include "StatsPerHost.h" 2 | 3 | // MSVC: Disable C4351 warning message: 4 | // new behavior: elements of array 'StatsPerHost::same_srv_counts' will be default initialized 5 | #ifdef _MSC_VER 6 | #pragma warning(disable:4351) 7 | #endif 8 | 9 | namespace FeatureExtractor { 10 | 11 | StatsPerHost::StatsPerHost(FeatureUpdater *feature_updater) 12 | : feature_updater(feature_updater) 13 | , count(0), serror_count(0), rerror_count() 14 | , same_srv_counts() // zero-initialize 15 | { 16 | } 17 | 18 | 19 | StatsPerHost::~StatsPerHost() 20 | { 21 | } 22 | 23 | void StatsPerHost::report_conversation_removal(const Conversation *conv) 24 | { 25 | count--; 26 | 27 | // SYN error 28 | if (conv->is_serror()) 29 | serror_count--; 30 | 31 | // REJ error 32 | if (conv->is_rerror()) 33 | rerror_count--; 34 | 35 | // Number of conv. per service 36 | service_t service = conv->get_service(); 37 | same_srv_counts[service]--; 38 | 39 | } 40 | 41 | void StatsPerHost::report_new_conversation(ConversationFeatures *cf) 42 | { 43 | const Conversation *conv = cf->get_conversation(); 44 | service_t service = conv->get_service(); 45 | 46 | /* 47 | * Set derived window features based on previous conversations in window 48 | */ 49 | // Feature 23/32 50 | feature_updater->set_count(cf, count); 51 | 52 | // Feature 25/38 53 | double serror_rate = (count == 0) ? 0.0 : (serror_count / (double)count); 54 | feature_updater->set_serror_rate(cf, serror_rate); 55 | 56 | // Feature 27/40 57 | double rerror_rate = (count == 0) ? 0.0 : (rerror_count / (double)count); 58 | feature_updater->set_rerror_rate(cf, rerror_rate); 59 | 60 | // Feature 29/34 61 | double same_srv_rate = (count == 0) ? 0.0 : (same_srv_counts[service] / (double)count); 62 | feature_updater->set_same_srv_rate(cf, same_srv_rate); 63 | 64 | // Feature 30 65 | double diff_srv_rate = (count == 0) ? 0.0 : (1.0 - same_srv_rate); 66 | feature_updater->set_diff_srv_rate(cf, diff_srv_rate); 67 | 68 | // Part of feature 31/37 69 | feature_updater->set_same_srv_count(cf, same_srv_counts[service]); 70 | 71 | /* 72 | * Include new conversation to stats 73 | */ 74 | count++; 75 | 76 | // SYN error 77 | if (conv->is_serror()) 78 | serror_count++; 79 | 80 | // REJ error 81 | if (conv->is_rerror()) 82 | rerror_count++; 83 | 84 | // Number of conv. per service 85 | same_srv_counts[service]++; 86 | } 87 | 88 | bool StatsPerHost::is_empty() 89 | { 90 | return (count == 0); 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | Snort with Machine Learning 3 | 5 | 6 | 7 | 8 |
9 |
10 |
11 |
12 |
13 | GÓI TIN BÌNH THƯỜNG 14 |
15 |
16 |
Số lượng
17 |

0

18 |
19 |
20 |
21 |
22 |
23 |
24 | GÓI TIN BẤT THƯỜNG 25 |
26 |
27 |
Số lượng
28 |

0

29 |
30 |
31 |
32 |
33 |
34 |
35 | TỔNG SỐ GÓI TIN 36 |
37 |
38 |
Số lượng
39 |

0

40 |
41 |
42 |
43 |
44 |
45 | 46 | 61 | -------------------------------------------------------------------------------- /docs/sections/flatbuffer.tex: -------------------------------------------------------------------------------- 1 | FlatBuffers là một thư viện serialization đa nền tảng hiệu quả cho C++, C\#, C, Go, Java, JavaScript, TypeScript, PHP và Python. 2 | Ban đầu nó được tạo ra tại Google để phát triển trò chơi và các ứng dụng quan trọng khác về hiệu suất. 3 | \subsection{Tại sao sử dụng FlatBuffers?} 4 | \begin{itemize} 5 | \item \textbf{Truy cập vào dữ liệu được tuần tự hóa mà không cần phân tích cú pháp / giải nén} 6 | - Những gì đặt ngoài FlatBuffers là nó đại diện cho dữ liệu phân cấp trong một bộ đệm nhị phân phẳng theo cách mà nó vẫn có thể được truy cập trực tiếp mà không cần phân tích cú pháp / giải nén, trong khi vẫn hỗ trợ tiến hóa cấu trúc dữ liệu (chuyển tiếp / khả năng tương thích ngược). 7 | \item \textbf{Tốc độ và bộ nhớ hiệu quả} 8 | - Bộ nhớ duy nhất cần để truy cập dữ liệu của bạn là bộ đệm. Nó yêu cầu 0 phân bổ bổ sung (bằng C ++, các ngôn ngữ khác có thể thay đổi). FlatBuffers cũng rất thích hợp để sử dụng với mmap (hoặc streaming), chỉ yêu cầu một phần của bộ đệm có trong bộ nhớ. Truy cập gần với tốc độ truy cập cấu trúc thô chỉ với một thêm một hướng (một loại vtable) để cho phép phát triển định dạng và các trường tùy chọn. Đó là nhằm vào các dự án mà chi tiêu thời gian và không gian (phân bổ bộ nhớ nhiều) để có thể truy cập hoặc xây dựng dữ liệu tuần tự là không mong muốn, chẳng hạn như trong trò chơi hoặc bất kỳ ứng dụng nhạy cảm hiệu suất nào khác. 9 | \item \textbf{Linh hoạt} 10 | - Các trường không bắt buọc có nghĩa là không chỉ có khả năng tương thích tốt và tương thích ngược (ngày càng quan trọng đối với các ứng dụng tồn tại lâu dài: không phải cập nhật tất cả dữ liệu với mỗi phiên bản mới!). Nó cũng có nghĩa là bạn có nhiều lựa chọn trong dữ liệu nào bạn viết và dữ liệu nào bạn không sử dụng và cách bạn thiết kế cấu trúc dữ liệu. 11 | \item \textbf{Lượng mã nhỏ} 12 | - Một lượng nhỏ mã được tạo ra, rất dễ tích hợp. 13 | \item \textbf{Kiểu dữ liệu cứng} 14 | - Lỗi xảy ra tại thời gian biên dịch thay vì phải viết kiểm tra thời gian chạy lặp đi lặp lại và dễ bị lỗi. Mã có thể được sinh tự động. 15 | \item \textbf{Sử dụng thuận tiện} 16 | - Mã C++ được tạo cho phép truy cập và xây dựng mã. Sau đó, có chức năng tùy chọn để phân tích các lược đồ và các biểu diễn văn bản giống JSON khi chạy hiệu quả nếu cần (bộ nhớ nhanh hơn và hiệu quả hơn các trình phân tích cú pháp JSON khác). 17 | \newline 18 | Mã Java và Go hỗ trợ tái sử dụng đối tượng. C\# có các trình truy cập dựa trên cấu trúc hiệu quả. 19 | \item \textbf{Đa nền tảng và không có phụ thuộc} 20 | - mã C ++ sẽ hoạt động với bất kỳ gcc / clang và VS2010 gần đây nào. Đi kèm với các tệp xây dựng cho các thử nghiệm và mẫu (tệp .mk Android và cmake cho tất cả các nền tảng khác). 21 | \end{itemize} -------------------------------------------------------------------------------- /plugin/extractor/net.cpp: -------------------------------------------------------------------------------- 1 | #include "net.h" 2 | 3 | namespace FeatureExtractor { 4 | bool ether_header_t::is_ethernet2() const 5 | { 6 | return (ntohs(type_length) >= MIN_ETH2); 7 | } 8 | 9 | bool ether_header_t::is_type_ipv4() const 10 | { 11 | return (ntohs(type_length) == IPV4); 12 | } 13 | 14 | uint8_t* ether_header_t::get_eth2_sdu() const 15 | { 16 | return (((uint8_t *) this) + ETH2_HEADER_LENGTH); 17 | } 18 | 19 | 20 | uint8_t ip_header_t::ihl() const 21 | { 22 | return (ver_ihl & 0x0F); 23 | } 24 | 25 | size_t ip_header_t::header_length() const 26 | { 27 | return ihl() * sizeof(uint32_t); 28 | } 29 | 30 | uint8_t ip_header_t::flags() const 31 | { 32 | return (ntohs(flags_fo) >> 13) & 0x7; 33 | } 34 | 35 | bool ip_header_t::flag_eb() const 36 | { 37 | return ((flags() & 0x1) != 0); 38 | } 39 | 40 | bool ip_header_t::flag_df() const 41 | { 42 | return ((flags() & 0x2) != 0); 43 | } 44 | 45 | bool ip_header_t::flag_mf() const 46 | { 47 | return ((flags() & 0x4) != 0); 48 | } 49 | 50 | size_t ip_header_t::frag_offset() const 51 | { 52 | return (ntohs(flags_fo) & 0x01FFF) << 3; // 1 unit = 8 bytes 53 | } 54 | 55 | const char *ip_header_t::protocol_str() const 56 | { 57 | switch (protocol) { 58 | case ICMP: 59 | return "ICMP"; 60 | break; 61 | case TCP: 62 | return "TCP"; 63 | break; 64 | case UDP: 65 | return "UDP"; 66 | break; 67 | default: 68 | break; 69 | } 70 | return "other"; 71 | } 72 | 73 | uint8_t* ip_header_t::get_sdu() const 74 | { 75 | return (((uint8_t *) this) + header_length()); 76 | } 77 | 78 | tcp_field_flags_t::tcp_field_flags_t(uint8_t flags) 79 | : flags(flags) 80 | {} 81 | 82 | tcp_field_flags_t::tcp_field_flags_t() 83 | : flags(0) 84 | {} 85 | 86 | bool tcp_field_flags_t::fin() const 87 | { 88 | return ((flags & 0x01) != 0); 89 | } 90 | 91 | bool tcp_field_flags_t::syn() const 92 | { 93 | return ((flags & 0x02) != 0); 94 | } 95 | 96 | bool tcp_field_flags_t::rst() const 97 | { 98 | return ((flags & 0x04) != 0); 99 | } 100 | 101 | bool tcp_field_flags_t::psh() const 102 | { 103 | return ((flags & 0x08) != 0); 104 | } 105 | 106 | bool tcp_field_flags_t::ack() const 107 | { 108 | return ((flags & 0x10) != 0); 109 | } 110 | 111 | bool tcp_field_flags_t::urg() const 112 | { 113 | return ((flags & 0x20) != 0); 114 | } 115 | 116 | bool tcp_field_flags_t::ece() const 117 | { 118 | return ((flags & 0x40) != 0); 119 | } 120 | 121 | bool tcp_field_flags_t::cwr() const 122 | { 123 | return ((flags & 0x80) != 0); 124 | } 125 | } -------------------------------------------------------------------------------- /plugin/extractor/Timestamp.cpp: -------------------------------------------------------------------------------- 1 | #include "Timestamp.h" 2 | 3 | 4 | namespace FeatureExtractor { 5 | Timestamp::Timestamp() 6 | { 7 | ts.tv_sec = 0; 8 | ts.tv_usec = 0; 9 | } 10 | 11 | Timestamp::Timestamp(const struct timeval &ts) 12 | { 13 | this->ts = ts; 14 | } 15 | Timestamp::Timestamp(int64_t usecs) 16 | { 17 | ts.tv_sec = (long) (usecs / 1000000); 18 | ts.tv_usec = (long) (usecs % 1000000); 19 | } 20 | 21 | Timestamp::~Timestamp() 22 | { 23 | } 24 | 25 | 26 | struct timeval Timestamp::get_timeval() const 27 | { 28 | return ts; 29 | } 30 | 31 | int64_t Timestamp::get_usecs() const 32 | { 33 | return ts.tv_usec; 34 | } 35 | 36 | 37 | int64_t Timestamp::get_secs() const 38 | { 39 | return ts.tv_sec; 40 | } 41 | 42 | int64_t Timestamp::get_total_usecs() const 43 | { 44 | return ts.tv_sec * (uint64_t)1000000 + ts.tv_usec; 45 | } 46 | 47 | 48 | int64_t Timestamp::get_total_msecs() const 49 | { 50 | return (ts.tv_sec * (uint64_t)1000) + (ts.tv_usec / 1000); 51 | } 52 | 53 | 54 | bool Timestamp::operator==(const Timestamp &b) const 55 | { 56 | return (ts.tv_sec == b.ts.tv_sec && ts.tv_usec == b.ts.tv_usec); 57 | } 58 | 59 | bool Timestamp::operator!=(const Timestamp &b) const 60 | { 61 | return (ts.tv_sec != b.ts.tv_sec || ts.tv_usec != b.ts.tv_usec); 62 | } 63 | 64 | bool Timestamp::operator<(const Timestamp &b) const 65 | { 66 | return (ts.tv_sec < b.ts.tv_sec 67 | || (ts.tv_sec == b.ts.tv_sec && ts.tv_usec < b.ts.tv_usec)); 68 | } 69 | 70 | bool Timestamp::operator<=(const Timestamp &b) const 71 | { 72 | return (ts.tv_sec < b.ts.tv_sec 73 | || (ts.tv_sec == b.ts.tv_sec && ts.tv_usec <= b.ts.tv_usec)); 74 | } 75 | 76 | bool Timestamp::operator>(const Timestamp &b) const 77 | { 78 | return (ts.tv_sec > b.ts.tv_sec 79 | || (ts.tv_sec == b.ts.tv_sec && ts.tv_usec > b.ts.tv_usec)); 80 | } 81 | 82 | bool Timestamp::operator>=(const Timestamp &b) const 83 | { 84 | return (ts.tv_sec > b.ts.tv_sec 85 | || (ts.tv_sec == b.ts.tv_sec && ts.tv_usec >= b.ts.tv_usec)); 86 | } 87 | 88 | Timestamp Timestamp::operator+(const Timestamp &b) const 89 | { 90 | return Timestamp(this->get_total_usecs() + b.get_total_usecs()); 91 | } 92 | 93 | Timestamp Timestamp::operator-(const Timestamp &b) const 94 | { 95 | return Timestamp(this->get_total_usecs() - b.get_total_usecs()); 96 | } 97 | 98 | Timestamp Timestamp::operator+(int64_t b) const 99 | { 100 | return Timestamp(this->get_total_usecs() + b); 101 | } 102 | 103 | Timestamp Timestamp::operator-(int64_t b) const 104 | { 105 | Timestamp t = Timestamp(this->get_total_usecs() - b); 106 | return t; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /plugin/extractor/StatsWindow.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "Conversation.h" 6 | #include "ConversationFeatures.h" 7 | #include "FeatureUpdater.h" 8 | 9 | namespace FeatureExtractor { 10 | using namespace std; 11 | 12 | /** 13 | * Abstract template for mantaining connection window and calculating derived features. 14 | * 15 | * General idea is to keep sums of desired values for conversations currently in window. 16 | * For new conversations values are added. If conversation gets out of window, its values 17 | * are substracted from these sums. This prevents the need of iteration over whole queue 18 | * for each conversation (while calculatig its features). 19 | * 20 | * Algorithm performing window maintenance (keeping it's size) must be specified 21 | * in derived class. 22 | */ 23 | template 24 | class StatsWindow 25 | { 26 | protected: 27 | // TODO: create here everything templated + virtual functions for keeping the size of window 28 | // Queue, methods, feature src_diff_host_rate 29 | 30 | // Queue of conversation in observed window 31 | queuefinished_convs; 32 | 33 | // Statistics per host (destination IP) 34 | map per_host; 35 | 36 | // Statistics per service 37 | TStatsPerService per_service[NUMBER_OF_SERVICES]; 38 | 39 | FeatureUpdater *feature_updater; 40 | 41 | /** 42 | * Finds stats record in map<> for given host. If there is no record for such 43 | * a host, a new one is inserted into map. 44 | */ 45 | TStatsPerHost *find_or_insert_host_stats(uint32_t dst_ip); 46 | 47 | /** 48 | * Report conversation that should be excluded from window. 49 | * 50 | * The aim of calling this method is to keep stat. sums updated. 51 | * Derived class should use this to report conversation that falls out of window 52 | */ 53 | void report_conversation_removal(const Conversation *conv); 54 | 55 | /** 56 | * Method performing window maintenance. 57 | * 58 | * Implementation of this method should remove "old" conversations from window 59 | * represented by queue. 60 | * - Each removed conversation must be reported by calling report_conversation_removal(). 61 | * - Conversation must be deallocated by calling deregister_reference() 62 | * on it after removing it from queue. Conversation object commits suicide 63 | * automatically when there are no more references to it. 64 | * - This method is called after every new conversation being added to window. 65 | */ 66 | virtual void perform_window_maintenance(const Conversation *new_conv) = 0; 67 | 68 | public: 69 | StatsWindow(FeatureUpdater *feature_updater); 70 | virtual ~StatsWindow(); 71 | 72 | /** 73 | * Adds conversation to window, calculates & sets derived statistics. 74 | * Queue (window) size maintenance is performed after each new conversation. 75 | */ 76 | void add_conversation(ConversationFeatures *cf); 77 | }; 78 | } 79 | -------------------------------------------------------------------------------- /kmeans/default_clf.py: -------------------------------------------------------------------------------- 1 | """Default Classifier for Benchmark""" 2 | import pandas as pd 3 | 4 | COL_NAMES = ["duration", "protocol_type", "service", "flag", "src_bytes", 5 | "dst_bytes", "land", "wrong_fragment", "urgent", "hot", "num_failed_logins", 6 | "logged_in", "num_compromised", "root_shell", "su_attempted", "num_root", 7 | "num_file_creations", "num_shells", "num_access_files", "num_outbound_cmds", 8 | "is_host_login", "is_guest_login", "count", "srv_count", "serror_rate", 9 | "srv_serror_rate", "rerror_rate", "srv_rerror_rate", "same_srv_rate", 10 | "diff_srv_rate", "srv_diff_host_rate", "dst_host_count", "dst_host_srv_count", 11 | "dst_host_same_srv_rate", "dst_host_diff_srv_rate", "dst_host_same_src_port_rate", 12 | "dst_host_srv_diff_host_rate", "dst_host_serror_rate", "dst_host_srv_serror_rate", 13 | "dst_host_rerror_rate", "dst_host_srv_rerror_rate", "labels"] 14 | 15 | ATTACKS = { 16 | 'normal': 'normal', 17 | 18 | 'back': 'DoS', 19 | 'land': 'DoS', 20 | 'neptune': 'DoS', 21 | 'pod': 'DoS', 22 | 'smurf': 'DoS', 23 | 'teardrop': 'DoS', 24 | 'mailbomb': 'DoS', 25 | 'apache2': 'DoS', 26 | 'processtable': 'DoS', 27 | 'udpstorm': 'DoS', 28 | 29 | 'ipsweep': 'Probe', 30 | 'nmap': 'Probe', 31 | 'portsweep': 'Probe', 32 | 'satan': 'Probe', 33 | 'mscan': 'Probe', 34 | 'saint': 'Probe', 35 | 36 | 'ftp_write': 'R2L', 37 | 'guess_passwd': 'R2L', 38 | 'imap': 'R2L', 39 | 'multihop': 'R2L', 40 | 'phf': 'R2L', 41 | 'spy': 'R2L', 42 | 'warezclient': 'R2L', 43 | 'warezmaster': 'R2L', 44 | 'sendmail': 'R2L', 45 | 'named': 'R2L', 46 | 'snmpgetattack': 'R2L', 47 | 'snmpguess': 'R2L', 48 | 'xlock': 'R2L', 49 | 'xsnoop': 'R2L', 50 | 'worm': 'R2L', 51 | 52 | 'buffer_overflow': 'U2R', 53 | 'loadmodule': 'U2R', 54 | 'perl': 'U2R', 55 | 'rootkit': 'U2R', 56 | 'httptunnel': 'U2R', 57 | 'ps': 'U2R', 58 | 'sqlattack': 'U2R', 59 | 'xterm': 'U2R' 60 | } 61 | 62 | 63 | class DefaultNSL(object): 64 | 65 | def __init__(self): 66 | self.clf = None 67 | self.training = [] 68 | self.testing = [] 69 | 70 | def load_training_data(self, filepath): 71 | self.training = self.load_data(filepath) 72 | 73 | def load_test_data(self, filepath): 74 | self.testing = self.load_data(filepath) 75 | 76 | @staticmethod 77 | def load_data(filepath): 78 | data = pd.read_csv(filepath, names=COL_NAMES, index_col=False) 79 | labels = data['labels'] 80 | del data['labels'] 81 | return [data, labels] 82 | 83 | def train_clf(self): 84 | pass 85 | 86 | def test_clf(self, train=False): 87 | pass 88 | 89 | def evaluate_results(self, ans=None, train=False): 90 | if not ans: 91 | ans = self.test_clf(train) 92 | print("Accuracy on data: {0:1%}".format(ans[1])) 93 | return ans 94 | -------------------------------------------------------------------------------- /docs/sections/data-mining.tex: -------------------------------------------------------------------------------- 1 | \subsection{Khái niệm} 2 | Là quá trình tính toán để tìm ra các mẫu trong các bộ dữ liệu lớn liên quan đến các phương pháp tại giao điểm của máy học, thống kê và các hệ thống cơ sở dữ liệu. 3 | Đây là một lĩnh vực liên ngành của khoa học máy tính. Mục tiêu tổng thể của quá trình khai thác dữ liệu là trích xuất thông tin từ một bộ dữ liệu và chuyển nó thành một cấu trúc dễ hiểu để sử dụng tiếp. 4 | Ngoài bước phân tích thô, nó còn liên quan tới cơ sở dữ liệu và các khía cạnh quản lý dữ liệu, xử lý dữ liệu trước, suy xét mô hình và suy luận thống kê, các thước đo thú vị, các cân nhắc phức tạp, xuất kết quả về các cấu trúc được phát hiện, hiện hình hóa và cập nhật trực tuyến. 5 | \subsection{Các bước trong quá trình khai phá} 6 | Quá trình được thực hiện qua 9 bước: 7 | \begin{enumerate} 8 | \item \textbf{Tìm hiểu lĩnh vực của bài toán (ứng dụng)}: Các mục đích của bài toán, 9 | các tri thức cụ thể của lĩnh vực. 10 | \item \textbf{Tạo nên (thu thập) một tập dữ liệu phù hợp.} 11 | \item \textbf{Làm sạch và tiền xử lý dữ liệu.} 12 | \item \textbf{Giảm kích thức của dữ liệu, chuyển đổi dữ liệu}: Xác định thuộc tính quan 13 | trọng, giảm số chiều (số thuộc tính), biểu diễn bất biến. 14 | \item \textbf{Lựa chọn chức năng khai phá dữ liệu}: Phân loại, gom cụm, dự báo, sinh 15 | ra các luật kết hợp. 16 | \item \textbf{Lựa chọn/ Phát triển (các) giải thuật khai phá dữ liệu phù hợp.} 17 | \item \textbf{Tiến hành khai phá dữ liệu.} 18 | \item \textbf{Đánh giá mẫu thu được và biểu diễn tri thức}: Hiển thị hóa, chuyển đổi, bỏ 19 | đi các mẫu dư thừa,… 20 | \item \textbf{Sử dụng tri thức được khai phá.} 21 | \end{enumerate} 22 | Quá trình khám phá tri thức theo cách nhìn của giới nghiên cứu về các hệ 23 | thống dữ liệu và kho dữ liệu về quá trình khám phá tri thức 24 | \begin{itemize} 25 | \item Chuẩn bị dữ liệu \textit{(data preparation)}, bao gồm các quá trình làm sạch dữ liệu 26 | \textit{(data cleaning)}, tích hợp dữ liệu \textit{(data integration)}, chọn dữ liệu \textit{(data selection)}, 27 | biến đổi dữ liệu \textit{(data transformation)}. 28 | \item Khai thác dữ liệu \textit{(data mining)}: xác định nhiệm vụ khai thác dữ liệu và lựa 29 | chọn kỹ thuật khai thác dữ liệu. Kết quả cho ta một nguồn tri thức thô. 30 | \item Đánh giá \textit{(evaluation)}: dựa trên một số tiêu chí tiến hành kiểm tra và lọc 31 | nguồn tri thức thu được. 32 | \item Triển khai \textit{(deployment)}. 33 | \item Quá trình khai thác tri thức không chỉ là một quá trình tuần tự từ bước đầu 34 | tiên đến bước cuối cùng mà là một quá trình lặp và có quay trở lại các bước đã qua. 35 | \end{itemize} 36 | \begin{figure}[!htbp] 37 | \centering 38 | \includegraphics[scale=0.7]{data_mining} 39 | \caption{Quá trình khai phá tri thức} 40 | \label{fig:x cubed graph} 41 | \end{figure} 42 | \FloatBarrier 43 | \subsection{Ứng dụng của khai phá dữ liệu} 44 | \begin{itemize} 45 | \item Kinh tế - ứng dụng trong kinh doanh, tài chính, tiếp thị bán hàng, bảo hiểm, 46 | thương mại, ngân hàng, … Đưa ra các bản báo cáo giàu thông tin; phân tích rủi ro 47 | trước khi đưa ra các chiến lược kinh doanh, sản xuất; phân loại khách hàng từ đó phân định thị trường, thị phần; … 48 | \item Khoa học: Thiên văn học – dự đoán đường đi các thiên thể, hành tinh, …; 49 | Công nghệ sinh học – tìm ra các gen mới, cây con giống mới, …; … 50 | \item Web: các công cụ tìm kiếm. 51 | \end{itemize} -------------------------------------------------------------------------------- /plugin/extractor/Config.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | 5 | namespace FeatureExtractor { 6 | 7 | /** 8 | * Class to store timeout settings 9 | * 10 | * If not specified otherwise, all time values are meant to be in seconds. 11 | */ 12 | class Config 13 | { 14 | /** 15 | * Frame sniffing & parsing 16 | */ 17 | int files_c; // Count of files, if 0 interface number should be used 18 | char **files_v; 19 | int interface_num; 20 | int pcap_read_timeout; 21 | size_t additional_frame_len; 22 | 23 | /** 24 | * IP reassembly 25 | */ 26 | uint32_t ipfrag_timeout; 27 | uint32_t ipfrag_check_interval_ms; 28 | 29 | /** 30 | * Conversation reconstruction 31 | */ 32 | uint32_t tcp_syn_timeout; // S0, S1 33 | uint32_t tcp_estab_timeout; // ESTAB 34 | uint32_t tcp_rst_timeout; // REJ, RSTO, RSTR, RSTOS0 35 | uint32_t tcp_fin_timeout; // S2, S3 36 | uint32_t tcp_last_ack_timeout; // S2F, S2F 37 | uint32_t udp_timeout; 38 | uint32_t icmp_timeout; 39 | uint32_t conversation_check_interval_ms; 40 | 41 | /** 42 | * Conversation reconstruction 43 | */ 44 | unsigned int time_window_size_ms; // Size of window in miliseconds 45 | unsigned int count_window_size; 46 | 47 | /** 48 | * Output 49 | */ 50 | bool print_extra_features; // IPs, ports, end timestamp 51 | bool print_filename; 52 | 53 | public: 54 | Config(); 55 | ~Config(); 56 | 57 | int get_files_count() const; 58 | void set_files_count(int files_c); 59 | 60 | char **get_files_values() const; 61 | void set_files_values(char **files_v); 62 | 63 | int get_interface_num() const; 64 | void set_interface_num(int interface_num); 65 | 66 | int get_pcap_read_timeout() const; 67 | void set_pcap_read_timeout(int pcap_read_timeout); 68 | 69 | size_t get_additional_frame_len() const; 70 | void set_additional_frame_len(size_t additional_frame_len); 71 | 72 | uint32_t get_ipfrag_timeout() const; 73 | void set_ipfrag_timeout(uint32_t ipfrag); 74 | 75 | uint32_t get_ipfrag_check_interval_ms() const; 76 | void set_ipfrag_check_interval_ms(uint32_t ipfrag_check_interval_ms); 77 | 78 | uint32_t get_tcp_syn_timeout() const; 79 | void set_tcp_syn_timeout(uint32_t tcp_syn); 80 | 81 | uint32_t get_tcp_estab_timeout() const; 82 | void set_tcp_estab_timeout(uint32_t tcp_estab); 83 | 84 | uint32_t get_tcp_rst_timeout() const; 85 | void set_tcp_rst_timeout(uint32_t tcp_rst); 86 | 87 | uint32_t get_tcp_fin_timeout() const; 88 | void set_tcp_fin_timeout(uint32_t tcp_fin); 89 | 90 | uint32_t get_tcp_last_ack_timeout() const; 91 | void set_tcp_last_ack_timeout(uint32_t tcp_last_ack); 92 | 93 | uint32_t get_udp_timeout() const; 94 | void set_udp_timeout(uint32_t udp); 95 | 96 | uint32_t get_icmp_timeout() const; 97 | void set_icmp_timeout(uint32_t icmp); 98 | 99 | uint32_t get_conversation_check_interval_ms() const; 100 | void set_conversation_check_interval_ms(uint32_t conversation_check_interval_ms); 101 | 102 | unsigned int get_time_window_size_ms() const; 103 | void set_time_window_size_ms(unsigned int time_window_size_ms); 104 | 105 | unsigned int get_count_window_size() const; 106 | void set_count_window_size(unsigned int count_window_size); 107 | 108 | bool should_print_extra_features() const; 109 | void set_print_extra_features(bool print_extra_features); 110 | 111 | bool should_print_filename() const; 112 | void set_print_filename(bool print_filename); 113 | }; 114 | } 115 | -------------------------------------------------------------------------------- /kmeans/kmeans_nsl.py: -------------------------------------------------------------------------------- 1 | """K-Means Classifier""" 2 | import collections 3 | import pandas as pd 4 | import numpy as np 5 | from sklearn.cluster import KMeans 6 | from sklearn.preprocessing import minmax_scale 7 | from default_clf import DefaultNSL, COL_NAMES, ATTACKS 8 | 9 | 10 | class KMeansNSL(DefaultNSL): 11 | 12 | def __init__(self): 13 | super(KMeansNSL, self).__init__() 14 | self.cols = None 15 | self.clusters = {0: None, 1: None, 2: None, 3: None} 16 | 17 | def load_training_data(self, filepath): 18 | data, labels = self.load_data(filepath) 19 | self.cols = data.columns 20 | self.training = [data, labels] 21 | 22 | def load_test_data(self, filepath): 23 | data, labels = self.load_data(filepath) 24 | map_data = pd.DataFrame(columns=self.cols) 25 | map_data = map_data.append(data) 26 | data = map_data.fillna(0) 27 | self.testing = [data[self.cols], labels] 28 | 29 | @staticmethod 30 | def load_data(filepath): 31 | data = pd.read_csv(filepath, names=COL_NAMES, index_col=False) 32 | # Shuffle data 33 | data = data.sample(frac=1).reset_index(drop=True) 34 | NOM_IND = [1, 2, 3] 35 | BIN_IND = [6, 11, 13, 14, 20, 21] 36 | # Need to find the numerical columns for normalization 37 | NUM_IND = list(set(range(40)).difference(NOM_IND).difference(BIN_IND)) 38 | 39 | # Scale all numerical data to [0-1] 40 | data.iloc[:, NUM_IND] = minmax_scale(data.iloc[:, NUM_IND]) 41 | labels = data['labels'] 42 | del data['labels'] 43 | data = pd.get_dummies(data) 44 | return [data, labels] 45 | 46 | def train_clf(self): 47 | self.clf = KMeans(n_clusters=4, init='random').fit(self.training[0]) 48 | self.set_categories() 49 | 50 | def test_clf(self, train=False): 51 | if train: 52 | data, labels = self.training 53 | else: 54 | data, labels = self.testing 55 | test_preds = self.clf.predict(data) 56 | test_preds = [self.clusters[x] for x in test_preds] 57 | bin_labels = labels.apply(lambda x: x if x == 'normal' else 'anomaly') 58 | test_acc = sum(test_preds == bin_labels)/(len(test_preds) * 1.0) 59 | return [test_preds, test_acc] 60 | 61 | def set_categories(self): 62 | labels = self.training[1] 63 | bin_labels = labels.apply(lambda x: x if x == 'normal' else 'anomaly') 64 | clust_preds = self.clf.labels_ 65 | count = collections.Counter(zip(clust_preds, bin_labels)) 66 | num = [0, 0, 0, 0] 67 | for k, val in count.items(): 68 | clust = k[0] 69 | if val > num[clust]: 70 | num[clust] = val 71 | self.clusters[clust] = k[1] 72 | 73 | def predict(self, packet): 74 | data = pd.DataFrame([packet], columns=COL_NAMES) 75 | 76 | data = data.sample(frac=1).reset_index(drop=True) 77 | NOM_IND = [1, 2, 3] 78 | BIN_IND = [6, 11, 13, 14, 20, 21] 79 | 80 | NUM_IND = list(set(range(40)).difference(NOM_IND).difference(BIN_IND)) 81 | 82 | data.iloc[:, NUM_IND] = minmax_scale(data.iloc[:, NUM_IND]) 83 | del data['labels'] 84 | data = pd.get_dummies(data) 85 | 86 | map_data = pd.DataFrame(columns=self.cols) 87 | map_data = map_data.append(data) 88 | data = map_data.fillna(0) 89 | 90 | predict = self.clf.predict(data[self.cols]) 91 | predict = [self.clusters[x] for x in predict] 92 | return predict[0] 93 | -------------------------------------------------------------------------------- /plugin/extractor/IpReassemblyBufferHoleList.cpp: -------------------------------------------------------------------------------- 1 | #include "IpReassemblyBufferHoleList.h" 2 | #include 3 | #include 4 | 5 | namespace FeatureExtractor { 6 | IpReassemblyBufferHoleList::Hole::Hole() 7 | : start(0), end(SIZE_MAX), next(nullptr) 8 | {} 9 | 10 | IpReassemblyBufferHoleList::Hole::Hole(size_t start, size_t end, Hole *next) 11 | { 12 | this->start = start; 13 | this->end = end; 14 | this->next = next; 15 | } 16 | 17 | IpReassemblyBufferHoleList::IpReassemblyBufferHoleList() 18 | : first_hole(new Hole()) 19 | {} 20 | 21 | IpReassemblyBufferHoleList::~IpReassemblyBufferHoleList() 22 | { 23 | // Deallocate linked list of holes 24 | Hole *next; 25 | while (first_hole) { 26 | next = first_hole->next; 27 | delete first_hole; 28 | first_hole = next; 29 | } 30 | } 31 | 32 | bool IpReassemblyBufferHoleList::is_empty() const 33 | { 34 | return (first_hole == nullptr); 35 | } 36 | 37 | /* 38 | * RFC 815 - section 3: Fragment Processing Algorithm 39 | * Terms start (end) in code bellow corresponds to first (last) in RFC. 40 | */ 41 | void IpReassemblyBufferHoleList::add_fragment(size_t frag_start, size_t frag_end, bool is_last_frag) { 42 | // Should not insert to completed datagram 43 | assert(!this->is_empty() && "Attempt to insert fragment to reassembled datagram"); 44 | 45 | Hole *prev = nullptr; 46 | Hole *hole = this->first_hole; 47 | while (hole) { // 7. + 1. Loop finished when no next hole descriptor 48 | 49 | // 1.-3. Find hole that fragment fits 50 | while (hole && (frag_start > hole->end || frag_end < hole->start)) { 51 | 52 | // Part of 6. If last fragment change update last hole end (initiated to infinity) 53 | if (is_last_frag && !hole->next) { 54 | hole->end = frag_end; 55 | 56 | // If hole makes no sense, destroy it 57 | if (hole->start > hole->end) { 58 | if (prev) 59 | prev->next = hole->next; 60 | else 61 | first_hole = hole->next; 62 | delete hole; 63 | hole = nullptr; 64 | break; 65 | } 66 | } 67 | 68 | // 1. Select the next hole descriptor from the hole descriptor list. 69 | prev = hole; 70 | hole = hole->next; 71 | } // End of 1.-3. Find hole... 72 | 73 | if (hole) { 74 | Hole *next = hole->next; 75 | 76 | // 5. New hole before fragment 77 | if (frag_start > hole->start) { 78 | Hole *new_hole = new Hole(hole->start, frag_end - 1, next); 79 | if (prev) 80 | prev->next = new_hole; 81 | else 82 | first_hole = new_hole; 83 | prev = new_hole; 84 | } 85 | 86 | // 6. New hole after fragment 87 | // If last fragment change update last hole end (initiated to infinity) 88 | if (is_last_frag && !next) { 89 | hole->end = frag_end; 90 | } 91 | if (frag_end < hole->end) { 92 | Hole *new_hole = new Hole(frag_end + 1, hole->end, next); 93 | if (prev) 94 | prev->next = new_hole; 95 | else 96 | first_hole = new_hole; 97 | prev = new_hole; 98 | } 99 | 100 | // 4. Delete hole descriptor 101 | delete hole; 102 | 103 | // 1. Select the next hole descriptor 104 | hole = next; 105 | 106 | // If no hole except the one to be deleted, the list is empty now 107 | if (!prev && !next) 108 | first_hole = nullptr; 109 | } 110 | } 111 | 112 | // 8: If the hole descriptor list is now empty, the datagram is now complete 113 | if (this->is_empty()) { 114 | //TODO: got the datagram bitch! 115 | } 116 | } 117 | } -------------------------------------------------------------------------------- /plugin/extractor/StatsWindow.cpp: -------------------------------------------------------------------------------- 1 | #include "StatsWindow.h" 2 | #include "StatsPerHost.h" 3 | #include "StatsPerService.h" 4 | #include "StatsPerServiceWithSrcPort.h" 5 | #include 6 | 7 | 8 | namespace FeatureExtractor { 9 | template 10 | StatsWindow::StatsWindow(FeatureUpdater *feature_updater) 11 | : feature_updater(feature_updater) 12 | { 13 | // Initialize stats per service 14 | for (int i = 0; i < NUMBER_OF_SERVICES; i++) { 15 | per_service[i] = TStatsPerService(feature_updater); 16 | } 17 | } 18 | 19 | template 20 | StatsWindow::~StatsWindow() 21 | { 22 | // Deallocate leftover conversations in the queue 23 | while (!finished_convs.empty()) { 24 | Conversation *conv = finished_convs.front(); 25 | finished_convs.pop(); 26 | 27 | // Object commits suicide if no more references to it 28 | conv->deregister_reference(); 29 | } 30 | 31 | // per_host map<> should automatically be deallocated 32 | } 33 | 34 | template 35 | TStatsPerHost *StatsWindow::find_or_insert_host_stats(uint32_t dst_ip) 36 | { 37 | TStatsPerHost *stats = nullptr; 38 | 39 | // Find or insert with single lookup: 40 | // http://stackoverflow.com/a/101980/3503528 41 | typename map::iterator it = per_host.lower_bound(dst_ip); 42 | if (it != per_host.end() && !(per_host.key_comp()(dst_ip, it->first))) 43 | { 44 | // Found 45 | stats = &it->second; 46 | } 47 | else { 48 | // The key does not exist in the map 49 | // Add it to the map + update iterator to point to new item 50 | it = per_host.insert(it, typename map::value_type(dst_ip, TStatsPerHost(feature_updater))); 51 | stats = &it->second; 52 | } 53 | 54 | return stats; 55 | } 56 | 57 | template 58 | void StatsWindow::report_conversation_removal(const Conversation *conv) 59 | { 60 | uint32_t dst_ip = conv->get_five_tuple_ptr()->get_dst_ip(); 61 | service_t service = conv->get_service(); 62 | 63 | // Forward to per host stats 64 | typename map::iterator it = per_host.find(dst_ip); 65 | assert(it != per_host.end() && "Reporting removal of convesation not in queue: no such dst. IP record"); 66 | TStatsPerHost *this_host = &it->second; 67 | this_host->report_conversation_removal(conv); 68 | 69 | // Remove per-host stats for this host if it's "empty" for this window 70 | if (this_host->is_empty()) 71 | per_host.erase(it); 72 | 73 | // Forward to per service stats 74 | per_service[service].report_conversation_removal(conv); 75 | } 76 | 77 | template 78 | void StatsWindow::add_conversation(ConversationFeatures *cf) 79 | { 80 | Conversation *conv = cf->get_conversation(); 81 | uint32_t dst_ip = conv->get_five_tuple_ptr()->get_dst_ip(); 82 | service_t service = conv->get_service(); 83 | 84 | // Per host statitics 85 | TStatsPerHost *this_host = find_or_insert_host_stats(dst_ip); 86 | this_host->report_new_conversation(cf); 87 | 88 | // Per service statitics 89 | per_service[service].report_new_conversation(cf); 90 | 91 | // Add new connection to window queue (+ register reference) 92 | conv->register_reference(); 93 | finished_convs.push(conv); 94 | 95 | perform_window_maintenance(conv); 96 | } 97 | 98 | // Explicit template specialisation http://stackoverflow.com/q/115703/3503528 99 | template class StatsWindow; 100 | template class StatsWindow; 101 | } 102 | -------------------------------------------------------------------------------- /plugin/extractor/ConversationFeatures.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | #include "Conversation.h" 5 | 6 | namespace FeatureExtractor { 7 | 8 | /** 9 | * Set of features with link to conversation 10 | */ 11 | class ConversationFeatures 12 | { 13 | // Link to conversation 14 | Conversation *conv; 15 | 16 | /** 17 | * Derived features for 2s time window 18 | */ 19 | uint32_t count; 20 | uint32_t srv_count; 21 | double serror_rate; 22 | double srv_serror_rate; 23 | double rerror_rate; 24 | double srv_rerror_rate; 25 | double same_srv_rate; 26 | double diff_srv_rate; 27 | 28 | /** 29 | * Derived features for 100 connection window 30 | */ 31 | uint32_t dst_host_count; 32 | uint32_t dst_host_srv_count; 33 | double dst_host_same_srv_rate; 34 | double dst_host_diff_srv_rate; 35 | double dst_host_same_src_port_rate; 36 | double dst_host_serror_rate; 37 | double dst_host_srv_serror_rate; 38 | double dst_host_rerror_rate; 39 | double dst_host_srv_rerror_rate; 40 | 41 | /** 42 | * Additional values kept to calculate feature 31(37) 43 | * (srv_diff_host_rate/dst_host_srv_diff_host_rate) 44 | * srv_diff_host_rate = (srv_count - same_srv_count) / srv_count 45 | */ 46 | uint32_t same_srv_count; 47 | uint32_t dst_host_same_srv_count; 48 | 49 | public: 50 | ConversationFeatures(Conversation *); 51 | ~ConversationFeatures(); 52 | 53 | Conversation *get_conversation(); 54 | 55 | // Time window features 56 | 57 | uint32_t get_count() const; 58 | void set_count(uint32_t count); 59 | 60 | uint32_t get_srv_count() const; 61 | void set_srv_count(uint32_t srv_count); 62 | 63 | double get_serror_rate() const; 64 | void set_serror_rate(double serror_rate); 65 | 66 | double get_srv_serror_rate() const; 67 | void set_srv_serror_rate(double srv_serror_rate); 68 | 69 | double get_rerror_rate() const; 70 | void set_rerror_rate(double rerror_rate); 71 | 72 | double get_srv_rerror_rate() const; 73 | void set_srv_rerror_rate(double srv_rerror_rate); 74 | 75 | double get_same_srv_rate() const; 76 | void set_same_srv_rate(double same_srv_rate); 77 | 78 | double get_diff_srv_rate() const; 79 | void set_diff_srv_rate(double diff_srv_rate); 80 | 81 | double get_srv_diff_host_rate() const; 82 | 83 | uint32_t get_same_srv_count() const; 84 | void set_same_srv_count(uint32_t same_srv_count); 85 | 86 | // Count window features 87 | 88 | uint32_t get_dst_host_count() const; 89 | void set_dst_host_count(uint32_t dst_host_count); 90 | 91 | uint32_t get_dst_host_srv_count() const; 92 | void set_dst_host_srv_count(uint32_t dst_host_srv_count); 93 | 94 | double get_dst_host_same_srv_rate() const; 95 | void set_dst_host_same_srv_rate(double dst_host_same_srv_rate); 96 | 97 | double get_dst_host_diff_srv_rate() const; 98 | void set_dst_host_diff_srv_rate(double dst_host_diff_srv_rate); 99 | 100 | double get_dst_host_same_src_port_rate() const; 101 | void set_dst_host_same_src_port_rate(double dst_host_same_src_port_rate); 102 | 103 | double get_dst_host_serror_rate() const; 104 | void set_dst_host_serror_rate(double dst_host_serror_rate); 105 | 106 | double get_dst_host_srv_serror_rate() const; 107 | void set_dst_host_srv_serror_rate(double dst_host_srv_serror_rate); 108 | 109 | double get_dst_host_rerror_rate() const; 110 | void set_dst_host_rerror_rate(double dst_host_rerror_rate); 111 | 112 | double get_dst_host_srv_rerror_rate() const; 113 | void set_dst_host_srv_rerror_rate(double dst_host_srv_rerror_rate); 114 | 115 | double get_dst_host_srv_diff_host_rate() const; 116 | 117 | uint32_t get_dst_host_same_srv_count() const; 118 | void set_dst_host_same_srv_count(uint32_t same_srv_count); 119 | 120 | /** 121 | * Print in KDD style + optionally extra features 122 | */ 123 | void print(bool print_extra_features = true) const; 124 | 125 | /** 126 | * Human readable print to stdout 127 | */ 128 | void print_human() const; 129 | }; 130 | } 131 | -------------------------------------------------------------------------------- /plugin/extractor/net.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | 5 | // ntoh fuctions 6 | #if !defined(_WIN32) && !defined(WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(__BORLANDC__) 7 | #include 8 | #endif 9 | 10 | // Bug in win WpdPack_4_1_2: On line 69 of pcap-stdinc.h, 'inline' is re-defined 11 | // http://www.winpcap.org/pipermail/winpcap-bugs/2013-November/001760.html 12 | // Solved by including pcap.h after standard libs 13 | #include 14 | 15 | /* 16 | * Structs for parsing network protocol headers 17 | * Inspired by http://stackoverflow.com/a/16523804/3503528 18 | */ 19 | namespace FeatureExtractor { 20 | /* 21 | * Ethernet type/length field 22 | */ 23 | enum eth_field_type_t : uint16_t { 24 | TYPE_ZERO = 0, 25 | MIN_ETH2 = 0x600, 26 | IPV4 = 0x800 27 | }; 28 | 29 | /* 30 | * Ethernet header 31 | */ 32 | struct ether_header_t { 33 | uint8_t dst_addr[6]; 34 | uint8_t src_addr[6]; 35 | eth_field_type_t type_length; 36 | 37 | static const size_t ETH2_HEADER_LENGTH = 14; 38 | 39 | bool is_ethernet2() const; 40 | bool is_type_ipv4() const; 41 | uint8_t *get_eth2_sdu() const; 42 | }; 43 | 44 | /* 45 | * IP protocol field 46 | */ 47 | enum ip_field_protocol_t : uint8_t { 48 | PROTO_ZERO = 0, 49 | ICMP = 1, 50 | TCP = 6, 51 | UDP = 17 52 | }; 53 | 54 | /* 55 | * IP header 56 | */ 57 | struct ip_header_t { 58 | uint8_t ver_ihl; // 4 bits version and 4 bits internet header length 59 | uint8_t tos; 60 | uint16_t total_length; 61 | uint16_t id; 62 | uint16_t flags_fo; // 3 bits flags and 13 bits fragment-offset 63 | uint8_t ttl; 64 | ip_field_protocol_t protocol; 65 | uint16_t checksum; 66 | uint32_t src_addr; 67 | uint32_t dst_addr; 68 | 69 | static const int IP_MIN_HEADER_LENGTH = 20; 70 | 71 | uint8_t ihl() const; 72 | size_t header_length() const; 73 | uint8_t flags() const; 74 | bool flag_eb() const; // Evil bit (reserved) 75 | bool flag_df() const; // Do Not Fragment 76 | bool flag_mf() const; // More Fragments 77 | size_t frag_offset() const; 78 | const char *protocol_str() const; 79 | uint8_t *get_sdu() const; 80 | }; 81 | 82 | /* 83 | * UDP header 84 | */ 85 | struct udp_header_t { 86 | uint16_t src_port; 87 | uint16_t dst_port; 88 | uint16_t length; 89 | uint16_t checksum; 90 | 91 | static const size_t UDP_MIN_HEADER_LENGTH = 8; 92 | }; 93 | 94 | /* 95 | * TCP flags field 96 | */ 97 | struct tcp_field_flags_t { 98 | uint8_t flags; 99 | 100 | tcp_field_flags_t(); 101 | tcp_field_flags_t(uint8_t flags); 102 | bool fin() const; 103 | bool syn() const; 104 | bool rst() const; 105 | bool psh() const; 106 | bool ack() const; 107 | bool urg() const; // Urgent 108 | bool ece() const; // ECN Echo 109 | bool cwr() const; // Congestion Window Reduced 110 | }; 111 | 112 | /* 113 | * TCP header 114 | */ 115 | struct tcp_header_t { 116 | uint16_t src_port; 117 | uint16_t dst_port; 118 | uint32_t seq; 119 | uint32_t ack; 120 | uint8_t data_offset; // 4 bits offset + 4 bits reserved 121 | tcp_field_flags_t flags; 122 | uint16_t window_size; 123 | uint16_t checksum; 124 | uint16_t urgent_p; 125 | 126 | static const size_t TCP_MIN_HEADER_LENGTH = 20; 127 | }; 128 | 129 | 130 | 131 | /* 132 | * ICMP type field 133 | * Values from linux source code used 134 | * https://github.com/torvalds/linux/blob/master/include/uapi/linux/icmp.h 135 | */ 136 | enum icmp_field_type_t : uint8_t { 137 | ECHOREPLY = 0, 138 | DEST_UNREACH = 3, 139 | SOURCE_QUENCH = 4, 140 | REDIRECT = 5, 141 | ECHO = 8, 142 | TIME_EXCEEDED = 11, 143 | PARAMETERPROB = 12, 144 | TIMESTAMP = 13, 145 | TIMESTAMPREPLY = 14, 146 | INFO_REQUEST = 15, 147 | INFO_REPLY = 16, 148 | ADDRESS = 17, 149 | ADDRESSREPLY = 18 150 | }; 151 | 152 | /* 153 | * ICMP header 154 | */ 155 | struct icmp_header_t { 156 | icmp_field_type_t type; 157 | uint8_t code; 158 | uint16_t checksum; 159 | 160 | static const size_t ICMP_MIN_HEADER_LENGTH = 8; 161 | }; 162 | } -------------------------------------------------------------------------------- /plugin/extractor/IpReassembler.cpp: -------------------------------------------------------------------------------- 1 | #include "IpReassembler.h" 2 | 3 | 4 | namespace FeatureExtractor { 5 | // 6 | 7 | IpReassembler::IpReassembler() 8 | : timeouts() 9 | , timeout_interval(timeouts.get_conversation_check_interval_ms()) 10 | { 11 | } 12 | 13 | IpReassembler::IpReassembler(Config &timeouts) 14 | : timeouts(timeouts) 15 | , timeout_interval(timeouts.get_conversation_check_interval_ms()) 16 | { 17 | } 18 | 19 | 20 | IpReassembler::~IpReassembler() 21 | { 22 | // Deallocate leftover active buffers 23 | for (BufferMap::iterator it = buffer_map.begin(); it != buffer_map.end(); ++it) { 24 | delete it->second; 25 | } 26 | 27 | } 28 | 29 | IpReassembler::IpReassemblyBufferKey::IpReassemblyBufferKey() 30 | : src(0), dst(0), proto(PROTO_ZERO), id(0) 31 | {} 32 | 33 | IpReassembler::IpReassemblyBufferKey::IpReassemblyBufferKey(const IpFragment *fragment) { 34 | this->src = fragment->get_src_ip(); 35 | this->dst = fragment->get_dst_ip(); 36 | this->proto = fragment->get_ip_proto(); 37 | this->id = fragment->get_ip_id(); 38 | } 39 | 40 | bool IpReassembler::IpReassemblyBufferKey::operator<(const IpReassemblyBufferKey& other) const 41 | { 42 | if (src < other.src) 43 | return true; 44 | if (src > other.src) 45 | return false; 46 | 47 | // src IPs are equal 48 | if (dst < other.dst) 49 | return true; 50 | if (dst > other.dst) 51 | return false; 52 | 53 | // dst IPs are equal 54 | if (id < other.id) 55 | return true; 56 | if (id > other.id) 57 | return false; 58 | 59 | // IDs are equal 60 | return (proto < other.proto); 61 | } 62 | 63 | 64 | Packet *IpReassembler::reassemble(IpFragment *frag) 65 | { 66 | // Remove timed out reassembly buffers 67 | Timestamp now = frag->get_end_ts(); 68 | check_timeouts(now); 69 | 70 | // Check whether packet is part of fragmented datagram 71 | bool is_fragmented = (frag->get_ip_flag_mf() || frag->get_ip_frag_offset() != 0); 72 | 73 | // If fragmented forward to correct reassembly buffer 74 | if (is_fragmented) 75 | return forward_to_buffer(frag); 76 | 77 | // Not fragmented, nothing to do 78 | return frag; 79 | } 80 | 81 | IpDatagram *IpReassembler::forward_to_buffer(IpFragment *frag) 82 | { 83 | IpReassemblyBufferKey key(frag); 84 | IpReassemblyBuffer *buffer = nullptr; 85 | 86 | // Find or insert with single lookup: 87 | // http://stackoverflow.com/a/101980/3503528 88 | // - iterator can will also used to remove buffer for reassembled datagram 89 | BufferMap::iterator it = buffer_map.lower_bound(key); 90 | if (it != buffer_map.end() && !(buffer_map.key_comp()(key, it->first))) 91 | { 92 | // Key already exists; update lb->second if you care to 93 | buffer = it->second; 94 | } 95 | else { 96 | // The key does not exist in the map 97 | // Add it to the map + update iterator to point to new item 98 | buffer = new IpReassemblyBuffer(); 99 | it = buffer_map.insert(it, BufferMap::value_type(key, buffer)); 100 | } 101 | 102 | // Call IP reassembly algorithm 103 | IpDatagram *datagram = buffer->add_fragment(frag); 104 | 105 | // If new IP datagram reassembled, destroy the buffer for it 106 | // and enqueue datagram to output queue 107 | if (datagram) { 108 | buffer_map.erase(it); 109 | delete buffer; 110 | } 111 | 112 | // Free fragment from memory 113 | delete frag; 114 | 115 | return datagram; 116 | } 117 | 118 | void IpReassembler::check_timeouts(const Timestamp &now) 119 | { 120 | // Run no more often than once per timeout check interval 121 | if (!timeout_interval.is_timedout(now)) { 122 | timeout_interval.update_time(now); 123 | return; 124 | } 125 | timeout_interval.update_time(now); 126 | 127 | // Maximal timestamps that timedout conversation in given state can have 128 | Timestamp max_timeout_ts = now - (timeouts.get_ipfrag_timeout() * 1000000); 129 | 130 | // Erasing during iteration available since C++11 131 | // http://stackoverflow.com/a/263958/3503528 132 | BufferMap::iterator it = buffer_map.begin(); 133 | while (it != buffer_map.end()) { 134 | 135 | // If buffer is timed out, DROP the incomplete datagram 136 | if (it->second->get_last_fragment_ts() <= max_timeout_ts) { 137 | // Erase 138 | buffer_map.erase(it++); // Use iterator + post increment 139 | } 140 | else { 141 | ++it; 142 | } 143 | } // end of while(it.. 144 | 145 | } 146 | 147 | } 148 | -------------------------------------------------------------------------------- /test_predict.py: -------------------------------------------------------------------------------- 1 | import flatbuffers 2 | from kmeans.packet import * 3 | import requests 4 | import pandas as pd 5 | 6 | COL_NAMES = ["duration", "protocol_type", "service", "flag", "src_bytes", 7 | "dst_bytes", "land", "wrong_fragment", "urgent", "hot", "num_failed_logins", 8 | "logged_in", "num_compromised", "root_shell", "su_attempted", "num_root", 9 | "num_file_creations", "num_shells", "num_access_files", "num_outbound_cmds", 10 | "is_host_login", "is_guest_login", "count", "srv_count", "serror_rate", 11 | "srv_serror_rate", "rerror_rate", "srv_rerror_rate", "same_srv_rate", 12 | "diff_srv_rate", "srv_diff_host_rate", "dst_host_count", "dst_host_srv_count", 13 | "dst_host_same_srv_rate", "dst_host_diff_srv_rate", "dst_host_same_src_port_rate", 14 | "dst_host_srv_diff_host_rate", "dst_host_serror_rate", "dst_host_srv_serror_rate", 15 | "dst_host_rerror_rate", "dst_host_srv_rerror_rate", "labels"] 16 | 17 | 18 | def test_predict(): 19 | df = pd.read_csv('datasets/KDDTest+.csv', names=COL_NAMES, 20 | index_col=False, nrows=1) 21 | correct = 0 22 | for index, row in df.iterrows(): 23 | builder = flatbuffers.Builder(1024) 24 | protocol_type = builder.CreateString(row['protocol_type']) 25 | service = builder.CreateString(row['service']) 26 | flag = builder.CreateString(row['flag']) 27 | 28 | PacketStart(builder) 29 | PacketAddDuration(builder, row['duration']) 30 | PacketAddProtocolType(builder, protocol_type) 31 | PacketAddService(builder, service) 32 | PacketAddFlag(builder, flag) 33 | PacketAddSrcBytes(builder, row['src_bytes']) 34 | PacketAddDstBytes(builder, row['dst_bytes']) 35 | PacketAddLand(builder, row['land']) 36 | PacketAddWrongFragment(builder, row['wrong_fragment']) 37 | PacketAddUrgent(builder, row['urgent']) 38 | PacketAddHot(builder, row['hot']) 39 | PacketAddNumFailedLogins(builder, row['num_failed_logins']) 40 | PacketAddLoggedIn(builder, row['logged_in']) 41 | PacketAddNumCompromised(builder, row['num_compromised']) 42 | PacketAddRootShell(builder, row['root_shell']) 43 | PacketAddSuAttempted(builder, row['su_attempted']) 44 | PacketAddNumRoot(builder, row['num_root']) 45 | PacketAddNumFileCreations(builder, row['num_file_creations']) 46 | PacketAddNumShells(builder, row['num_shells']) 47 | PacketAddNumAccessFiles(builder, row['num_access_files']) 48 | PacketAddNumOutboundCmds(builder, row['num_outbound_cmds']) 49 | PacketAddIsHostLogin(builder, row['is_host_login']) 50 | PacketAddIsGuestLogin(builder, row['is_guest_login']) 51 | PacketAddCount(builder, row['count']) 52 | PacketAddSrvCount(builder, row['srv_count']) 53 | PacketAddSerrorRate(builder, row['serror_rate']) 54 | PacketAddSrvSerrorRate(builder, row['srv_serror_rate']) 55 | PacketAddRerrorRate(builder, row['rerror_rate']) 56 | PacketAddSrvRerrorRate(builder, row['srv_rerror_rate']) 57 | PacketAddSameSrvRate(builder, row['same_srv_rate']) 58 | PacketAddDiffSrvRate(builder, row['diff_srv_rate']) 59 | PacketAddSrvDiffHostRate(builder, row['srv_diff_host_rate']) 60 | PacketAddDstHostCount(builder, row['dst_host_count']) 61 | PacketAddDstHostSrvCount(builder, row['dst_host_srv_count']) 62 | PacketAddDstHostSameSrvRate(builder, row['dst_host_same_srv_rate']) 63 | PacketAddDstHostDiffSrvRate(builder, row['dst_host_diff_srv_rate']) 64 | PacketAddDstHostSameSrcPortRate( 65 | builder, row['dst_host_same_src_port_rate']) 66 | PacketAddDstHostSrvDiffHostRate( 67 | builder, row['dst_host_srv_diff_host_rate']) 68 | PacketAddDstHostSerrorRate(builder, row['dst_host_serror_rate']) 69 | PacketAddDstHostSrvSerrorRate(builder, row['dst_host_srv_serror_rate']) 70 | PacketAddDstHostRerrorRate(builder, row['dst_host_rerror_rate']) 71 | PacketAddDstHostSrvRerrorRate(builder, row['dst_host_srv_rerror_rate']) 72 | 73 | orc = PacketEnd(builder) 74 | builder.Finish(orc) 75 | buf = builder.Output() 76 | 77 | r = requests.post('http://localhost:5000/predict', data=buf, headers={'Content-Type': 'application/octet-stream'}) 78 | if r.text.strip() == 'normal' and row['labels'].strip() == 'normal': 79 | correct = correct + 1 80 | if r.text.strip() == 'anomaly' and row['labels'].strip() != 'normal': 81 | correct = correct + 1 82 | accuracy = (correct * 1.0)/200*100 83 | assert accuracy > 74 84 | 85 | 86 | # if __name__ == '__main__': 87 | # for col_name in COL_NAMES: 88 | # col_name_split = [x.capitalize() for x in col_name.split('_')] 89 | # print 'PacketAdd' + ''.join(col_name_split) + "(builder, row['" + col_name + "'])" 90 | # print 'packetBuilder.add_' + col_name + '(0);' 91 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | 49 | # Translations 50 | *.mo 51 | *.pot 52 | 53 | # Django stuff: 54 | *.log 55 | local_settings.py 56 | 57 | # Flask stuff: 58 | instance/ 59 | .webassets-cache 60 | 61 | # Scrapy stuff: 62 | .scrapy 63 | 64 | # Sphinx documentation 65 | docs/_build/ 66 | 67 | # PyBuilder 68 | target/ 69 | 70 | # Jupyter Notebook 71 | .ipynb_checkpoints 72 | 73 | # pyenv 74 | .python-version 75 | 76 | # celery beat schedule file 77 | celerybeat-schedule 78 | 79 | # SageMath parsed files 80 | *.sage.py 81 | 82 | # dotenv 83 | .env 84 | 85 | # virtualenv 86 | .venv 87 | venv/ 88 | ENV/ 89 | 90 | # Spyder project settings 91 | .spyderproject 92 | .spyproject 93 | 94 | # Rope project settings 95 | .ropeproject 96 | 97 | # mkdocs documentation 98 | /site 99 | 100 | # mypy 101 | .mypy_cache/ 102 | 103 | ## Core latex/pdflatex auxiliary files: 104 | *.aux 105 | *.lof 106 | *.log 107 | *.lot 108 | *.fls 109 | *.out 110 | *.toc 111 | *.fmt 112 | *.fot 113 | *.cb 114 | *.cb2 115 | .*.lb 116 | 117 | ## Intermediate documents: 118 | *.dvi 119 | *.xdv 120 | *-converted-to.* 121 | # these rules might exclude image files for figures etc. 122 | # *.ps 123 | # *.eps 124 | # *.pdf 125 | 126 | ## Generated if empty string is given at "Please type another file name for output:" 127 | .pdf 128 | 129 | ## Bibliography auxiliary files (bibtex/biblatex/biber): 130 | *.bbl 131 | *.bcf 132 | *.blg 133 | *-blx.aux 134 | *-blx.bib 135 | *.run.xml 136 | 137 | ## Build tool auxiliary files: 138 | *.fdb_latexmk 139 | *.synctex 140 | *.synctex(busy) 141 | *.synctex.gz 142 | *.synctex.gz(busy) 143 | *.pdfsync 144 | 145 | ## Auxiliary and intermediate files from other packages: 146 | # algorithms 147 | *.alg 148 | *.loa 149 | 150 | # achemso 151 | acs-*.bib 152 | 153 | # amsthm 154 | *.thm 155 | 156 | # beamer 157 | *.nav 158 | *.pre 159 | *.snm 160 | *.vrb 161 | 162 | # changes 163 | *.soc 164 | 165 | # cprotect 166 | *.cpt 167 | 168 | # elsarticle (documentclass of Elsevier journals) 169 | *.spl 170 | 171 | # endnotes 172 | *.ent 173 | 174 | # fixme 175 | *.lox 176 | 177 | # feynmf/feynmp 178 | *.mf 179 | *.mp 180 | *.t[1-9] 181 | *.t[1-9][0-9] 182 | *.tfm 183 | 184 | #(r)(e)ledmac/(r)(e)ledpar 185 | *.end 186 | *.?end 187 | *.[1-9] 188 | *.[1-9][0-9] 189 | *.[1-9][0-9][0-9] 190 | *.[1-9]R 191 | *.[1-9][0-9]R 192 | *.[1-9][0-9][0-9]R 193 | *.eledsec[1-9] 194 | *.eledsec[1-9]R 195 | *.eledsec[1-9][0-9] 196 | *.eledsec[1-9][0-9]R 197 | *.eledsec[1-9][0-9][0-9] 198 | *.eledsec[1-9][0-9][0-9]R 199 | 200 | # glossaries 201 | *.acn 202 | *.acr 203 | *.glg 204 | *.glo 205 | *.gls 206 | *.glsdefs 207 | 208 | # gnuplottex 209 | *-gnuplottex-* 210 | 211 | # gregoriotex 212 | *.gaux 213 | *.gtex 214 | 215 | # htlatex 216 | *.4ct 217 | *.4tc 218 | *.idv 219 | *.lg 220 | *.trc 221 | *.xref 222 | 223 | # hyperref 224 | *.brf 225 | 226 | # knitr 227 | *-concordance.tex 228 | # TODO Comment the next line if you want to keep your tikz graphics files 229 | *.tikz 230 | *-tikzDictionary 231 | 232 | # listings 233 | *.lol 234 | 235 | # makeidx 236 | *.idx 237 | *.ilg 238 | *.ind 239 | *.ist 240 | 241 | # minitoc 242 | *.maf 243 | *.mlf 244 | *.mlt 245 | *.mtc[0-9]* 246 | *.slf[0-9]* 247 | *.slt[0-9]* 248 | *.stc[0-9]* 249 | 250 | # minted 251 | _minted* 252 | *.pyg 253 | 254 | # morewrites 255 | *.mw 256 | 257 | # nomencl 258 | *.nlo 259 | 260 | # pax 261 | *.pax 262 | 263 | # pdfpcnotes 264 | *.pdfpc 265 | 266 | # sagetex 267 | *.sagetex.sage 268 | *.sagetex.py 269 | *.sagetex.scmd 270 | 271 | # scrwfile 272 | *.wrt 273 | 274 | # sympy 275 | *.sout 276 | *.sympy 277 | sympy-plots-for-*.tex/ 278 | 279 | # pdfcomment 280 | *.upa 281 | *.upb 282 | 283 | # pythontex 284 | *.pytxcode 285 | pythontex-files-*/ 286 | 287 | # thmtools 288 | *.loe 289 | 290 | # TikZ & PGF 291 | *.dpth 292 | *.md5 293 | *.auxlock 294 | 295 | # todonotes 296 | *.tdo 297 | 298 | # easy-todo 299 | *.lod 300 | 301 | # xindy 302 | *.xdy 303 | 304 | # xypic precompiled matrices 305 | *.xyc 306 | 307 | # endfloat 308 | *.ttt 309 | *.fff 310 | 311 | # Latexian 312 | TSWLatexianTemp* 313 | 314 | ## Editors: 315 | # WinEdt 316 | *.bak 317 | *.sav 318 | 319 | # Texpad 320 | .texpadtmp 321 | 322 | # Kile 323 | *.backup 324 | 325 | # KBibTeX 326 | *~[0-9]* 327 | 328 | # auto folder when using emacs and auctex 329 | ./auto/* 330 | *.el 331 | 332 | # expex forward references with \gathertags 333 | *-tags.tex 334 | 335 | # standalone packages 336 | *.sta 337 | 338 | .vscode 339 | .pytest_cache -------------------------------------------------------------------------------- /plugin/extractor/Config.cpp: -------------------------------------------------------------------------------- 1 | #include "Config.h" 2 | 3 | namespace FeatureExtractor { 4 | /** 5 | * Constructor for default timeout values: 6 | * - IP Fragmentation timeout 30s (Linux default) 7 | * http://www.linuxinsight.com/proc_sys_net_ipv4_ipfrag_time.html 8 | * - Other values derived from iptables doc 9 | * http://www.iptables.info/en/connection-state.html 10 | */ 11 | Config::Config() 12 | : files_c(0) 13 | , files_v(nullptr) 14 | , interface_num(1) 15 | , pcap_read_timeout(1000) 16 | , additional_frame_len(0) 17 | , ipfrag_timeout(30) 18 | , ipfrag_check_interval_ms(1000) 19 | , tcp_syn_timeout(120) 20 | , tcp_estab_timeout(5 * 24 * 3600) // 5 days 21 | , tcp_rst_timeout(10) 22 | , tcp_fin_timeout(120) 23 | , tcp_last_ack_timeout(30) 24 | , udp_timeout(180) 25 | , icmp_timeout(30) 26 | , conversation_check_interval_ms(1000) 27 | , time_window_size_ms(2000) 28 | , count_window_size(100) 29 | , print_extra_features(false) 30 | , print_filename(false) 31 | { 32 | } 33 | 34 | 35 | Config::~Config() 36 | { 37 | } 38 | 39 | int Config::get_files_count() const 40 | { 41 | return files_c; 42 | } 43 | void Config::set_files_count(int files_c) 44 | { 45 | this->files_c = files_c; 46 | } 47 | 48 | char **Config::get_files_values() const 49 | { 50 | return files_v; 51 | } 52 | void Config::set_files_values(char **files_v) 53 | { 54 | this->files_v = files_v; 55 | } 56 | 57 | int Config::get_interface_num() const 58 | { 59 | return interface_num; 60 | } 61 | void Config::set_interface_num(int interface_num) 62 | { 63 | this->interface_num = interface_num; 64 | } 65 | 66 | int Config::get_pcap_read_timeout() const 67 | { 68 | return pcap_read_timeout; 69 | } 70 | void Config::set_pcap_read_timeout(int pcap_read_timeout) 71 | { 72 | this->pcap_read_timeout = pcap_read_timeout; 73 | } 74 | 75 | size_t Config::get_additional_frame_len() const 76 | { 77 | return additional_frame_len; 78 | } 79 | void Config::set_additional_frame_len(size_t additional_frame_len) 80 | { 81 | this->additional_frame_len = additional_frame_len; 82 | } 83 | 84 | 85 | uint32_t Config::get_ipfrag_timeout() const 86 | { 87 | return ipfrag_timeout; 88 | } 89 | void Config::set_ipfrag_timeout(uint32_t ipfrag_timeout) 90 | { 91 | this->ipfrag_timeout = ipfrag_timeout; 92 | } 93 | 94 | uint32_t Config::get_ipfrag_check_interval_ms() const 95 | { 96 | return ipfrag_check_interval_ms; 97 | } 98 | void Config::set_ipfrag_check_interval_ms(uint32_t ipfrag_check_interval_ms) 99 | { 100 | this->ipfrag_check_interval_ms = ipfrag_check_interval_ms; 101 | } 102 | 103 | uint32_t Config::get_tcp_syn_timeout() const 104 | { 105 | return tcp_syn_timeout; 106 | } 107 | void Config::set_tcp_syn_timeout(uint32_t tcp_syn_timeout) 108 | { 109 | this->tcp_syn_timeout = tcp_syn_timeout; 110 | } 111 | 112 | uint32_t Config::get_tcp_estab_timeout() const 113 | { 114 | return tcp_estab_timeout; 115 | } 116 | void Config::set_tcp_estab_timeout(uint32_t tcp_estab_timeout) 117 | { 118 | this->tcp_estab_timeout = tcp_estab_timeout; 119 | } 120 | 121 | uint32_t Config::get_tcp_rst_timeout() const 122 | { 123 | return tcp_rst_timeout; 124 | } 125 | void Config::set_tcp_rst_timeout(uint32_t tcp_rst_timeout) 126 | { 127 | this->tcp_rst_timeout = tcp_rst_timeout; 128 | } 129 | 130 | uint32_t Config::get_tcp_fin_timeout() const 131 | { 132 | return tcp_fin_timeout; 133 | } 134 | void Config::set_tcp_fin_timeout(uint32_t tcp_fin_timeout) 135 | { 136 | this->tcp_fin_timeout = tcp_fin_timeout; 137 | } 138 | 139 | uint32_t Config::get_tcp_last_ack_timeout() const 140 | { 141 | return tcp_last_ack_timeout; 142 | } 143 | void Config::set_tcp_last_ack_timeout(uint32_t tcp_last_ack_timeout) 144 | { 145 | this->tcp_last_ack_timeout = tcp_last_ack_timeout; 146 | } 147 | 148 | uint32_t Config::get_udp_timeout() const 149 | { 150 | return udp_timeout; 151 | } 152 | void Config::set_udp_timeout(uint32_t udp_timeout) 153 | { 154 | this->udp_timeout = udp_timeout; 155 | } 156 | 157 | uint32_t Config::get_icmp_timeout() const 158 | { 159 | return icmp_timeout; 160 | } 161 | void Config::set_icmp_timeout(uint32_t icmp_timeout) 162 | { 163 | this->icmp_timeout = icmp_timeout; 164 | } 165 | 166 | uint32_t Config::get_conversation_check_interval_ms() const 167 | { 168 | return conversation_check_interval_ms; 169 | } 170 | void Config::set_conversation_check_interval_ms(uint32_t conversation_check_interval_ms) 171 | { 172 | this->conversation_check_interval_ms = conversation_check_interval_ms; 173 | } 174 | 175 | unsigned int Config::get_time_window_size_ms() const 176 | { 177 | return time_window_size_ms; 178 | } 179 | void Config::set_time_window_size_ms(unsigned int time_window_size_ms) 180 | { 181 | this->time_window_size_ms = time_window_size_ms; 182 | } 183 | 184 | unsigned int Config::get_count_window_size() const 185 | { 186 | return count_window_size; 187 | } 188 | void Config::set_count_window_size(unsigned int count_window_size) 189 | { 190 | this->count_window_size = count_window_size; 191 | } 192 | 193 | bool Config::should_print_extra_features() const 194 | { 195 | return print_extra_features; 196 | } 197 | void Config::set_print_extra_features(bool print_extra_features) 198 | { 199 | this->print_extra_features = print_extra_features; 200 | } 201 | 202 | bool Config::should_print_filename() const 203 | { 204 | return print_filename; 205 | } 206 | void Config::set_print_filename(bool print_filename) 207 | { 208 | this->print_filename = print_filename; 209 | } 210 | 211 | 212 | } 213 | -------------------------------------------------------------------------------- /docs/sections/experiment.tex: -------------------------------------------------------------------------------- 1 | \section{Mô hình hệ thống} 2 | Hệ thống được chia làm 2 phần: 3 | \begin{enumerate} 4 | \item Snort Plugin: có nhiệm vụ nhận và phân tích gói tin thành 41 thuộc tính \cite{featureextraction} phù hợp với tập dữ liệu 5 | NSL-KDD, sau đó mã hóa dùng Flatbuffer và gửi đến máy chủ thông qua http request 6 | \item Máy chủ dự đoán: có nhiệm vụ huấn luyện mạng dự đoán dùng thuật toán KMeans với tập dữ liệu NSL-KDD \cite{kmeanswithnslkdd}, 7 | đồng thời khởi tạo máy chủ web có endpoint \textbf{/predict} để snort gửi request đến dự đoán 8 | và trả về kết quả 9 | \end{enumerate} 10 | \begin{figure}[!htbp] 11 | \centering 12 | \includegraphics[scale=0.5]{workflow} 13 | \caption{Mô hình hoạt động} 14 | \label{fig:x cubed graph} 15 | \end{figure} 16 | \FloatBarrier 17 | \subsection{Snort Plugin} 18 | \begin{figure}[!htbp] 19 | \centering 20 | \includegraphics[scale=0.4]{snort1} 21 | \caption{Đăng ký plugin với snort} 22 | \label{fig:x cubed graph} 23 | \end{figure} 24 | \FloatBarrier 25 | Khi có gói tin mới đến, snort sẽ gọi đến plugin thông qua hàm eval để xử lý gói tin. 26 | Ở đây ta chỉ chấp nhận các gói tin UDP, TCP và ICMP. Đầu tiên ta cần phân tích thông tin riêng lẻ của từng gói tin, sau đó đưa vào conversation 27 | để phân tích các thông tin liên quan đến thời gian cũng như máy nhận của các packet. 28 | Nếu gói tin bất thường sẽ được gọi đến DetectionEngine của Snort. 29 | \begin{figure}[!htbp] 30 | \centering 31 | \includegraphics[scale=0.4]{snort2} 32 | \caption{Hàm xử lý khi có gói tin mới} 33 | \label{fig:x cubed graph} 34 | \end{figure} 35 | \FloatBarrier 36 | Phân tích gói tin để lấy các thông tin cơ bản riêng biệt chuẩn bị để dự đoán 37 | \begin{figure}[!htbp] 38 | \centering 39 | \includegraphics[scale=0.4]{snort6} 40 | \caption{Phân tích các thông tin cơ bản của gói tin} 41 | \label{fig:x cubed graph} 42 | \end{figure} 43 | \FloatBarrier 44 | \begin{figure}[!htbp] 45 | \centering 46 | \includegraphics[scale=0.4]{snort7} 47 | \caption{Phân tích các thông tin cơ bản của gói tin} 48 | \label{fig:x cubed graph} 49 | \end{figure} 50 | \FloatBarrier 51 | Sau khi trích xuất các thông tin cần thiết từ gói tin, dữ liệu được tách thành 41 features cho dự đoán, 52 | được mã hóa bằng Flatbuffer. Chỉ phân tích được các thuộc tính từ 1 đến 10 và từ 23 đến 41. 53 | Các thuộc tính chứa nội dung từ 10 đến 22 không phân tích được. 54 | \begin{figure}[!htbp] 55 | \centering 56 | \includegraphics[scale=0.4]{snort3} 57 | \caption{Mã hóa thông tin gói tin dùng Flatbuffer} 58 | \label{fig:x cubed graph} 59 | \end{figure} 60 | \FloatBarrier 61 | \begin{figure}[!htbp] 62 | \centering 63 | \includegraphics[scale=0.4]{snort4} 64 | \caption{Mã hóa thông tin gói tin dùng Flatbuffer} 65 | \label{fig:x cubed graph} 66 | \end{figure} 67 | \FloatBarrier 68 | Sau khi đã phân tích và mã hóa dùng Flatbuffer, chuỗi đã mã hóa được đến máy chủ dự đoán dùng libcurl 69 | \begin{figure}[!htbp] 70 | \centering 71 | \includegraphics[scale=0.4]{snort5} 72 | \caption{Gọi đến máy chủ dự đoán} 73 | \label{fig:x cubed graph} 74 | \end{figure} 75 | \FloatBarrier 76 | \subsection{Máy chủ dự đoán} 77 | Máy chủ dự đoán có nhiệm vụ huấn luyện mạng dự đoán, khởi tạo endpoint /predict để plugin snort gửi yêu cầu http đến kiểm tra gói tin. 78 | Máy chủ cũng cung cấp trang thống kê đơn giản để người dùng quan sát 79 | \begin{figure}[!htbp] 80 | \centering 81 | \includegraphics[scale=0.5]{server1} 82 | \caption{Máy chủ dự đoán} 83 | \label{fig:x cubed graph} 84 | \end{figure} 85 | \FloatBarrier 86 | \begin{figure}[!htbp] 87 | \centering 88 | \includegraphics[scale=0.4]{server5} 89 | \caption{Nhập và xử lý tập dữ liệu} 90 | \label{fig:x cubed graph} 91 | \end{figure} 92 | \FloatBarrier 93 | \begin{figure}[!htbp] 94 | \centering 95 | \includegraphics[scale=0.5]{server4} 96 | \caption{Dùng thuật toán KMeans tạo 4 clusters} 97 | \label{fig:x cubed graph} 98 | \end{figure} 99 | \FloatBarrier 100 | Endpoint sẽ phân tích request lấy và giải mã Flatbuffer để lấy được cái thông tin gói tin để đưa vào mạng dự đoán 101 | \begin{figure}[!htbp] 102 | \centering 103 | \includegraphics[scale=0.6]{server2} 104 | \caption{Nhận và giải mã Flatbuffer} 105 | \label{fig:x cubed graph} 106 | \end{figure} 107 | \FloatBarrier 108 | Sau khi đã giải mã thành công, sẽ đưa vào mạng dự đoán Kmeans để dự đoán và trả về kết quả cho Snort plugin 109 | \begin{figure}[!htbp] 110 | \centering 111 | \includegraphics[scale=0.6]{server3} 112 | \caption{Dự đoán gói tin} 113 | \label{fig:x cubed graph} 114 | \end{figure} 115 | \FloatBarrier 116 | \section{Thử nghiệm và nhận xét} 117 | \begin{figure}[!htbp] 118 | \centering 119 | \includegraphics[scale=0.4]{test1} 120 | \caption{Màn hình thống kê ban đầu} 121 | \label{fig:x cubed graph} 122 | \end{figure} 123 | \FloatBarrier 124 | \begin{figure}[!htbp] 125 | \centering 126 | \includegraphics[scale=0.4]{test2} 127 | \caption{Khởi tạo Docker Compose để thử nghiệm} 128 | \label{fig:x cubed graph} 129 | \end{figure} 130 | \FloatBarrier 131 | \begin{figure}[!htbp] 132 | \centering 133 | \includegraphics[scale=0.6]{test3} 134 | \caption{Thử tấn công Ping Flood sử dụng công cụ hping3} 135 | \label{fig:x cubed graph} 136 | \end{figure} 137 | \FloatBarrier 138 | \begin{figure}[!htbp] 139 | \centering 140 | \includegraphics[scale=0.4]{test4} 141 | \caption{Không phát hiện được tấn công} 142 | \label{fig:x cubed graph} 143 | \end{figure} 144 | \FloatBarrier 145 | \begin{figure}[!htbp] 146 | \centering 147 | \includegraphics[scale=0.6]{test5} 148 | \caption{Thử tấn công Scan port bằng công cụ nmap} 149 | \label{fig:x cubed graph} 150 | \end{figure} 151 | \FloatBarrier 152 | \begin{figure}[!htbp] 153 | \centering 154 | \includegraphics[scale=0.4]{test6} 155 | \caption{Không phát hiện được tấn công} 156 | \label{fig:x cubed graph} 157 | \end{figure} 158 | \FloatBarrier -------------------------------------------------------------------------------- /plugin/extractor/Packet.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Packet.h" 4 | 5 | namespace FeatureExtractor { 6 | using namespace std; 7 | 8 | Packet::Packet() 9 | : start_ts(), eth2(false), eth_type(TYPE_ZERO), five_tuple() 10 | , tcp_flags(), icmp_type(ECHOREPLY), icmp_code(0) 11 | , length(0) 12 | { 13 | } 14 | 15 | 16 | Packet::~Packet() 17 | { 18 | } 19 | 20 | Timestamp Packet::get_start_ts() const 21 | { 22 | return start_ts; 23 | } 24 | 25 | void Packet::set_start_ts(const Timestamp &start_ts) 26 | { 27 | this->start_ts = start_ts; 28 | } 29 | 30 | Timestamp Packet::get_end_ts() const 31 | { 32 | // Return the start timestamp by default 33 | return start_ts; 34 | } 35 | 36 | bool Packet::is_eth2() const 37 | { 38 | return eth2; 39 | } 40 | 41 | void Packet::set_eth2(bool is_eth2) 42 | { 43 | this->eth2 = is_eth2; 44 | } 45 | 46 | eth_field_type_t Packet::get_eth_type() const 47 | { 48 | return eth_type; 49 | } 50 | 51 | void Packet::set_eth_type(eth_field_type_t eth_type){ 52 | this->eth_type = eth_type; 53 | } 54 | 55 | FiveTuple Packet::get_five_tuple() const 56 | { 57 | return five_tuple; 58 | } 59 | void Packet::set_five_tuple(const FiveTuple &five_tuple) 60 | { 61 | this->five_tuple = five_tuple; 62 | } 63 | 64 | ip_field_protocol_t Packet::get_ip_proto() const 65 | { 66 | return five_tuple.get_ip_proto(); 67 | } 68 | 69 | void Packet::set_ip_proto(ip_field_protocol_t ip_proto) 70 | { 71 | this->five_tuple.set_ip_proto(ip_proto); 72 | } 73 | 74 | uint32_t Packet::get_src_ip() const 75 | { 76 | return five_tuple.get_src_ip(); 77 | } 78 | 79 | void Packet::set_src_ip(uint32_t src_ip) 80 | { 81 | this->five_tuple.set_src_ip(src_ip); 82 | } 83 | 84 | uint32_t Packet::get_dst_ip() const 85 | { 86 | return five_tuple.get_dst_ip(); 87 | } 88 | 89 | void Packet::set_dst_ip(uint32_t dst_ip) 90 | { 91 | this->five_tuple.set_dst_ip(dst_ip); 92 | } 93 | 94 | uint16_t Packet::get_src_port() const 95 | { 96 | return five_tuple.get_src_port(); 97 | } 98 | 99 | void Packet::set_src_port(uint16_t src_port) 100 | { 101 | this->five_tuple.set_src_port(src_port); 102 | } 103 | 104 | uint16_t Packet::get_dst_port() const 105 | { 106 | return five_tuple.get_dst_port(); 107 | } 108 | 109 | void Packet::set_dst_port(uint16_t dst_port) 110 | { 111 | this->five_tuple.set_dst_port(dst_port); 112 | } 113 | 114 | tcp_field_flags_t Packet::get_tcp_flags() const 115 | { 116 | return tcp_flags; 117 | } 118 | 119 | void Packet::set_tcp_flags(tcp_field_flags_t tcp_flags) 120 | { 121 | this->tcp_flags = tcp_flags; 122 | } 123 | 124 | icmp_field_type_t Packet::get_icmp_type() const 125 | { 126 | return icmp_type; 127 | } 128 | void Packet::set_icmp_type(icmp_field_type_t icmp_type) 129 | { 130 | this->icmp_type = icmp_type; 131 | } 132 | 133 | uint8_t Packet::get_icmp_code() const 134 | { 135 | return icmp_code; 136 | } 137 | void Packet::set_icmp_code(uint8_t icmp_code) 138 | { 139 | this->icmp_code = icmp_code; 140 | } 141 | 142 | size_t Packet::get_length() const 143 | { 144 | return length; 145 | } 146 | 147 | void Packet::set_length(size_t length) 148 | { 149 | this->length = length; 150 | } 151 | 152 | uint16_t Packet::get_frame_count() const 153 | { 154 | // By default packet consists of 1 frame 155 | return 1; 156 | } 157 | 158 | // Allow using localtime instead of localtime_s 159 | #ifdef _MSC_VER 160 | #pragma warning(disable:4996) 161 | #endif 162 | void Packet::print_human() const 163 | { 164 | // TODO: WTF ugly code, just for debugging, mal si branic.. 165 | stringstream ss; 166 | 167 | struct tm *ltime; 168 | //struct tm timeinfo; 169 | char timestr[16]; 170 | time_t local_tv_sec; 171 | //local_tv_sec = start_ts.get_secs(); 172 | ltime = localtime(&local_tv_sec); 173 | //localtime_s(&timeinfo, &local_tv_sec); 174 | strftime(timestr, sizeof timestr, "%H:%M:%S", ltime); 175 | //strftime(timestr, sizeof timestr, "%H:%M:%S", &timeinfo); 176 | ss << timestr; 177 | 178 | ss << (is_eth2() ? " ETHERNET II" : " NON-ETHERNET"); 179 | if (!is_eth2()) { 180 | cout << endl << ss.str() << endl; 181 | return; 182 | } 183 | ss << (eth_type == IPV4 ? " > IP" : " > NON-IP"); 184 | if (eth_type != IPV4) { 185 | ss << "(0x" << hex << eth_type << dec << ")"; 186 | cout << endl << ss.str() << endl; 187 | return; 188 | } 189 | 190 | if (get_ip_proto() == ICMP) { 191 | ss << " > ICMP " << endl; 192 | } 193 | else if (get_ip_proto() == TCP) { 194 | ss << " > TCP " << endl; 195 | } 196 | else if (get_ip_proto() == UDP) { 197 | ss << " > UDP " << endl; 198 | } 199 | else { 200 | ss << " > Other(0x" << hex << get_ip_proto() << dec << ")" << endl; 201 | } 202 | 203 | // Cast ips to arrays of octets 204 | uint32_t src_ip = get_src_ip(); 205 | uint32_t dst_ip = get_dst_ip(); 206 | uint8_t *sip = (uint8_t *)&src_ip; 207 | uint8_t *dip = (uint8_t *)&dst_ip; 208 | 209 | if (get_ip_proto() != TCP && get_ip_proto() != UDP) { 210 | ss << " src=" << (int)sip[0] << "." << (int)sip[1] << "." << (int)sip[2] << "." << (int)sip[3]; 211 | ss << " dst=" << (int)dip[0] << "." << (int)dip[1] << "." << (int)dip[2] << "." << (int)dip[3]; 212 | ss << " length=" << get_length(); 213 | if (get_frame_count() > 1) 214 | ss << " frames=" << get_frame_count(); 215 | ss << endl; 216 | if (get_ip_proto() == ICMP) { 217 | ss << " icmp_type=" << icmp_type << " icmp_code=" << icmp_code << endl; 218 | } 219 | } 220 | else { 221 | ss << " src=" << (int)sip[0] << "." << (int)sip[1] << "." << (int)sip[2] << "." << (int)sip[3] << ":" << get_src_port(); 222 | ss << " dst=" << (int)dip[0] << "." << (int)dip[1] << "." << (int)dip[2] << "." << (int)dip[3] << ":" << get_dst_port(); 223 | ss << " length=" << get_length(); 224 | if (get_frame_count() > 1) 225 | ss << " frames=" << get_frame_count(); 226 | ss << endl; 227 | 228 | if (get_ip_proto() == TCP) { 229 | ss << " Flags(0x" << hex << (int) tcp_flags.flags << dec << "): "; 230 | ss << (tcp_flags.fin() ? "F" : ""); 231 | ss << (tcp_flags.syn() ? "S" : ""); 232 | ss << (tcp_flags.rst() ? "R" : ""); 233 | ss << (tcp_flags.ack() ? "A" : ""); 234 | ss << (tcp_flags.urg() ? "U" : ""); 235 | ss << endl; 236 | } 237 | } 238 | 239 | cout << endl << ss.str(); 240 | } 241 | 242 | } -------------------------------------------------------------------------------- /docs/sections/kmeans.tex: -------------------------------------------------------------------------------- 1 | \subsection{Giới thiệu} 2 | Thuật toán \textbf{K-means clustering} \cite{kmeans} do MacQueen giới thiệu trong tài liệu “J. Some Methods for Classification and Analysis of Multivariate Observations” năm 1967. 3 | K-means Clustering là một thuật toán dùng trong các bài toán phân loại/nhóm n đối tượng thành k nhóm dựa trên đặc tính/thuộc tính của đối tượng (k £n nguyên, dương). 4 | Về nguyên lý, có n đối tượng, mỗi đối tượng có m thuộc tính, ta phân chia được các đối tượng thành k nhóm dựa trên các thuộc tính của đối tượng bằng việc áp dụng thuật toán này. 5 | Coi mỗi thuộc tính của đối tượng (đối tượng có m thuộc tính) như một toạ độ của không gian m chiều và biểu diễn đối tượng như một điểm của không gian m chiều. 6 | \par 7 | Trong thuật toán K-means clustering, chúng ta không biết nhãn (label) của từng điểm dữ liệu. 8 | Mục đích là làm thể nào để phân dữ liệu thành các cụm (cluster) khác nhau sao cho dữ liệu trong cùng một cụm có tính chất giống nhau. 9 | \par 10 | \textbf{Ví dụ}: Một công ty muốn tạo ra những chính sách ưu đãi cho những nhóm khách hàng khác nhau dựa trên sự tương tác giữa mỗi khách hàng với công ty đó (số năm là khách hàng; số tiền khách hàng đã chi trả cho công ty; độ tuổi; giới tính; thành phố; nghề nghiệp; …). 11 | Giả sử công ty đó có rất nhiều dữ liệu của rất nhiều khách hàng nhưng chưa có cách nào chia toàn bộ khách hàng đó thành một số nhóm/cụm khác nhau. 12 | Nếu một người biết Machine Learning được đặt câu hỏi này, phương pháp đầu tiên ta nghĩ đến sẽ là K-means Clustering. 13 | Sau khi đã phân ra được từng nhóm, nhân viên công ty đó có thể lựa chọn ra một vài khách hàng trong mỗi nhóm để quyết định xem mỗi nhóm tương ứng với nhóm khách hàng nào. 14 | Phần việc cuối cùng này cần sự can thiệp của con người, nhưng lượng công việc đã được rút gọn đi rất nhiều. 15 | \par 16 | Ý tưởng đơn giản nhất về cluster (cụm) là tập hợp các điểm ở gần nhau trong một không gian nào đó (không gian này có thể có rất nhiều chiều trong trường hợp thông tin về một điểm dữ liệu là rất lớn). 17 | Hình bên dưới là một ví dụ về 3 cụm dữ liệu. 18 | \begin{figure}[!htbp] 19 | \centering 20 | \includegraphics[scale=0.5]{kmeans} 21 | \caption{Bài toán với 3 clusters.} 22 | \label{fig:x cubed graph} 23 | \end{figure} 24 | \FloatBarrier 25 | Giả sử mỗi cluster có một điểm đại diện (center) màu vàng. Và những điểm xung quanh mỗi center thuộc vào cùng nhóm với center đó. Một cách đơn giản nhất, xét một điểm bất kỳ, ta xét xem điểm đó gần với center nào nhất thì nó thuộc về cùng nhóm với center đó. Tới đây, chúng ta có một bài toán thú vị: \textit{Trên một vùng biển hình vuông lớn có ba đảo hình vuông, tam giác, và tròn màu vàng như hình trên. Một điểm trên biển được gọi là thuộc lãnh hải của một đảo nếu nó nằm gần đảo này hơn so với hai đảo kia . Hãy xác định ranh giới lãnh hải của các đảo} 26 | \subsection{Phân tích chi tiết} 27 | Đầu tiên là chuẩn bị dữ liệu cần phân cụm. Tiếp theo quyết định số lượng cụm (cluster) cần phân chia. Ở ví dụ này thử chọn số cluster là 3. Ở đây data được thể hiện dưới dạng các điểm cho dễ quan sát. Cự ly của các dữ liệu được hiểu là độ dài đoạn thẳng nối giữa 2 điểm với nhau. 28 | \begin{figure}[!htbp] 29 | \centering 30 | \includegraphics[scale=0.5]{kmeans_detail1} 31 | \caption{Cụm ban đầu.} 32 | \label{fig:x cubed graph} 33 | \end{figure} 34 | \FloatBarrier 35 | \textbf{Bước 2} 36 | \par 37 | Chọn ngẫu nhiên 3 điểm làm điểm trung tâm của cluster. 38 | \begin{figure}[!htbp] 39 | \centering 40 | \includegraphics[scale=0.5]{kmeans_detail2} 41 | \caption{Chọn ngẫu nhiên trung điểm.} 42 | \label{fig:x cubed graph} 43 | \end{figure} 44 | \FloatBarrier 45 | \textbf{Bước 3} 46 | \par 47 | Với các điểm dữ liệu không được chọn là điểm trung tâm thì tính toán khoảng cách từ chính điểm đó đến các cluster và quyết định cluster nào gần với mình nhất. 48 | \begin{figure}[!htbp] 49 | \centering 50 | \includegraphics[scale=0.5]{kmeans_detail3} 51 | \caption{Tính toán khoảng cách tới điểm.} 52 | \label{fig:x cubed graph} 53 | \end{figure} 54 | \FloatBarrier 55 | \textbf{Bước 4} 56 | \par 57 | Từ bước tính toán trên, tiến hành phân loại các điểm về các cluster đã quyết định(cluster gần nó nhất). Vậy là đã phân ra được 3 cụm. 58 | \begin{figure}[!htbp] 59 | \centering 60 | \includegraphics[scale=0.5]{kmeans_detail4} 61 | \caption{Phân thành 3 clusters.} 62 | \label{fig:x cubed graph} 63 | \end{figure} 64 | \FloatBarrier 65 | \textbf{Bước 5} 66 | \par 67 | Bước trên chúng ta đã thu được 3 cụm, bây giờ tiến hành tính trọng tâm của các điểm dữ liệu của từng cụm. Sau đó di chuyển điểm trung tâm của cụm sang vị trí vừa tính được. 68 | \begin{figure}[!htbp] 69 | \centering 70 | \includegraphics[scale=0.5]{kmeans_detail5} 71 | \caption{Tính trọng điểm.} 72 | \label{fig:x cubed graph} 73 | \end{figure} 74 | \FloatBarrier 75 | Vị trí mà 3 điểm trung tâm của cluster vừa di chuyển đến được hiểu ngắn gọn chính là điểm trung tâm đang di chuyển đến vị trí chính xác hơn. 76 | \newline 77 | \textbf{Bước 6} 78 | \par 79 | Một lần nữa tiến hành bước 3, tính toán lại khoảng các các điểm đến các điểm trung tâm. Sau đó phân loại lại các điểm dữ liệu về các cụm. 80 | \begin{figure}[!htbp] 81 | \centering 82 | \includegraphics[scale=0.5]{kmeans_detail6} 83 | \caption{Tính toán lại khoảng cách.} 84 | \label{fig:x cubed graph} 85 | \end{figure} 86 | \FloatBarrier 87 | \textbf{Bước 7} 88 | \par 89 | Sau đó lặp lại quá trình di chuyển cluster trung tâm và phân loại lại các điểm về các cụm gần nhất. 90 | Quá trình này sẽ dừng khi sau khi dữ liệu sau khi phân cụm lại không thay đổi gì so với lần trước. 91 | \begin{figure}[!htbp] 92 | \centering 93 | \includegraphics[scale=0.5]{kmeans_detail7} 94 | \caption{Kết quả.} 95 | \label{fig:x cubed graph} 96 | \end{figure} 97 | \FloatBarrier 98 | \subsection{Lưu ý} 99 | Trước khi sử dụng phương pháp này, chúng ta phải quyết định trước số lượng cluster, tuy nhiên trong quá trình tính toán số lượng cluster có thể khác với số lượng cluster mình dự đoán nên kết quả sẽ không chính xác. 100 | \par 101 | Vì vậy để giải quyết vấn đề này, để có thể chọn ra số lượng cluster thích hợp thì cần phải phân tích dữ liệu cẩn thận, chạy thử k-means với nhiều biến số số lượng cluster. 102 | \par 103 | Cùng ví dụ trên nếu thay số lượng cluster thành 2, kết quả phân loại sẽ thành ra như sau: 104 | \begin{figure}[!htbp] 105 | \centering 106 | \includegraphics[scale=0.5]{kmeans_2_clusters} 107 | \caption{Khi chia thành 2 cụm.} 108 | \label{fig:x cubed graph} 109 | \end{figure} 110 | \FloatBarrier -------------------------------------------------------------------------------- /docs/main.tex: -------------------------------------------------------------------------------- 1 | \documentclass[12pt,twoside]{report} 2 | \usepackage{geometry} 3 | \geometry{ 4 | a4paper, 5 | total={170mm,257mm}, 6 | left=20mm, 7 | top=20mm, 8 | } 9 | \usepackage[utf8]{inputenc} 10 | \usepackage[vietnamese,english]{babel} 11 | \usepackage{placeins} 12 | \usepackage{listings} 13 | \usepackage{pslatex} 14 | \usepackage{graphicx} 15 | \usepackage{multirow} 16 | \usepackage{fancyhdr} 17 | \usepackage{pdfpages} 18 | \graphicspath{{images/}{../images/}} 19 | 20 | \title{ 21 | {Thiết kế và triển khai hệ thống phát hiện xâm nhập dựa trên kĩ thuật máy học}\\ 22 | {\includegraphics[width=4cm]{logo}} 23 | } 24 | \author{ 25 | Nguyễn Đức Thông 26 | \\ 27 | Phạm Ngọc Hiếu Minh 28 | \\ 29 | Trần Thanh Tín 30 | } 31 | 32 | \pagestyle{fancy} 33 | \fancyhf{} 34 | \rhead{\thepage} 35 | \lfoot{GVHD: TS. Đàm Quang Hồng Hải} 36 | \rfoot{SVTH: 14520901 – 14520533 - 14520960} 37 | 38 | \begin{document} 39 | \selectlanguage{vietnamese} 40 | \pagenumbering{gobble} 41 | \includepdf[pages={1}]{cover.pdf} 42 | \newpage 43 | \begin{center} 44 | {\LARGE \textbf{Lời nói đầu}} 45 | \end{center} 46 | Bên cạnh sự phát triển nhanh chóng và những khả năng mạnh mẽ của công nghệ thông tin thì những vấn đề nhạy cảm như 47 | an toàn thông tin luôn làm cho chúng ta cảm thấy dè dặt. Chúng ta cần phải tăng cường khả năng an toàn thông tin để tránh 48 | khỏi sự mất mát dữ liệu do các lỗ hỏng bảo mật hay bị hacker, virus tấn công. Hàng loạt các giải pháp, cơ chế được các 49 | chuyên gia đưa ra để ngăn chặn, giảm thiểu rủi ro mà các lỗ hỏng bảo mật mang lại. Một trong những giải pháp có thể 50 | đáp ứng tốt cho vấn đề này là Triển khai hệ thống phát hiện xâm nhập dựa trên kĩ thuật máy học. 51 | \par 52 | Hệ thống phát hiện xâm nhập dựa trên kĩ thuật máy học là hệ thống có khả năng giám sát các luồng dữ liệu lưu thông trên mạng 53 | có khả năng phát hiện những hành động khả nghi, những xâm nhập trái phép cũng như các dấu hiệu khai thác bất hợp pháp 54 | nguồn tài nguyên của hệ thống mà từ đó ảnh hưởng tính ổn định, toàn vẹn và sẵn sàng của hệ thống mạng. 55 | Khi triển khai một hệ thống sử dụng máy học, thường phải giải quyết hai bài toán, một là chi phí triển khai, 56 | hai là khả năng đáp ứng linh hoạt của nó trước sự phát triển nhanh chóng của thời đại công nghệ hiện nay. 57 | Máy học ngày càng được tin dùng như 1 giải pháp tối ưu có thể đáp ứng cả hai yêu cầu này. 58 | \newpage 59 | \begin{center} 60 | {\LARGE \textbf{Lời cảm ơn}} 61 | \end{center} 62 | \par 63 | Chúng em xin chân thành cảm ơn Thầy Đàm Quang Hồng Hải đã tận tình hướng dẫn, chỉ bảo chúng em trong suốt thời gian thực hiện đồ án. Cảm ơn thầy vì tất cả những chỉ bảo và tài liệu mà thầy đã cung cấp cho chúng em để có thể hoàn thành được đề tài. Trong quá trình làm việc với Thầy, chúng em không những học hỏi được nhiều kiến thức bổ ích mà còn học được tinh thần làm việc,sự chuyên nghiệp trong công tác giảng dạy và kinh nghiệm nghiên cứu khoa học của Thầy. 64 | \par 65 | Mặc dù chúng em đã cố gắng hoàn thiện đồ án với tất cả sự nỗ lực của bản thân nhưng chắc chắn không thể tránh khỏi những thiếu sót. Kính mong quý Thầy Cô tận tình giúp chúng em hoàn thiện đồ án tốt hơn 66 | \par 67 | Một lần nữa, chúng em xin chân thành cảm ơn và luôn mong nhận được sự đóng góp quý báu của quý Thầy Cô. 68 | 69 | \hfill 70 | \begin{minipage}[t]{0.48\textwidth} 71 | \begin{center} 72 | TP.HCM, ngày 14 tháng 01 năm 2018\\ 73 | Sinh viên\\ 74 | Nguyễn Đức Thông\\ 75 | Phạm Ngọc Hiếu Minh\\ 76 | Trần Thanh Tín\\ 77 | \end{center} 78 | \end{minipage} 79 | \newpage 80 | \begin{center} 81 | {\LARGE \textbf{Lời cam đoan}} 82 | \end{center} 83 | \par 84 | Nhóm em, Nguyễn Đức Thông, Phạm Ngọc Hiếu Minh, Trần Thanh Tín xin cam đoan tất cả các nội dung và tài liệu trình bày trong đồ án này là thành quả của việc tự nghiên cứu, tổng hợp các kiến thức đã được học và làm việc thực tế của nhóm. Các thông tin trích dẫn từ các nguồn tài liệu khác nhau đều được ghi rõ và kèm với phần tài liệu tham khảo 85 | \par 86 | Chúng em xác nhận đồ án này là sản phẩm của nhóm chúng em thực hiện dưới sự hướng dẫn của TS. Đàm Quang Hồng Hải cùng với những sự giúp đỡ khác đều đã được ghi rõ trong báo cáo này. 87 | 88 | \hfill 89 | \begin{minipage}[t]{0.48\textwidth} 90 | \begin{center} 91 | TP.HCM, ngày 14 tháng 01 năm 2018\\ 92 | Sinh viên\\ 93 | Nguyễn Đức Thông\\ 94 | Phạm Ngọc Hiếu Minh\\ 95 | Trần Thanh Tín\\ 96 | \end{center} 97 | \end{minipage} 98 | \newpage 99 | \tableofcontents 100 | \listoffigures 101 | \listoftables 102 | \newpage 103 | \pagenumbering{arabic} 104 | \chapter{Giới thiệu} 105 | \input{sections/introduce} 106 | \newpage 107 | \chapter{Lí thuyết} 108 | \section{Hệ thống phát hiện xâm nhập} 109 | \input{sections/ids} 110 | \section{Khai phá dữ liệu} 111 | \input{sections/data-mining} 112 | \section{Máy học} 113 | \input{sections/machine-learning} 114 | \newpage 115 | \chapter{Công nghệ tiếp cận} 116 | \section{Snort 3} 117 | \input{sections/snort} 118 | \section{Scikit} 119 | \input{sections/scikit} 120 | \section{Thuật toán KMeans} 121 | \input{sections/kmeans} 122 | \section{Tập dữ liệu NSL-KDD} 123 | \input{sections/nsl-kdd} 124 | \section{Flatbuffer} 125 | \input{sections/flatbuffer} 126 | \newpage 127 | \chapter{Triển khai và thử nghiệm} 128 | \input{sections/experiment} 129 | \newpage 130 | \chapter{Kết luận} 131 | \input{sections/conclusion} 132 | 133 | \newpage 134 | \begin{thebibliography}{9} 135 | \bibitem{nslkdd} 136 | M. Tavallaee, E. Bagheri, W. Lu, and A. Ghorbani, 137 | \textit{A Detailed Analysis of the KDD CUP 99 Data Set}. 138 | Submitted to Second IEEE Symposium on Computational Intelligence for Security and Defense Applications (CISDA), 2009. 139 | 140 | \bibitem{machinelearning} 141 | L.Dhanabal, Dr. S.P. Shantharajah, 142 | \textit{A Study on NSL-KDD Dataset for Intrusion Detection System Based on Classification Algorithms}. 143 | International Journal of Advanced Research in Computer and Com- 144 | munication Engineering, Vol. 4, Issue 6, June 2015 145 | 146 | \bibitem{system} 147 | Sandeep Kumar Chandel, 148 | \textit{Intrusion Detection System 149 | using K-Means Data Mining 150 | and Outlier Detection 151 | Approach}. 152 | Masaryk University Faculty of Informatics, Bangalore, Spring 2017 153 | 154 | \bibitem{kmeans} 155 | K-means Clustering 156 | \\\texttt{https://machinelearningcoban.com/2017/01/01/kmeans/} 157 | 158 | \bibitem{featureextraction} 159 | KDD99 Feature Extraction 160 | \\\texttt{https://github.com/AI-IDS/kdd99\_feature\_extractor} 161 | 162 | \bibitem{kmeanswithnslkdd} 163 | K-means Clustering with NSL-KDD 164 | \\\texttt{https://github.com/AnomalyIDSBenchmark/KMeansNSL-KDD/} 165 | 166 | \end{thebibliography} 167 | \end{document} -------------------------------------------------------------------------------- /docs/sections/machine-learning.tex: -------------------------------------------------------------------------------- 1 | \subsection{Giới thiệu} 2 | Những năm gần đây, AI - Artificial Intelligence (Trí Tuệ Nhân Tạo), và cụ thể hơn là Machine Learning (Học Máy hoặc Máy Học) nổi lên như một bằng chứng của cuộc cách mạng công nghiệp lần thứ tư (1 - động cơ hơi nước, 2 - năng lượng điện, 3 - công nghệ thông tin). 3 | Trí Tuệ Nhân Tạo đang len lỏi vào mọi lĩnh vực trong đời sống mà có thể chúng ta không nhận ra. 4 | Xe tự hành của Google và Tesla, hệ thống tự tag khuôn mặt trong ảnh của Facebook, trợ lý ảo Siri của Apple, hệ thống gợi ý sản phẩm của Amazon, hệ thống gợi ý phim của Netflix, máy chơi cờ vây AlphaGo của Google DeepMind, …, chỉ là một vài trong vô vàn những ứng dụng của AI/Machine Learning. 5 | \par 6 | Machine Learning là một tập con của AI. 7 | Theo định nghĩa của Wikipedia, Machine learning is the subfield of computer science that “gives computers the ability to learn without being explicitly programmed”. 8 | Nói đơn giản, Machine Learning là một lĩnh vực nhỏ của Khoa Học Máy Tính, nó có khả năng tự học hỏi dựa trên dữ liệu đưa vào mà không cần phải được lập trình cụ thể. 9 | \par 10 | Những năm gần đây, khi mà khả năng tính toán của các máy tính được nâng lên một tầm cao mới và lượng dữ liệu khổng lồ được thu thập bởi các hãng công nghệ lớn, Machine Learning đã tiến thêm một bước dài và một lĩnh vực mới được ra đời gọi là Deep Learning (Học Sâu - thực sự tôi không muốn dịch từ này ra tiếng Việt). 11 | Deep Learning đã giúp máy tính thực thi những việc tưởng chừng như không thể vào 10 năm trước: phân loại cả ngàn vật thể khác nhau trong các bức ảnh, tự tạo chú thích cho ảnh, bắt chước giọng nói và chữ viết của con người, giao tiếp với con người, hay thậm chí cả sáng tác văn hay âm nhạc 12 | \subsection{Phân nhóm các thuật toán} 13 | Theo phương thức học, các thuật toán Machine Learning thường được chia làm 4 nhóm: 14 | \begin{itemize} 15 | \item Supervise learning (học có giám sát) 16 | \item Unsupervised learning ( học không có giám sát) 17 | \item Semi-supervised lerning ( Học bán giám sát) 18 | \item Reinforcement learning ( Học củng cố) 19 | \end{itemize} 20 | \begin{enumerate} 21 | \item \textbf{Học có giám sát (Supervised Learning)} 22 | \par 23 | Supervised learning là thuật toán dự đoán đầu ra (outcome) của một dữ liệu mới (new input) dựa trên các cặp (input, outcome) đã biết từ trước. 24 | Cặp dữ liệu này còn được gọi là (data, label), tức (dữ liệu, nhãn). 25 | Supervised learning là nhóm phổ biến nhất trong các thuật toán Machine Learning 26 | \begin{enumerate} 27 | \item \textbf{Classification (Phân loại)}: Một bài toán được gọi là classification nếu các label của input data được chia thành một số hữu hạn nhóm. 28 | Ví dụ: Gmail xác định xem một email có phải là spam hay không; các hãng tín dụng xác định xem một khách hàng có khả năng thanh toán nợ hay không. 29 | Ba ví dụ phía trên được chia vào loại này 30 | \par 31 | \item \textbf{Regression (Hồi quy)} 32 | Nếu label không được chia thành các nhóm mà là một giá trị thực cụ thể. Ví dụ: một căn nhà rộng x m2x m2, có yy phòng ngủ và cách trung tâm thành phố z kmz km sẽ có giá là bao nhiêu? 33 | \par 34 | Gần đây Microsoft có một ứng dụng dự đoán giới tính và tuổi dựa trên khuôn mặt. 35 | Phần dự đoán giới tính có thể coi là thuật toán Classification, phần dự đoán tuổi có thể coi là thuật toán Regression.  36 | Chú ý rằng phần dự đoán tuổi cũng có thể coi là Classification nếu ta coi tuổi là một số nguyên dương không lớn hơn 150, chúng ta sẽ có 150 class (lớp) khác nhau 37 | \end{enumerate} 38 | \item \textbf{Học không giám sát ( Unsupervise learning)} 39 | \par 40 | Trong thuật toán này, chúng ta không biết được outcome hay nhãn mà chỉ có dữ liệu đầu vào. 41 | Thuật toán unsupervised learning sẽ dựa vào cấu trúc của dữ liệu để thực hiện một công việc nào đó, ví dụ như phân nhóm (clustering) hoặc giảm số chiều của dữ liệu (dimension reduction) để thuận tiện trong việc lưu trữ và tính toán. 42 | \par 43 | Một cách toán học, Unsupervised learning là khi chúng ta chỉ có dữ liệu vào XX mà không biết nhãn YY tương ứng. 44 | Những thuật toán loại này được gọi là Unsupervised learning vì không giống như Supervised learning, chúng ta không biết câu trả lời chính xác cho mỗi dữ liệu đầu vào. 45 | Giống như khi ta học, không có thầy cô giáo nào chỉ cho ta biết đó là chữ A hay chữ B. 46 | Cụm không giám sát được đặt tên theo nghĩa này. 47 | \par 48 | Các bài toán Unsupervised learning được tiếp tục chia nhỏ thành hai loại: 49 | \begin{enumerate} 50 | \item \textbf{Clustering (phân nhóm)} 51 | \par 52 | Một bài toán phân nhóm toàn bộ dữ liệu XX thành các nhóm nhỏ dựa trên sự liên quan giữa các dữ liệu trong mỗi nhóm. 53 | Ví dụ: phân nhóm khách hàng dựa trên hành vi mua hàng. Điều này cũng giống như việc ta đưa cho một đứa trẻ rất nhiều mảnh ghép với các hình thù và màu sắc khác nhau, ví dụ tam giác, vuông, tròn với màu xanh và đỏ, sau đó yêu cầu trẻ phân chúng thành từng nhóm. 54 | Mặc dù không cho trẻ biết mảnh nào tương ứng với hình nào hoặc màu nào, nhiều khả năng chúng vẫn có thể phân loại các mảnh ghép theo màu hoặc hình dạng. 55 | \newline 56 | \newline 57 | \item \textbf{Association (kết hợp)} 58 | \par 59 | Là bài toán khi chúng ta muốn khám phá ra một quy luật dựa trên nhiều dữ liệu cho trước. 60 | Ví dụ: những khách hàng nam mua quần áo thường có xu hướng mua thêm đồng hồ hoặc thắt lưng; những khán giả xem phim Spider Man thường có xu hướng xem thêm phim Bat Man, dựa vào đó tạo ra một hệ thống gợi ý khách hàng (Recommendation System), thúc đẩy nhu cầu mua sắm. 61 | \end{enumerate} 62 | \item \textbf{Học bán giám sát ( Semi-Supervise Learning)} 63 | \par 64 | Các bài toán khi chúng ta có một lượng lớn dữ liệu XX nhưng chỉ một phần trong chúng được gán nhãn được gọi là Semi-Supervised Learning. Những bài toán thuộc nhóm này nằm giữa hai nhóm được nêu bên trên. 65 | \par 66 | Một ví dụ điển hình của nhóm này là chỉ có một phần ảnh hoặc văn bản được gán nhãn (ví dụ bức ảnh về người, động vật hoặc các văn bản khoa học, chính trị) và phần lớn các bức ảnh/văn bản khác chưa được gán nhãn được thu thập từ internet. 67 | Thực tế cho thấy rất nhiều các bài toán Machine Learning thuộc vào nhóm này vì việc thu thập dữ liệu có nhãn tốn rất nhiều thời gian và có chi phí cao. 68 | Rất nhiều loại dữ liệu thậm chí cần phải có chuyên gia mới gán nhãn được (ảnh y học chẳng hạn). 69 | Ngược lại, dữ liệu chưa có nhãn có thể được thu thập với chi phí thấp từ internet. 70 | \newline 71 | \newline 72 | \item \textbf{Học củng cố ( Reinforcement Learning)} 73 | \par 74 | Reinforcement learning là các bài toán giúp cho một hệ thống tự động xác định hành vi dựa trên hoàn cảnh để đạt được lợi ích cao nhất (maximizing the performance). Hiện tại, Reinforcement learning chủ yếu được áp dụng vào Lý Thuyết Trò Chơi (Game Theory), các thuật toán cần xác định nước đi tiếp theo để đạt được điểm số cao nhất 75 | \begin{figure}[!htbp] 76 | \centering 77 | \includegraphics[scale=0.5]{reinforcement_learning} 78 | \caption{AlphaGo chơi cờ vây với Lee Sedol. AlphaGo là một ví dụ điển hình của Reinforcement Learing} 79 | \label{fig:x cubed graph} 80 | \end{figure} 81 | \FloatBarrier 82 | \end{enumerate} -------------------------------------------------------------------------------- /docs/sections/nsl-kdd.tex: -------------------------------------------------------------------------------- 1 | \subsection{Giới thiệu} 2 | Bộ dữ liệu NSL-KDD \cite{nslkdd}, được đề xuất để giải quyết một số vấn đề cố hữu của tập dữ liệu KDD CUP'99. 3 | \par 4 | KDD CUP’99 là bộ dữ liệu được sử dụng rộng rãi nhất để phát hiện bất thường trong máy học. 5 | Nhưng Tavallaee và cộng sự đã tiến hành một phân tích thống kê về tập dữ liệu này và tìm thấy hai vấn đề quan trọng ảnh hưởng rất lớn đến hiệu năng của các hệ thống được đánh giá và kết quả đánh giá rất kém về các phương pháp phát hiện bất thường. 6 | Để giải quyết những vấn đề này, họ đề xuất một bộ dữ liệu mới, NSL-KDD, bao gồm các bản ghi đã chọn của bộ dữ liệu KDD hoàn chỉnh. 7 | \newline 8 | \par 9 | Sau đây là những ưu điểm của NSL-KDD so với bộ dữ liệu KDD gốc: 10 | \par 11 | \begin{itemize} 12 | \item Đầu tiên, nó không bao gồm các bản ghi dự phòng trong huấn luyện, vì vậy các bộ phân loại sẽ không bị thiên vị đối với các bản ghi thường xuyên hơn. 13 | \item Thứ hai, số lượng các bản ghi được chọn từ mỗi nhóm mức độ khó tỷ lệ nghịch với tỷ lệ phần trăm của các bản ghi trong bộ dữ liệu KDD gốc. 14 | Kết quả là, tỷ lệ phân loại của các phương pháp học máy riêng biệt khác nhau ở phạm vi rộng hơn, làm cho nó nhiều hiệu quả hơn để có một đánh giá chính xác về các kỹ thuật học tập khác nhau. 15 | \item Thứ ba, số lượng hồ sơ trong tập huấn và kiểm tra là hợp lý, điều này làm cho nó hợp lý để chạy thử nghiệm trên bộ hoàn chỉnh mà không cần phải chọn ngẫu nhiên một phần nhỏ. Do đó, kết quả đánh giá của các công trình nghiên cứu khác nhau sẽ nhất quán và có thể so sánh được. 16 | \end{itemize} 17 | \subsection{Đặc tính} 18 | \begin{figure}[!htbp] 19 | \centering 20 | \includegraphics[scale=0.5]{table1} 21 | \label{fig:x cubed graph} 22 | \end{figure} 23 | \FloatBarrier 24 | \begin{figure}[!htbp] 25 | \centering 26 | \includegraphics[scale=0.5]{table2} 27 | \label{fig:x cubed graph} 28 | \end{figure} 29 | \FloatBarrier 30 | \begin{figure}[!htbp] 31 | \centering 32 | \includegraphics[scale=0.5]{table3} 33 | \label{fig:x cubed graph} 34 | \end{figure} 35 | \FloatBarrier 36 | \begin{figure}[!htbp] 37 | \centering 38 | \includegraphics[scale=0.5]{table4} 39 | \label{fig:x cubed graph} 40 | \end{figure} 41 | \FloatBarrier 42 | \begin{figure}[!htbp] 43 | \centering 44 | \includegraphics[scale=0.5]{table5} 45 | \label{fig:x cubed graph} 46 | \end{figure} 47 | \FloatBarrier 48 | \begin{figure}[!htbp] 49 | \centering 50 | \includegraphics[scale=0.5]{table6} 51 | \label{fig:x cubed graph} 52 | \end{figure} 53 | \FloatBarrier 54 | \begin{figure}[!htbp] 55 | \centering 56 | \includegraphics[scale=0.5]{table7} 57 | \label{fig:x cubed graph} 58 | \end{figure} 59 | \FloatBarrier 60 | \begin{figure}[!htbp] 61 | \centering 62 | \includegraphics[scale=0.5]{table8} 63 | \label{fig:x cubed graph} 64 | \end{figure} 65 | \FloatBarrier 66 | \begin{figure}[!htbp] 67 | \centering 68 | \includegraphics[scale=0.5]{table9} 69 | \label{fig:x cubed graph} 70 | \end{figure} 71 | \FloatBarrier 72 | 73 | \begin{table}[!h] 74 | \begin{center} 75 | \begin{tabular}{ | c | c | } 76 | \hline 77 | \textbf{Loại} & \textbf{Đặc tính} \\ 78 | \hline 79 | \multirow{3}{2cm}{Nominal} & protocol\_type(2) \\ & 80 | service(3) \\ & 81 | flag(4) \\ 82 | \hline 83 | \multirow{10}{2cm}{Binary} & land(7) \\ & 84 | logged\_in(12) \\ & 85 | root\_shell(14) \\ & 86 | su\_attempted(15) \\ & 87 | is\_host\_login(21) \\ & 88 | is\_guest\_login(22) \\ 89 | \hline 90 | \multirow{22}{2cm}{Numeric} & duration(1) \\ & 91 | src\_bytes(5), \\ & 92 | dst\_bytes(6) \\ & 93 | wrong\_fragment(8) \\ & 94 | urgent(9) \\ & hot(10) \\ & 95 | num\_failed\_logins(11) \\ & 96 | num\_compromised(13) \\ & 97 | num\_root(16) \\ & 98 | num\_file\_creations(17) \\ & 99 | num\_shells(18) \\ & 100 | num\_access\_files(19) \\ & 101 | num\_outbound\_cmds(20) \\ & 102 | count(23) 103 | srv\_count(24) \\ & 104 | serror\_rate(25) \\ & 105 | srv\_serror\_rate(26) \\ & 106 | rerror\_rate(27) \\ & 107 | srv\_rerror\_rate(28) \\ & 108 | same\_srv\_rate(29) 109 | diff\_srv\_rate(30) \\ & 110 | srv\_diff\_host\_rate(31) \\ & 111 | dst\_host\_count(32) \\ & 112 | dst\_host\_srv\_count(33) \\ & 113 | dst\_host\_same\_srv\_rate(34) \\ & 114 | dst\_host\_diff\_srv\_rate(35) \\ & 115 | dst\_host\_same\_src\_port\_rate(36) \\ & 116 | dst\_host\_srv\_diff\_host\_rate(37) \\ & 117 | dst\_host\_serror\_rate(38) \\ & 118 | dst\_host\_srv\_serror\_rate(39) \\ & 119 | dst\_host\_rerror\_rate(40) \\ & 120 | dst\_host\_srv\_rerror\_rate(41) \\ 121 | \hline 122 | \end{tabular} 123 | 124 | \end{center} 125 | \caption{Bảng phân loại các đặc tính \cite{machinelearning}} 126 | \label{table:1} 127 | \end{table} 128 | \FloatBarrier 129 | 130 | \subsection{Phân nhóm} 131 | Các lớp tấn công có trong bộ dữ liệu NSL-KDD được nhóm thành bốn loại: 132 | \begin{enumerate} 133 | \item \textbf{DOS}: Từ chối dịch vụ là một thể loại tấn công, làm cạn kiệt tài nguyên của nạn nhân qua đó khiến cho nó không thể xử lý các yêu cầu hợp pháp - ví dụ: syn flood. 134 | Các mục có liên quan: “byte nguồn” và “tỷ lệ phần trăm của gói có lỗi ” 135 | \item \textbf{Probing}: Mục tiêu của cuộc tấn công giám sát và thăm dò khác là thu thập thông tin về nạn nhân từ xa, ví dụ: quét cổng. 136 | Các mục có liên quan: “thời lượng kết nối” và “byte nguồn” 137 | \item \textbf{U2R}: quyền truy cập trái phép vào đặc quyền người dùng (root) cục bộ là một kiểu tấn công, mà kẻ tấn công sử dụng tài khoản thông thường để đăng nhập vào hệ thống nạn nhân và cố gắng giành quyền root / quản trị viên bằng cách khai thác một số lỗ hổng trong nạn nhân. 138 | Các cuộc tấn công tràn bộ đệm. Các tính năng liên quan: “số lượng tệp được tạo” và “số lời nhắc shell được gọi,” 139 | \item \textbf{R2L}: truy cập trái phép từ một máy từ xa, kẻ tấn công xâm nhập vào một máy từ xa và truy cập nội bộ của máy nạn nhân. 140 | Ví dụ: đoán mật khẩu. Các tính năng liên quan: Tính năng ở cấp mạng - "thời lượng kết nối" và "dịch vụ được yêu cầu" và các tính năng ở cấp máy chủ - "số lần đăng nhập không thành công" 141 | \end{enumerate} -------------------------------------------------------------------------------- /docs/sections/ids.tex: -------------------------------------------------------------------------------- 1 | \subsection{Giới thiệu} 2 | \textbf{IDS ( Intrusion Detection System – hệ thống phát hiện xâm nhập)} là một hệ thống giám sát lưu lượng mạng, có khả năng phát hiện các hoạt động khả nghi và cảnh báo cho hệ thống hoặc người quản trị mạng. 3 | IDS phát hiện dựa trên các dấu hiệu đặc biệt về các nguy cơ đã biết hoặc dựa trên việc so sánh lưu lượng mạng hiện tại với baseline. 4 | Trong đó baseline cho những hành vi bình thường được thiết lập bởi hồ sơ người dùng, máy chủ, hoặc hoạt động mạng trong quá trình học. 5 | Sau khi quá trình học kết thúc, những phát hiện bất thường được tìm ra sau quá trình thăm dò của IDS bị chệch đi so với baseline này. 6 | Phát hiện xâm nhập là một công việc khó khăn do sự phát triển nhanh chóng các của mạng lưới mạng, quá nhiều môi trường máy tính dẫn đến tính bất đồng bộ, nhiều giao thức mạng và sự phân loại đáng kể của các ứng dụng thông dụng và độc quyền. 7 | Hầu hết IDS sử dụng các dấu hiệu đặc biệt về nguy cơ xâm nhập đã biết( tương tự đối với cách mà các chương trình diệt virus hiện nay sử dụng để phát hiện và diệt virus), và sự khác biệt ứng xử của dấu hiệu xâm nhập so với những dấu hiệu đến từ người dùng thông thường. 8 | \par 9 | IDS thường được đặt ở nhiều vị trí trong hệ thống mạng, trong đó, vị trí phía sau Firewall được nhiều nhà quản trị tin dùng nhất. ở vị trí này, IDS có nhiệm vụ phân tích các gói tin đã được Firewall thông qua, xác định các dấu hiệu đã được định nghĩa mà Firewall không thể kiểm tra hoặc ngăn chặn. Từ các dấu hiệu này, IDS cung cấp thông tin và đưa ra các cảnh báo cho người quản trị viên. 10 | \par 11 | Với việc bảo vệ an toàn thông tin mạng ở một mức độ cao. 12 | Nhiều chuyên gia cho rằng IDS có giá trị giống như Firewall và VPN là ngăn ngừa các cuộc tấn công mà trong đó IDS cung cấp sự an toàn bằng cách trang bị cho bạn thông tin về các cuộc tấn công. 13 | Chính vì điều này, IDS có thể đáp ứng nhu cầu về an toàn hệ thống bằng cách cảnh báo về khả năng có thể xảy ra của các cuộc tấn công và đôi khi bên cạnh các cảnh báo đúng thì chúng cũng mắc phải một số nhầm lẫn dần đến các cảnh báo chưa chính xác. 14 | \subsection{Chức năng} 15 | Nhìn chung, bản thân IDS không có khả năng tự động ngăn chặn các cuộc tấn công, tuy nhiên, các phiên bản hiện đại của IDS như IPS (sẽ được nhắc đến ở những chương sau) đã có thể thực hiện nhiều vai trò hơn và có thể ngăn chặn các cuộc tấn công khi nó xảy ra. 16 | Thực tế, IDS dường như chỉ thông báo cho chúng ta biết rằng mạng đang có dấu hiệu bị tấn công và đang ở trong giai đoạn nguy hiểm. 17 | \par 18 | Hệ thống phát hiện xâm nhập cho phép các tổ chức bảo vệ hệ thống mạng khỏi những đe dọa với việc gia tăng kết nối mạng và sự tin cậy của hệ thống thông tin, bổ sung cho những điểm yếu của hệ thống khác… 19 | Sau đây là một vài lý do mà một hệ thống nên sử dụng IDS: 20 | \begin{itemize} 21 | \item Bảo vệ tính toàn vẹn dữ liệu, đảm bảo sự nhất quán của dữ liệu trong hệ thống. Các biện pháp đưa ra có khả năng ngăn chặn được sử thay đổi bất hợp pháp hoặc phá hoại dữ liệu. 22 | \item Bảo vệ tính riêng tư, nghĩa là đảm bảo cho người sử dụng khai thác tài nguyên của hệ thống theo đúng chức năng nhiệm vụ đã được phân quyền, ngăn chặn được sự truy cập thong tin bất hợp pháp. 23 | \item Bảo vệ tính bí mật, giữ cho thông tin không bị để lộ ra ngoài phạm vi cho phép. 24 | \item Bảo vệ tính khả dụng, nghĩa là hệ thống luôn sẵn sàng thực hiện yêu cầu truy cập thông tin của người dùng hợp pháp. 25 | \item Cung cấp thông tin về sự truy cập, đưa ra các chính sách đối phó, khôi phục, sửa chữa… 26 | \end{itemize} 27 | Về cơ bản, hệ thống IDS có thể giúp chúng ta ngăn ngừa các sự kiện tấn công trước khi nó xảy ra, cung cấp một số các giải pháp cho mạng và máy chủ, thậm chí cũng có thể hoạt động như một chuông báo động. 28 | Tuy nhiên chức năng chính của nó là thông báo cho người quản trị biết về các sự kiện có liên quan đến an ninh hệ thống đang sắp sửa xảy ra trong mạng và hệ thống mà người quản trị hiện đang kiểm soát. 29 | \par 30 | Thông thường, để phân loại IDS (IPS), người ta thường dựa vào đặc điểm của nguồn dữ liệu thu thập được. Trong trường hợp này, các hệ thống IDS được chia thành hai loại phổ biến như sau: 31 | \begin{itemize} 32 | \item Host-Based IDS (HIDS): Sử dụng dữ liệu kiểm tra từ một máy trạm đơn để phát hiện xâm nhập. 33 | \item Network-Based IDS (NIDS): Sử dụng dữ liệu trên toàn bộ lưu thông mạng, cùng với dữ liệu kiểm tra từ một hoặc một vài máy trạm để phát hiện xâm nhập. 34 | \end{itemize} 35 | \subsection{NIDS} 36 | Hệ thống IDS dựa trên mạng sử dụng bộ dò và bộ cảm biến được cài đặt trên toàn mạng. Những bộ dò này theo dõi trên mạng với mục đích tìm kiếm những lưu lượng mạng khớp với những dấu hiệu được mô tả, định nghĩa từ trước. Những bộ cảm biến thu nhận và phân tích lưu lượng trong hệ thống thời gian thực. Khi nhận được mẫu lưu lượng hay dấu hiệu, bộ cảm biến gửi cảnh báo đến trạm quản trị và có thể được cấu hình nhằm tìm ra biện pháp ngăn chặn những xâm nhập xa hơn. NIDS là tập hợp nhiều cảm biến được cài đặt ở trên toàn mạng nhằm theo dõi những gói tin trong mạng, so sánh với mạng được định nghĩa để phát hiện đó là tấn công hay không. 37 | \par 38 | NIDS được đặt giữa hệ thống mạng bên trong và hệ thống mạng bên ngoài để giám sát toàn bộ lưu lượng vào ra. Có thể là một thiết bị phần cứng riêng biệt được thiết lập sẵn hay phần mềm cài đặt trên máy tinh, chủ yếu dùng để đo lưu lượng mạng được sử dụng. 39 | \begin{figure}[!htbp] 40 | \centering 41 | \includegraphics[scale=0.7]{nids} 42 | \caption{Luồng hoạt động của NIDS} 43 | \label{fig:x cubed graph} 44 | \end{figure} 45 | \FloatBarrier 46 | NIDS giám sát toàn bộ mạng con của nó bằng cách lắng nghe tất cả các luồng dữ liệu trên mạng con đó. (Nó thay đổi chế độ hoạt động của card mạng NIC vào trong chế độ promisuous). Bình thường, một NIC hoạt động ở chế độ nonpromisuous nghĩa là nó chỉ nhận các gói tin mà có địa chỉ MAC khớp với địa chỉ của nó, các gói tin khác sẽ không nhận, hoặc không xử lý và bị loại bỏ. 47 | Để giám sát tất cả các đường truyền trong mạng con, NIDS phải chấp nhận tất cả các gói tin và chuyển chúng tới ngăn xếp để xử lý. Do vậy nó sẽ phải cài đặt chế độ hoạt động cho card mạng là promisuous. 48 | \newline 49 | \newline 50 | \textbf{Ưu điểm} 51 | \begin{itemize} 52 | \item Chi phí triển khai thấp 53 | \item Phát hiện được các cuộc tấn công mà HIDS bỏ qua. 54 | \newline Khác với HIDS, NIDS kiểm tra header của tất cả các gói tin vì thế hầu như không bỏ sót các dấu hiệu xuất phát từ đây. 55 | \item Khó xóa bỏ dấu vết (evidence) 56 | \item Phát hiện và đối phó kịp thời 57 | \item Có tính độc lập cao 58 | \end{itemize} 59 | \textbf{Nhược điểm} 60 | \begin{itemize} 61 | \item Bị hạn chế với Switch 62 | \item Hạn chế về hiệu năng 63 | \item Tăng băng thông mạng 64 | \item Một hệ thống NIDS thường gặp khó khăn trong việc xử lý các cuộc tấn công trong một phiên được mã hóa 65 | \item Một hệ thống NIDS cũng gặp khó khăn khi phát hiện các cuộc tấn công mạng từ các gói tin phân mảnh 66 | \end{itemize} 67 | \subsection{HIDS} 68 | Host-based IDS tìm kiếm dấu hiệu của xâm nhập trong một máy chủ cục bộ; thường sử dụng các cơ chế kiểm tra và phân tích các thông tin được lưu lại. 69 | Chủ yếu tìm kiếm các hoạt động bất thường như đăng nhập, truy cập tập tin không được cấp phép, bước leo thang các đặc quyền không được chấp nhận. 70 | Kiến trúc IDS này thường dựa trên các luật (rule-based) để phân tích các hoạt động. 71 | Ví dụ, đặc quyền của người sử dụng ở quyền bậc cao chỉ có thể thành công thông qua lệnh su-select user, như vậy những hành vi đăng nhập liên tục vào tài khoản root có thể được coi là một cuộc tấn công. 72 | \newline 73 | \newline 74 | \textbf{Ưu điểm} 75 | \begin{itemize} 76 | \item Xác định được kết quả của cuộc tấn công 77 | \item Khả năng giám sát các hoạt động cụ thể của hệ thống 78 | \item Phát hiện các hoạt động xâm nhập mà NIDS không phát hiện được: chẳng hạn kẻ tấn công sử dụng bàn phím xâm nhập vào một máy chủ sẽ không bị NIDS phát hiện. 79 | \item Không yêu cầu thêm phần cứng 80 | \end{itemize} 81 | \textbf{Nhược điểm} 82 | \begin{itemize} 83 | \item Khó quản trị 84 | \item Nguồn thông tin phân tích không an toàn 85 | \item Hệ thống host-based khá đắt 86 | \item Chiếm tài nguyên hệ thống 87 | \end{itemize} 88 | -------------------------------------------------------------------------------- /plugin/extractor/ConversationReconstructor.cpp: -------------------------------------------------------------------------------- 1 | #include "ConversationReconstructor.h" 2 | #include "types.h" 3 | #include "TcpConnection.h" 4 | #include "UdpConversation.h" 5 | #include "IcmpConversation.h" 6 | #include 7 | #include 8 | 9 | 10 | namespace FeatureExtractor { 11 | using namespace std; 12 | 13 | ConversationReconstructor::ConversationReconstructor() 14 | : timeouts() 15 | , timeout_interval(timeouts.get_conversation_check_interval_ms()) 16 | { 17 | } 18 | 19 | ConversationReconstructor::ConversationReconstructor(Config &timeouts) 20 | : timeouts(timeouts) 21 | , timeout_interval(timeouts.get_conversation_check_interval_ms()) 22 | { 23 | } 24 | 25 | ConversationReconstructor::~ConversationReconstructor() 26 | { 27 | // Deallocate leftover conversations in output queue 28 | while (!output_queue.empty()) { 29 | delete output_queue.front(); 30 | output_queue.pop(); 31 | } 32 | 33 | // Deallocate leftover active conversations 34 | for (ConversationMap::iterator it = conv_map.begin(); it != conv_map.end(); ++it) { 35 | delete it->second; 36 | } 37 | } 38 | 39 | void ConversationReconstructor::add_packet(const Packet *packet) 40 | { 41 | // Remove timed out reassembly conversations 42 | Timestamp now = packet->get_end_ts(); 43 | check_timeouts(now); 44 | 45 | FiveTuple key = packet->get_five_tuple(); 46 | Conversation *conversation = nullptr; 47 | ip_field_protocol_t ip_proto = key.get_ip_proto(); 48 | 49 | // Find or insert with single lookup: 50 | // http://stackoverflow.com/a/101980/3503528 51 | // - iterator can will also used to remove finished connection from map 52 | // - if connection not found, try with swapped src & dst (opposite direction) 53 | ConversationMap::iterator it = conv_map.lower_bound(key); 54 | if (it != conv_map.end() && !(conv_map.key_comp()(key, it->first))) 55 | { 56 | // Key (connection) already exists 57 | conversation = it->second; 58 | } 59 | else { 60 | // If not found, try with opposite direction for TCP & UDP (bidirectional) 61 | if (ip_proto == TCP || ip_proto == UDP) { 62 | FiveTuple rev_key = key.get_reversed(); 63 | ConversationMap::iterator rev_it = conv_map.lower_bound(rev_key); 64 | if (rev_it != conv_map.end() && !(conv_map.key_comp()(rev_key, rev_it->first))) 65 | { 66 | // Key for opposite direction already exists 67 | conversation = rev_it->second; 68 | it = rev_it; // Remember iterator if connection should be erased below 69 | } 70 | } 71 | } 72 | 73 | // The key (connection) does not exist in the map 74 | if (!conversation) { 75 | switch (ip_proto) 76 | { 77 | case TCP: 78 | conversation = new TcpConnection(packet); 79 | break; 80 | 81 | case UDP: 82 | conversation = new UdpConversation(packet); 83 | break; 84 | 85 | case ICMP: 86 | conversation = new IcmpConversation(packet); 87 | break; 88 | 89 | default: 90 | break; 91 | } 92 | assert(conversation != nullptr && "Attempt to add NULL " 93 | "conversation to conversation map. Possible unhadnled IP protocol value"); 94 | 95 | it = conv_map.insert(it, ConversationMap::value_type(key, conversation)); 96 | } 97 | 98 | // Pass new packet to conversation 99 | bool is_finished = conversation->add_packet(packet); 100 | 101 | // If connection is in final state, remove it from map & enqueue to output 102 | if (is_finished) { 103 | conv_map.erase(it); 104 | output_queue.push(conversation); 105 | } 106 | } 107 | 108 | 109 | void ConversationReconstructor::report_time(const Timestamp &now) 110 | { 111 | check_timeouts(now); 112 | } 113 | 114 | Conversation *ConversationReconstructor::get_next_conversation() 115 | { 116 | if (output_queue.empty()) 117 | return nullptr; 118 | 119 | Conversation *conv = output_queue.front(); 120 | output_queue.pop(); 121 | return conv; 122 | } 123 | 124 | 125 | void ConversationReconstructor::check_timeouts(const Timestamp &now) 126 | { 127 | // find, sort, add to queue 128 | // Run no more often than once per timeout check interval 129 | if (!timeout_interval.is_timedout(now)) { 130 | timeout_interval.update_time(now); 131 | return; 132 | } 133 | timeout_interval.update_time(now); 134 | 135 | // Maximal timestamp that timedout connection can have 136 | Timestamp max_tcp_syn = now - (timeouts.get_tcp_syn_timeout() * 1000000); 137 | Timestamp max_tcp_estab = now - (timeouts.get_tcp_estab_timeout() * 1000000); 138 | Timestamp max_tcp_rst = now - (timeouts.get_tcp_rst_timeout() * 1000000); 139 | Timestamp max_tcp_fin = now - (timeouts.get_tcp_fin_timeout() * 1000000); 140 | Timestamp max_tcp_last_ack = now - (timeouts.get_tcp_last_ack_timeout() * 1000000); 141 | Timestamp max_udp = now - (timeouts.get_udp_timeout() * 1000000); 142 | Timestamp max_icmp = now - (timeouts.get_icmp_timeout() * 1000000); 143 | 144 | // Temporary list of timed out conversations 145 | vector timedout_convs; 146 | 147 | // Erasing during iteration available since C++11 148 | // http://stackoverflow.com/a/263958/3503528 149 | ConversationMap::iterator it = conv_map.begin(); 150 | while (it != conv_map.end()) { 151 | bool is_timedout = false; 152 | Conversation *conv = it->second; 153 | ip_field_protocol_t ip_proto = conv->get_five_tuple_ptr()->get_ip_proto(); 154 | 155 | // Check if conversation is timedout 156 | if (ip_proto == UDP) { 157 | is_timedout = (conv->get_last_ts() <= max_udp); 158 | } 159 | else if (ip_proto == ICMP) { 160 | is_timedout = (conv->get_last_ts() <= max_icmp); 161 | } 162 | else if (ip_proto == TCP) { 163 | switch (conv->get_internal_state()) { 164 | case S0: 165 | case S1: 166 | is_timedout = (conv->get_last_ts() <= max_tcp_syn); 167 | break; 168 | 169 | case ESTAB: 170 | is_timedout = (conv->get_last_ts() <= max_tcp_estab); 171 | break; 172 | 173 | case REJ: 174 | case RSTO: 175 | case RSTOS0: 176 | case RSTR: 177 | is_timedout = (conv->get_last_ts() <= max_tcp_rst); 178 | break; 179 | 180 | case S2: 181 | case S3: 182 | is_timedout = (conv->get_last_ts() <= max_tcp_fin); 183 | break; 184 | 185 | case S2F: 186 | case S3F: 187 | is_timedout = (conv->get_last_ts() <= max_tcp_last_ack); 188 | break; 189 | 190 | default: 191 | break; 192 | } 193 | } 194 | 195 | // If buffer is timed out, remove conversation from active conversations 196 | // and to temporary list of timed out conversations 197 | if (is_timedout) { 198 | timedout_convs.push_back(conv); 199 | conv_map.erase(it++); 200 | } 201 | else { 202 | ++it; 203 | } 204 | } // end of while(it.. 205 | 206 | // Sort timed out conversations by timestamp of last fragmet seen 207 | // Overriden operator '<' of class Conversation is used 208 | sort(timedout_convs.begin(), timedout_convs.end()); 209 | 210 | // Add timedout conversation to output queue in order of their last timestamp 211 | for (vector::iterator it = timedout_convs.begin(); it != timedout_convs.end(); ++it) { 212 | output_queue.push(*it); 213 | } 214 | } 215 | 216 | void ConversationReconstructor::finish_all_conversations() 217 | { 218 | // Temporary list of timed out conversations 219 | vector timedout_convs; 220 | 221 | // Erasing during iteration available since C++11 222 | // http://stackoverflow.com/a/263958/3503528 223 | ConversationMap::iterator it = conv_map.begin(); 224 | while (it != conv_map.end()) { 225 | Conversation *conv = it->second; 226 | timedout_convs.push_back(conv); 227 | conv_map.erase(it++); 228 | } 229 | 230 | // Sort timed out conversations by timestamp of last fragmet seen 231 | // Overriden operator '<' of class Conversation is used 232 | sort(timedout_convs.begin(), timedout_convs.end()); 233 | 234 | // Add timeout conversation to output queue in order of their last timestamp 235 | for (vector::iterator it = timedout_convs.begin(); it != timedout_convs.end(); ++it) { 236 | output_queue.push(*it); 237 | } 238 | } 239 | } 240 | -------------------------------------------------------------------------------- /plugin/snort.lua: -------------------------------------------------------------------------------- 1 | --------------------------------------------------------------------------- 2 | -- Snort++ configuration 3 | --------------------------------------------------------------------------- 4 | 5 | -- there are over 200 modules available to tune your policy. 6 | -- many can be used with defaults w/o any explicit configuration. 7 | -- use this conf as a template for your specific configuration. 8 | 9 | -- 1. configure environment 10 | -- 2. configure defaults 11 | -- 3. configure inspection 12 | -- 4. configure bindings 13 | -- 5. configure performance 14 | -- 6. configure detection 15 | -- 7. configure filters 16 | -- 8. configure outputs 17 | 18 | --------------------------------------------------------------------------- 19 | -- 1. configure environment 20 | --------------------------------------------------------------------------- 21 | 22 | -- given: 23 | -- export DIR=/install/path 24 | -- configure --prefix=$DIR 25 | -- make install 26 | 27 | -- then: 28 | -- export LUA_PATH=$DIR/include/snort/lua/?.lua\;\; 29 | -- export SNORT_LUA_PATH=$DIR/etc/snort 30 | 31 | -- this depends on LUA_PATH 32 | -- used to load this conf into Snort 33 | require('snort_config') 34 | 35 | -- this depends on SNORT_LUA_PATH 36 | -- where to find other config files 37 | conf_dir = os.getenv('SNORT_LUA_PATH') 38 | 39 | if ( not conf_dir ) then 40 | conf_dir = '.' 41 | end 42 | 43 | --------------------------------------------------------------------------- 44 | -- 2. configure defaults 45 | --------------------------------------------------------------------------- 46 | 47 | -- HOME_NET and EXTERNAL_NET must be set now 48 | -- setup the network addresses you are protecting 49 | HOME_NET = 'any' 50 | 51 | -- set up the external network addresses. 52 | -- (leave as "any" in most situations) 53 | EXTERNAL_NET = 'any' 54 | 55 | dofile(conf_dir .. '/snort_defaults.lua') 56 | dofile(conf_dir .. '/file_magic.lua') 57 | 58 | --------------------------------------------------------------------------- 59 | -- 3. configure inspection 60 | --------------------------------------------------------------------------- 61 | 62 | -- mod = { } uses internal defaults 63 | -- you can see them with snort --help-module mod 64 | 65 | -- mod = default_mod uses external defaults 66 | -- you can see them in snort_defaults.lua 67 | 68 | -- the following are quite capable with defaults: 69 | 70 | stream = { } 71 | stream_ip = { } 72 | stream_icmp = { } 73 | stream_tcp = { } 74 | stream_udp = { } 75 | stream_user = { } 76 | stream_file = { } 77 | 78 | arp_spoof = { } 79 | back_orifice = { } 80 | dnp3 = { } 81 | dns = { } 82 | http_inspect = { } 83 | http2_inspect = { } 84 | imap = { } 85 | modbus = { } 86 | normalizer = { } 87 | pop = { } 88 | rpc_decode = { } 89 | sip = { } 90 | ssh = { } 91 | ssl = { } 92 | telnet = { } 93 | 94 | dce_smb = { } 95 | dce_tcp = { } 96 | dce_udp = { } 97 | dce_http_proxy = { } 98 | dce_http_server = { } 99 | 100 | -- see snort_defaults.lua for default_* 101 | gtp_inspect = default_gtp 102 | port_scan = default_med_port_scan 103 | smtp = default_smtp 104 | 105 | ftp_server = default_ftp_server 106 | ftp_client = { } 107 | ftp_data = { } 108 | 109 | -- see file_magic.lua for file id rules 110 | file_id = { file_rules = file_magic } 111 | 112 | -- the following require additional configuration to be fully effective: 113 | dpx = { 114 | host = "predict-server:5000/predict" 115 | } 116 | 117 | appid = 118 | { 119 | -- appid requires this to use appids in rules 120 | --app_detector_dir = 'directory to load appid detectors from' 121 | } 122 | 123 | --[[ 124 | reputation = 125 | { 126 | -- configure one or both of these, then uncomment reputation 127 | --blacklist = 'blacklist file name with ip lists' 128 | --whitelist = 'whitelist file name with ip lists' 129 | } 130 | --]] 131 | 132 | --------------------------------------------------------------------------- 133 | -- 4. configure bindings 134 | --------------------------------------------------------------------------- 135 | 136 | wizard = default_wizard 137 | 138 | binder = 139 | { 140 | -- port bindings required for protocols without wizard support 141 | { when = { proto = 'udp', ports = '53' }, use = { type = 'dns' } }, 142 | { when = { proto = 'tcp', ports = '111' }, use = { type = 'rpc_decode' } }, 143 | { when = { proto = 'tcp', ports = '502' }, use = { type = 'modbus' } }, 144 | { when = { proto = 'tcp', ports = '2123 2152 3386' }, use = { type = 'gtp' } }, 145 | 146 | { when = { proto = 'tcp', service = 'dcerpc' }, use = { type = 'dce_tcp' } }, 147 | { when = { proto = 'udp', service = 'dcerpc' }, use = { type = 'dce_udp' } }, 148 | 149 | { when = { service = 'netbios-ssn' }, use = { type = 'dce_smb' } }, 150 | { when = { service = 'dce_http_server' }, use = { type = 'dce_http_server' } }, 151 | { when = { service = 'dce_http_proxy' }, use = { type = 'dce_http_proxy' } }, 152 | 153 | { when = { service = 'dnp3' }, use = { type = 'dnp3' } }, 154 | { when = { service = 'dns' }, use = { type = 'dns' } }, 155 | { when = { service = 'ftp' }, use = { type = 'ftp_server' } }, 156 | { when = { service = 'ftp-data' }, use = { type = 'ftp_data' } }, 157 | { when = { service = 'gtp' }, use = { type = 'gtp_inspect' } }, 158 | { when = { service = 'imap' }, use = { type = 'imap' } }, 159 | { when = { service = 'http' }, use = { type = 'http_inspect' } }, 160 | { when = { service = 'http2' }, use = { type = 'http2_inspect' } }, 161 | { when = { service = 'modbus' }, use = { type = 'modbus' } }, 162 | { when = { service = 'pop3' }, use = { type = 'pop' } }, 163 | { when = { service = 'ssh' }, use = { type = 'ssh' } }, 164 | { when = { service = 'sip' }, use = { type = 'sip' } }, 165 | { when = { service = 'smtp' }, use = { type = 'smtp' } }, 166 | { when = { service = 'ssl' }, use = { type = 'ssl' } }, 167 | { when = { service = 'sunrpc' }, use = { type = 'rpc_decode' } }, 168 | { when = { service = 'telnet' }, use = { type = 'telnet' } }, 169 | 170 | { use = { type = 'wizard' } } 171 | } 172 | 173 | --------------------------------------------------------------------------- 174 | -- 5. configure performance 175 | --------------------------------------------------------------------------- 176 | 177 | -- use latency to monitor / enforce packet and rule thresholds 178 | latency = 179 | { 180 | packet = { max_time = 1500 }, 181 | rule = { max_time = 200 }, 182 | } 183 | 184 | -- use these to capture perf data for analysis and tuning 185 | --profiler = { } 186 | --perf_monitor = { } 187 | 188 | --------------------------------------------------------------------------- 189 | -- 6. configure detection 190 | --------------------------------------------------------------------------- 191 | 192 | references = default_references 193 | classifications = default_classifications 194 | 195 | ips = 196 | { 197 | -- use this to enable decoder and inspector alerts 198 | --enable_builtin_rules = true, 199 | 200 | -- use include for rules files; be sure to set your path 201 | -- note that rules files can include other rules files 202 | --include = 'snort3_community.rules' 203 | } 204 | 205 | -- use these to configure additional rule actions 206 | -- react = { } 207 | -- reject = { } 208 | -- rewrite = { } 209 | 210 | --------------------------------------------------------------------------- 211 | -- 7. configure filters 212 | --------------------------------------------------------------------------- 213 | 214 | -- below are examples of filters 215 | -- each table is a list of records 216 | 217 | --[[ 218 | suppress = 219 | { 220 | -- don't want to any of see these 221 | { gid = 1, sid = 1 }, 222 | 223 | -- don't want to see these for a given server 224 | { gid = 1, sid = 2, track = 'by_dst', ip = '1.2.3.4' }, 225 | } 226 | --]] 227 | 228 | --[[ 229 | event_filter = 230 | { 231 | -- reduce the number of events logged for some rules 232 | { gid = 1, sid = 1, type = 'limit', track = 'by_src', count = 2, seconds = 10 }, 233 | { gid = 1, sid = 2, type = 'both', track = 'by_dst', count = 5, seconds = 60 }, 234 | } 235 | --]] 236 | 237 | --[[ 238 | rate_filter = 239 | { 240 | -- alert on connection attempts from clients in SOME_NET 241 | { gid = 135, sid = 1, track = 'by_src', count = 5, seconds = 1, 242 | new_action = 'alert', timeout = 4, apply_to = '[$SOME_NET]' }, 243 | 244 | -- alert on connections to servers over threshold 245 | { gid = 135, sid = 2, track = 'by_dst', count = 29, seconds = 3, 246 | new_action = 'alert', timeout = 1 }, 247 | } 248 | --]] 249 | 250 | --------------------------------------------------------------------------- 251 | -- 8. configure outputs 252 | --------------------------------------------------------------------------- 253 | 254 | -- event logging 255 | -- you can enable with defaults from the command line with -A 256 | -- uncomment below to set non-default configs 257 | --alert_csv = { } 258 | --alert_fast = { } 259 | --alert_full = { } 260 | --alert_sfsocket = { } 261 | --alert_syslog = { } 262 | --unified2 = { } 263 | 264 | -- packet logging 265 | -- you can enable with defaults from the command line with -L 266 | --log_codecs = { } 267 | --log_hext = { } 268 | --log_pcap = { } 269 | 270 | -- additional logs 271 | --packet_capture = { } 272 | --file_log = { } 273 | -------------------------------------------------------------------------------- /plugin/extractor/Conversation.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Conversation.h" 4 | 5 | namespace FeatureExtractor { 6 | using namespace std; 7 | 8 | // Array for mapping service_t to string (char *) 9 | // ! Update with enum service_t (in Conversation.h) 10 | const char* const Conversation::SERVICE_NAMES[NUMBER_OF_SERVICES] = { 11 | // General 12 | "other", 13 | "private", 14 | 15 | // ICMP 16 | "ecr_i", 17 | "urp_i", 18 | "urh_i", 19 | "red_i", 20 | "eco_i", 21 | "tim_i", 22 | "oth_i", 23 | 24 | // UDP 25 | "domain_u", 26 | "tftp_u", 27 | "ntp_u", 28 | 29 | // TCP 30 | "IRC", 31 | "X11", 32 | "Z39_50", 33 | "aol", 34 | "auth", 35 | "bgp", 36 | "courier", 37 | "csnet_ns", 38 | "ctf", 39 | "daytime", 40 | "discard", 41 | "domain", 42 | "echo", 43 | "efs", 44 | "exec", 45 | "finger", 46 | "ftp", 47 | "ftp_data", 48 | "gopher", 49 | "harvest", 50 | "hostnames", 51 | "http", 52 | "http_2784", 53 | "http_443", 54 | "http_8001", 55 | "icmp", 56 | "imap4", 57 | "iso_tsap", 58 | "klogin", 59 | "kshell", 60 | "ldap", 61 | "link", 62 | "login", 63 | "mtp", 64 | "name", 65 | "netbios_dgm", 66 | "netbios_ns", 67 | "netbios_ssn", 68 | "netstat", 69 | "nnsp", 70 | "nntp", 71 | "pm_dump", 72 | "pop_2", 73 | "pop_3", 74 | "printer", 75 | "remote_job", 76 | "rje", 77 | "shell", 78 | "smtp", 79 | "sql_net", 80 | "ssh", 81 | "sunrpc", 82 | "supdup", 83 | "systat", 84 | "telnet", 85 | "time", 86 | "uucp", 87 | "uucp_path", 88 | "vmnet", 89 | "whois" 90 | }; 91 | 92 | Conversation::Conversation() 93 | : five_tuple(), state(INIT) 94 | , start_ts(), last_ts() 95 | , src_bytes(0), dst_bytes(0) 96 | , packets(0), src_packets(0), dst_packets(0) 97 | , wrong_fragments(0), urgent_packets(0) 98 | { 99 | } 100 | 101 | Conversation::Conversation(const FiveTuple *tuple) 102 | : five_tuple(*tuple), state(INIT) 103 | , start_ts(), last_ts() 104 | , src_bytes(0), dst_bytes(0) 105 | , packets(0), src_packets(0), dst_packets(0) 106 | , wrong_fragments(0), urgent_packets(0) 107 | { 108 | } 109 | 110 | Conversation::Conversation(const Packet *packet) 111 | : five_tuple(packet->get_five_tuple()), state(INIT) 112 | , start_ts(), last_ts() 113 | , src_bytes(0), dst_bytes(0) 114 | , packets(0), src_packets(0), dst_packets(0) 115 | , wrong_fragments(0), urgent_packets(0) 116 | { 117 | } 118 | 119 | 120 | Conversation::~Conversation() 121 | { 122 | } 123 | 124 | 125 | FiveTuple Conversation::get_five_tuple() const 126 | { 127 | return five_tuple; 128 | } 129 | 130 | const FiveTuple *Conversation::get_five_tuple_ptr() const 131 | { 132 | return &five_tuple; 133 | } 134 | 135 | conversation_state_t Conversation::get_internal_state() const 136 | { 137 | return state; 138 | } 139 | 140 | conversation_state_t Conversation::get_state() const 141 | { 142 | // Replace internal states 143 | switch (state) { 144 | case ESTAB: 145 | return S1; 146 | break; 147 | 148 | case S4: 149 | return OTH; 150 | break; 151 | 152 | case S2F: 153 | return S2; 154 | break; 155 | 156 | case S3F: 157 | return S3; 158 | break; 159 | 160 | default: 161 | return state; 162 | break; 163 | } 164 | return state; 165 | } 166 | 167 | bool Conversation::is_in_final_state() const 168 | { 169 | // By default conversation will not end by state transition. 170 | // TCP subclass will by the special case that will override this. 171 | return false; 172 | } 173 | 174 | Timestamp Conversation::get_start_ts() const 175 | { 176 | return start_ts; 177 | } 178 | 179 | Timestamp Conversation::get_last_ts() const 180 | { 181 | return last_ts; 182 | } 183 | 184 | uint64_t Conversation::get_duration_ms() const 185 | { 186 | return (last_ts - start_ts).get_total_msecs(); 187 | } 188 | 189 | size_t Conversation::get_src_bytes() const 190 | { 191 | return src_bytes; 192 | } 193 | 194 | size_t Conversation::get_dst_bytes() const 195 | { 196 | return dst_bytes; 197 | } 198 | 199 | uint32_t Conversation::get_packets() const 200 | { 201 | return packets; 202 | } 203 | 204 | uint32_t Conversation::get_src_packets() const 205 | { 206 | return src_packets; 207 | } 208 | 209 | uint32_t Conversation::get_dst_packets() const 210 | { 211 | return dst_packets; 212 | } 213 | 214 | uint32_t Conversation::get_wrong_fragments() const 215 | { 216 | return wrong_fragments; 217 | } 218 | 219 | uint32_t Conversation::get_urgent_packets() const 220 | { 221 | return urgent_packets; 222 | } 223 | 224 | const char *Conversation::get_service_str() const 225 | { 226 | // Ensure size of strins matches number of values for enum at compilation time 227 | #ifdef static_assert 228 | static_assert(sizeof(Conversation::SERVICE_NAMES) / sizeof(char *) == NUMBER_OF_SERVICES, 229 | "Mapping of services to strings failed: number of string does not match number of values"); 230 | #endif 231 | 232 | return SERVICE_NAMES[get_service()]; 233 | } 234 | 235 | const char * Conversation::get_protocol_type_str() const 236 | { 237 | switch (five_tuple.get_ip_proto()) { 238 | case TCP: 239 | return "tcp"; 240 | break; 241 | case UDP: 242 | return "udp"; 243 | break; 244 | case ICMP: 245 | return "icmp"; 246 | break; 247 | default: 248 | break; 249 | } 250 | return "UNKNOWN"; 251 | } 252 | 253 | bool Conversation::land() const 254 | { 255 | return five_tuple.land(); 256 | } 257 | 258 | bool Conversation::is_serror() const 259 | { 260 | switch (get_state()) { 261 | case S0: 262 | case S1: 263 | case S2: 264 | case S3: 265 | return true; 266 | break; 267 | 268 | default: 269 | break; 270 | } 271 | 272 | return false; 273 | } 274 | 275 | bool Conversation::is_rerror() const 276 | { 277 | return (get_state() == REJ); 278 | } 279 | 280 | bool Conversation::add_packet(const Packet *packet) 281 | { 282 | // Timestamps 283 | if (packets == 0) 284 | start_ts = packet->get_start_ts(); 285 | last_ts = packet->get_end_ts(); 286 | 287 | // Add byte counts for correct direction 288 | if (packet->get_src_ip() == five_tuple.get_src_ip()) { 289 | src_bytes += packet->get_length(); 290 | src_packets++; 291 | } 292 | else { 293 | dst_bytes += packet->get_length(); 294 | dst_packets++; 295 | } 296 | 297 | // Packet counts 298 | //TODO: wrong_fragments 299 | packets++; 300 | if (packet->get_tcp_flags().urg()) 301 | urgent_packets++; 302 | 303 | // Make state transitions according to packet 304 | update_state(packet); 305 | 306 | return is_in_final_state(); 307 | } 308 | 309 | void Conversation::update_state(const Packet *packet) 310 | { 311 | // By default conversation can only get to state SF (after any packet). 312 | // TCP subclass will by the special case that will override this. 313 | state = SF; 314 | } 315 | 316 | const char *Conversation::get_state_str() const 317 | { 318 | return state_to_str(get_state()); 319 | } 320 | 321 | // TODO: use mapping by array fo char*s ? 322 | const char *Conversation::state_to_str(conversation_state_t state) 323 | { 324 | switch (state) { 325 | case INIT: return "INIT"; break; 326 | case S0: return "S0"; break; 327 | case S1: return "S1"; break; 328 | case S2: return "S2"; break; 329 | case S3: return "S3"; break; 330 | case SF: return "SF"; break; 331 | case REJ: return "REJ"; break; 332 | case RSTOS0: return "RSTOS0"; break; 333 | case RSTO: return "RSTO"; break; 334 | case RSTR: return "RSTR"; break; 335 | case SH: return "SH"; break; 336 | case RSTRH: return "RSTRH"; break; 337 | case SHR: return "SHR"; break; 338 | case OTH: return "OTH"; break; 339 | case ESTAB: return "ESTAB"; break; 340 | case S4: return "S4"; break; 341 | case S2F: return "S2F"; break; 342 | case S3F: return "S3F"; break; 343 | default: break; 344 | } 345 | 346 | return "UNKNOWN"; 347 | } 348 | 349 | bool Conversation::operator<(const Conversation& other) const 350 | { 351 | return (this->get_last_ts() < other.get_last_ts()); 352 | } 353 | 354 | 355 | // Allow using localtime instead of localtime_s 356 | #ifdef _MSC_VER 357 | #pragma warning(disable:4996) 358 | #endif 359 | void Conversation::print_human() const 360 | { 361 | // TODO: WTF ugly code, just for debugging, so nasrac.. 362 | stringstream ss; 363 | 364 | struct tm *ltime; 365 | //struct tm timeinfo; 366 | char timestr[16]; 367 | time_t local_tv_sec; 368 | //local_tv_sec = start_ts.get_secs(); 369 | ltime = localtime(&local_tv_sec); 370 | //localtime_s(&timeinfo, &local_tv_sec); 371 | strftime(timestr, sizeof timestr, "%H:%M:%S", ltime); 372 | //strftime(timestr, sizeof timestr, "%H:%M:%S", &timeinfo); 373 | 374 | ss << "CONVERSATION "; 375 | if (five_tuple.get_ip_proto() == ICMP) { 376 | ss << " > ICMP"; 377 | } 378 | else if (five_tuple.get_ip_proto() == TCP) { 379 | ss << " > TCP "; 380 | } 381 | else if (five_tuple.get_ip_proto() == UDP) { 382 | ss << " > UDP "; 383 | } 384 | ss << " > " << get_service_str() << endl; 385 | ss << timestr; 386 | ss << " duration=" << get_duration_ms() << "ms" << endl; 387 | 388 | // Cast ips to arrays of octets 389 | // TODO: WTF ugly code, aaah.. 390 | uint32_t src_ip = five_tuple.get_src_ip(); 391 | uint32_t dst_ip = five_tuple.get_dst_ip(); 392 | uint8_t *sip = (uint8_t *)&src_ip; 393 | uint8_t *dip = (uint8_t *)&dst_ip; 394 | 395 | ss << " " << (int)sip[0] << "." << (int)sip[1] << "." << (int)sip[2] << "." << (int)sip[3] << ":" << five_tuple.get_src_port(); 396 | ss << " --> " << (int)dip[0] << "." << (int)dip[1] << "." << (int)dip[2] << "." << (int)dip[3] << ":" << five_tuple.get_dst_port() << endl; 397 | ss << " src_bytes=" << src_bytes << " dst_bytes=" << dst_bytes << " land=" << land() << endl; 398 | ss << " pkts=" << packets << " src_pkts=" << src_packets << " dst_pkts=" << dst_packets << endl; 399 | ss << " wrong_frags=" << wrong_fragments << " urg_pkts=" << urgent_packets << endl; 400 | ss << " state=" << get_state_str() << " internal_state=" << state_to_str(state) << endl; 401 | ss << endl; 402 | 403 | cout << ss.str(); 404 | } 405 | } -------------------------------------------------------------------------------- /plugin/extractor/ConversationFeatures.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "ConversationFeatures.h" 5 | 6 | 7 | namespace FeatureExtractor { 8 | using namespace std; 9 | 10 | ConversationFeatures::ConversationFeatures(Conversation *conv) 11 | : conv(conv) 12 | { 13 | conv->register_reference(); 14 | } 15 | 16 | 17 | ConversationFeatures::~ConversationFeatures() 18 | { 19 | // Conversation object commits suicide when nobody needs it anymore 20 | conv->deregister_reference(); 21 | } 22 | 23 | 24 | Conversation *ConversationFeatures::get_conversation() 25 | { 26 | return conv; 27 | } 28 | 29 | /** 30 | * Getters, setters, inc & dec for derived feature values 31 | */ 32 | uint32_t ConversationFeatures::get_count() const { 33 | return count; 34 | } 35 | void ConversationFeatures::set_count(uint32_t count) { 36 | this->count = count; 37 | } 38 | 39 | uint32_t ConversationFeatures::get_srv_count() const { 40 | return srv_count; 41 | } 42 | void ConversationFeatures::set_srv_count(uint32_t srv_count) { 43 | this->srv_count = srv_count; 44 | } 45 | 46 | double ConversationFeatures::get_serror_rate() const { 47 | return serror_rate; 48 | } 49 | void ConversationFeatures::set_serror_rate(double serror_rate) { 50 | this->serror_rate = serror_rate; 51 | } 52 | 53 | double ConversationFeatures::get_srv_serror_rate() const { 54 | return srv_serror_rate; 55 | } 56 | void ConversationFeatures::set_srv_serror_rate(double srv_serror_rate) { 57 | this->srv_serror_rate = srv_serror_rate; 58 | } 59 | 60 | double ConversationFeatures::get_rerror_rate() const { 61 | return rerror_rate; 62 | } 63 | void ConversationFeatures::set_rerror_rate(double rerror_rate) { 64 | this->rerror_rate = rerror_rate; 65 | } 66 | 67 | double ConversationFeatures::get_srv_rerror_rate() const { 68 | return srv_rerror_rate; 69 | } 70 | void ConversationFeatures::set_srv_rerror_rate(double srv_rerror_rate) { 71 | this->srv_rerror_rate = srv_rerror_rate; 72 | } 73 | 74 | double ConversationFeatures::get_same_srv_rate() const { 75 | return same_srv_rate; 76 | } 77 | void ConversationFeatures::set_same_srv_rate(double same_srv_rate) { 78 | this->same_srv_rate = same_srv_rate; 79 | } 80 | 81 | double ConversationFeatures::get_diff_srv_rate() const { 82 | return diff_srv_rate; 83 | } 84 | void ConversationFeatures::set_diff_srv_rate(double diff_srv_rate) { 85 | this->diff_srv_rate = diff_srv_rate; 86 | } 87 | 88 | double ConversationFeatures::get_srv_diff_host_rate() const { 89 | return (srv_count == 0) ? 0.0 : ((srv_count - same_srv_count) / (double)srv_count); 90 | } 91 | 92 | uint32_t ConversationFeatures::get_same_srv_count() const { 93 | return same_srv_count; 94 | } 95 | void ConversationFeatures::set_same_srv_count(uint32_t same_srv_count) { 96 | this->same_srv_count = same_srv_count; 97 | } 98 | 99 | uint32_t ConversationFeatures::get_dst_host_count() const { 100 | return dst_host_count; 101 | } 102 | void ConversationFeatures::set_dst_host_count(uint32_t dst_host_count) { 103 | this->dst_host_count = dst_host_count; 104 | } 105 | 106 | uint32_t ConversationFeatures::get_dst_host_srv_count() const { 107 | return dst_host_srv_count; 108 | } 109 | void ConversationFeatures::set_dst_host_srv_count(uint32_t dst_host_srv_count) { 110 | this->dst_host_srv_count = dst_host_srv_count; 111 | } 112 | 113 | double ConversationFeatures::get_dst_host_same_srv_rate() const { 114 | return dst_host_same_srv_rate; 115 | } 116 | void ConversationFeatures::set_dst_host_same_srv_rate(double dst_host_same_srv_rate) { 117 | this->dst_host_same_srv_rate = dst_host_same_srv_rate; 118 | } 119 | 120 | double ConversationFeatures::get_dst_host_diff_srv_rate() const { 121 | return dst_host_diff_srv_rate; 122 | } 123 | void ConversationFeatures::set_dst_host_diff_srv_rate(double dst_host_diff_srv_rate) { 124 | this->dst_host_diff_srv_rate = dst_host_diff_srv_rate; 125 | } 126 | 127 | double ConversationFeatures::get_dst_host_same_src_port_rate() const { 128 | return dst_host_same_src_port_rate; 129 | } 130 | void ConversationFeatures::set_dst_host_same_src_port_rate(double dst_host_same_src_port_rate) { 131 | this->dst_host_same_src_port_rate = dst_host_same_src_port_rate; 132 | } 133 | 134 | double ConversationFeatures::get_dst_host_serror_rate() const { 135 | return dst_host_serror_rate; 136 | } 137 | void ConversationFeatures::set_dst_host_serror_rate(double dst_host_serror_rate) { 138 | this->dst_host_serror_rate = dst_host_serror_rate; 139 | } 140 | 141 | double ConversationFeatures::get_dst_host_srv_serror_rate() const { 142 | return dst_host_srv_serror_rate; 143 | } 144 | void ConversationFeatures::set_dst_host_srv_serror_rate(double dst_host_srv_serror_rate) { 145 | this->dst_host_srv_serror_rate = dst_host_srv_serror_rate; 146 | } 147 | 148 | double ConversationFeatures::get_dst_host_rerror_rate() const { 149 | return dst_host_rerror_rate; 150 | } 151 | void ConversationFeatures::set_dst_host_rerror_rate(double dst_host_rerror_rate) { 152 | this->dst_host_rerror_rate = dst_host_rerror_rate; 153 | } 154 | 155 | double ConversationFeatures::get_dst_host_srv_rerror_rate() const { 156 | return dst_host_srv_rerror_rate; 157 | } 158 | void ConversationFeatures::set_dst_host_srv_rerror_rate(double dst_host_srv_rerror_rate) { 159 | this->dst_host_srv_rerror_rate = dst_host_srv_rerror_rate; 160 | } 161 | 162 | double ConversationFeatures::get_dst_host_srv_diff_host_rate() const { 163 | return (dst_host_srv_count == 0) ? 0.0 : ((dst_host_srv_count - dst_host_same_srv_count) / (double)dst_host_srv_count); 164 | } 165 | 166 | uint32_t ConversationFeatures::get_dst_host_same_srv_count() const { 167 | return dst_host_same_srv_count; 168 | } 169 | void ConversationFeatures::set_dst_host_same_srv_count(uint32_t dst_host_same_srv_count) { 170 | this->dst_host_same_srv_count = dst_host_same_srv_count; 171 | } 172 | 173 | // Allow using localtime instead of localtime_s 174 | #pragma warning(disable : 4996) 175 | void ConversationFeatures::print(bool print_extra_features) const 176 | { 177 | stringstream ss; 178 | 179 | // Intrinsic features 180 | ss << noshowpoint << setprecision(0) << (conv->get_duration_ms() / 1000) << ','; // Cut fractional part 181 | ss << conv->get_protocol_type_str() << ','; 182 | ss << conv->get_service_str() << ','; 183 | ss << conv->get_state_str() << ','; 184 | ss << conv->get_src_bytes() << ','; 185 | ss << conv->get_dst_bytes() << ','; 186 | ss << conv->land() << ','; 187 | ss << conv->get_wrong_fragments() << ','; 188 | ss << conv->get_urgent_packets() << ','; 189 | 190 | // Derived time windows features 191 | ss << fixed << showpoint <get_five_tuple_ptr(); 216 | 217 | // TODO: ugly wtf, but working 218 | uint32_t src_ip = ft->get_src_ip(); 219 | uint32_t dst_ip = ft->get_dst_ip(); 220 | uint8_t *sip = (uint8_t *)&src_ip; 221 | uint8_t *dip = (uint8_t *)&dst_ip; 222 | ss << ','; 223 | ss << (int)sip[0] << "." << (int)sip[1] << "." << (int)sip[2] << "." << (int)sip[3] << ','; 224 | ss << ft->get_src_port() << ','; 225 | ss << (int)dip[0] << "." << (int)dip[1] << "." << (int)dip[2] << "." << (int)dip[3] << ','; 226 | ss << ft->get_dst_port() << ','; 227 | 228 | // Time (e.g.: 2010-06-14T00:11:23) 229 | struct tm *ltime; 230 | //struct tm timeinfo; 231 | char timestr[20]; 232 | time_t local_tv_sec; 233 | local_tv_sec = conv->get_last_ts().get_secs(); 234 | ltime = localtime(&local_tv_sec); 235 | //localtime_s(&timeinfo, &local_tv_sec); 236 | strftime(timestr, sizeof timestr, "%Y-%m-%dT%H:%M:%S", ltime); 237 | //strftime(timestr, sizeof timestr, "%Y-%m-%dT%H:%M:%S", &timeinfo); 238 | ss << timestr; 239 | } 240 | 241 | cout << ss.str() << endl; 242 | } 243 | 244 | 245 | void ConversationFeatures::print_human() const 246 | { 247 | conv->print_human(); 248 | 249 | stringstream ss; 250 | ss << fixed << setprecision(2); 251 | ss << "count = " << count << endl; 252 | ss << "srv_count = " << srv_count << endl; 253 | ss << "serror_rate = " << serror_rate << endl; 254 | ss << "srv_serror_rate = " << srv_serror_rate << endl; 255 | ss << "rerror_rate = " << rerror_rate << endl; 256 | ss << "srv_rerror_rate = " << srv_rerror_rate << endl; 257 | ss << "same_srv_rate = " << same_srv_rate << endl; 258 | ss << "diff_srv_rate = " << diff_srv_rate << endl; 259 | ss << "get_srv_diff_host_rate = " << get_srv_diff_host_rate() << endl; 260 | ss << "dst_host_count = " << dst_host_count << endl; 261 | ss << "dst_host_srv_count = " << dst_host_srv_count << endl; 262 | ss << "dst_host_same_srv_rate = " << dst_host_same_srv_rate << endl; 263 | ss << "dst_host_diff_srv_rate = " << dst_host_diff_srv_rate << endl; 264 | ss << "dst_host_same_src_port_rate = " << dst_host_same_src_port_rate << endl; 265 | ss << "get_dst_host_srv_diff_host_rate = " << get_dst_host_srv_diff_host_rate() << endl; 266 | ss << "dst_host_serror_rate = " << dst_host_serror_rate << endl; 267 | ss << "dst_host_srv_serror_rate = " << dst_host_srv_serror_rate << endl; 268 | ss << "dst_host_rerror_rate = " << dst_host_rerror_rate << endl; 269 | ss << "dst_host_srv_rerror_rate = " << dst_host_srv_rerror_rate << endl; 270 | cout << ss.str() << endl; 271 | } 272 | 273 | } 274 | --------------------------------------------------------------------------------