Compare commits
7 Commits
04b9010f13
...
master
Author | SHA1 | Date | |
---|---|---|---|
adeb02f7ce | |||
9a4fcee3dd | |||
51c7738b12 | |||
d5c26d6198 | |||
6a6b9844a9 | |||
954b4ffd96 | |||
bc80482813 |
17
Dockerfile
Normal file
17
Dockerfile
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
FROM node:16
|
||||||
|
# Create app directory
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
ENV WEB_IP "$WEB_ADDRESS_INT"
|
||||||
|
# Install app dependencies
|
||||||
|
# A wildcard is used to ensure both package.json AND package-lock.json are copied
|
||||||
|
# where available (npm@5+)
|
||||||
|
COPY package*.json ./
|
||||||
|
|
||||||
|
RUN npm install
|
||||||
|
# If you are building your code for production
|
||||||
|
# RUN npm ci --only=production
|
||||||
|
# Bundle app source
|
||||||
|
COPY . .
|
||||||
|
EXPOSE 3100
|
||||||
|
EXPOSE 8999
|
||||||
|
CMD [ "npm", "start" ]
|
75
README.md
75
README.md
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
Ntopng alerts are displayed in Globe.gl
|
Ntopng alerts are displayed in Globe.gl
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
### Install packages
|
### Install packages
|
||||||
``` sh
|
``` sh
|
||||||
npm install
|
npm install
|
||||||
@ -15,6 +17,19 @@ npm install
|
|||||||
npm start
|
npm start
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Docker
|
||||||
|
[DockerHub link](https://hub.docker.com/r/dergeorg/ntopngglobe)
|
||||||
|
|
||||||
|
#### Run with config file
|
||||||
|
```sh
|
||||||
|
docker run -p 3100:3100 -p 8999:8999 --name ntopngglobe -v /PATH/TO/CONF/FOLDER:/usr/src/app/public/conf -d dergeorg/ntopngglobe
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Run without config file (default config)
|
||||||
|
```sh
|
||||||
|
docker run -p 3100:3100 -p 8999:8999 --name ntopngglobe -d dergeorg/ntopngglobe
|
||||||
|
```
|
||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
> :notebook: **Open in browser**: ```http://<ADRESS>:3100```
|
> :notebook: **Open in browser**: ```http://<ADRESS>:3100```
|
||||||
|
|
||||||
@ -23,7 +38,67 @@ npm start
|
|||||||
* Manual refresh on left-click
|
* Manual refresh on left-click
|
||||||
* Click on arc reveals whole "Ntopng Alert"
|
* Click on arc reveals whole "Ntopng Alert"
|
||||||
* Hover on arc reveals src/dest ip/hostname
|
* Hover on arc reveals src/dest ip/hostname
|
||||||
|
|
||||||
#### Colors
|
#### Colors
|
||||||
* Orange arc is a bidirectional request (sender and receiver are swapped)
|
* Orange arc is a bidirectional request (sender and receiver are swapped)
|
||||||
* Red side of arc is receiving
|
* Red side of arc is receiving
|
||||||
* Green side of arc is sending
|
* Green side of arc is sending
|
||||||
|
|
||||||
|
### Settings example
|
||||||
|
[settings.json](https://git.dergeorg.at/dergeorg/NtopngGlobe/src/branch/master/public/conf/settings.json)
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"location": {
|
||||||
|
"home": {
|
||||||
|
"lat": 48.1, // must be set to lat of home wan ip --> https://www.maxmind.com/en/locate-my-ip-address
|
||||||
|
"lng": 16.3 // must be set to lng of home wan ip --> https://www.maxmind.com/en/locate-my-ip-address
|
||||||
|
},
|
||||||
|
"precision": 0 // how to round the decimal. 0 is no decimal
|
||||||
|
},
|
||||||
|
"colors": {
|
||||||
|
"loc": {
|
||||||
|
"default": "green",
|
||||||
|
"dualsender": "orange"
|
||||||
|
},
|
||||||
|
"arc": {
|
||||||
|
"default": [
|
||||||
|
"green",
|
||||||
|
"red"
|
||||||
|
],
|
||||||
|
"dualsender": [
|
||||||
|
"orange",
|
||||||
|
"orange"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sizes": {
|
||||||
|
"loc": {
|
||||||
|
"default": 0.1
|
||||||
|
},
|
||||||
|
"arc": {
|
||||||
|
"default": 1.1
|
||||||
|
},
|
||||||
|
"globe": {
|
||||||
|
"arcDashLength": 0.4,
|
||||||
|
"arcAltitudeAutoScale": 0.4,
|
||||||
|
"arcDashGap": 0.1,
|
||||||
|
"arcDashInitialGap": 0.1,
|
||||||
|
"arcDashAnimateTime": 7000,
|
||||||
|
"arcStroke": 0.5,
|
||||||
|
"labelSize": 0,
|
||||||
|
"labelDotRadius": 0.4,
|
||||||
|
"labelResolution": 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"timer": {
|
||||||
|
"del": 30, // deletes alerts older than 30 minutes
|
||||||
|
"refreshTimer": 1 // 1 --> refresh globe every 1 minute; 0 --> refresh globe on every new Data set
|
||||||
|
},
|
||||||
|
"ips": {
|
||||||
|
"home": "192.168.1.", //Private home adress
|
||||||
|
"loopback": "127.0.0.1",
|
||||||
|
"server": "localhost:3100", //Server adress
|
||||||
|
"serverws": "localhost:8999" //websocket adress
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
4
app.js
4
app.js
@ -18,7 +18,9 @@ var usersRouter = require('./routes/users');
|
|||||||
// view engine setup
|
// view engine setup
|
||||||
app.set('views', path.join(__dirname, 'views'));
|
app.set('views', path.join(__dirname, 'views'));
|
||||||
app.set('view engine', 'jade');
|
app.set('view engine', 'jade');
|
||||||
app.use(cors())
|
app.use(cors({
|
||||||
|
origin: 'globe.dergeorg.at'
|
||||||
|
}))
|
||||||
app.use(logger('dev'));
|
app.use(logger('dev'));
|
||||||
app.use(express.json());
|
app.use(express.json());
|
||||||
app.use(express.urlencoded({ extended: false }));
|
app.use(express.urlencoded({ extended: false }));
|
||||||
|
@ -3,47 +3,7 @@ var data = {
|
|||||||
arc: []
|
arc: []
|
||||||
}
|
}
|
||||||
|
|
||||||
var settings = {
|
var settings = require('../public/conf/settings.json')
|
||||||
location: {
|
|
||||||
home: {
|
|
||||||
lat: 48.1,
|
|
||||||
lng: 16.3
|
|
||||||
},
|
|
||||||
precision: 0
|
|
||||||
},
|
|
||||||
colors: {
|
|
||||||
loc: {
|
|
||||||
default: "green",
|
|
||||||
dualsender: "orange"
|
|
||||||
},
|
|
||||||
arc: {
|
|
||||||
default: ["green", "red"],
|
|
||||||
dualsender: ["orange", "orange"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
sizes: {
|
|
||||||
loc: {
|
|
||||||
default: 0.1
|
|
||||||
},
|
|
||||||
arc: {
|
|
||||||
default: 1.1
|
|
||||||
},
|
|
||||||
globe: {
|
|
||||||
arcDashLength: 0.4,
|
|
||||||
arcAltitudeAutoScale: 0.4,
|
|
||||||
arcDashGap: 0.1,
|
|
||||||
arcDashInitialGap: 0.1,
|
|
||||||
arcDashAnimateTime: 7000,
|
|
||||||
arcStroke: 0.5,
|
|
||||||
labelSize: 0,
|
|
||||||
labelDotRadius: 0.4,
|
|
||||||
labelResolution: 2
|
|
||||||
}
|
|
||||||
},
|
|
||||||
timer:{
|
|
||||||
del: 30
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var geoip = require('fast-geoip');
|
var geoip = require('fast-geoip');
|
||||||
|
|
||||||
@ -56,7 +16,7 @@ async function addArc(src, dest, uid, src_name, dest_name){
|
|||||||
var endLat = undefined;
|
var endLat = undefined;
|
||||||
var endLng = undefined;
|
var endLng = undefined;
|
||||||
if(!data.arc.some(x => x.src === src && x.dest === dest)) {
|
if(!data.arc.some(x => x.src === src && x.dest === dest)) {
|
||||||
if (src.includes("192.168.1.") || src.includes("127.0.0.1")) {
|
if (src.includes(settings.ips.home) || src.includes("127.0.0.1")) {
|
||||||
startLat = round(settings.location.home.lat, settings.location.precision)
|
startLat = round(settings.location.home.lat, settings.location.precision)
|
||||||
startLng = round(settings.location.home.lng, settings.location.precision)
|
startLng = round(settings.location.home.lng, settings.location.precision)
|
||||||
} else {
|
} else {
|
||||||
|
29
package-lock.json
generated
29
package-lock.json
generated
@ -17,7 +17,8 @@
|
|||||||
"jade": "~1.11.0",
|
"jade": "~1.11.0",
|
||||||
"morgan": "~1.9.1",
|
"morgan": "~1.9.1",
|
||||||
"node-cron": "^3.0.0",
|
"node-cron": "^3.0.0",
|
||||||
"uuid": "^8.3.2"
|
"uuid": "^8.3.2",
|
||||||
|
"ws": "^8.4.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/accepts": {
|
"node_modules/accepts": {
|
||||||
@ -1002,6 +1003,26 @@
|
|||||||
"node": ">=0.4.0"
|
"node": ">=0.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ws": {
|
||||||
|
"version": "8.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.4.2.tgz",
|
||||||
|
"integrity": "sha512-Kbk4Nxyq7/ZWqr/tarI9yIt/+iNNFOjBXEWgTb4ydaNHBNGgvf2QHbS9fdfsndfjFlFwEd4Al+mw83YkaD10ZA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"bufferutil": "^4.0.1",
|
||||||
|
"utf-8-validate": "^5.0.2"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"bufferutil": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"utf-8-validate": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/yargs": {
|
"node_modules/yargs": {
|
||||||
"version": "3.10.0",
|
"version": "3.10.0",
|
||||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
|
"resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
|
||||||
@ -1774,6 +1795,12 @@
|
|||||||
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
|
||||||
"integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8="
|
"integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8="
|
||||||
},
|
},
|
||||||
|
"ws": {
|
||||||
|
"version": "8.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.4.2.tgz",
|
||||||
|
"integrity": "sha512-Kbk4Nxyq7/ZWqr/tarI9yIt/+iNNFOjBXEWgTb4ydaNHBNGgvf2QHbS9fdfsndfjFlFwEd4Al+mw83YkaD10ZA==",
|
||||||
|
"requires": {}
|
||||||
|
},
|
||||||
"yargs": {
|
"yargs": {
|
||||||
"version": "3.10.0",
|
"version": "3.10.0",
|
||||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
|
"resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
"jade": "~1.11.0",
|
"jade": "~1.11.0",
|
||||||
"morgan": "~1.9.1",
|
"morgan": "~1.9.1",
|
||||||
"node-cron": "^3.0.0",
|
"node-cron": "^3.0.0",
|
||||||
"uuid": "^8.3.2"
|
"uuid": "^8.3.2",
|
||||||
|
"ws": "^8.4.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
54
public/conf/settings.json
Normal file
54
public/conf/settings.json
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
{
|
||||||
|
"location": {
|
||||||
|
"home": {
|
||||||
|
"lat": 48.1,
|
||||||
|
"lng": 16.3
|
||||||
|
},
|
||||||
|
"precision": 0
|
||||||
|
},
|
||||||
|
"colors": {
|
||||||
|
"loc": {
|
||||||
|
"default": "green",
|
||||||
|
"dualsender": "orange"
|
||||||
|
},
|
||||||
|
"arc": {
|
||||||
|
"default": [
|
||||||
|
"green",
|
||||||
|
"red"
|
||||||
|
],
|
||||||
|
"dualsender": [
|
||||||
|
"orange",
|
||||||
|
"orange"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sizes": {
|
||||||
|
"loc": {
|
||||||
|
"default": 0.1
|
||||||
|
},
|
||||||
|
"arc": {
|
||||||
|
"default": 1.1
|
||||||
|
},
|
||||||
|
"globe": {
|
||||||
|
"arcDashLength": 0.4,
|
||||||
|
"arcAltitudeAutoScale": 0.4,
|
||||||
|
"arcDashGap": 0.1,
|
||||||
|
"arcDashInitialGap": 0.1,
|
||||||
|
"arcDashAnimateTime": 7000,
|
||||||
|
"arcStroke": 0.5,
|
||||||
|
"labelSize": 0,
|
||||||
|
"labelDotRadius": 0.4,
|
||||||
|
"labelResolution": 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"timer": {
|
||||||
|
"del": 30,
|
||||||
|
"refreshTimer": 1
|
||||||
|
},
|
||||||
|
"ips": {
|
||||||
|
"home": "192.168.1.",
|
||||||
|
"loopback": "127.0.0.1",
|
||||||
|
"server": "localhost:3100",
|
||||||
|
"serverws": "localhost:8999"
|
||||||
|
}
|
||||||
|
}
|
@ -80,77 +80,72 @@
|
|||||||
item.cli_os + " \nis_srv_vic " + item.is_srv_vic
|
item.cli_os + " \nis_srv_vic " + item.is_srv_vic
|
||||||
}
|
}
|
||||||
|
|
||||||
function componentDidMount() {
|
|
||||||
var data = {};
|
|
||||||
if ("WebSocket" in window) {
|
|
||||||
console.log("WebSocket is supported by your Browser!");
|
|
||||||
const ws = new WebSocket('ws://localhost:8999');
|
|
||||||
ws.onopen = function () {
|
|
||||||
// Web Socket is connected, send data using send()
|
|
||||||
console.log("Message is sent...");
|
|
||||||
};
|
|
||||||
ws.onmessage = function (evt) {
|
|
||||||
var received_msg = evt.data;
|
|
||||||
console.log("Message is received...");
|
|
||||||
componentDidMount()
|
|
||||||
};
|
|
||||||
ws.onclose = function () {
|
|
||||||
// websocket is closed.
|
|
||||||
console.log("Connection is closed...");
|
|
||||||
};
|
|
||||||
}else {
|
|
||||||
// The browser doesn't support WebSocket
|
|
||||||
alert("WebSocket NOT supported by your Browser! A left click on the globe will refresh the data");
|
|
||||||
}
|
|
||||||
|
|
||||||
axios.get("http://localhost:3100/display").then(res => {
|
function componentDidMount() {
|
||||||
data = res.data;
|
axios.get('/conf/settings.json').then(res => {
|
||||||
console.log(data)
|
const settings = res.data;
|
||||||
ReactDOM.render(
|
var data = {};
|
||||||
<Globe
|
if ("WebSocket" in window) {
|
||||||
onGlobeClick={() => {
|
console.log("WebSocket is supported by your Browser!");
|
||||||
axios.get("http://localhost:3100/display").then(res => {
|
const ws = new WebSocket('ws://'+settings.ips.server);
|
||||||
data = res.data;
|
ws.onmessage = function (evt) {
|
||||||
componentDidMount()
|
var received_msg = evt.data;
|
||||||
});
|
componentDidMount()
|
||||||
}}
|
};
|
||||||
globeImageUrl="/images/earth-night.jpg"
|
}else {
|
||||||
backgroundImageUrl="/images/night-sky.png"
|
// The browser doesn't support WebSocket
|
||||||
backgroundColor={"#000011"}
|
alert("WebSocket NOT supported by your Browser! A left click on the globe will refresh the data");
|
||||||
// edges
|
}
|
||||||
arcsData={data.arc}
|
|
||||||
arcColor={(d) => [d.color[0], d.color[1]]}
|
axios.get("http://"+settings.ips.server+"/display").then(res => {
|
||||||
arcDashLength={data.settings.sizes.globe.arcDashLength}
|
data = res.data;
|
||||||
arcAltitudeAutoScale={data.settings.sizes.globe.arcAltitudeAutoScale}
|
console.log(data)
|
||||||
arcDashGap={data.settings.sizes.globe.arcDashGap}
|
ReactDOM.render(
|
||||||
arcDashInitialGap={data.settings.sizes.globe.arcDashInitialGap}
|
<Globe
|
||||||
arcDashAnimateTime={data.settings.sizes.globe.arcDashAnimateTime}
|
onGlobeClick={() => {
|
||||||
arcStroke={data.settings.sizes.globe.arcStroke}
|
axios.get("http://"+settings.ips.server+"/display").then(res => {
|
||||||
arcLabel={(d) => generateHoverText(d.txrx)}
|
data = res.data;
|
||||||
onArcClick={function (d) {
|
componentDidMount()
|
||||||
axios.get("http://localhost:3100/alert/" + d.uid).then(res => {
|
});
|
||||||
const resdata = res.data;
|
}}
|
||||||
alert(generateClickText(resdata))
|
globeImageUrl="/images/earth-night.jpg"
|
||||||
})
|
backgroundImageUrl="/images/night-sky.png"
|
||||||
}}
|
backgroundColor={"#000011"}
|
||||||
//arcCircularResolution={64}
|
// edges
|
||||||
// arcLabel={() => "test"}
|
arcsData={data.arc}
|
||||||
// labels
|
arcColor={(d) => [d.color[0], d.color[1]]}
|
||||||
labelsData={data.loc}
|
arcDashLength={data.settings.sizes.globe.arcDashLength}
|
||||||
labelLat={(d) => d.lat}
|
arcAltitudeAutoScale={data.settings.sizes.globe.arcAltitudeAutoScale}
|
||||||
labelLng={(d) => d.lng}
|
arcDashGap={data.settings.sizes.globe.arcDashGap}
|
||||||
labelText={(d) => d.name}
|
arcDashInitialGap={data.settings.sizes.globe.arcDashInitialGap}
|
||||||
// labelSize={(d) => 0.5 + d.size}
|
arcDashAnimateTime={data.settings.sizes.globe.arcDashAnimateTime}
|
||||||
labelSize={0}
|
arcStroke={data.settings.sizes.globe.arcStroke}
|
||||||
labelDotRadius={0.4}
|
arcLabel={(d) => generateHoverText(d.txrx)}
|
||||||
// labelDotRadius={(d) => 0.5 + d.size}
|
onArcClick={function (d) {
|
||||||
labelColor={(d) => d.color}
|
axios.get("http://"+settings.ips.server+"/alert/" + d.uid).then(res => {
|
||||||
labelResolution={2}
|
const resdata = res.data;
|
||||||
enablePointerInteraction={true}
|
alert(generateClickText(resdata))
|
||||||
/>,
|
})
|
||||||
document.getElementById('globeViz')
|
}}
|
||||||
);
|
//arcCircularResolution={64}
|
||||||
}).catch(err => alert(err))
|
// arcLabel={() => "test"}
|
||||||
|
// labels
|
||||||
|
labelsData={data.loc}
|
||||||
|
labelLat={(d) => d.lat}
|
||||||
|
labelLng={(d) => d.lng}
|
||||||
|
labelText={(d) => d.name}
|
||||||
|
// labelSize={(d) => 0.5 + d.size}
|
||||||
|
labelSize={0}
|
||||||
|
labelDotRadius={0.4}
|
||||||
|
// labelDotRadius={(d) => 0.5 + d.size}
|
||||||
|
labelColor={(d) => d.color}
|
||||||
|
labelResolution={2}
|
||||||
|
enablePointerInteraction={true}
|
||||||
|
/>,
|
||||||
|
document.getElementById('globeViz')
|
||||||
|
);
|
||||||
|
}).catch(err => alert(err))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount()
|
componentDidMount()
|
||||||
|
BIN
public/images/example.png
Normal file
BIN
public/images/example.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 814 KiB |
@ -53,6 +53,9 @@ router.get('/alerts/dates', function(req, res, next) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
var task = cron.schedule('* * * * *', () => {
|
var task = cron.schedule('* * * * *', () => {
|
||||||
|
if(globe.getSettigns().timer.refreshTimer === 1) {
|
||||||
|
wss.broadcast("new data is da")
|
||||||
|
}
|
||||||
const TEN_MINUTES = globe.getSettigns().timer.del*60*1000;
|
const TEN_MINUTES = globe.getSettigns().timer.del*60*1000;
|
||||||
const date = new Date();
|
const date = new Date();
|
||||||
alerts.getAlertDates().forEach(ad => {
|
alerts.getAlertDates().forEach(ad => {
|
||||||
@ -79,7 +82,9 @@ router.post('/ws', async function(req, res, next) {
|
|||||||
if (typeof src !== 'undefined' || typeof dest !== 'undefined')
|
if (typeof src !== 'undefined' || typeof dest !== 'undefined')
|
||||||
await globe.addArc(src, dest, uid, item.srv_name, item.cli_name)
|
await globe.addArc(src, dest, uid, item.srv_name, item.cli_name)
|
||||||
}
|
}
|
||||||
wss.broadcast("new data is da")
|
if(globe.getSettigns().timer.refreshTimer === 0) {
|
||||||
|
wss.broadcast("new data is da")
|
||||||
|
}
|
||||||
res.sendStatus(200);
|
res.sendStatus(200);
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user