1
|
<?php
|
2
|
/*
|
3
|
* ntopng.inc
|
4
|
*
|
5
|
* part of pfSense (https://www.pfsense.org)
|
6
|
* Copyright (c) 2015-2017 Rubicon Communications, LLC (Netgate)
|
7
|
* All rights reserved.
|
8
|
*
|
9
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
10
|
* you may not use this file except in compliance with the License.
|
11
|
* You may obtain a copy of the License at
|
12
|
*
|
13
|
* http://www.apache.org/licenses/LICENSE-2.0
|
14
|
*
|
15
|
* Unless required by applicable law or agreed to in writing, software
|
16
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
17
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
18
|
* See the License for the specific language governing permissions and
|
19
|
* limitations under the License.
|
20
|
*/
|
21
|
|
22
|
require_once("config.inc");
|
23
|
require_once("globals.inc");
|
24
|
require_once("interfaces.inc");
|
25
|
require_once("pkg-utils.inc");
|
26
|
require_once("service-utils.inc");
|
27
|
require_once("util.inc");
|
28
|
require_once("certs.inc");
|
29
|
|
30
|
|
31
|
global $redis_path;
|
32
|
$redis_path = "/usr/local/bin";
|
33
|
|
34
|
function ntopng_php_install_command() {
|
35
|
/* Create dirs for Redis DB, data and graphs */
|
36
|
ntopng_create_datadir();
|
37
|
}
|
38
|
|
39
|
function ntopng_php_deinstall_command() {
|
40
|
global $config;
|
41
|
|
42
|
/* Wipe data and settings if the user does not wish to keep them */
|
43
|
init_config_arr(array('installedpackages', 'ntopng', 'config', 0));
|
44
|
$ntopng_config = $config['installedpackages']['ntopng']['config'][0];
|
45
|
if ($ntopng_config['keepdata'] != "on") {
|
46
|
if (is_dir("/var/db/ntopng/")) {
|
47
|
exec("rm -rf /var/db/ntopng/");
|
48
|
}
|
49
|
if (is_array($config['installedpackages']['ntopng'])) {
|
50
|
unset($config['installedpackages']['ntopng']);
|
51
|
write_config("[ntopng] Removed package settings on uninstall.");
|
52
|
}
|
53
|
log_error(gettext("[ntopng] Removed package data and settings since 'Keep Data/Settings' is disabled."));
|
54
|
}
|
55
|
}
|
56
|
|
57
|
function ntopng_write_cert_file($file, $cert) {
|
58
|
$fd = fopen($file, "w");
|
59
|
if (!$fd) {
|
60
|
log_error("ERROR: Could not open {$file} for writing");
|
61
|
return;
|
62
|
}
|
63
|
chmod($file, 0600);
|
64
|
/* newline to deal with certs/keys lacking newline at end */
|
65
|
fwrite($fd, base64_decode($cert['crt']) . "\n");
|
66
|
fwrite($fd, base64_decode($cert['prv']) . "\n");
|
67
|
fclose($fd);
|
68
|
}
|
69
|
|
70
|
|
71
|
function ntopng_sync_package() {
|
72
|
global $config, $ntopng_config, $redis_path;
|
73
|
/* These are done via ntopng_validate_input(), just return */
|
74
|
if ($_POST['Submit'] == "Update GeoIP Data") {
|
75
|
return;
|
76
|
}
|
77
|
if ($_POST['Delete'] == "Delete Data") {
|
78
|
return;
|
79
|
}
|
80
|
|
81
|
$ifaces = "";
|
82
|
init_config_arr(array('installedpackages', 'ntopng', 'config', 0));
|
83
|
$ntopng_config = &$config['installedpackages']['ntopng']['config'][0];
|
84
|
|
85
|
/* Just stop services and unlink rc script if disabled */
|
86
|
if ($ntopng_config['enable'] != "on") {
|
87
|
ntopng_services_stop();
|
88
|
unlink_if_exists("/usr/local/etc/rc.d/ntopng.sh");
|
89
|
unlink_if_exists("/usr/local/share/ntopng/httpdocs/ssl/ntopng-cert.pem");
|
90
|
return;
|
91
|
}
|
92
|
|
93
|
foreach ($ntopng_config['interface_array'] as $iface) {
|
94
|
$if = convert_friendly_interface_to_real_interface_name($iface);
|
95
|
if ($if) {
|
96
|
$ifaces .= " -i " . escapeshellarg("{$if}");
|
97
|
}
|
98
|
}
|
99
|
|
100
|
/* DNS Mode */
|
101
|
if (is_numeric($ntopng_config['dns_mode']) && ($ntopng_config['dns_mode'] >= 0) && ($ntopng_config['dns_mode'] <= 3)) {
|
102
|
$dns_mode = "--dns-mode " . escapeshellarg($ntopng_config['dns_mode']);
|
103
|
}
|
104
|
|
105
|
/* Local Networks */
|
106
|
switch ($ntopng_config['local_networks']) {
|
107
|
case "selected":
|
108
|
$nets = array();
|
109
|
foreach ($ntopng_config['interface_array'] as $iface) {
|
110
|
if (is_ipaddr(get_interface_ip($iface))) {
|
111
|
$nets[] = gen_subnet(get_interface_ip($iface), get_interface_subnet($iface)) . '/' . get_interface_subnet($iface);
|
112
|
}
|
113
|
}
|
114
|
if (!empty($nets)) {
|
115
|
$local_networks = "--local-networks " . escapeshellarg(implode(",", $nets));
|
116
|
}
|
117
|
break;
|
118
|
case "lanonly":
|
119
|
if (is_ipaddr(get_interface_ip('lan'))) {
|
120
|
$local_networks = "--local-networks " . escapeshellarg(gen_subnet(get_interface_ip('lan'), get_interface_subnet('lan')) . '/' . get_interface_subnet('lan'));
|
121
|
}
|
122
|
break;
|
123
|
case "custom":
|
124
|
$nets = array();
|
125
|
foreach ($ntopng_config['row'] as $net) {
|
126
|
if (is_subnet($net['cidr'])) {
|
127
|
$nets[] = trim($net['cidr']);
|
128
|
}
|
129
|
}
|
130
|
if (!empty($nets)) {
|
131
|
$local_networks = "--local-networks " . escapeshellarg(implode(",", $nets));
|
132
|
}
|
133
|
break;
|
134
|
case "rfc1918":
|
135
|
default:
|
136
|
$local_networks = "--local-networks '192.168.0.0/16,172.16.0.0/12,10.0.0.0/8'";
|
137
|
break;
|
138
|
}
|
139
|
|
140
|
// Pending rework - see https://redmine.pfsense.org/issues/7000
|
141
|
/* Historical Data Storage, Dump expired flows
|
142
|
if ($ntopng_config['dump_flows'] == "on") {
|
143
|
$dump_flows = "-F";
|
144
|
}
|
145
|
*/
|
146
|
|
147
|
if ($config['system']['webgui']['protocol'] == "https") {
|
148
|
$cert = lookup_cert($config['system']['webgui']['ssl-certref']);
|
149
|
ntopng_write_cert_file("/usr/local/share/ntopng/httpdocs/ssl/ntopng-cert.pem", $cert);
|
150
|
$http_args = "-w 0 -W 3000";
|
151
|
} else {
|
152
|
unlink_if_exists("/usr/local/share/ntopng/httpdocs/ssl/ntopng-cert.pem");
|
153
|
$http_args = "-w 3000";
|
154
|
}
|
155
|
|
156
|
/* Create rc script */
|
157
|
$stop = <<<EOD
|
158
|
# Kill ntopng and redis
|
159
|
/usr/bin/killall ntopng redis-cli redis-server
|
160
|
EOD;
|
161
|
|
162
|
$start = <<<EOD
|
163
|
### Make sure library path cache is updated
|
164
|
/etc/rc.d/ldconfig start
|
165
|
# Create DB dir before starting, in case it was removed. Otherwise redis will fail.
|
166
|
/bin/mkdir -p /var/db/ntopng
|
167
|
{$redis_path}/redis-server --bind 127.0.0.1 ::1 --dir /var/db/ntopng/ --dbfilename ntopng.rdb &
|
168
|
/usr/local/bin/ntopng -d /var/db/ntopng -G /var/run/ntopng.pid -s -e {$http_args} {$disable_alerts} {$dump_flows} {$ifaces} {$dns_mode} {$aggregations} {$local_networks} &
|
169
|
EOD;
|
170
|
// TODO:
|
171
|
// Add support for --data-dir /somewhere, --httpdocs-dir /somewhereelse,
|
172
|
// --dump-timeline (on/off) --http-port, --https-port
|
173
|
|
174
|
write_rcfile(array("file" => "ntopng.sh", "start" => $start, "stop" => $stop));
|
175
|
|
176
|
/* Set up admin password */
|
177
|
ntopng_set_redis_password();
|
178
|
|
179
|
/* (Re)start services if not booting */
|
180
|
if (!platform_booting()) {
|
181
|
ntopng_services_stop();
|
182
|
start_service("ntopng");
|
183
|
sleep(20);
|
184
|
}
|
185
|
}
|
186
|
|
187
|
function ntopng_services_stop() {
|
188
|
if ((is_process_running("redis-server")) || (is_process_running("ntopng"))) {
|
189
|
stop_service("ntopng");
|
190
|
}
|
191
|
for ($i = 0; $i <= 10; $i++) {
|
192
|
if ((!is_process_running("redis-server")) && (!is_process_running("ntopng"))) {
|
193
|
break;
|
194
|
}
|
195
|
sleep(2);
|
196
|
}
|
197
|
}
|
198
|
|
199
|
function ntopng_redis_started() {
|
200
|
global $redis_path, $redis_started;
|
201
|
$redis_started = false;
|
202
|
|
203
|
if (!is_process_running("redis-server")) {
|
204
|
exec_bg("{$redis_path}/redis-server --bind 127.0.0.1 ::1 --dir /var/db/ntopng/ --dbfilename ntopng.rdb");
|
205
|
for ($i = 0; $i <= 10; $i++) {
|
206
|
if (is_process_running("redis-server")) {
|
207
|
$redis_started = true;
|
208
|
break;
|
209
|
}
|
210
|
sleep(1);
|
211
|
}
|
212
|
} else {
|
213
|
$redis_started = true;
|
214
|
}
|
215
|
return $redis_started;
|
216
|
}
|
217
|
|
218
|
function ntopng_set_redis_password() {
|
219
|
global $config, $ntopng_config, $redis_path;
|
220
|
init_config_arr(array('installedpackages', 'ntopng', 'config', 0));
|
221
|
$ntopng_config = $config['installedpackages']['ntopng']['config'][0];
|
222
|
|
223
|
if (!empty($ntopng_config['redis_password'])) {
|
224
|
$password = md5($ntopng_config['redis_password']);
|
225
|
if (ntopng_redis_started()) {
|
226
|
exec("{$redis_path}/redis-cli SET ntopng.user.admin.password " . escapeshellarg($password));
|
227
|
// Make sure the preferences menu is accessible (Bug #6999)
|
228
|
exec("{$redis_path}/redis-cli SET ntopng.user.admin.group administrator");
|
229
|
exec("{$redis_path}/redis-cli save");
|
230
|
} else {
|
231
|
log_error(gettext("[ntopng] Cannot set admin password - redis-server is not running."));
|
232
|
}
|
233
|
}
|
234
|
}
|
235
|
|
236
|
function ntopng_create_datadir() {
|
237
|
safe_mkdir("/var/db/ntopng/rrd/graphics", 0755);
|
238
|
exec("/bin/chmod -R 755 /var/db/ntopng");
|
239
|
exec("/usr/sbin/chown -R nobody:nobody /var/db/ntopng");
|
240
|
}
|
241
|
|
242
|
function ntopng_update_geoip() {
|
243
|
global $config;
|
244
|
$fetchcmd = "/usr/bin/fetch";
|
245
|
$geolite_city = "https://geolite.manjot.xyz/download/geoip/database/GeoLite2-City.tar.gz";
|
246
|
$geoip_asnum = "https://geolite.manjot.xyz/download/geoip/database/GeoLite2-ASN.tar.gz";
|
247
|
$output_dir = "/usr/local/share/ntopng";
|
248
|
|
249
|
exec("{$fetchcmd} -o {$output_dir} -T 5 {$geolite_city}");
|
250
|
exec("{$fetchcmd} -o {$output_dir} -T 5 {$geoip_asnum}");
|
251
|
|
252
|
ntopng_fixup_geoip();
|
253
|
|
254
|
/* Do not (re)start services on package (re)install, only on manual GeoIP updates via the GUI */
|
255
|
if ($_POST['Submit'] == "Update GeoIP Data") {
|
256
|
init_config_arr(array('installedpackages', 'ntopng', 'config', 0));
|
257
|
$ntopng_config = $config['installedpackages']['ntopng']['config'][0];
|
258
|
ntopng_services_stop();
|
259
|
if ($ntopng_config['enable'] == "on") {
|
260
|
start_service("ntopng");
|
261
|
}
|
262
|
}
|
263
|
}
|
264
|
|
265
|
function ntopng_fixup_geoip() {
|
266
|
$target_dir = "/usr/local/share/ntopng/httpdocs/geoip";
|
267
|
$source_dir = "/usr/local/share/ntopng";
|
268
|
|
269
|
safe_mkdir($target_dir, 0755);
|
270
|
|
271
|
foreach(glob("{$source_dir}/Geo*.tar.gz") as $geofile) {
|
272
|
/* Decompress if needed. */
|
273
|
if (substr($geofile, -7, 7) == ".tar.gz") {
|
274
|
exec("tar -C {$source_dir} -f {$geofile} --strip 1 -xz '*.mmdb'");
|
275
|
}
|
276
|
}
|
277
|
|
278
|
/* Use a separate glob since the filenames could have changed since the last run */
|
279
|
foreach(glob("{$source_dir}/Geo*.mmdb") as $geofile) {
|
280
|
$target_file = $target_dir . '/' . basename($geofile);
|
281
|
if (!file_exists($target_file)) {
|
282
|
symlink($geofile, $target_file);
|
283
|
}
|
284
|
}
|
285
|
}
|
286
|
|
287
|
function ntopng_flush_historical_data() {
|
288
|
global $config, $ntopng_config, $redis_path;
|
289
|
init_config_arr(array('installedpackages', 'ntopng', 'config', 0));
|
290
|
$ntopng_config = $config['installedpackages']['ntopng']['config'][0];
|
291
|
|
292
|
if (ntopng_redis_started()) {
|
293
|
/* Delete all the keys of all the existing Redis databases */
|
294
|
exec("{$redis_path}/redis-cli flushall");
|
295
|
log_error(gettext("[ntopng] Flushed Redis DB."));
|
296
|
/* Set admin password while redis-server is still running */
|
297
|
ntopng_set_redis_password();
|
298
|
log_error(gettext("[ntopng] Set admin password for Redis DB."));
|
299
|
/* Stop services and delete all graphs, data and dump flows */
|
300
|
ntopng_services_stop();
|
301
|
if (is_dir("/var/db/ntopng/")) {
|
302
|
exec("rm -rf /var/db/ntopng/");
|
303
|
log_error(gettext("[ntopng] Deleted ntopng traffic data and graphs."));
|
304
|
} else {
|
305
|
log_error(gettext("[ntopng] Nothing to delete; /var/db/ntopng/ directory not found."));
|
306
|
}
|
307
|
/* Re-create the required directory structure with proper permissions */
|
308
|
ntopng_create_datadir();
|
309
|
log_error(gettext("[ntopng] Re-created required data directory structure."));
|
310
|
/* Resync settings and restart services if enabled */
|
311
|
unset($_POST['Delete']);
|
312
|
ntopng_sync_package();
|
313
|
log_error(gettext("[ntopng] Resynced ntopng settings."));
|
314
|
} else {
|
315
|
$error = "Cannot delete data - redis-server is not running.";
|
316
|
log_error(gettext("[ntopng] {$error}"));
|
317
|
file_notice("ntopng", $error, "ntopng Delete Data", "");
|
318
|
}
|
319
|
}
|
320
|
|
321
|
function ntopng_validate_input($post, &$input_errors) {
|
322
|
if (empty($post['redis_password']) || empty($post['redis_passwordagain'])) {
|
323
|
$input_errors[] = "You must provide (and confirm) ntopng's password.";
|
324
|
}
|
325
|
if ((strlen($post['redis_password']) < 5) || (strlen($post['redis_passwordagain']) < 5)) {
|
326
|
$input_errors[] = "Password must have at least 5 characters.";
|
327
|
}
|
328
|
if ($post['redis_password'] != $post['redis_passwordagain']) {
|
329
|
$input_errors[] = "The provided passwords did not match.";
|
330
|
}
|
331
|
if($_POST["local_networks"] == "custom") {
|
332
|
$idx = 0;
|
333
|
while (isset($_POST["cidr{$idx}"])) {
|
334
|
$cidr = $_POST["cidr" . $idx++];
|
335
|
if (!is_subnet($cidr)) {
|
336
|
$input_errors[] = "Invalid CIDR in custom local networks list at position {$idx}.";
|
337
|
}
|
338
|
}
|
339
|
}
|
340
|
if ($post['Submit'] == "Update GeoIP Data") {
|
341
|
ntopng_update_geoip();
|
342
|
}
|
343
|
if ($post['Delete'] == "Delete Data") {
|
344
|
ntopng_flush_historical_data();
|
345
|
}
|
346
|
}
|
347
|
|
348
|
?>
|