Portfolio / Projects / network-threat-detection

Cybersecurity × Data · Academic team project

Can we reliably spot attacks in network flows?

The project builds a network-intrusion detector from flow statistics: data exploration and cleaning, comparison of three models, alert-threshold selection, then a demo application using the same model artifact as the evaluation.

91.6%Attacks detectedtest set
16.7%Benign flows flaggedfalse alarms
0.877Macro F1test set
≥ 99.9%Attack familiesexcept Infiltration

Tools & technologies

Pythonpandasscikit-learnFlask

Flask demo for analyzing network flows.

01 / Context & question

A detection system has to flag attacks without burying analysts under false alarms.

Signature-based tools recognise known attacks well, but not their variants. A machine-learning model can learn behaviour instead: packet volumes, timing, duration, TCP flags.

Completed by a three-student ESAIP team in the Technical Project course in 2024, the project received 15/20. The case study covers data analysis, modeling, evaluation and the demo application without publicly assigning team work to one individual.

Network flow: each row is one exchange described by 64 CICFlowMeter statistics such as packet counts, timing, TCP flags and activity. The model acts as an IDS here by classifying each flow as benign or attack.

Question: can these statistics distinguish benign traffic from attacks while balancing missed attacks and false alarms?

02 / Key takeaways

The model detects most attacks in the dataset, but the real difficulty is the boundary between benign traffic and Infiltration.

Attack detection91.6%

14,540 of 15,872 attack flows in the test set are flagged.

False alarms16.7%

1,781 of 10,642 benign flows are flagged incorrectly, still too high for direct unattended use.

Weak pointInfiltration · 75%

Almost every other family is detected at 99.9% or better; Infiltration looks much more like normal traffic.

Operational meaning: the global score is good, but it hides an important asymmetry. The model is better viewed as an analyst-prioritization layer than an automatic decision engine.

03 / Exploration & quality checks (EDA)

Exploration reveals massive duplicates, contradictory labels and one attack class that looks like normal traffic.

What was checked
  1. the class distribution: benign traffic and ten attack types (FTP and SSH brute force; Hulk, GoldenEye, Slowloris, SlowHTTPTest denial of service; HOIC and LOIC-UDP DDoS; botnet; Infiltration);
  2. constant columns and impossible values (negative durations);
  3. exactly identical rows;
  4. identical flows carrying different labels;
  5. the destination ports of each class.
Raw flows246,730

Round counts per class: 70% attacks.

Exact duplicates66,935

27% of rows.

Contradictory labels3,036

Same values, different labels.

Rows in the sample and distinct flows kept, per class
Some attacks are almost pure repetition: FTP-BruteForce has 15,000 rows but only 31 distinct flows.
Destination ports of benign and Infiltration traffic
Most attacks target a single service (port 80, 21, 22 or 8080). Infiltration uses the same services as normal traffic: DNS, HTTPS, RDP.
What these findings change

Duplicates must go before the split: otherwise the same flow would be learned and then “recognised” at test time, inflating the score. The high share of attacks (far more than in reality) rules out judging on accuracy alone. And the resemblance between Infiltration and normal traffic anticipates where the errors will concentrate.

04 / Cleaning

Remove what would distort the evaluation, keep what carries meaning.

Cleaning decisions
  1. removed the 66,935 exact duplicates;
  2. removed the 3,036 rows whose identical values carry different labels: no model can be right on both;
  3. removed one row with a negative flow duration (measurement error);
  4. removed 8 constant columns, which carry no information;
  5. kept the −1 value of Init Bwd Win Byts, which means “TCP window not observed” and remains useful information.
Flows kept176,758

After full cleaning.

Features64

Flow statistics.

Attack share60%

Still far more than in reality.

On this clean data, the evaluation had to be organised before training any model.

05 / Training, validation and test split

Three separate sets, each with a precise role.

Training · 123,730models learn
Validation · 26,514model and threshold choice
Test · 26,514final evaluation, once

Validation compares models and chooses the threshold without touching the test set. The test stays untouched until the end. The split is stratified to preserve attack-family proportions.

A fingerprint check confirms that no flow appears in two sets at once.

06 / Three models, one rule for judging them

A linear model, a forest of trees and gradient boosting.

Linear baselineLogistic Regression

Weighs the statistics to separate benign from attack with a simple boundary. Durations range from microseconds to minutes, so A log transform is applied first, followed by scaling.

Tree ensembleRandom Forest

Many decision trees, learned on different draws of the data, voting together.

BoostingGradient boosting

Trees built one after another, each correcting the previous ones’ errors.

The models are compared with three complementary measures: detection rate, false-alarm rate and Macro F1, which balances performance across benign and attack traffic.

Transformations and models only see the 123,730 training flows; their settings are judged on validation only.

