Skip to content

Commit 48600f2

Browse files
Merge pull request #49 from nttgin/dev
v1.21.0
2 parents 2c608e4 + fb7f8b3 commit 48600f2

File tree

19 files changed

+6856
-1021
lines changed

19 files changed

+6856
-1021
lines changed

.eslintrc.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"parser": "babel-eslint",
3+
"ecmaFeatures": {
4+
"modules": true,
5+
"spread" : true,
6+
"restParams" : true
7+
},
8+
"env" : {
9+
"browser" : false,
10+
"node" : true,
11+
"es6" : true,
12+
"mocha": true
13+
},
14+
"parserOptions": {
15+
"ecmaVersion": 6,
16+
"sourceType": "module",
17+
"ecmaFeatures": {
18+
"jsx": true
19+
}
20+
}
21+
}

.hound.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
jshint:
2+
enabled: false
3+
4+
eslint:
5+
enabled: true
6+
config_file: .eslintrc.json

README.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
[![Build Status](https://api.travis-ci.org/nttgin/bgpalerter.svg)](https://travis-ci.org/nttgin/bgpalerter)
22
![Dependabot Status](https://badgen.net/dependabot/nttgin/BGPalerter/?icon=dependabot)
3+
[![Reviewed by Hound](https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg)](https://houndci.com)
34

45
# BGPalerter
56
Real-time BGP monitoring tool, pre-configured for visibility loss and hijacks detection.
67

7-
You just run it. You don't need to provide any data source or connect it to anything in your network since it connects to publiic repos.
8+
You just run it. You don't need to provide any data source or connect it to anything in your network since it connects to public repos.
89

910
It can deliver alerts on files, by email, on slack, and more.
1011

@@ -27,8 +28,6 @@ If you want to know more about the source code (which is completely open) please
2728
In `config.yml.example` you can find other reporting mechanisms (e.g. email and slack) in addition to logging to files.
2829
Please uncomment the related section and configure according to your needs.
2930

30-
If you enable email reporting, download also the directory `reports/email_templates` in the same directory of the executable.
31-
3231

3332
## Documentation
3433

config.yml.example

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ reports:
5353
# - visibility
5454
# - path
5555
# params:
56+
# showPaths: 5 # Amount of AS_PATHs to report in the alert
5657
# senderEmail: bgpalerter@xxxx
5758
# # BGPalerter uses nodemailer.
5859
# # The smtp section can be configured with all the parameters available at https://nodemailer.com/smtp/
@@ -86,13 +87,36 @@ reports:
8687
# path: '#42cbf5'
8788
# hooks:
8889
# default: _YOUR_SLACK_WEBHOOK_URL_
90+
#
91+
# - file: reportKafka
92+
# channels:
93+
# - hijack
94+
# - newprefix
95+
# - visibility
96+
# - path
97+
# params:
98+
# host: localhost:9092
99+
# topics:
100+
# default: bgpalerter
101+
102+
103+
############################
104+
# Notification settings:
105+
# - notificationIntervalSeconds
106+
# Defines the amount of seconds after which an alert can be repeated. An alert is repeated only if the event that
107+
# triggered it is not yet solved. Please, don't set this value to Infinity, use instead alertOnlyOnce.
108+
#
109+
# - alertOnlyOnce - A boolean that, if set to true, will prevent repetitions of the same alert even if the event that
110+
# triggered it is not yet solved. In this case notificationIntervalSeconds will be ignored.
111+
# If set to true, the signature of all alerts will be cached in order to recognize if they already happened in
112+
# the past. This may lead to a memory leak if the amount of alerts is considerable.
89113

114+
notificationIntervalSeconds: 7200
115+
alertOnlyOnce: false
90116

91-
checkStaleNotificationsSeconds: 60
92-
notificationIntervalSeconds: 1800 # Repeat the same alert (which keeps being triggered) after x seconds
93-
clearNotificationQueueAfterSeconds: 1900 # Stop with the alert for an event which didn't happen again in x seconds
117+
############################
94118

95-
# The file containing the monitored prefixes. Please see prefixes.yml for an example
119+
# Below the files containing the monitored prefixes. Please see prefixes.yml for an example.
96120
# This is an array (use new lines and dashes!)
97121
monitoredPrefixesFiles:
98122
- prefixes.yml
@@ -101,7 +125,7 @@ logging:
101125
directory: logs
102126
logRotatePattern: YYYY-MM-DD # Whenever the pattern changes, a new file is created and the old one rotated
103127
zippedArchive: true
104-
maxSize: 20m
128+
maxSize: 80m
105129
maxFiles: 14d
106130

107-
checkForUpdatesAtBoot: true
131+
checkForUpdatesAtBoot: true

docs/configuration.md

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,8 @@ The following are common parameters which it is possible to specify in the confi
77
| Parameter | Description | Expected format | Example | Required |
88
|---|---|---|---|---|
99
|environment| You can specify various environments. The values "production" (not verbose) and "development" (verbose) will affect the verbosity of the error/debug logs. Other values don't affect the functionalities, they will be used to identify from which environment the log is coming from. | A string | production | Yes |
10-
|notificationIntervalSeconds| The amount of seconds before the same alert can be repeated. An alert is repeated only if the cause of it has not being solved. | An integer | 1800 | Yes |
11-
|clearNotificationQueueAfterSeconds| If the cause of an alert is resolved, then stop waiting for more information about the issue. | An integer (greater than notificationIntervalSeconds) | 1900 | Yes |
12-
|checkStaleNotificationsSeconds| The amount of seconds between a check on stale alerts. A stale alert happens when the cause of an alert is resolved before the next notification round, in such a case send it anyway. | An integer | 60 | Yes |
10+
|notificationIntervalSeconds|Defines the amount of seconds after which an alert can be repeated. An alert is repeated only if the event that triggered it is not yet solved. Please, don't set this value to Infinity, use instead alertOnlyOnce. | An integer | 1800 | Yes |
11+
|alertOnlyOnce| A boolean that, if set to true, will prevent repetitions of the same alert even if the event that triggered it is not yet solved. In this case notificationIntervalSeconds will be ignored. If set to true, the signature of all alerts will be cached in order to recognize if they already happened in the past. This may lead to a memory leak if the amount of alerts is considerable. | A boolean | false | No |
1312
|monitoredPrefixesFiles| The [list](docs/prefixes.md#array) of files containing the prefixes to monitor. See [here](docs/prefixes.md#prefixes) for more informations. | A list of strings (valid .yml files) | -prefixes.yml | Yes |
1413
|logging| A dictionary of parameters containing the configuration for the file logging. | || Yes|
1514
|logging.directory| The directory where the log files will be generated. The directory will be created if not existent. | A string | logs | Yes |
@@ -159,6 +158,7 @@ Parameters for this report module:
159158

160159
|Parameter| Description|
161160
|---|---|
161+
|showPaths| Amount of AS_PATHs to report in the alert (0 to disable). |
162162
|senderEmail| The email address that will be used as sender for the alerts. |
163163
|smtp| A dictionary containing the SMTP configuration. Some parameters are described in `config.yml.example`. For all the options refer to the [nodemailer documentation](https://nodemailer.com/smtp/). |
164164
|notifiedEmails| A dictionary containing email addresses grouped by user groups. (key: group, value: list of emails)|
@@ -179,3 +179,14 @@ Parameters for this report module:
179179
|hooks.default| The default user group. Each user group is a WebHook (url). |
180180

181181

182+
#### reportKafka
183+
184+
This report sends the alerts (including the BGP messages triggering them) to Kafka. By default it creates a topic `bgpalerter`.
185+
186+
Parameters for this report module:
187+
188+
|Parameter| Description|
189+
|---|---|
190+
|host| Host and port of the Kafka instance/broker (e.g. localhost:9092).|
191+
|topics| A dictionary containing a mapping from BGPalerter channels to Kafka topics (e.g. `hijack: hijack-topic`). By default all channels are sent to the topic `bgpalerter` (`default: bgpalerter`) |
192+

docs/develop.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,6 @@ To start development see how to install the source [here](installation.md#runnin
99

1010
* `npm run serve` to run the application from the source
1111

12-
* `npm run start|stop|restart` to run the application as a service in background
13-
14-
* `npm run status` to see the status of the service
15-
1612
* `npm run test` to run the tests
1713

1814
* `npm run build` to compile and build OS native applications

docs/prefixes.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@ Below the list of possible parameters. **Remember to prepend them with a `--` in
1414

1515
| Parameter | Description | Expected format | Example | Required |
1616
|---|---|---|---|---|
17-
| -a | The AS number(s) you want to generate the list for | A comma-separated list of integers | 2914,3333 | Yes |
18-
| -o | The YAML output file | A string ending in ".yml" | prefixes.yml | Yes
17+
| -o | The YAML output file | A string ending in ".yml" | prefixes.yml | Yes |
18+
| -a | The AS number(s) you want to generate the list for | A comma-separated list of integers | 2914,3333 | No (one among -a, -p, -pf is required) |
1919
| -e | Prefixes to exclude from the list | A comma-separated list of prefixes | 165.254.255.0/24,192.147.168.0/24 | No |
2020
| -i | Avoid monitoring delegated prefixes. If a more specific prefix is found and it results announced by an AS different from the one declared in -a, then set `ignore: true` and `ignoreMorespecifics: true` | Nothing | | No
21+
| -p | Prefixes for which the list will be generated | A comma-separated list of prefixes | 165.254.255.0/24,192.147.168.0/24 | No (one among -a, -p, -pf is required) |
22+
| -pf | A file containing the prefixes for which the list will be generated | A text file having a prefix for each line | prefixes.txt | No (one among -a, -p, -pf is required) |
2123

2224

2325
## <a name="prefixes-fields"></a>Prefixes list fields

env.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,15 +106,14 @@ let config = {
106106
channels: ["hijack", "newprefix", "visibility", "path"]
107107
}
108108
],
109-
checkStaleNotificationsSeconds : 60,
110-
notificationIntervalSeconds: 1800,
111-
clearNotificationQueueAfterSeconds: 1900,
109+
notificationIntervalSeconds: 7200,
110+
alarmOnlyOnce: false,
112111
monitoredPrefixesFiles: ["prefixes.yml"],
113112
logging: {
114113
directory: "logs",
115114
logRotatePattern: "YYYY-MM-DD",
116115
zippedArchive: true,
117-
maxSize: "20m",
116+
maxSize: "80m",
118117
maxFiles: "14d",
119118
},
120119
checkForUpdatesAtBoot: true

generatePrefixesList.js

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,22 @@ import yaml from "js-yaml";
44
import fs from "fs";
55
const batchPromises = require('batch-promises');
66

7-
module.exports = function generatePrefixes(asns, outputFile, exclude, excludeDelegated) {
7+
module.exports = function generatePrefixes(asnList, outputFile, exclude, excludeDelegated, prefixes) {
88
const generateList = {};
99
let someNotValidatedPrefixes = false;
1010

11-
if (!asns) {
12-
throw new Error("One or more comma-separated AS numbers have to be specified");
11+
if (!asnList && !prefixes) {
12+
throw new Error("You need to specify at least an AS number or a list of prefixes.");
13+
}
14+
15+
if (asnList && prefixes) {
16+
throw new Error("You can specify an AS number or a list of prefixes, not both.");
1317
}
1418

1519
if (!outputFile) {
1620
throw new Error("Output file not specified");
1721
}
1822

19-
const asnList = asns.split(",");
20-
2123
const getMultipleOrigins = (prefix) => {
2224
const url = brembo.build("https://stat.ripe.net", {
2325
path: ["data", "prefix-overview", "data.json"],
@@ -73,7 +75,6 @@ module.exports = function generatePrefixes(asns, outputFile, exclude, excludeDel
7375

7476
};
7577

76-
7778
const generateRule = (prefix, asn, ignoreMorespecifics, description, excludeDelegated) =>
7879
getMultipleOrigins(prefix)
7980
.then(asns => {
@@ -152,8 +153,17 @@ module.exports = function generatePrefixes(asns, outputFile, exclude, excludeDel
152153
})
153154
};
154155

155-
return Promise
156-
.all(asnList.map(getAnnouncedPrefixes))
156+
const getBaseRules = () => {
157+
if (prefixes) {
158+
return Promise
159+
.all(prefixes.map(p => generateRule(p, null, false, null, false)))
160+
.then(() => prefixes);
161+
} else {
162+
return Promise.all(asnList.map(getAnnouncedPrefixes));
163+
}
164+
};
165+
166+
return getBaseRules()
157167
.then(items => [].concat.apply([], items))
158168
.then(prefixes => {
159169
return batchPromises(20, prefixes, prefix => {
@@ -179,7 +189,7 @@ module.exports = function generatePrefixes(asns, outputFile, exclude, excludeDel
179189
fs.writeFileSync(outputFile, yamlContent);
180190

181191
if (someNotValidatedPrefixes) {
182-
console.log("WARNING: The generated configuration is a snapshot of what is currently announced by " + asns + " but some of the prefixes don't have ROA objects associated. Please, verify the config file by hand!");
192+
console.log("WARNING: The generated configuration is a snapshot of what is currently announced. Some of the prefixes don't have ROA objects associated or are RPKI invalid. Please, verify the config file by hand!");
183193
}
184194
console.log("Done!");
185195
})

index.js

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,19 @@ const params = yargs
5353
.nargs('e', 1)
5454
.describe('e', 'Prefixes to exclude')
5555

56+
.alias('p', 'prefixes')
57+
.nargs('p', 1)
58+
.describe('p', 'Prefixes to include')
59+
60+
.alias('pf', 'prefixes-file')
61+
.nargs('pf', 1)
62+
.describe('pf', 'File containing the prefixes to include')
63+
5664
.alias('i', 'ignore-delegated')
5765
.nargs('i', 0)
5866
.describe('i', 'Ignore delegated prefixes')
5967

60-
.demandOption(['o', 'a'])
68+
.demandOption(['o']);
6169
})
6270
.example('$0 generate -a 2914 -o prefixes.yml', 'Generate prefixes for AS2914')
6371

@@ -70,12 +78,28 @@ const params = yargs
7078
switch(params._[0]) {
7179
case "generate":
7280
const generatePrefixes = require("./generatePrefixesList");
81+
let prefixes = null;
82+
if (params.p && params.pf) {
83+
throw new Error("The argument -p is not compatible with the argument -pf");
84+
} else if (params.p) {
85+
prefixes = params.p.split(",");
86+
} else if (params.pf) {
87+
const fs = require("fs");
88+
if (fs.existsSync(params.pf)) {
89+
prefixes = fs.readFileSync(params.pf, 'utf8').split(/\r?\n/).filter(i => i && true);
90+
} else {
91+
throw new Error("The prefix list file (-pf) is not readable");
92+
}
93+
}
94+
7395
generatePrefixes(
74-
params.a.toString(),
96+
(params.a) ? params.a.toString().split(",") : null,
7597
params.o,
7698
(params.e || "").split(","),
77-
params.i || false
99+
params.i || false,
100+
prefixes
78101
);
102+
79103
break;
80104

81105
default: // Run monitor

0 commit comments

Comments
 (0)