Skip to content

Instantly share code, notes, and snippets.

@RolphH
Created February 16, 2021 16:27
Show Gist options
  • Save RolphH/26c3dfab601508f723882a88e932ec5e to your computer and use it in GitHub Desktop.
Save RolphH/26c3dfab601508f723882a88e932ec5e to your computer and use it in GitHub Desktop.
Javascript which opens websocket and plots the geopoints on Mapbox map
// Set the IP to your webserver IP
const WEBSOCKET_SERVER = 'ws://<YOUR_WEBSERVERIP:8081>';
// Set your mapboxGL AccessToken
const MAPBOX_TOKEN = 'YOUR_ACCESS_TOKEN';
// Remove points from map after x-seconds
var displayTime = 300;
// Set some defaults for the map
var framesPerSecond = 15;
var initialOpacity = 1;
var opacity = initialOpacity;
var initialRadius = 3;
var radius = initialRadius;
var maxRadius = 15;
let points = new Map();
var timers = [];
//Set your accessToken here
mapboxgl.accessToken = MAPBOX_TOKEN;
//Create new mapboxGl Map. Set your used style
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/leaseweb/ckkiepmg40ds717ry6l0htwag',
center: [0, 0],
zoom: 1.75
});
// Create a popup, but don't add it to the map yet.
var popup = new mapboxgl.Popup({
closeButton: false,
closeOnClick: false
});
// Once the map is loaded, we open the Websockets
map.on('load', function () {
openWebSockets(map);
});
function openWebSockets(map) {
if ("WebSocket" in window) {
// Let us open a web socket
var ws = new WebSocket( WEBSOCKET_SERVER);
ws.onopen = function() {
// Web Socket is connected, send data using send()
console.log("WS Open...");
};
ws.onmessage = function (event) {
var received_msg = JSON.parse(event.data);
addPoint(received_msg);
};
ws.onerror = function(error) {
console.log('Websocket error: ');
console.log(error);
}
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!");
}
}
function animateMarker(timestamp, pointId) {
if(!(pointId === undefined)) {
if (points.has(pointId)) {
timers[pointId] = setTimeout(function() {
requestAnimationFrame(function(timestamp) {
animateMarker(timestamp, pointId);
});
radius = points.get(pointId)[0];
opacity = points.get(pointId)[1];
radius += (maxRadius - radius) / framesPerSecond;
opacity -= ( .9 / framesPerSecond );
if (opacity < 0) {
opacity = 0;
}
map.setPaintProperty('point-'+pointId, 'circle-radius', radius);
map.setPaintProperty('point-'+pointId, 'circle-opacity', opacity);
if (opacity <= 0) {
radius = initialRadius;
opacity = initialOpacity;
}
points.set(pointId,[radius, opacity ]);
}, 1000 / framesPerSecond);
} else {
//The point is removed, we don't do anything at this moment
}
}
}
function addPoint(msg) {
geo = JSON.parse(msg.geoip);
var ip = geo.ip;
//Create a geohash based on the lat/lon of the IP. We used factor 7 to prevent overlapping point animations
var geohash = encodeGeoHash(geo.latitude, geo.longitude, 7);
//Get the AS Organisation name (or unknown)
var ASORG = (geo.as_org === undefined ? 'Unknown' : geo.as_org);
//Remove the flashrow style from last added row
var flashrows = document.getElementById("tickettable").getElementsByClassName('flashrow');
while (flashrows[0]) {
flashrows[0].classList.remove('flashrow');
}
//Get table to add the newly added point information
var tbody = document.getElementById("tickettable").getElementsByTagName('tbody')[0];
tbody.insertRow().innerHTML = '<tr><td class="flashrow">' + new Date().toLocaleTimeString() + '</td>' +
'<td class="flashrow">' + geo.country_name + '</td>' +
'<td class="flashrow">' + ASORG + '</td>' +
'<td class="flashrow">' + msg.protocol.toUpperCase() + ' Attack on port ' + msg.dest_port +'</td>' +
'</tr>';
//If we have more than 5 items in the list, remove the first one
if (tbody.rows.length > 5) {
tbody.deleteRow(0);
}
//Add the point to the map if it is not already on the map
if (!(geohash === undefined)) {
if (!(points.has(geohash))) {
//Add the point to hash to keep of all active points and prevent duplicate points.
points.set(geohash, [initialRadius, initialOpacity ]);
//Set a timer to remove the poinrt after 5minutes
setTimeout(function() { removePoint(geohash) }, displayTime * 1000);
map.addSource('points-'+geohash, {
"type": "geojson",
"data": {
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [ geo.longitude, geo.latitude]
},
"properties": {
"description": "<strong>" + ASORG + " (AS " + geo.asn +")</strong><p>IP: " + ip + "<BR>City: " + (geo.city_name === undefined ? 'Unknown' : geo.city_name) +
"<BR>Region: " + (geo.region_name === undefined ? 'Unknown' : geo.region_name) + "<BR>Country: " + (geo.country_name === undefined ? 'Unknown' : geo.country_name) + "</P>"
}
}
});
map.addLayer({
"id": "point-"+geohash,
"source": "points-"+geohash,
"type": "circle",
"paint": {
"circle-radius": initialRadius,
"circle-radius-transition": {duration: 0},
"circle-opacity-transition": {duration: 0},
"circle-color": "#dd7cbf"
}
});
map.on('mouseenter', 'point-'+geohash, function (e) {
// Change the cursor style as a UI indicator.
map.getCanvas().style.cursor = 'pointer';
var coordinates = e.features[0].geometry.coordinates.slice();
var description = e.features[0].properties.description;
// Ensure that if the map is zoomed out such that multiple
// copies of the feature are visible, the popup appears
// over the copy being pointed to.
while (Math.abs(e.lngLat.lng - coordinates[0]) > 180) {
coordinates[0] += e.lngLat.lng > coordinates[0] ? 360 : -360;
}
// Populate the popup and set its coordinates
// based on the feature found.
popup.setLngLat(coordinates).setHTML(description).addTo(map);
});
map.on('mouseleave', 'point-'+geohash, function () {
map.getCanvas().style.cursor = '';
popup.remove();
});
//Animate the added point.
animateMarker(0, geohash);
}
}
}
function removePoint(ip) {
clearTimeout(timers[ip]);
points.delete(ip);
map.removeLayer('point-'+ip);
map.removeSource('points-'+ip);
}
function encodeGeoHash(latitude, longitude, precision) {
var BITS = [16, 8, 4, 2, 1];
var BASE32 = "0123456789bcdefghjkmnpqrstuvwxyz";
var isEven = 1;
var lat = [-90.0, 90.0];
var lon = [-180.0, 180.0];
var bit = 0;
var ch = 0;
precision = precision || 12;
var geohash = "";
while (geohash.length < precision) {
var mid;
if (isEven) {
mid = (lon[0] + lon[1]) / 2;
if (longitude > mid) {
ch |= BITS[bit];
lon[0] = mid;
} else {
lon[1] = mid;
}
} else {
mid = (lat[0] + lat[1]) / 2;
if (latitude > mid) {
ch |= BITS[bit];
lat[0] = mid;
} else {
lat[1] = mid;
}
}
isEven = !isEven;
if (bit < 4) {
bit++;
} else {
geohash += BASE32[ch];
bit = 0;
ch = 0;
}
}
return geohash;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment