diff --git a/README.md b/README.md index 275106d3a990ba4aaeae54a9d8c0f61a0d82b205..59563b0761c8defcbadb63a258268423f6bdc2b6 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ # Snort2 grafana dashboard +While production IDS/IPS still wait for Snort3 where JSON logging is available (or Suricata) it may be useful give elasticity of logs handling given by Elasticsearch and Grafana for Snort2 + + Project is based on existing grafana security dashboard but removes existing hard-coded dependencies and provides all configuration details for Snort, Barnyard2, Elasticsearch and Grafana. @@ -15,7 +18,25 @@ Example dashboards:  -TODO -- add Snort/Barnyard config -- add Logstash config -- add Grafana dashboard +<b>Snort configuration:</b> +Snort uses "-l" configuration inside systemd service definition to inform what is the log output directory. + +<b>Barnyard2 configuration:</b> + +Barnyard2 takes files from snort and sends them via UDP protocol to Logstash server listening to 5142 udp port + +<b>Logstash:</b> + +Logstash listen to 5142 and all logs marks with "snort" tag. +Tagged "snort" logs are treated with grok and later some transformation. +Output for snort log is set to elasticsearch and index name like snortids-%YY-%MM-%dd + +<b>Grafana:</b> + +Just connects to defined Elasticsearch clusters: + +<p>EL datasource definition (before importing Grafana dashboard):</p> + + + + diff --git a/_images/elasticsearch-datasource01.png.png b/_images/elasticsearch-datasource01.png.png new file mode 100644 index 0000000000000000000000000000000000000000..e5db60a2377b1b824acb5675f5e26094124e192c Binary files /dev/null and b/_images/elasticsearch-datasource01.png.png differ diff --git a/grafana_dashboard/Snort Dashboard-v05.json b/grafana_dashboard/Snort Dashboard-v05.json new file mode 100644 index 0000000000000000000000000000000000000000..475b09c3a46a3bff20c840d8c67f7442c2cdae44 --- /dev/null +++ b/grafana_dashboard/Snort Dashboard-v05.json @@ -0,0 +1,1504 @@ +{ + "__inputs": [ + { + "name": "DS_ELASTICSEARCH", + "label": "elasticsearch", + "description": "", + "type": "datasource", + "pluginId": "elasticsearch", + "pluginName": "Elasticsearch" + } + ], + "__requires": [ + { + "type": "datasource", + "id": "elasticsearch", + "name": "Elasticsearch", + "version": "5.0.0" + }, + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "5.3.2" + }, + { + "type": "panel", + "id": "grafana-clock-panel", + "name": "Clock", + "version": "1.0.2" + }, + { + "type": "panel", + "id": "grafana-piechart-panel", + "name": "Pie Chart", + "version": "1.3.6" + }, + { + "type": "panel", + "id": "grafana-worldmap-panel", + "name": "Worldmap Panel", + "version": "0.2.0" + }, + { + "type": "panel", + "id": "graph", + "name": "Graph", + "version": "5.0.0" + }, + { + "type": "panel", + "id": "singlestat", + "name": "Singlestat", + "version": "5.0.0" + }, + { + "type": "panel", + "id": "table", + "name": "Table", + "version": "5.0.0" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "description": "Snort Dashboard", + "editable": true, + "gnetId": 3099, + "graphTooltip": 0, + "id": null, + "iteration": 1561322148390, + "links": [ + { + "asDropdown": true, + "icon": "external link", + "tags": [], + "type": "dashboards" + } + ], + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 17, + "panels": [], + "repeat": null, + "title": "Event Severity", + "type": "row" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "datasource": "${DS_ELASTICSEARCH}", + "editable": true, + "error": false, + "format": "none", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 1 + }, + "id": 9, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(189, 31, 111, 0.18)", + "full": true, + "lineColor": "#bf1b00", + "show": true + }, + "tableColumn": "", + "targets": [ + { + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto", + "min_doc_count": 0, + "trimEdges": 0 + }, + "type": "date_histogram" + } + ], + "dsType": "elasticsearch", + "metrics": [ + { + "field": "select field", + "id": "1", + "type": "count" + } + ], + "query": "severity.keyword:High AND $sensor_name", + "refId": "A", + "timeField": "@timestamp" + } + ], + "thresholds": "", + "title": "High Severity", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "total" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "datasource": "${DS_ELASTICSEARCH}", + "editable": true, + "error": false, + "format": "none", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 6, + "y": 1 + }, + "id": 10, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(204, 181, 21, 0.18)", + "full": true, + "lineColor": "rgb(193, 180, 31)", + "show": true + }, + "tableColumn": "", + "targets": [ + { + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto", + "min_doc_count": 0, + "trimEdges": 0 + }, + "type": "date_histogram" + } + ], + "dsType": "elasticsearch", + "metrics": [ + { + "field": "select field", + "id": "1", + "type": "count" + } + ], + "query": "severity.keyword:Medium AND $sensor_name", + "refId": "A", + "timeField": "@timestamp" + } + ], + "thresholds": "", + "title": "Medium Severity", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "total" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "datasource": "${DS_ELASTICSEARCH}", + "editable": true, + "error": false, + "format": "none", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 12, + "y": 1 + }, + "id": 11, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 204, 21, 0.18)", + "full": true, + "lineColor": "rgb(8, 126, 33)", + "show": true + }, + "tableColumn": "", + "targets": [ + { + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto", + "min_doc_count": 0, + "trimEdges": 0 + }, + "type": "date_histogram" + } + ], + "dsType": "elasticsearch", + "metrics": [ + { + "field": "select field", + "id": "1", + "type": "count" + } + ], + "query": "severity.keyword:Low AND $sensor_name", + "refId": "A", + "timeField": "@timestamp" + } + ], + "thresholds": "", + "title": "Low Severity", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "total" + }, + { + "bgColor": null, + "clockType": "24 hour", + "countdownSettings": { + "customFormat": null, + "endCountdownTime": "2017-08-31T13:35:00.000Z", + "endText": "00:00:00" + }, + "dateSettings": { + "dateFormat": "YYYY-MM-DD", + "fontSize": "20px", + "fontWeight": "normal", + "showDate": true + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 18, + "y": 1 + }, + "id": 16, + "links": [], + "mode": "time", + "offsetFromUtc": null, + "offsetFromUtcMinutes": null, + "refreshSettings": { + "syncWithDashboard": false + }, + "timeSettings": { + "customFormat": "HH:mm:ss", + "fontSize": "54px", + "fontWeight": "normal" + }, + "title": "Current Time", + "type": "grafana-clock-panel" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 4 + }, + "id": 18, + "panels": [], + "repeat": null, + "title": "Row", + "type": "row" + }, + { + "aliasColors": { + "Events": "#962d82" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_ELASTICSEARCH}", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 9, + "w": 14, + "x": 0, + "y": 5 + }, + "id": 1, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": null, + "sortDesc": null, + "total": true, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "percentage": false, + "pointradius": 2, + "points": true, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/.*Low/", + "color": "#629e51" + }, + { + "alias": "/.*High/", + "color": "#bf1b00" + }, + { + "alias": "/.*Medium/", + "color": "#e5ac0e" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "alias": "{{sensor_name.keyword}} severity {{severity.keyword}}", + "bucketAggs": [ + { + "fake": true, + "field": "severity.keyword", + "id": "5", + "settings": { + "min_doc_count": 1, + "order": "desc", + "orderBy": "_term", + "size": "10" + }, + "type": "terms" + }, + { + "fake": true, + "field": "sensor_name.keyword", + "id": "4", + "settings": { + "min_doc_count": 1, + "order": "desc", + "orderBy": "_term", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto", + "min_doc_count": 0, + "trimEdges": 0 + }, + "type": "date_histogram" + } + ], + "dsType": "elasticsearch", + "metrics": [ + { + "field": "select field", + "id": "3", + "type": "count" + } + ], + "query": "$sensor_name", + "refId": "A", + "timeField": "@timestamp" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Event by sensor", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "transparent": false, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Events", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "breakPoint": "50%", + "cacheTimeout": null, + "combine": { + "label": "Others", + "threshold": 0 + }, + "datasource": "${DS_ELASTICSEARCH}", + "editable": true, + "error": false, + "fontSize": "60%", + "format": "short", + "gridPos": { + "h": 9, + "w": 10, + "x": 14, + "y": 5 + }, + "height": "250px", + "id": 14, + "interval": null, + "legend": { + "show": true, + "values": true + }, + "legendType": "Right side", + "links": [], + "maxDataPoints": 3, + "nullPointMode": "connected", + "pieType": "donut", + "strokeWidth": 1, + "targets": [ + { + "bucketAggs": [ + { + "fake": true, + "field": "alert_description.keyword", + "id": "3", + "settings": { + "min_doc_count": 1, + "order": "desc", + "orderBy": "_count", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto", + "min_doc_count": 0, + "trimEdges": 0 + }, + "type": "date_histogram" + } + ], + "dsType": "elasticsearch", + "metrics": [ + { + "field": "alert_description", + "id": "1", + "meta": {}, + "settings": {}, + "type": "count" + } + ], + "query": "$sensor_name", + "refId": "A", + "timeField": "@timestamp" + } + ], + "title": "Top Alert Type", + "type": "grafana-piechart-panel", + "valueName": "total" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 14 + }, + "id": 19, + "panels": [], + "repeat": null, + "title": "New row", + "type": "row" + }, + { + "circleMaxSize": 30, + "circleMinSize": 2, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "datasource": "${DS_ELASTICSEARCH}", + "decimals": 0, + "editable": true, + "error": false, + "esGeoPoint": "DstGeoip.location", + "esLocationName": "DstGeoip.ip", + "esMetric": "Count", + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 15 + }, + "hideEmpty": false, + "hideTimeOverride": false, + "hideZero": false, + "id": 3, + "initialZoom": 1, + "jsonUrl": "", + "links": [], + "locationData": "geohash", + "mapCenter": "Europe", + "mapCenterLatitude": 46, + "mapCenterLongitude": 14, + "maxDataPoints": 1, + "mouseWheelZoom": false, + "showLegend": true, + "stickyLabels": false, + "tableLabel": "DstGeo", + "tableQueryOptions": { + "geohashField": "geohash", + "latitudeField": "latitude", + "longitudeField": "longitude", + "metricField": "metric", + "queryType": "geohash" + }, + "targets": [ + { + "bucketAggs": [ + { + "fake": true, + "field": "DstGeoip.ip", + "id": "5", + "settings": { + "min_doc_count": 1, + "order": "asc", + "orderBy": "_term", + "size": "10" + }, + "type": "terms" + }, + { + "fake": true, + "field": "DstGeoip.location", + "id": "3", + "settings": { + "precision": 3 + }, + "type": "geohash_grid" + } + ], + "dsType": "elasticsearch", + "metrics": [ + { + "field": "ip", + "id": "1", + "meta": {}, + "settings": {}, + "type": "count" + } + ], + "query": "", + "refId": "A", + "timeField": "@timestamp" + } + ], + "thresholds": "0,10", + "timeFrom": null, + "title": "Destination IPs", + "transparent": false, + "type": "grafana-worldmap-panel", + "unitPlural": "ips", + "unitSingle": "", + "unitSingular": "ip", + "valueName": "total" + }, + { + "circleMaxSize": 30, + "circleMinSize": 2, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "datasource": "${DS_ELASTICSEARCH}", + "decimals": 0, + "editable": true, + "error": false, + "esGeoPoint": "SrcGeoip.location", + "esLocationName": "SrcGeoip.ip", + "esMetric": "Count", + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 15 + }, + "hideEmpty": false, + "hideTimeOverride": false, + "hideZero": false, + "id": 21, + "initialZoom": 1, + "jsonUrl": "", + "links": [], + "locationData": "geohash", + "mapCenter": "Europe", + "mapCenterLatitude": 46, + "mapCenterLongitude": 14, + "maxDataPoints": 1, + "mouseWheelZoom": false, + "showLegend": true, + "stickyLabels": false, + "tableLabel": "DstGeo", + "tableQueryOptions": { + "geohashField": "geohash", + "latitudeField": "latitude", + "longitudeField": "longitude", + "metricField": "metric", + "queryType": "geohash" + }, + "targets": [ + { + "bucketAggs": [ + { + "fake": true, + "field": "SrcGeoip.ip", + "id": "5", + "settings": { + "min_doc_count": 1, + "order": "asc", + "orderBy": "_term", + "size": "10" + }, + "type": "terms" + }, + { + "fake": true, + "field": "SrcGeoip.location", + "id": "3", + "settings": { + "precision": 3 + }, + "type": "geohash_grid" + } + ], + "dsType": "elasticsearch", + "metrics": [ + { + "field": "ip", + "id": "1", + "meta": {}, + "settings": {}, + "type": "count" + } + ], + "query": "", + "refId": "A", + "timeField": "@timestamp" + } + ], + "thresholds": "0,10", + "timeFrom": null, + "title": "Source IPs", + "transparent": false, + "type": "grafana-worldmap-panel", + "unitPlural": "ips", + "unitSingle": "", + "unitSingular": "ip", + "valueName": "total" + }, + { + "columns": [ + { + "text": "event_timestamp", + "value": "event_timestamp" + }, + { + "text": "sensor_name", + "value": "sensor_name" + }, + { + "text": "alert_description", + "value": "alert_description" + }, + { + "text": "SrcIp", + "value": "SrcIp" + }, + { + "text": "SrcPort", + "value": "SrcPort" + }, + { + "text": "DstIp", + "value": "DstIp" + }, + { + "text": "DstPort", + "value": "DstPort" + }, + { + "text": "classification", + "value": "classification" + } + ], + "datasource": "${DS_ELASTICSEARCH}", + "editable": true, + "error": false, + "fontSize": "90%", + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 24 + }, + "height": "300px", + "id": 5, + "links": [], + "pageSize": null, + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": true + }, + "styles": [ + { + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "@timestamp", + "thresholds": [], + "type": "date", + "unit": "short" + }, + { + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "alias": "Alert_description", + "bucketAggs": [], + "dsType": "elasticsearch", + "metrics": [ + { + "field": "select field", + "id": "1", + "meta": {}, + "settings": { + "size": 500 + }, + "type": "raw_document" + } + ], + "query": "$sensor_name", + "refId": "A", + "timeField": "@timestamp" + } + ], + "title": "Panel Title", + "transform": "json", + "type": "table" + }, + { + "aliasColors": {}, + "breakPoint": "50%", + "cacheTimeout": null, + "combine": { + "label": "Others", + "threshold": 0 + }, + "datasource": "${DS_ELASTICSEARCH}", + "editable": true, + "error": false, + "fontSize": "60%", + "format": "short", + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 32 + }, + "height": "250px", + "id": 7, + "interval": null, + "legend": { + "show": true, + "values": true + }, + "legendType": "Right side", + "links": [], + "maxDataPoints": 3, + "nullPointMode": "connected", + "pieType": "pie", + "strokeWidth": 1, + "targets": [ + { + "bucketAggs": [ + { + "fake": true, + "field": "SrcIp", + "id": "3", + "settings": { + "min_doc_count": 1, + "order": "desc", + "orderBy": "_count", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto", + "min_doc_count": 0, + "trimEdges": 0 + }, + "type": "date_histogram" + } + ], + "dsType": "elasticsearch", + "metrics": [ + { + "field": "select field", + "id": "1", + "meta": {}, + "settings": {}, + "type": "count" + } + ], + "query": "$sensor_name", + "refId": "A", + "timeField": "@timestamp" + } + ], + "title": "Top Source IP", + "type": "grafana-piechart-panel", + "valueName": "total" + }, + { + "aliasColors": {}, + "breakPoint": "50%", + "cacheTimeout": null, + "combine": { + "label": "Others", + "threshold": 0 + }, + "datasource": "${DS_ELASTICSEARCH}", + "editable": true, + "error": false, + "fontSize": "60%", + "format": "short", + "gridPos": { + "h": 7, + "w": 6, + "x": 6, + "y": 32 + }, + "height": "250px", + "id": 8, + "interval": null, + "legend": { + "show": true, + "values": true + }, + "legendType": "Right side", + "links": [], + "maxDataPoints": 3, + "nullPointMode": "connected", + "pieType": "pie", + "strokeWidth": 1, + "targets": [ + { + "bucketAggs": [ + { + "fake": true, + "field": "DstPort", + "id": "3", + "settings": { + "min_doc_count": 1, + "order": "desc", + "orderBy": "_count", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto", + "min_doc_count": 0, + "trimEdges": 0 + }, + "type": "date_histogram" + } + ], + "dsType": "elasticsearch", + "metrics": [ + { + "field": "select field", + "id": "1", + "meta": {}, + "settings": {}, + "type": "count" + } + ], + "query": "$sensor_name", + "refId": "A", + "timeField": "@timestamp" + } + ], + "title": "Top Destination Port", + "type": "grafana-piechart-panel", + "valueName": "total" + }, + { + "aliasColors": {}, + "breakPoint": "50%", + "cacheTimeout": null, + "combine": { + "label": "Others", + "threshold": 0 + }, + "datasource": "${DS_ELASTICSEARCH}", + "editable": true, + "error": false, + "fontSize": "60%", + "format": "short", + "gridPos": { + "h": 7, + "w": 6, + "x": 12, + "y": 32 + }, + "height": "300px", + "id": 6, + "interval": null, + "legend": { + "show": true, + "values": true + }, + "legendType": "Right side", + "links": [], + "maxDataPoints": 3, + "nullPointMode": "connected", + "pieType": "pie", + "strokeWidth": 1, + "targets": [ + { + "bucketAggs": [ + { + "fake": true, + "field": "DstIp", + "id": "3", + "settings": { + "min_doc_count": 1, + "order": "desc", + "orderBy": "_count", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto", + "min_doc_count": 0, + "trimEdges": 0 + }, + "type": "date_histogram" + } + ], + "dsType": "elasticsearch", + "metrics": [ + { + "field": "select field", + "id": "1", + "meta": {}, + "settings": {}, + "type": "count" + } + ], + "query": "$sensor_name", + "refId": "A", + "timeField": "@timestamp" + } + ], + "title": "Top Destination IP", + "type": "grafana-piechart-panel", + "valueName": "total" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 39 + }, + "id": 20, + "panels": [], + "repeat": null, + "title": "New row", + "type": "row" + }, + { + "aliasColors": { + "TCP": "#1f78c1", + "UDP": "#cca300", + "tcp": "#6D1F62", + "udp": "#64B0C8" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_ELASTICSEARCH}", + "editable": true, + "error": false, + "fill": 1, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 40 + }, + "id": 13, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "bucketAggs": [ + { + "fake": true, + "field": "protocol.keyword", + "id": "3", + "settings": { + "min_doc_count": 1, + "order": "asc", + "orderBy": "_term", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto", + "min_doc_count": 0, + "trimEdges": 0 + }, + "type": "date_histogram" + } + ], + "dsType": "elasticsearch", + "metrics": [ + { + "field": "select field", + "id": "1", + "type": "count" + } + ], + "query": "$sensor_name", + "refId": "A", + "timeField": "@timestamp" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Protocole vs Time", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Events", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "breakPoint": "50%", + "cacheTimeout": null, + "combine": { + "label": "Others", + "threshold": 0 + }, + "datasource": "${DS_ELASTICSEARCH}", + "editable": true, + "error": false, + "fontSize": "80%", + "format": "short", + "gridPos": { + "h": 7, + "w": 10, + "x": 12, + "y": 40 + }, + "id": 15, + "interval": null, + "legend": { + "show": true, + "values": true + }, + "legendType": "Right side", + "links": [], + "maxDataPoints": 3, + "nullPointMode": "connected", + "pieType": "donut", + "strokeWidth": 1, + "targets": [ + { + "bucketAggs": [ + { + "fake": true, + "field": "classification.keyword", + "id": "3", + "settings": { + "min_doc_count": 1, + "order": "desc", + "orderBy": "_count", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto", + "min_doc_count": 0, + "trimEdges": 0 + }, + "type": "date_histogram" + } + ], + "dsType": "elasticsearch", + "metrics": [ + { + "field": "select field", + "id": "1", + "type": "count" + } + ], + "query": "$sensor_name", + "refId": "A", + "timeField": "@timestamp" + } + ], + "title": "Top Classifications", + "type": "grafana-piechart-panel", + "valueName": "total" + } + ], + "refresh": false, + "schemaVersion": 16, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "allValue": null, + "current": {}, + "datasource": "${DS_ELASTICSEARCH}", + "hide": 0, + "includeAll": true, + "label": "sensor_location", + "multi": true, + "name": "sensor_name", + "options": [], + "query": "{\"find\":\"terms\",\"field\":\"sensor_name.keyword\"}", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now/d", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "browser", + "title": "Snort Dashboard", + "uid": "ALgSiPiWk", + "version": 17 +} \ No newline at end of file diff --git a/logstash-configs/filter-snort.conf b/logstash-configs/filter-snort.conf new file mode 100644 index 0000000000000000000000000000000000000000..0a3f01d106b9ba031dc8bcc2579ce0d1ec1f89b5 --- /dev/null +++ b/logstash-configs/filter-snort.conf @@ -0,0 +1,149 @@ +# /etc/logstash/conf.d/filter-snort.conf +filter { + if [type] == "snort" { + # This is the initial parsing of the log + grok { + match => { "message" => "\|%{SPACE}\[%{WORD:msg_source}\[%{WORD:msg}\]:%{SPACE}\[%{GREEDYDATA:sensor_name}\]%{SPACE}\]%{SPACE}\|\|%{SPACE}%{TIMESTAMP_ISO8601:event_timestamp}%{SPACE}%{INT:event_priority}%{SPACE}\[%{INT:gid}:%{INT:sid}:%{INT:rev}\]%{SPACE}%{DATA:alert_description}\|\|%{SPACE}%{DATA:classification}%{SPACE}\|\|%{SPACE}%{INT:protocol}%{SPACE}%{IP:SrcIp}%{SPACE}%{IP:DstIp}%{SPACE}%{INT:IpVersion}%{SPACE}%{INT:IpHeaderLength}%{SPACE}%{INT:IpTos}%{SPACE}%{INT:PacketLength}%{SPACE}%{INT:IpId}%{SPACE}%{INT:IpReserved}%{SPACE}%{INT:FragOffset}%{SPACE}%{INT:TTL}%{SPACE}%{INT:Checksum}%{SPACE}\|\|%{SPACE}%{INT:SrcPort}%{SPACE}%{INT:DstPort}%{SPACE}"} + } + if [protocol] == 6 { + mutate { + replace => { "protocol" => "TCP" } + } + grok { + match => { "IPTypeHeader" => "%{INT:SrcPort}·%{INT:DstPort}·%{INT:TcpSequence}·%{INT:TcpAck}·%{INT:TcpOffset}·%{INT:TcpReserved}·%{INT:TcpFlags}·%{INT:TcpWindow}·%{INT:TcpChecksum}·%{INT:TcpUrgentPointer}" } + } + } + if [protocol] == 17 { + mutate { + replace => { "protocol" => "UDP" } + } + grok { + match => { "IPTypeHeader" => "%{INT:SrcPort}·%{INT:DstPort}·%{INT:UdpLen}·%{INT:UdpChecksum}" } + } + } + if [protocol] == 1 { + mutate { + replace => { "protocol" => "ICMP" } + } + grok { + match => { "IPTypeHeader" => "%{INT:IcmpType}·%{INT:IcmpCode}·%{INT:IcmpChecksum}·%{INT:IcmpId}·%{INT:IcmpSequence}" } + } + } + if [protocol] == 2 { + mutate { + replace => { "protocol" => "IGMP" } + } + } + + # Geoip check for the SrcIP + geoip { + source => "SrcIp" + target => "SrcGeoip" + database => "/etc/logstash/GeoLite2-City.mmdb" + add_field => [ "[SrcGeoip][coordinates]", "%{[geoip][longitude]}" ] + add_field => [ "[SrcGeoip][coordinates]", "%{[geoip][latitude]}" ] + } + mutate { + convert => [ "[SrcGeoip][coordinates]", "float"] + } + + # Geoip check for DstIP + geoip { + source => "DstIp" + target => "DstGeoip" + database => "/etc/logstash/GeoLite2-City.mmdb" + add_field => [ "[DstGeoip][coordinates]", "%{[DstGeoip][longitude]}" ] + add_field => [ "[DstGeoip][coordinates]", "%{[DstGeoip][latitude]}" ] + } + mutate { + convert => [ "[DstGeoip][coordinates]", "float"] + } + + # If the alert is a Snort GPL alert break it apart for easier reading and categorization + if [alert_description] =~ "GPL " { + # This will parse out the category type from the alert + grok { + match => { "alert" => "GPL\s+%{DATA:category}\s" } + } + # This will store the category + mutate { + add_field => { "rule_type" => "Snort GPL" } + lowercase => [ "category"] + } + } + + # If the alert is an Emerging Threat alert break it apart for easier reading and categorization + if [alert_description] =~ "ET " { + # This will parse out the category type from the alert + grok { + match => { "alert" => "ET\s+%{DATA:category}\s" } + } + # This will store the category + mutate { + add_field => { "rule_type" => "Emerging Threats" } + lowercase => [ "category"] + } + } + + # I recommend changing the field types below to integer so searches can do greater than or less than + # and also so math functions can be ran against them + mutate { + convert => [ "SrcPort", "integer" ] + convert => [ "DstPort", "integer" ] + convert => [ "event_priority", "integer" ] + convert => [ "protocol", "integer" ] + } + # Remove message - if wanna save space uncomment it + # remove_field => [ "message"] + #} + + # This will translate the priority field into a severity field of either High, Medium, or Low + if [event_priority] == 1 { + mutate { + add_field => { "severity" => "High" } + } + } + if [event_priority] == 2 { + mutate { + add_field => { "severity" => "Medium" } + } + } + if [event_priority] == 3 { + mutate { + add_field => { "severity" => "Low" } + } + } + + # This section adds URLs to lookup information about a rule online + mutate { + add_field => [ "ET_Signature_Info", "http://doc.emergingthreats.net/%{sid}" ] + add_field => [ "Snort_Signature_Info", "https://www.snort.org/search?query=%{gid}-%{sid}" ] + } + + + #protocol type detection + if [protocol] == 17 { + mutate { + replace => { "protocol" => "UDP" } + } + } + + if [protocol] == 6 { + mutate { + replace => { "protocol" => "TCP" } + } + } + + if [protocol] == 1 { + mutate { + replace => { "protocol" => "ICMP" } + } + } + + if [protocol] == 2 { + mutate { + replace => { "protocol" => "IGMP" } + } + } + } +} diff --git a/logstash-configs/input-snort.conf b/logstash-configs/input-snort.conf new file mode 100644 index 0000000000000000000000000000000000000000..17ba91676e09e5d6992ebeab0af96e84fcb6b2b6 --- /dev/null +++ b/logstash-configs/input-snort.conf @@ -0,0 +1,7 @@ +# /etc/logstash/conf.d/input-snort.conf +input { + udp { + port => 5142 + type => snort + } +} diff --git a/logstash-configs/snort-output.conf b/logstash-configs/snort-output.conf new file mode 100644 index 0000000000000000000000000000000000000000..2773701f7c482c748df03df926421ddce890024a --- /dev/null +++ b/logstash-configs/snort-output.conf @@ -0,0 +1,13 @@ +output { + if [msg_source]== "SNORTIDS" { + elasticsearch { + template => "/etc/logstash/templates/snortids-template.json" + template_overwrite => true + index => "snortids-%{+YYYY.MM.dd}" + hosts => ["IP_ELASTICSEARCH_SERVER:9200"] + } + stdout { + codec => rubydebug + } + } +} diff --git a/logstash-configs/snortids-template.json b/logstash-configs/snortids-template.json new file mode 100644 index 0000000000000000000000000000000000000000..66c00a6c0fe986b1bf7168a20a43e922b6b61a40 --- /dev/null +++ b/logstash-configs/snortids-template.json @@ -0,0 +1,478 @@ +{ + "template" : "snortids*", + "version" : 50001, + "settings" : { + "index.refresh_interval" : "5s" + }, + "mappings" : { + "_default_" : { + "properties" : { + "@timestamp" : { + "type" : "date" + }, + "@version" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "Checksum" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "DstGeoip" : { + "properties" : { + "city_name" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "continent_code" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "coordinates" : { + "type" : "float" + }, + "country_code2" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "country_code3" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "country_name" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "dma_code" : { + "type" : "long" + }, + "ip" : { "type" : "ip" }, + "latitude" : { + "type" : "float" + }, + "location" : { "type" : "geo_point" }, + "longitude" : { + "type" : "float" + }, + "postal_code" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "region_code" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "region_name" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "timezone" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + } + } + }, + "DstIp" : { "type" : "ip" }, + "DstPort" : { + "type" : "long" + }, + "ET_Signature_Info" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "FragOffset" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "IpHeaderLength" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "IpId" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "IpReserved" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "IpTos" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "IpVersion" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "PacketLength" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "Snort_Signature_Info" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "SrcGeoip" : { + "properties" : { + "city_name" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "continent_code" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "coordinates" : { + "type" : "float" + }, + "country_code2" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "country_code3" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "country_name" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "dma_code" : { + "type" : "long" + }, + "ip" : { "type" : "ip" }, + "latitude" : { + "type" : "float" + }, + "location" : { "type" : "geo_point" }, + "longitude" : { + "type" : "float" + }, + "postal_code" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "region_code" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "region_name" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "timezone" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + } + } + }, + "SrcIp" : { "type" : "ip" }, + "SrcPort" : { + "type" : "long" + }, + "TTL" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "alert_description" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "classification" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "event_priority" : { + "type" : "long" + }, + "event_timestamp" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "gid" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "host" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "message" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "msg" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "msg_source" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "protocol" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "rev" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "rule_type" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "sensor_name" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "severity" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "sid" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "tags" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "type" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + } + } + } + } + } + diff --git a/snort-configs/barnyard2.conf b/snort-configs/barnyard2.conf new file mode 100644 index 0000000000000000000000000000000000000000..c7e4e213c033ba742534b74b851168076829cf9b --- /dev/null +++ b/snort-configs/barnyard2.conf @@ -0,0 +1,16 @@ +# /etc/snort/barnyard2.conf +# Sending output to standard log file "alert_barnyard2" and to logstash server "IP_LOGSTAH_SERVER" udp port 5142 +config reference_file: /etc/snort/reference.config +config classification_file: /etc/snort/classification.config +config gen_file: /etc/snort/gen-msg.map +config sid_file: /etc/snort/sid-msg.map +config logdir: /var/log/barnyard2 +config hostname: mysnortids1 +config interface: eth0 +config alert_with_interface_name +config waldo_file: /var/log/snort/barnyard2.waldo +config archivedir: /var/log/snort/archived_logs +config process_new_records_only +input unified2 +output alert_fast: /var/log/snort/alert_barnyard2 +output log_syslog_full: sensor_name em1, server IP_LOGSTASH_SERVER protocol udp, port 5142, operation_mode complete, log_facility LOG_LOCAL1, log_priority LOG_ALERT diff --git a/snort-configs/barnyard2.service b/snort-configs/barnyard2.service new file mode 100644 index 0000000000000000000000000000000000000000..d7a259fda506126d4e6a8614162188943d395358 --- /dev/null +++ b/snort-configs/barnyard2.service @@ -0,0 +1,12 @@ +# /etc/systemd/system/multi-user.target.wants/barnyard2.service +# SystemD control file for Barnyard2 service +[Unit] +Description=Barnyard2 Daemon +After=syslog.target network.target + +[Service] +Type=simple +ExecStart=/usr/local/bin/barnyard2 -c /etc/snort/barnyard2.conf -l /var/log/barnyard2 -d /var/log/snort -f merged.log -v -w /var/log/snort/waldo2.file -g snort -u snort -D -a /var/log/snort/archived_logs --pid-path /var/log/barnyard2 + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/snort-configs/snort.service b/snort-configs/snort.service new file mode 100644 index 0000000000000000000000000000000000000000..0f0514eaa1c03ca49b1fabb9d1f7802c9ff6d0d1 --- /dev/null +++ b/snort-configs/snort.service @@ -0,0 +1,13 @@ +# /etc/systemd/system/multi-user.target.wants/snort.service +# SystemD control file for Snort service +# -l parameter configures output log directory to be processed further by Barnyard2 +[Unit] +Description=Snort NIDS/IPS Daemon em1 interface +After=syslog.target network.target + +[Service] +Type=simple +ExecStart=/usr/sbin/snort -q -u snort -g snort -c /etc/snortem1/snort.conf -i eth0 -l /var/log/snort + +[Install] +WantedBy=multi-user.target \ No newline at end of file