117 lines
4.0 KiB
Markdown
117 lines
4.0 KiB
Markdown
# Traffic Viewer - JSON Event Format
|
|
|
|
The traffic viewer is now fully integrated and supports **TCP, HTTP, and UDP** protocols. To enable structured event display, the NFProxy C++ binary (`backend/binsrc/nfproxy.cpp`) should emit JSON lines to stdout with the following format:
|
|
|
|
## JSON Event Schema
|
|
|
|
```json
|
|
{
|
|
"ts": 1701964234567,
|
|
"direction": "in",
|
|
"src_ip": "192.168.1.100",
|
|
"src_port": 54321,
|
|
"dst_ip": "10.0.0.5",
|
|
"dst_port": 443,
|
|
"proto": "tcp",
|
|
"size": 1420,
|
|
"verdict": "accept",
|
|
"filter": "filter_sanitize",
|
|
"sample_hex": "474554202f20485454502f312e310d0a486f73743a206578616d706c652e636f6d..."
|
|
}
|
|
```
|
|
|
|
## Fields
|
|
|
|
- `ts` (required): Unix timestamp in milliseconds
|
|
- `direction`: `"in"` (client→server) or `"out"` (server→client)
|
|
- `src_ip`, `dst_ip`: Source and destination IP addresses
|
|
- `src_port`, `dst_port`: Source and destination ports
|
|
- `proto`: Protocol name (e.g., `"tcp"`, `"udp"`)
|
|
- `size`: Packet/payload size in bytes
|
|
- `verdict` (required): `"accept"`, `"drop"`, `"reject"`, or `"edited"`
|
|
- `filter`: Name of the Python filter that processed this packet
|
|
- `sample_hex`: Hex-encoded sample of payload (first 64-128 bytes recommended)
|
|
|
|
## Implementation Notes
|
|
|
|
1. **Backward Compatibility**: The parser in `firegex.py::_stream_handler` only processes lines starting with `{`. Non-JSON output (logs, ACK messages) continues to work as before.
|
|
|
|
2. **Performance**: Emit JSON only when needed. Consider an env flag:
|
|
```cpp
|
|
bool emit_traffic_json = getenv("FIREGEX_TRAFFIC_JSON") != nullptr;
|
|
if (emit_traffic_json) {
|
|
std::cout << json_event << std::endl;
|
|
}
|
|
```
|
|
|
|
3. **Sample Code** (C++ with nlohmann/json or similar):
|
|
```cpp
|
|
#include <nlohmann/json.hpp>
|
|
using json = nlohmann::json;
|
|
|
|
void emit_traffic_event(const PacketInfo& pkt, const char* verdict, const char* filter_name) {
|
|
json event = {
|
|
{"ts", current_timestamp_ms()},
|
|
{"direction", pkt.is_inbound ? "in" : "out"},
|
|
{"src_ip", pkt.src_addr},
|
|
{"src_port", pkt.src_port},
|
|
{"dst_ip", pkt.dst_addr},
|
|
{"dst_port", pkt.dst_port},
|
|
{"proto", pkt.protocol},
|
|
{"size", pkt.payload_len},
|
|
{"verdict", verdict},
|
|
{"filter", filter_name},
|
|
{"sample_hex", hex_encode(pkt.payload, std::min(64, pkt.payload_len))}
|
|
};
|
|
std::cout << event.dump() << std::endl;
|
|
}
|
|
```
|
|
|
|
## Testing Without Binary Changes
|
|
|
|
The viewer works immediately—it will display "No traffic events yet" until the binary is updated. You can manually test the Socket.IO flow by emitting mock events from Python:
|
|
|
|
```python
|
|
# In backend shell or script
|
|
import asyncio
|
|
import json
|
|
from utils import socketio
|
|
|
|
async def emit_test_event():
|
|
event = {
|
|
"ts": int(time.time() * 1000),
|
|
"direction": "in",
|
|
"src_ip": "192.168.1.50",
|
|
"src_port": 12345,
|
|
"dst_ip": "10.0.0.1",
|
|
"dst_port": 80,
|
|
"proto": "tcp",
|
|
"size": 512,
|
|
"verdict": "accept",
|
|
"filter": "test_filter"
|
|
}
|
|
await socketio.emit("nfproxy-traffic-YOUR_SERVICE_ID", event, room="nfproxy-traffic-YOUR_SERVICE_ID")
|
|
```
|
|
|
|
## Current Features
|
|
|
|
✅ **Backend**:
|
|
- Ring buffer stores last 500 events per service
|
|
- REST endpoint: `GET /api/nfproxy/services/{id}/traffic?limit=500`
|
|
- REST endpoint: `POST /api/nfproxy/services/{id}/traffic/clear`
|
|
- Socket.IO channels: `nfproxy-traffic-{service_id}` for live events, `nfproxy-traffic-history` on join
|
|
|
|
✅ **Frontend**:
|
|
- Live table view at `/nfproxy/{service_id}/traffic`
|
|
- Client-side text filter (searches IP, verdict, filter name, proto)
|
|
- Click row to view full event details + hex payload
|
|
- Auto-scroll, clear history button
|
|
- Accessible via new button (double-arrow icon) in ServiceDetails page
|
|
|
|
## Next Steps
|
|
|
|
1. Update `backend/binsrc/nfproxy.cpp` to emit JSON events as shown above
|
|
2. Rebuild the C++ binary
|
|
3. Start a service and generate traffic—viewer will populate in real-time
|
|
4. Optionally add more filters (by verdict, time range) or export to PCAP
|