ftagent-lite 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ftagent_lite-1.0.0/LICENSE +21 -0
- ftagent_lite-1.0.0/PKG-INFO +186 -0
- ftagent_lite-1.0.0/README.md +150 -0
- ftagent_lite-1.0.0/ftagent_lite.egg-info/PKG-INFO +186 -0
- ftagent_lite-1.0.0/ftagent_lite.egg-info/SOURCES.txt +10 -0
- ftagent_lite-1.0.0/ftagent_lite.egg-info/dependency_links.txt +1 -0
- ftagent_lite-1.0.0/ftagent_lite.egg-info/entry_points.txt +2 -0
- ftagent_lite-1.0.0/ftagent_lite.egg-info/requires.txt +10 -0
- ftagent_lite-1.0.0/ftagent_lite.egg-info/top_level.txt +1 -0
- ftagent_lite-1.0.0/ftagent_lite.py +401 -0
- ftagent_lite-1.0.0/pyproject.toml +44 -0
- ftagent_lite-1.0.0/setup.cfg +4 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Flowtriq (https://flowtriq.com)
|
|
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.
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: ftagent-lite
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Lightweight open-source DDoS traffic monitor — stdout output, no account required
|
|
5
|
+
Author-email: Flowtriq <hello@flowtriq.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://flowtriq.com
|
|
8
|
+
Project-URL: Repository, https://github.com/flowtriq/ftagent-lite
|
|
9
|
+
Project-URL: Bug Tracker, https://github.com/flowtriq/ftagent-lite/issues
|
|
10
|
+
Project-URL: Full Version, https://flowtriq.com
|
|
11
|
+
Keywords: ddos,network,traffic,monitor,security,ids
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: System Administrators
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
24
|
+
Classifier: Topic :: System :: Monitoring
|
|
25
|
+
Classifier: Topic :: System :: Networking :: Monitoring
|
|
26
|
+
Requires-Python: >=3.7
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
License-File: LICENSE
|
|
29
|
+
Provides-Extra: full
|
|
30
|
+
Requires-Dist: scapy>=2.4.5; extra == "full"
|
|
31
|
+
Requires-Dist: psutil>=5.9.0; extra == "full"
|
|
32
|
+
Provides-Extra: scapy
|
|
33
|
+
Requires-Dist: scapy>=2.4.5; extra == "scapy"
|
|
34
|
+
Provides-Extra: psutil
|
|
35
|
+
Requires-Dist: psutil>=5.9.0; extra == "psutil"
|
|
36
|
+
|
|
37
|
+
# ftagent-lite
|
|
38
|
+
|
|
39
|
+
**Open-source, zero-config DDoS traffic monitor. Outputs to stdout.**
|
|
40
|
+
|
|
41
|
+
`ftagent-lite` is a lightweight network traffic monitor that detects DDoS attack patterns in real-time and prints structured stats to stdout. No API key. No account. No cloud.
|
|
42
|
+
|
|
43
|
+
It's the open-source sibling of the [Flowtriq](https://flowtriq.com) detection agent — great for quick diagnostics, CI pipelines, or building your own tooling on top.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Install
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pip install scapy psutil
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Then run with sudo (packet capture requires root):
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
sudo python3 ftagent_lite.py
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Usage
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
sudo python3 ftagent_lite.py [options]
|
|
65
|
+
|
|
66
|
+
Options:
|
|
67
|
+
-i, --interface IFACE Network interface (default: any)
|
|
68
|
+
-t, --interval SECS Reporting interval in seconds (default: 2)
|
|
69
|
+
-T, --threshold PPS PPS alert threshold (default: 5000)
|
|
70
|
+
-j, --json Machine-readable JSON output (one object per line)
|
|
71
|
+
-w, --watch Live updating terminal display
|
|
72
|
+
--no-color Disable ANSI colors
|
|
73
|
+
-V, --version Show version
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Examples
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
# Monitor all interfaces, 2-second intervals
|
|
80
|
+
sudo python3 ftagent_lite.py
|
|
81
|
+
|
|
82
|
+
# Monitor eth0 with 5-second intervals
|
|
83
|
+
sudo python3 ftagent_lite.py --interface eth0 --interval 5
|
|
84
|
+
|
|
85
|
+
# Alert threshold at 50k pps
|
|
86
|
+
sudo python3 ftagent_lite.py --threshold 50000
|
|
87
|
+
|
|
88
|
+
# Pipe JSON to jq
|
|
89
|
+
sudo python3 ftagent_lite.py --json | jq '{pps: .pps, srcs: .src_ip_count}'
|
|
90
|
+
|
|
91
|
+
# Live dashboard view
|
|
92
|
+
sudo python3 ftagent_lite.py --watch
|
|
93
|
+
|
|
94
|
+
# Log to file
|
|
95
|
+
sudo python3 ftagent_lite.py --json >> /var/log/traffic.jsonl
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Output
|
|
101
|
+
|
|
102
|
+
### Human-readable (default)
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
2026-03-11 18:04:21 [HIGH]
|
|
106
|
+
Traffic : 47.8K pps 1.7 Gbps
|
|
107
|
+
Proto : TCP 3.2% UDP 94.1% ICMP 0.4%
|
|
108
|
+
Sources : 8,421 unique IPs | Avg pkt: 38 bytes
|
|
109
|
+
Top dst : :11211(31042) :53(12831) :80(3201)
|
|
110
|
+
Top src : 203.0.113.5 198.51.100.8 192.0.2.99 ...
|
|
111
|
+
|
|
112
|
+
! Attack pattern detected. Try Flowtriq for full alerting + auto-mitigation: https://flowtriq.com
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### JSON (`--json`)
|
|
116
|
+
|
|
117
|
+
```json
|
|
118
|
+
{
|
|
119
|
+
"timestamp": "2026-03-11T18:04:21+00:00",
|
|
120
|
+
"pps": 47821,
|
|
121
|
+
"bps": 215000,
|
|
122
|
+
"tcp": 1530,
|
|
123
|
+
"udp": 45100,
|
|
124
|
+
"icmp": 191,
|
|
125
|
+
"other": 0,
|
|
126
|
+
"tcp_pct": 3.2,
|
|
127
|
+
"udp_pct": 94.1,
|
|
128
|
+
"icmp_pct": 0.4,
|
|
129
|
+
"src_ip_count": 8421,
|
|
130
|
+
"top_src_ips": ["203.0.113.5", "198.51.100.8", "192.0.2.99"],
|
|
131
|
+
"top_dst_ports": [[11211, 31042], [53, 12831], [80, 3201]],
|
|
132
|
+
"avg_pkt_size": 38
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Attack detection
|
|
139
|
+
|
|
140
|
+
`ftagent-lite` classifies traffic severity based on your `--threshold`:
|
|
141
|
+
|
|
142
|
+
| PPS vs threshold | Severity |
|
|
143
|
+
|---|---|
|
|
144
|
+
| < threshold | normal |
|
|
145
|
+
| ≥ threshold | MEDIUM |
|
|
146
|
+
| ≥ 2× threshold | HIGH |
|
|
147
|
+
| ≥ 5× threshold | CRITICAL |
|
|
148
|
+
|
|
149
|
+
For production DDoS detection with automatic alerting (Discord, Slack, PagerDuty, Teams, Telegram, DataDog, Prometheus, and more), PCAP capture, AI classification, escalation policies, and auto-mitigation (Cloudflare WAF, iptables, DigitalOcean, Vultr) — see **[Flowtriq](https://flowtriq.com)**.
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Requirements
|
|
154
|
+
|
|
155
|
+
- Python 3.7+
|
|
156
|
+
- `scapy` — packet capture and protocol parsing
|
|
157
|
+
- `psutil` — fallback if scapy unavailable (no protocol breakdown)
|
|
158
|
+
- Root/sudo — required for raw socket capture
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Limitations vs Flowtriq Pro
|
|
163
|
+
|
|
164
|
+
| Feature | ftagent-lite | Flowtriq |
|
|
165
|
+
|---|---|---|
|
|
166
|
+
| Real-time PPS/BPS | ✓ | ✓ |
|
|
167
|
+
| Protocol breakdown | ✓ | ✓ |
|
|
168
|
+
| Source IP tracking | ✓ | ✓ |
|
|
169
|
+
| JSON output | ✓ | ✓ |
|
|
170
|
+
| Attack alerts (Discord, Slack, etc.) | ✗ | ✓ |
|
|
171
|
+
| PCAP capture | ✗ | ✓ |
|
|
172
|
+
| AI attack classification | ✗ | ✓ |
|
|
173
|
+
| Auto-mitigation (iptables, CF WAF) | ✗ | ✓ |
|
|
174
|
+
| Cloud dashboard | ✗ | ✓ |
|
|
175
|
+
| Multi-node | ✗ | ✓ |
|
|
176
|
+
| Team notifications + escalation | ✗ | ✓ |
|
|
177
|
+
|
|
178
|
+
**[Start a free 7-day Flowtriq trial →](https://flowtriq.com)**
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## License
|
|
183
|
+
|
|
184
|
+
MIT License — Copyright (c) 2026 Flowtriq
|
|
185
|
+
|
|
186
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the software, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the software.
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# ftagent-lite
|
|
2
|
+
|
|
3
|
+
**Open-source, zero-config DDoS traffic monitor. Outputs to stdout.**
|
|
4
|
+
|
|
5
|
+
`ftagent-lite` is a lightweight network traffic monitor that detects DDoS attack patterns in real-time and prints structured stats to stdout. No API key. No account. No cloud.
|
|
6
|
+
|
|
7
|
+
It's the open-source sibling of the [Flowtriq](https://flowtriq.com) detection agent — great for quick diagnostics, CI pipelines, or building your own tooling on top.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install scapy psutil
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Then run with sudo (packet capture requires root):
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
sudo python3 ftagent_lite.py
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
sudo python3 ftagent_lite.py [options]
|
|
29
|
+
|
|
30
|
+
Options:
|
|
31
|
+
-i, --interface IFACE Network interface (default: any)
|
|
32
|
+
-t, --interval SECS Reporting interval in seconds (default: 2)
|
|
33
|
+
-T, --threshold PPS PPS alert threshold (default: 5000)
|
|
34
|
+
-j, --json Machine-readable JSON output (one object per line)
|
|
35
|
+
-w, --watch Live updating terminal display
|
|
36
|
+
--no-color Disable ANSI colors
|
|
37
|
+
-V, --version Show version
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Examples
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# Monitor all interfaces, 2-second intervals
|
|
44
|
+
sudo python3 ftagent_lite.py
|
|
45
|
+
|
|
46
|
+
# Monitor eth0 with 5-second intervals
|
|
47
|
+
sudo python3 ftagent_lite.py --interface eth0 --interval 5
|
|
48
|
+
|
|
49
|
+
# Alert threshold at 50k pps
|
|
50
|
+
sudo python3 ftagent_lite.py --threshold 50000
|
|
51
|
+
|
|
52
|
+
# Pipe JSON to jq
|
|
53
|
+
sudo python3 ftagent_lite.py --json | jq '{pps: .pps, srcs: .src_ip_count}'
|
|
54
|
+
|
|
55
|
+
# Live dashboard view
|
|
56
|
+
sudo python3 ftagent_lite.py --watch
|
|
57
|
+
|
|
58
|
+
# Log to file
|
|
59
|
+
sudo python3 ftagent_lite.py --json >> /var/log/traffic.jsonl
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Output
|
|
65
|
+
|
|
66
|
+
### Human-readable (default)
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
2026-03-11 18:04:21 [HIGH]
|
|
70
|
+
Traffic : 47.8K pps 1.7 Gbps
|
|
71
|
+
Proto : TCP 3.2% UDP 94.1% ICMP 0.4%
|
|
72
|
+
Sources : 8,421 unique IPs | Avg pkt: 38 bytes
|
|
73
|
+
Top dst : :11211(31042) :53(12831) :80(3201)
|
|
74
|
+
Top src : 203.0.113.5 198.51.100.8 192.0.2.99 ...
|
|
75
|
+
|
|
76
|
+
! Attack pattern detected. Try Flowtriq for full alerting + auto-mitigation: https://flowtriq.com
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### JSON (`--json`)
|
|
80
|
+
|
|
81
|
+
```json
|
|
82
|
+
{
|
|
83
|
+
"timestamp": "2026-03-11T18:04:21+00:00",
|
|
84
|
+
"pps": 47821,
|
|
85
|
+
"bps": 215000,
|
|
86
|
+
"tcp": 1530,
|
|
87
|
+
"udp": 45100,
|
|
88
|
+
"icmp": 191,
|
|
89
|
+
"other": 0,
|
|
90
|
+
"tcp_pct": 3.2,
|
|
91
|
+
"udp_pct": 94.1,
|
|
92
|
+
"icmp_pct": 0.4,
|
|
93
|
+
"src_ip_count": 8421,
|
|
94
|
+
"top_src_ips": ["203.0.113.5", "198.51.100.8", "192.0.2.99"],
|
|
95
|
+
"top_dst_ports": [[11211, 31042], [53, 12831], [80, 3201]],
|
|
96
|
+
"avg_pkt_size": 38
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Attack detection
|
|
103
|
+
|
|
104
|
+
`ftagent-lite` classifies traffic severity based on your `--threshold`:
|
|
105
|
+
|
|
106
|
+
| PPS vs threshold | Severity |
|
|
107
|
+
|---|---|
|
|
108
|
+
| < threshold | normal |
|
|
109
|
+
| ≥ threshold | MEDIUM |
|
|
110
|
+
| ≥ 2× threshold | HIGH |
|
|
111
|
+
| ≥ 5× threshold | CRITICAL |
|
|
112
|
+
|
|
113
|
+
For production DDoS detection with automatic alerting (Discord, Slack, PagerDuty, Teams, Telegram, DataDog, Prometheus, and more), PCAP capture, AI classification, escalation policies, and auto-mitigation (Cloudflare WAF, iptables, DigitalOcean, Vultr) — see **[Flowtriq](https://flowtriq.com)**.
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Requirements
|
|
118
|
+
|
|
119
|
+
- Python 3.7+
|
|
120
|
+
- `scapy` — packet capture and protocol parsing
|
|
121
|
+
- `psutil` — fallback if scapy unavailable (no protocol breakdown)
|
|
122
|
+
- Root/sudo — required for raw socket capture
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## Limitations vs Flowtriq Pro
|
|
127
|
+
|
|
128
|
+
| Feature | ftagent-lite | Flowtriq |
|
|
129
|
+
|---|---|---|
|
|
130
|
+
| Real-time PPS/BPS | ✓ | ✓ |
|
|
131
|
+
| Protocol breakdown | ✓ | ✓ |
|
|
132
|
+
| Source IP tracking | ✓ | ✓ |
|
|
133
|
+
| JSON output | ✓ | ✓ |
|
|
134
|
+
| Attack alerts (Discord, Slack, etc.) | ✗ | ✓ |
|
|
135
|
+
| PCAP capture | ✗ | ✓ |
|
|
136
|
+
| AI attack classification | ✗ | ✓ |
|
|
137
|
+
| Auto-mitigation (iptables, CF WAF) | ✗ | ✓ |
|
|
138
|
+
| Cloud dashboard | ✗ | ✓ |
|
|
139
|
+
| Multi-node | ✗ | ✓ |
|
|
140
|
+
| Team notifications + escalation | ✗ | ✓ |
|
|
141
|
+
|
|
142
|
+
**[Start a free 7-day Flowtriq trial →](https://flowtriq.com)**
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## License
|
|
147
|
+
|
|
148
|
+
MIT License — Copyright (c) 2026 Flowtriq
|
|
149
|
+
|
|
150
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the software, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the software.
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: ftagent-lite
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Lightweight open-source DDoS traffic monitor — stdout output, no account required
|
|
5
|
+
Author-email: Flowtriq <hello@flowtriq.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://flowtriq.com
|
|
8
|
+
Project-URL: Repository, https://github.com/flowtriq/ftagent-lite
|
|
9
|
+
Project-URL: Bug Tracker, https://github.com/flowtriq/ftagent-lite/issues
|
|
10
|
+
Project-URL: Full Version, https://flowtriq.com
|
|
11
|
+
Keywords: ddos,network,traffic,monitor,security,ids
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: System Administrators
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
24
|
+
Classifier: Topic :: System :: Monitoring
|
|
25
|
+
Classifier: Topic :: System :: Networking :: Monitoring
|
|
26
|
+
Requires-Python: >=3.7
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
License-File: LICENSE
|
|
29
|
+
Provides-Extra: full
|
|
30
|
+
Requires-Dist: scapy>=2.4.5; extra == "full"
|
|
31
|
+
Requires-Dist: psutil>=5.9.0; extra == "full"
|
|
32
|
+
Provides-Extra: scapy
|
|
33
|
+
Requires-Dist: scapy>=2.4.5; extra == "scapy"
|
|
34
|
+
Provides-Extra: psutil
|
|
35
|
+
Requires-Dist: psutil>=5.9.0; extra == "psutil"
|
|
36
|
+
|
|
37
|
+
# ftagent-lite
|
|
38
|
+
|
|
39
|
+
**Open-source, zero-config DDoS traffic monitor. Outputs to stdout.**
|
|
40
|
+
|
|
41
|
+
`ftagent-lite` is a lightweight network traffic monitor that detects DDoS attack patterns in real-time and prints structured stats to stdout. No API key. No account. No cloud.
|
|
42
|
+
|
|
43
|
+
It's the open-source sibling of the [Flowtriq](https://flowtriq.com) detection agent — great for quick diagnostics, CI pipelines, or building your own tooling on top.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Install
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pip install scapy psutil
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Then run with sudo (packet capture requires root):
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
sudo python3 ftagent_lite.py
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Usage
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
sudo python3 ftagent_lite.py [options]
|
|
65
|
+
|
|
66
|
+
Options:
|
|
67
|
+
-i, --interface IFACE Network interface (default: any)
|
|
68
|
+
-t, --interval SECS Reporting interval in seconds (default: 2)
|
|
69
|
+
-T, --threshold PPS PPS alert threshold (default: 5000)
|
|
70
|
+
-j, --json Machine-readable JSON output (one object per line)
|
|
71
|
+
-w, --watch Live updating terminal display
|
|
72
|
+
--no-color Disable ANSI colors
|
|
73
|
+
-V, --version Show version
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Examples
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
# Monitor all interfaces, 2-second intervals
|
|
80
|
+
sudo python3 ftagent_lite.py
|
|
81
|
+
|
|
82
|
+
# Monitor eth0 with 5-second intervals
|
|
83
|
+
sudo python3 ftagent_lite.py --interface eth0 --interval 5
|
|
84
|
+
|
|
85
|
+
# Alert threshold at 50k pps
|
|
86
|
+
sudo python3 ftagent_lite.py --threshold 50000
|
|
87
|
+
|
|
88
|
+
# Pipe JSON to jq
|
|
89
|
+
sudo python3 ftagent_lite.py --json | jq '{pps: .pps, srcs: .src_ip_count}'
|
|
90
|
+
|
|
91
|
+
# Live dashboard view
|
|
92
|
+
sudo python3 ftagent_lite.py --watch
|
|
93
|
+
|
|
94
|
+
# Log to file
|
|
95
|
+
sudo python3 ftagent_lite.py --json >> /var/log/traffic.jsonl
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Output
|
|
101
|
+
|
|
102
|
+
### Human-readable (default)
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
2026-03-11 18:04:21 [HIGH]
|
|
106
|
+
Traffic : 47.8K pps 1.7 Gbps
|
|
107
|
+
Proto : TCP 3.2% UDP 94.1% ICMP 0.4%
|
|
108
|
+
Sources : 8,421 unique IPs | Avg pkt: 38 bytes
|
|
109
|
+
Top dst : :11211(31042) :53(12831) :80(3201)
|
|
110
|
+
Top src : 203.0.113.5 198.51.100.8 192.0.2.99 ...
|
|
111
|
+
|
|
112
|
+
! Attack pattern detected. Try Flowtriq for full alerting + auto-mitigation: https://flowtriq.com
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### JSON (`--json`)
|
|
116
|
+
|
|
117
|
+
```json
|
|
118
|
+
{
|
|
119
|
+
"timestamp": "2026-03-11T18:04:21+00:00",
|
|
120
|
+
"pps": 47821,
|
|
121
|
+
"bps": 215000,
|
|
122
|
+
"tcp": 1530,
|
|
123
|
+
"udp": 45100,
|
|
124
|
+
"icmp": 191,
|
|
125
|
+
"other": 0,
|
|
126
|
+
"tcp_pct": 3.2,
|
|
127
|
+
"udp_pct": 94.1,
|
|
128
|
+
"icmp_pct": 0.4,
|
|
129
|
+
"src_ip_count": 8421,
|
|
130
|
+
"top_src_ips": ["203.0.113.5", "198.51.100.8", "192.0.2.99"],
|
|
131
|
+
"top_dst_ports": [[11211, 31042], [53, 12831], [80, 3201]],
|
|
132
|
+
"avg_pkt_size": 38
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Attack detection
|
|
139
|
+
|
|
140
|
+
`ftagent-lite` classifies traffic severity based on your `--threshold`:
|
|
141
|
+
|
|
142
|
+
| PPS vs threshold | Severity |
|
|
143
|
+
|---|---|
|
|
144
|
+
| < threshold | normal |
|
|
145
|
+
| ≥ threshold | MEDIUM |
|
|
146
|
+
| ≥ 2× threshold | HIGH |
|
|
147
|
+
| ≥ 5× threshold | CRITICAL |
|
|
148
|
+
|
|
149
|
+
For production DDoS detection with automatic alerting (Discord, Slack, PagerDuty, Teams, Telegram, DataDog, Prometheus, and more), PCAP capture, AI classification, escalation policies, and auto-mitigation (Cloudflare WAF, iptables, DigitalOcean, Vultr) — see **[Flowtriq](https://flowtriq.com)**.
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Requirements
|
|
154
|
+
|
|
155
|
+
- Python 3.7+
|
|
156
|
+
- `scapy` — packet capture and protocol parsing
|
|
157
|
+
- `psutil` — fallback if scapy unavailable (no protocol breakdown)
|
|
158
|
+
- Root/sudo — required for raw socket capture
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Limitations vs Flowtriq Pro
|
|
163
|
+
|
|
164
|
+
| Feature | ftagent-lite | Flowtriq |
|
|
165
|
+
|---|---|---|
|
|
166
|
+
| Real-time PPS/BPS | ✓ | ✓ |
|
|
167
|
+
| Protocol breakdown | ✓ | ✓ |
|
|
168
|
+
| Source IP tracking | ✓ | ✓ |
|
|
169
|
+
| JSON output | ✓ | ✓ |
|
|
170
|
+
| Attack alerts (Discord, Slack, etc.) | ✗ | ✓ |
|
|
171
|
+
| PCAP capture | ✗ | ✓ |
|
|
172
|
+
| AI attack classification | ✗ | ✓ |
|
|
173
|
+
| Auto-mitigation (iptables, CF WAF) | ✗ | ✓ |
|
|
174
|
+
| Cloud dashboard | ✗ | ✓ |
|
|
175
|
+
| Multi-node | ✗ | ✓ |
|
|
176
|
+
| Team notifications + escalation | ✗ | ✓ |
|
|
177
|
+
|
|
178
|
+
**[Start a free 7-day Flowtriq trial →](https://flowtriq.com)**
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## License
|
|
183
|
+
|
|
184
|
+
MIT License — Copyright (c) 2026 Flowtriq
|
|
185
|
+
|
|
186
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the software, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the software.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
ftagent_lite.py
|
|
4
|
+
pyproject.toml
|
|
5
|
+
ftagent_lite.egg-info/PKG-INFO
|
|
6
|
+
ftagent_lite.egg-info/SOURCES.txt
|
|
7
|
+
ftagent_lite.egg-info/dependency_links.txt
|
|
8
|
+
ftagent_lite.egg-info/entry_points.txt
|
|
9
|
+
ftagent_lite.egg-info/requires.txt
|
|
10
|
+
ftagent_lite.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ftagent_lite
|
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
ftagent-lite — Lightweight DDoS Traffic Monitor
|
|
4
|
+
Open-source, MIT licensed.
|
|
5
|
+
|
|
6
|
+
Monitors network traffic in real-time and prints structured stats to stdout.
|
|
7
|
+
No API key required. No cloud dependency.
|
|
8
|
+
|
|
9
|
+
For full incident management, alerting, PCAP capture, AI classification,
|
|
10
|
+
and team notifications — see Flowtriq: https://flowtriq.com
|
|
11
|
+
|
|
12
|
+
Usage:
|
|
13
|
+
sudo python3 ftagent_lite.py
|
|
14
|
+
sudo python3 ftagent_lite.py --interface eth0
|
|
15
|
+
sudo python3 ftagent_lite.py --interval 5 --threshold 10000
|
|
16
|
+
sudo python3 ftagent_lite.py --json # machine-readable JSON output
|
|
17
|
+
sudo python3 ftagent_lite.py --watch # live updating terminal view
|
|
18
|
+
|
|
19
|
+
Requirements:
|
|
20
|
+
pip install scapy psutil
|
|
21
|
+
|
|
22
|
+
Author: Flowtriq (https://flowtriq.com)
|
|
23
|
+
License: MIT
|
|
24
|
+
Version: 1.0.0
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
import argparse
|
|
28
|
+
import json
|
|
29
|
+
import os
|
|
30
|
+
import signal
|
|
31
|
+
import sys
|
|
32
|
+
import threading
|
|
33
|
+
import time
|
|
34
|
+
from collections import defaultdict
|
|
35
|
+
from datetime import datetime, timezone
|
|
36
|
+
|
|
37
|
+
VERSION = "1.0.0"
|
|
38
|
+
|
|
39
|
+
# ── Optional deps ──────────────────────────────────────────────────────────────
|
|
40
|
+
|
|
41
|
+
try:
|
|
42
|
+
from scapy.all import IP, TCP, UDP, ICMP, sniff, conf as scapy_conf
|
|
43
|
+
SCAPY_OK = True
|
|
44
|
+
except ImportError:
|
|
45
|
+
SCAPY_OK = False
|
|
46
|
+
|
|
47
|
+
try:
|
|
48
|
+
import psutil
|
|
49
|
+
PSUTIL_OK = True
|
|
50
|
+
except ImportError:
|
|
51
|
+
PSUTIL_OK = False
|
|
52
|
+
|
|
53
|
+
# ── Globals ────────────────────────────────────────────────────────────────────
|
|
54
|
+
|
|
55
|
+
_running = True
|
|
56
|
+
_lock = threading.Lock()
|
|
57
|
+
|
|
58
|
+
_counters = {
|
|
59
|
+
"pps": 0, # packets this interval
|
|
60
|
+
"bps": 0, # bytes this interval
|
|
61
|
+
"tcp": 0,
|
|
62
|
+
"udp": 0,
|
|
63
|
+
"icmp": 0,
|
|
64
|
+
"other": 0,
|
|
65
|
+
"src_ips": set(),
|
|
66
|
+
"dst_ports": defaultdict(int),
|
|
67
|
+
"src_ports": defaultdict(int),
|
|
68
|
+
"pkt_sizes": [],
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
_stats_history = [] # list of interval snapshots
|
|
72
|
+
_alert_active = False
|
|
73
|
+
_alert_start = None
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
# ── Signal handling ────────────────────────────────────────────────────────────
|
|
77
|
+
|
|
78
|
+
def _shutdown(sig, frame):
|
|
79
|
+
global _running
|
|
80
|
+
_running = False
|
|
81
|
+
|
|
82
|
+
signal.signal(signal.SIGINT, _shutdown)
|
|
83
|
+
signal.signal(signal.SIGTERM, _shutdown)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
# ── Packet handler ─────────────────────────────────────────────────────────────
|
|
87
|
+
|
|
88
|
+
def _handle_packet(pkt):
|
|
89
|
+
if IP not in pkt:
|
|
90
|
+
return
|
|
91
|
+
with _lock:
|
|
92
|
+
_counters["pps"] += 1
|
|
93
|
+
pkt_len = len(pkt)
|
|
94
|
+
_counters["bps"] += pkt_len
|
|
95
|
+
_counters["pkt_sizes"].append(pkt_len)
|
|
96
|
+
_counters["src_ips"].add(pkt[IP].src)
|
|
97
|
+
|
|
98
|
+
if TCP in pkt:
|
|
99
|
+
_counters["tcp"] += 1
|
|
100
|
+
_counters["dst_ports"][pkt[TCP].dport] += 1
|
|
101
|
+
_counters["src_ports"][pkt[TCP].sport] += 1
|
|
102
|
+
elif UDP in pkt:
|
|
103
|
+
_counters["udp"] += 1
|
|
104
|
+
_counters["dst_ports"][pkt[UDP].dport] += 1
|
|
105
|
+
_counters["src_ports"][pkt[UDP].sport] += 1
|
|
106
|
+
elif ICMP in pkt:
|
|
107
|
+
_counters["icmp"] += 1
|
|
108
|
+
else:
|
|
109
|
+
_counters["other"] += 1
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
# ── Stats collection ───────────────────────────────────────────────────────────
|
|
113
|
+
|
|
114
|
+
def _collect_and_reset(interval: float) -> dict:
|
|
115
|
+
with _lock:
|
|
116
|
+
snap = {
|
|
117
|
+
"pps": int(_counters["pps"] / interval),
|
|
118
|
+
"bps": int(_counters["bps"] / interval),
|
|
119
|
+
"tcp": _counters["tcp"],
|
|
120
|
+
"udp": _counters["udp"],
|
|
121
|
+
"icmp": _counters["icmp"],
|
|
122
|
+
"other": _counters["other"],
|
|
123
|
+
"src_ip_count": len(_counters["src_ips"]),
|
|
124
|
+
"top_src_ips": sorted(list(_counters["src_ips"]))[:10],
|
|
125
|
+
"top_dst_ports": sorted(_counters["dst_ports"].items(), key=lambda x: x[1], reverse=True)[:5],
|
|
126
|
+
"avg_pkt_size": int(sum(_counters["pkt_sizes"]) / len(_counters["pkt_sizes"])) if _counters["pkt_sizes"] else 0,
|
|
127
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
128
|
+
}
|
|
129
|
+
total_proto = snap["tcp"] + snap["udp"] + snap["icmp"] + snap["other"]
|
|
130
|
+
snap["tcp_pct"] = round(100 * snap["tcp"] / total_proto, 1) if total_proto else 0
|
|
131
|
+
snap["udp_pct"] = round(100 * snap["udp"] / total_proto, 1) if total_proto else 0
|
|
132
|
+
snap["icmp_pct"] = round(100 * snap["icmp"] / total_proto, 1) if total_proto else 0
|
|
133
|
+
|
|
134
|
+
# Reset
|
|
135
|
+
_counters["pps"] = 0
|
|
136
|
+
_counters["bps"] = 0
|
|
137
|
+
_counters["tcp"] = 0
|
|
138
|
+
_counters["udp"] = 0
|
|
139
|
+
_counters["icmp"] = 0
|
|
140
|
+
_counters["other"] = 0
|
|
141
|
+
_counters["src_ips"] = set()
|
|
142
|
+
_counters["dst_ports"] = defaultdict(int)
|
|
143
|
+
_counters["src_ports"] = defaultdict(int)
|
|
144
|
+
_counters["pkt_sizes"] = []
|
|
145
|
+
return snap
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
# ── Formatting helpers ─────────────────────────────────────────────────────────
|
|
149
|
+
|
|
150
|
+
def _fmt_pps(n: int) -> str:
|
|
151
|
+
if n >= 1_000_000: return f"{n/1_000_000:.1f}M pps"
|
|
152
|
+
if n >= 1_000: return f"{n/1_000:.1f}K pps"
|
|
153
|
+
return f"{n} pps"
|
|
154
|
+
|
|
155
|
+
def _fmt_bps(n: int) -> str:
|
|
156
|
+
n8 = n * 8
|
|
157
|
+
if n8 >= 1_000_000_000: return f"{n8/1_000_000_000:.2f} Gbps"
|
|
158
|
+
if n8 >= 1_000_000: return f"{n8/1_000_000:.1f} Mbps"
|
|
159
|
+
if n8 >= 1_000: return f"{n8/1_000:.0f} Kbps"
|
|
160
|
+
return f"{n8} bps"
|
|
161
|
+
|
|
162
|
+
def _severity(pps: int, threshold: int) -> str:
|
|
163
|
+
if pps >= threshold * 5: return "CRITICAL"
|
|
164
|
+
if pps >= threshold * 2: return "HIGH"
|
|
165
|
+
if pps >= threshold: return "MEDIUM"
|
|
166
|
+
return "normal"
|
|
167
|
+
|
|
168
|
+
ANSI = {
|
|
169
|
+
"red": "\033[91m",
|
|
170
|
+
"yellow": "\033[93m",
|
|
171
|
+
"green": "\033[92m",
|
|
172
|
+
"cyan": "\033[96m",
|
|
173
|
+
"bold": "\033[1m",
|
|
174
|
+
"reset": "\033[0m",
|
|
175
|
+
"clear": "\033[2J\033[H",
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
def _col(text: str, color: str, use_color: bool = True) -> str:
|
|
179
|
+
if not use_color or not sys.stdout.isatty():
|
|
180
|
+
return text
|
|
181
|
+
return ANSI.get(color, "") + text + ANSI["reset"]
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
# ── Output modes ───────────────────────────────────────────────────────────────
|
|
185
|
+
|
|
186
|
+
def _print_human(snap: dict, threshold: int, color: bool):
|
|
187
|
+
sev = _severity(snap["pps"], threshold)
|
|
188
|
+
ts = snap["timestamp"][:19].replace("T", " ")
|
|
189
|
+
|
|
190
|
+
sev_color = {"CRITICAL": "red", "HIGH": "red", "MEDIUM": "yellow", "normal": "green"}.get(sev, "green")
|
|
191
|
+
alert_marker = f" [{_col(sev, sev_color, color)}]" if sev != "normal" else ""
|
|
192
|
+
|
|
193
|
+
print(f"{_col(ts, 'cyan', color)}{alert_marker}")
|
|
194
|
+
print(f" Traffic : {_col(_fmt_pps(snap['pps']), 'bold', color)} {_fmt_bps(snap['bps'])}")
|
|
195
|
+
print(f" Proto : TCP {snap['tcp_pct']}% UDP {snap['udp_pct']}% ICMP {snap['icmp_pct']}%")
|
|
196
|
+
print(f" Sources : {snap['src_ip_count']} unique IPs | Avg pkt: {snap['avg_pkt_size']} bytes")
|
|
197
|
+
|
|
198
|
+
if snap["top_dst_ports"]:
|
|
199
|
+
ports_str = " ".join(f":{p}({c})" for p, c in snap["top_dst_ports"])
|
|
200
|
+
print(f" Top dst : {ports_str}")
|
|
201
|
+
|
|
202
|
+
if sev != "normal" and snap["top_src_ips"]:
|
|
203
|
+
ips_str = " ".join(snap["top_src_ips"][:5])
|
|
204
|
+
print(f" Top src : {_col(ips_str, 'red', color)}")
|
|
205
|
+
|
|
206
|
+
if sev != "normal":
|
|
207
|
+
print(f"\n {_col('! Attack pattern detected. Try Flowtriq for full alerting + auto-mitigation: https://flowtriq.com', 'yellow', color)}\n")
|
|
208
|
+
|
|
209
|
+
print()
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def _print_watch(snap: dict, threshold: int, color: bool, interface: str):
|
|
213
|
+
sev = _severity(snap["pps"], threshold)
|
|
214
|
+
sev_color = {"CRITICAL": "red", "HIGH": "red", "MEDIUM": "yellow", "normal": "green"}.get(sev, "green")
|
|
215
|
+
|
|
216
|
+
if color and sys.stdout.isatty():
|
|
217
|
+
print(ANSI["clear"], end="")
|
|
218
|
+
|
|
219
|
+
print(_col("=" * 60, "cyan", color))
|
|
220
|
+
print(_col(" ftagent-lite | Flowtriq Open Source Monitor", "bold", color))
|
|
221
|
+
print(_col(" https://flowtriq.com | Full version: Flowtriq Pro", "cyan", color))
|
|
222
|
+
print(_col("=" * 60, "cyan", color))
|
|
223
|
+
print(f" Interface : {interface}")
|
|
224
|
+
print(f" Time : {snap['timestamp'][:19].replace('T',' ')} UTC")
|
|
225
|
+
print()
|
|
226
|
+
print(f" PPS : {_col(_fmt_pps(snap['pps']), sev_color, color)}")
|
|
227
|
+
print(f" Bandwidth : {_fmt_bps(snap['bps'])}")
|
|
228
|
+
print(f" Status : {_col(sev, sev_color, color)}")
|
|
229
|
+
print()
|
|
230
|
+
print(f" TCP {snap['tcp_pct']:5.1f}% UDP {snap['udp_pct']:5.1f}% ICMP {snap['icmp_pct']:5.1f}%")
|
|
231
|
+
print(f" Unique src IPs : {snap['src_ip_count']}")
|
|
232
|
+
print(f" Avg packet size: {snap['avg_pkt_size']} bytes")
|
|
233
|
+
|
|
234
|
+
if snap["top_dst_ports"]:
|
|
235
|
+
print()
|
|
236
|
+
print(" Top destination ports:")
|
|
237
|
+
for port, count in snap["top_dst_ports"]:
|
|
238
|
+
bar = "█" * min(20, int(20 * count / max(1, snap["tcp"] + snap["udp"])))
|
|
239
|
+
print(f" :{port:<6} {bar} {count}")
|
|
240
|
+
|
|
241
|
+
if sev != "normal":
|
|
242
|
+
print()
|
|
243
|
+
print(_col(" !! ATTACK PATTERN DETECTED !!", sev_color, color))
|
|
244
|
+
if snap["top_src_ips"]:
|
|
245
|
+
print(f" Top attackers: {', '.join(snap['top_src_ips'][:5])}")
|
|
246
|
+
print()
|
|
247
|
+
print(_col(" Get full alerting, PCAP capture, and auto-mitigation:", "yellow", color))
|
|
248
|
+
print(_col(" https://flowtriq.com (7-day free trial)", "yellow", color))
|
|
249
|
+
|
|
250
|
+
print(_col("=" * 60, "cyan", color))
|
|
251
|
+
print(" Press Ctrl+C to stop")
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
# ── Sniffer thread ─────────────────────────────────────────────────────────────
|
|
255
|
+
|
|
256
|
+
def _sniff_thread(interface: str):
|
|
257
|
+
kwargs = {"prn": _handle_packet, "store": False}
|
|
258
|
+
if interface and interface != "any":
|
|
259
|
+
kwargs["iface"] = interface
|
|
260
|
+
try:
|
|
261
|
+
sniff(**kwargs, stop_filter=lambda _: not _running)
|
|
262
|
+
except Exception as e:
|
|
263
|
+
print(f"[ftagent-lite] sniff error: {e}", file=sys.stderr)
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
# ── Psutil fallback (no scapy) ─────────────────────────────────────────────────
|
|
267
|
+
|
|
268
|
+
def _psutil_loop(interface: str, interval: float, threshold: int,
|
|
269
|
+
json_out: bool, watch: bool, color: bool):
|
|
270
|
+
iface = interface if interface and interface != "any" else None
|
|
271
|
+
prev = None
|
|
272
|
+
|
|
273
|
+
while _running:
|
|
274
|
+
counters = psutil.net_io_counters(pernic=bool(iface))
|
|
275
|
+
if iface:
|
|
276
|
+
curr = counters.get(iface)
|
|
277
|
+
else:
|
|
278
|
+
curr = psutil.net_io_counters()
|
|
279
|
+
|
|
280
|
+
if prev is not None and curr is not None:
|
|
281
|
+
pps = int((curr.packets_recv - prev.packets_recv) / interval)
|
|
282
|
+
bps = int((curr.bytes_recv - prev.bytes_recv) / interval)
|
|
283
|
+
snap = {
|
|
284
|
+
"pps": pps, "bps": bps,
|
|
285
|
+
"tcp": 0, "udp": 0, "icmp": 0, "other": 0,
|
|
286
|
+
"tcp_pct": 0.0, "udp_pct": 0.0, "icmp_pct": 0.0,
|
|
287
|
+
"src_ip_count": 0, "top_src_ips": [],
|
|
288
|
+
"top_dst_ports": [], "avg_pkt_size": 0,
|
|
289
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
290
|
+
"_note": "Protocol breakdown not available without scapy",
|
|
291
|
+
}
|
|
292
|
+
_stats_history.append(snap)
|
|
293
|
+
if json_out:
|
|
294
|
+
print(json.dumps(snap), flush=True)
|
|
295
|
+
elif watch:
|
|
296
|
+
_print_watch(snap, threshold, color, interface or "all")
|
|
297
|
+
else:
|
|
298
|
+
_print_human(snap, threshold, color)
|
|
299
|
+
|
|
300
|
+
prev = curr
|
|
301
|
+
time.sleep(interval)
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
# ── Main ───────────────────────────────────────────────────────────────────────
|
|
305
|
+
|
|
306
|
+
def main():
|
|
307
|
+
parser = argparse.ArgumentParser(
|
|
308
|
+
description="ftagent-lite: lightweight DDoS traffic monitor (open source)",
|
|
309
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
310
|
+
epilog="""
|
|
311
|
+
Examples:
|
|
312
|
+
sudo python3 ftagent_lite.py
|
|
313
|
+
sudo python3 ftagent_lite.py --interface eth0 --interval 5
|
|
314
|
+
sudo python3 ftagent_lite.py --json | jq .pps
|
|
315
|
+
sudo python3 ftagent_lite.py --watch --threshold 50000
|
|
316
|
+
|
|
317
|
+
For full DDoS detection with alerting, PCAP capture, team notifications,
|
|
318
|
+
AI classification, and auto-mitigation:
|
|
319
|
+
https://flowtriq.com (7-day free trial, no credit card)
|
|
320
|
+
""",
|
|
321
|
+
)
|
|
322
|
+
parser.add_argument("--interface", "-i", default="any",
|
|
323
|
+
help="Network interface to monitor (default: any)")
|
|
324
|
+
parser.add_argument("--interval", "-t", type=float, default=2.0,
|
|
325
|
+
help="Stats reporting interval in seconds (default: 2)")
|
|
326
|
+
parser.add_argument("--threshold", "-T", type=int, default=5000,
|
|
327
|
+
help="PPS alert threshold (default: 5000)")
|
|
328
|
+
parser.add_argument("--json", "-j", action="store_true",
|
|
329
|
+
help="Output machine-readable JSON (one object per line)")
|
|
330
|
+
parser.add_argument("--watch", "-w", action="store_true",
|
|
331
|
+
help="Live updating terminal display")
|
|
332
|
+
parser.add_argument("--no-color", action="store_true",
|
|
333
|
+
help="Disable ANSI color output")
|
|
334
|
+
parser.add_argument("--version", "-V", action="version", version=f"ftagent-lite {VERSION}")
|
|
335
|
+
args = parser.parse_args()
|
|
336
|
+
|
|
337
|
+
use_color = not args.no_color
|
|
338
|
+
interface = args.interface
|
|
339
|
+
|
|
340
|
+
if os.geteuid() != 0:
|
|
341
|
+
print("ftagent-lite requires root/sudo for packet capture.", file=sys.stderr)
|
|
342
|
+
sys.exit(1)
|
|
343
|
+
|
|
344
|
+
# Banner
|
|
345
|
+
if not args.json:
|
|
346
|
+
print(_col(f"ftagent-lite v{VERSION}", "bold", use_color) +
|
|
347
|
+
_col(" — open source DDoS traffic monitor", "cyan", use_color))
|
|
348
|
+
print(_col("Full monitoring at https://flowtriq.com", "cyan", use_color))
|
|
349
|
+
print()
|
|
350
|
+
|
|
351
|
+
if not SCAPY_OK:
|
|
352
|
+
if not PSUTIL_OK:
|
|
353
|
+
print("ERROR: Install scapy or psutil:\n pip install scapy psutil", file=sys.stderr)
|
|
354
|
+
sys.exit(1)
|
|
355
|
+
if not args.json:
|
|
356
|
+
print("Note: scapy not found — using psutil (no protocol breakdown).", file=sys.stderr)
|
|
357
|
+
print("Install scapy for full analysis: pip install scapy\n", file=sys.stderr)
|
|
358
|
+
_psutil_loop(interface, args.interval, args.threshold, args.json, args.watch, use_color)
|
|
359
|
+
return
|
|
360
|
+
|
|
361
|
+
# Start sniffer thread
|
|
362
|
+
t = threading.Thread(target=_sniff_thread, args=(interface,), daemon=True)
|
|
363
|
+
t.start()
|
|
364
|
+
|
|
365
|
+
if not args.json:
|
|
366
|
+
print(f"Monitoring interface: {_col(interface, 'cyan', use_color)}")
|
|
367
|
+
print(f"Interval: {args.interval}s | Alert threshold: {_fmt_pps(args.threshold)}")
|
|
368
|
+
print()
|
|
369
|
+
|
|
370
|
+
try:
|
|
371
|
+
while _running:
|
|
372
|
+
time.sleep(args.interval)
|
|
373
|
+
snap = _collect_and_reset(args.interval)
|
|
374
|
+
_stats_history.append(snap)
|
|
375
|
+
|
|
376
|
+
if args.json:
|
|
377
|
+
print(json.dumps(snap), flush=True)
|
|
378
|
+
elif args.watch:
|
|
379
|
+
_print_watch(snap, args.threshold, use_color, interface)
|
|
380
|
+
else:
|
|
381
|
+
_print_human(snap, args.threshold, use_color)
|
|
382
|
+
finally:
|
|
383
|
+
_running_ref = False # signal sniff thread
|
|
384
|
+
|
|
385
|
+
# Summary
|
|
386
|
+
if not args.json and _stats_history:
|
|
387
|
+
peak_pps = max(s["pps"] for s in _stats_history)
|
|
388
|
+
peak_bps = max(s["bps"] for s in _stats_history)
|
|
389
|
+
print()
|
|
390
|
+
print(_col("── Session summary ──", "cyan", use_color))
|
|
391
|
+
print(f" Intervals : {len(_stats_history)}")
|
|
392
|
+
print(f" Peak PPS : {_fmt_pps(peak_pps)}")
|
|
393
|
+
print(f" Peak BPS : {_fmt_bps(peak_bps)}")
|
|
394
|
+
print()
|
|
395
|
+
if peak_pps >= args.threshold:
|
|
396
|
+
print(_col(" Attack traffic detected during this session.", "yellow", use_color))
|
|
397
|
+
print(_col(" Get full alerting + PCAP capture at https://flowtriq.com", "yellow", use_color))
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
if __name__ == "__main__":
|
|
401
|
+
main()
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "ftagent-lite"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "Lightweight open-source DDoS traffic monitor — stdout output, no account required"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { text = "MIT" }
|
|
11
|
+
authors = [{ name = "Flowtriq", email = "hello@flowtriq.com" }]
|
|
12
|
+
keywords = ["ddos", "network", "traffic", "monitor", "security", "ids"]
|
|
13
|
+
classifiers = [
|
|
14
|
+
"Development Status :: 4 - Beta",
|
|
15
|
+
"Environment :: Console",
|
|
16
|
+
"Intended Audience :: System Administrators",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Operating System :: POSIX :: Linux",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Programming Language :: Python :: 3.7",
|
|
21
|
+
"Programming Language :: Python :: 3.8",
|
|
22
|
+
"Programming Language :: Python :: 3.9",
|
|
23
|
+
"Programming Language :: Python :: 3.10",
|
|
24
|
+
"Programming Language :: Python :: 3.11",
|
|
25
|
+
"Programming Language :: Python :: 3.12",
|
|
26
|
+
"Topic :: System :: Monitoring",
|
|
27
|
+
"Topic :: System :: Networking :: Monitoring",
|
|
28
|
+
]
|
|
29
|
+
requires-python = ">=3.7"
|
|
30
|
+
dependencies = []
|
|
31
|
+
|
|
32
|
+
[project.optional-dependencies]
|
|
33
|
+
full = ["scapy>=2.4.5", "psutil>=5.9.0"]
|
|
34
|
+
scapy = ["scapy>=2.4.5"]
|
|
35
|
+
psutil = ["psutil>=5.9.0"]
|
|
36
|
+
|
|
37
|
+
[project.scripts]
|
|
38
|
+
ftagent-lite = "ftagent_lite:main"
|
|
39
|
+
|
|
40
|
+
[project.urls]
|
|
41
|
+
Homepage = "https://flowtriq.com"
|
|
42
|
+
Repository = "https://github.com/flowtriq/ftagent-lite"
|
|
43
|
+
"Bug Tracker" = "https://github.com/flowtriq/ftagent-lite/issues"
|
|
44
|
+
"Full Version" = "https://flowtriq.com"
|