ModelDetectionFalse alarmsMacro F1
Gradient boosting90.8%15.2%0.879
Random Forest87.0%17.7%0.846
Logistic Regression79.8%17.6%0.804
Macro F1 of the three models on validation
Validation results at the default 0.5 threshold: gradient boosting leads on every metric.

07 / Choosing the alert threshold

The threshold expresses the trade-off a security team has to accept.

The alert threshold is the probability above which a flow is called an attack. Lowering it catches more attacks but raises more false alarms; raising it does the opposite.

Detection and false-alarm rates by threshold, on validation
At 0.30, 98% of attacks are caught but 30% of benign traffic is flagged; at 0.70, only 4% of benign traffic is flagged but one attack in five gets through.

The selected threshold is 0.48, the threshold that maximises Macro F1 on validation. It was frozen before any evaluation on the test set.

08 / Final evaluation on the test set

On unseen flows, the model detects 91.6% of attacks but still generates a 16.7% false-alarm rate.

Detection91.6%

14,540 attacks detected out of 15,872

False alarms16.7%

1,781 benign flows flagged out of 10,642

Macro F10.877

balanced overall performance across benign and attack traffic

Threat-detection confusion matrix on the test set
The confusion matrix makes the trade-off concrete: 1,332 attacks are still missed and 1,781 benign flows become false alarms.

Alert precision is 89.1%, so roughly one alert in nine is false. ROC-AUC reaches 0.964, showing strong ranking ability overall, but the aggregate score still hides which attack families remain difficult.

09 / Understanding the errors

The main weakness is not a noisy attack family: it is Infiltration, because its traffic looks much more like benign activity.

Detection rate by attack family
Most families are detected at 99.9% or better, while Infiltration drops to about 75%. It concentrates most of the remaining uncertainty.

This matches the initial exploration: highly characteristic service attacks are easier to separate, while Infiltration uses services that also appear in normal traffic. Published work on CSE-CIC-IDS2018 has also documented labeling issues, so part of the remaining error may come from the dataset itself.

Control

The model is not simply reading the port

Removing destination port reduces validation Macro F1 by less than 0.01, so behavior statistics carry most of the signal.

Caution

Some families are tiny

FTP-BruteForce and SlowHTTPTest contain only 4 and 6 test flows. A 100% rate on those classes is therefore fragile.

10 / Demo application

A local interface that uses the same model and threshold as the evaluation.

The application loads a model artifact containing the trained model, the ordered 64 features and threshold 0.48. A CSV can be scored row by row, or the 44-flow demo set can be launched directly from the interface.

How the application was checked
  1. the model reloaded from disk produces the same verdicts when the input columns are reordered;
  2. checks stop missing columns, non-numeric values or empty files before scoring;
  3. the local run on the 44 demo flows returns 38 attack flags, 6 benign flows and 95.5% agreement with the supplied labels.
Original ThreatLens home screen: CSV upload or analysis of 44 sample flows.
ThreatLens home screen: upload a CSV or analyze 44 demonstration flows.
ThreatLens summary of 44 demo flows: 38 flagged as attacks and 6 benign
Results summary: 44 flows scored, 38 flagged as attacks and 6 as benign; two predictions differ from the file labels.
ThreatLens workflow and model card
The interface summarises the scoring workflow, model, 0.48 threshold and test-set metrics.
ThreatLens results summary for 44 demo flows
For the 44 demo flows, 38 are flagged as attacks, 6 as benign and 2 verdicts differ from the supplied labels.
ThreatLens flow-level probabilities and verdicts
Each row shows destination service, duration, packet count, attack probability and verdict. The first visible error is an Infiltration flow, matching the earlier error analysis.
Scope.

The Flask demo runs locally: it loads CSV flows and tests 44 sample flows, with no authentication, no network exposure and no continuous traffic monitoring.

11 / Real-world value, limits & lessons

A triage tool to help analysts interpret alerts.

In a SOC (security operations centre), this kind of model would act as a triage layer: it flags flows for review alongside signature-based detection. The threshold would be set from the team’s tolerance for false alarms on real traffic volumes.

  • Public benchmark traffic used in a controlled lab.
  • Artificial attack share (60%): real-world precision would differ.
  • Questionable Infiltration labels.
  • Flow statistics exist only once a flow ends: no packet-level detection.
  • The traffic is not specific to IoT devices, despite the initial IoT use-case framing.
Main takeaway

A score is only worth something if the data is clean and the application serves exactly what was evaluated. That discipline (check, separate, validate before shipping) is the same as in analytics engineering, where a transformation that runs differently in production produces wrong numbers nobody notices.

Going further

A stronger follow-up would test the model on another capture day or dataset, recalibrate the threshold on a realistic benign/attack ratio and monitor drift once in service. The notebook details every step and its outputs.

Next project

Adversarial Machine Learning: test what a model retains under adversarial perturbation.