diff --git a/.gitignore b/.gitignore index e072e5d7a0..41830d6fcb 100644 --- a/.gitignore +++ b/.gitignore @@ -51,6 +51,7 @@ third-party/zeromq-*/tools/.dirstamp third-party/zeromq-*/tools/curve_keygen.o httpdocs/geoip/* httpdocs/ssl/ntopng-cert.pem +httpdocs/misc/ntopng-utils-manage-config include/config.h.in autom4te.cache* *# @@ -64,6 +65,7 @@ doc/doxygen.conf nDPI ntopng packages/*.spec +packages/etc/systemd/system/ntopng.service Makefile *.pcap *.lua.cpp diff --git a/httpdocs/misc/ntopng-utils-manage-config.in b/httpdocs/misc/ntopng-utils-manage-config.in index ad23b5fd52..a2d2b83c9f 100755 --- a/httpdocs/misc/ntopng-utils-manage-config.in +++ b/httpdocs/misc/ntopng-utils-manage-config.in @@ -34,6 +34,7 @@ function print_usage() { echo "`basename $0` -a backup [-d datadir] [-c archive.tar.gz]" echo "`basename $0` -a check-restore [-d datadir] [-c archive.tar.gz]" echo "`basename $0` -a install-n2disk-conf [-d datadir] -i interface" + echo "`basename $0` -a install-n2n-conf [-d datadir]" echo "" echo "[-d datadir]" echo " The path to the ntopng data directory." @@ -65,6 +66,10 @@ function print_usage() { echo "`basename $0` -a install-n2disk-conf [-d datadir] -i interface" echo "Installs a n2disk configuration file generated by ntopng to /etc/n2disk/ creating a symlink" echo "" + echo "-a install-n2n-conf" + echo "`basename $0` -a install-n2n-conf [-d datadir]" + echo "Installs a n2n edge configuration file generated by ntopng to /etc/n2n/ creating a symlink" + echo "" } POSITIONAL=() @@ -123,7 +128,7 @@ function cleanup() { trap cleanup EXIT -if [[ ( $ACTION != "backup" && $ACTION != "restore" && $ACTION != "check-restore" && $ACTION != "install-n2disk-conf" ) ]]; then +if [[ ( $ACTION != "backup" && $ACTION != "restore" && $ACTION != "check-restore" && $ACTION != "install-n2disk-conf" && $ACTION != "install-n2n-conf" ) ]]; then print_usage exit 1 fi @@ -418,6 +423,20 @@ function install_n2disk_conf() { ln -sf "${SOURCE_FILE}" "${DEST_PATH}" } +function install_n2n_conf() { + local SOURCE_FILE="${DATADIR}/n2n/edge.conf" + + if [ ! -f "${SOURCE_FILE}" ]; then + return + fi + + local DEST_PATH="/etc/n2n" + + mkdir -p "${DEST_PATH}" + + ln -sf "${SOURCE_FILE}" "${DEST_PATH}" +} + prepare_cur_data_dir_path prepare_tar_file_path @@ -454,6 +473,11 @@ elif [ $ACTION == "install-n2disk-conf" ]; then install_n2disk_conf +elif [ $ACTION == "install-n2n-conf" ]; then + [ $QUIET = false ] && echo "Installing n2n configuration ..." + + install_n2n_conf + else # never reached echo "Unknown action $ACTION" diff --git a/include/ntop_defines.h b/include/ntop_defines.h index d83162525b..71beaaf360 100644 --- a/include/ntop_defines.h +++ b/include/ntop_defines.h @@ -193,6 +193,7 @@ #define DROP_HOST_TRAFFIC "ntopng.prefs.drop_host_traffic" #define HOST_TRAFFIC_QUOTA "ntopng.prefs.hosts_quota" #define HTTP_ACL_MANAGEMENT_PORT "ntopng.prefs.http_acl_management_port" +#define TEMP_ADMIN_PASSWORD "ntopng.prefs.temp_admin_password" #define TRAFFIC_FILTERING_CACHE_DURATION 43200 /* 12 h */ #define DNS_CACHE_DURATION 3600 /* 1 h */ diff --git a/packages/etc/sudoers.d/ntopng b/packages/etc/sudoers.d/ntopng index a945c058a7..8c56b2cdcf 100644 --- a/packages/etc/sudoers.d/ntopng +++ b/packages/etc/sudoers.d/ntopng @@ -1 +1 @@ -ntopng ALL= NOPASSWD: /usr/local/bin/n2diskctl +ntopng ALL= NOPASSWD: /usr/bin/ntopctl diff --git a/packages/ntopng.spec.in b/packages/ntopng.spec.in index 8b32be16c9..e9cb7fd0a4 100644 --- a/packages/ntopng.spec.in +++ b/packages/ntopng.spec.in @@ -47,6 +47,7 @@ cp $HOME/ntopng/ntopng $RPM_BUILD_ROOT/usr/bin cp $HOME/ntopng/ntopng.8 $RPM_BUILD_ROOT/usr/share/man/man8/ cp -Lr $HOME/ntopng/httpdocs $HOME/ntopng/scripts $RPM_BUILD_ROOT/usr/share/ntopng # L to dereference symlinks mv $RPM_BUILD_ROOT/usr/share/ntopng/httpdocs/misc/ntopng-utils-manage-config $RPM_BUILD_ROOT/usr/bin +cp $HOME/ntopng/packages/usr/bin/ntopctl $RPM_BUILD_ROOT/usr/bin/ # Make sure dat files are not packaged by ntopng as they belong to ntopng-data rm -f $RPM_BUILD_ROOT/usr/share/ntopng/httpdocs/geoip/*dat mv $RPM_BUILD_ROOT/usr/share/ntopng/httpdocs/ssl/ntopng-cert.pem.dummy $RPM_BUILD_ROOT/usr/share/ntopng/httpdocs/ssl/ntopng-cert.pem @@ -86,6 +87,7 @@ rm -fr $RPM_BUILD_ROOT %files /usr/bin/ntopng +/usr/bin/ntopctl /usr/bin/ntopng-utils-manage-config /usr/share/man/man8/ntopng.8.gz %config(noreplace) /etc/ntopng/ntopng.conf diff --git a/packages/ubuntu/Makefile.in b/packages/ubuntu/Makefile.in index 40e786cfab..1def81e894 100644 --- a/packages/ubuntu/Makefile.in +++ b/packages/ubuntu/Makefile.in @@ -15,6 +15,7 @@ ntopng-prep: cp $(NTOPNG_HOME)/ntopng.8 ${NTOPNG_BUILD}/usr/share/man/man8 cp -r $(NTOPNG_HOME)/httpdocs ${NTOPNG_BUILD}/usr/share/ntopng mv ${NTOPNG_BUILD}/usr/share/ntopng/httpdocs/misc/ntopng-utils-manage-config ${NTOPNG_BUILD}/usr/bin/ + cp $(NTOPNG_HOME)/packages/usr/bin/ntopctl ${NTOPNG_BUILD}/usr/bin/ cp -Lr $(NTOPNG_HOME)/scripts ${NTOPNG_BUILD}/usr/share/ntopng # L to dereference symlinks mv ${NTOPNG_BUILD}/usr/share/ntopng/httpdocs/ssl/ntopng-cert.pem.dummy ${NTOPNG_BUILD}/usr/share/ntopng/httpdocs/ssl/ntopng-cert.pem if test -d "$(NTOPNG_HOME)/pro"; then \ diff --git a/packages/usr/bin/ntopctl b/packages/usr/bin/ntopctl new file mode 100755 index 0000000000..de0b0e4188 --- /dev/null +++ b/packages/usr/bin/ntopctl @@ -0,0 +1,311 @@ +#!/bin/bash +# +# Manage ntop services (mainly a proxy for systemd and init.d) +# + +SYSTEMD=false +QUIET=false +IFNAME="" +LICENSE="" +SERVICE_NAME= +SERVICE_PARAM= +SERVICE= +START_FILE= + +# The followings are only set if the given program supports them +SERVICE_STATS= +LOG_FILE= +LICENSE_INSTALLER= +CONFIG_INSTALL_TARGET= + +# ####################################################### + +get_systemd_service_name() { + SERVICE=${SERVICE_NAME} + + if [ ! -z $SERVICE_PARAM ]; then + SERVICE="${SERVICE_NAME}@${SERVICE_PARAM}" + fi +} + +get_initd_service_start_file() { + START_FILE="${SERVICE_NAME}".start + + if [ ! -z $SERVICE_PARAM ]; then + START_FILE="${SERVICE_NAME}-${SERVICE_PARAM}".start + fi +} + +check_interface() { + if [[ "$IFNAME" =~ ^[a-zA-Z0-9:_-]{1,24}$ ]]; then + : + else + [ $QUIET = false ] && echo "Invalid interface $IFNAME" + exit 1 + fi +} + +check_license() { + if [[ "$LICENSE" =~ ^[a-zA-Z0-9]{32,64}$ ]]; then + : + else + [ $QUIET = false ] && echo "Invalid license $LICENSE" + exit 1 + fi +} + +# ####################################################### + +start_service() { + if [ $SYSTEMD = true ]; then + get_systemd_service_name + /bin/systemctl start $SERVICE + else + /etc/init.d/${SERVICE_NAME} force-start ${SERVICE_PARAM} + fi +} + +stop_service() { + if [ $SYSTEMD = true ]; then + get_systemd_service_name + /bin/systemctl stop $SERVICE + else + /etc/init.d/${SERVICE_NAME} stop ${SERVICE_PARAM} + fi +} + +restart_service() { + if [ $SYSTEMD = true ]; then + get_systemd_service_name + /bin/systemctl restart $SERVICE + else + /etc/init.d/${SERVICE_NAME} stop ${SERVICE_PARAM} + /etc/init.d/${SERVICE_NAME} force-start ${SERVICE_PARAM} + fi +} + +enable_service() { + if [ $SYSTEMD = true ]; then + get_systemd_service_name + /bin/systemctl -q enable $SERVICE + else + get_initd_service_start_file + touch /etc/${SERVICE_NAME}/${START_FILE} + fi +} + +disable_service() { + if [ $SYSTEMD = true ]; then + get_systemd_service_name + /bin/systemctl -q disable $SERVICE + else + get_initd_service_start_file + rm /etc/${SERVICE_NAME}/${START_FILE} + fi +} + +get_service_status() { + if [ $SYSTEMD = true ]; then + get_systemd_service_name + /bin/systemctl status $SERVICE + else + /etc/init.d/${SERVICE_NAME} status ${SERVICE_PARAM} + fi +} + +is_active_service() { + if [ $SYSTEMD = true ]; then + get_systemd_service_name + /bin/systemctl is-active $SERVICE + else + if [ $(/etc/init.d/${SERVICE_NAME} status ${SERVICE_PARAM} 2>/dev/null | grep "${SERVICE_NAME} running" | wc -l) -gt 0 ]; then + echo "active" + else + echo "inactive" + fi + fi +} + +is_service_enabled() { + if [ $SYSTEMD = true ]; then + get_systemd_service_name + /bin/systemctl is-enabled $SERVICE + else + get_initd_service_start_file + if [ -f "/etc/${SERVICE_NAME}/${START_FILE}" ]; then + echo "enabled" + else + echo "disabled" + fi + fi +} + +has_service() { + if [ $SYSTEMD = true ]; then + get_systemd_service_name + /bin/systemctl status ${SERVICE} 2>/dev/null >/dev/null + + if [ $? -eq 0 ]; then + echo "yes" + else + echo "no" + fi + else + if [ -f /etc/init.d/${SERVICE_NAME} ]; then + echo "yes" + else + echo "no" + fi + fi +} + +print_service_log() { + if [ $SYSTEMD = true ]; then + get_systemd_service_name + /bin/journalctl -u ${SERVICE} + else + if [ -f $LOG_FILE ]; then + /bin/cat $LOG_FILE + fi + fi +} + +# ####################################################### +# n2disk +# ####################################################### + +get_n2disk_stats() { + if [ $SYSTEMD = true ]; then + PID=$(/bin/systemctl show -p MainPID n2disk@${IFNAME} | cut -d'=' -f2) + fi + if [ -n "$PID" ] && [ "$PID" -ne "0" ]; then + /bin/cat /proc/net/pf_ring/stats/${PID}-* 2>/dev/null + fi +} + +set_n2disk_license() { + echo "$LICENSE" > /etc/n2disk.license +} + +install_service_conf() { + NTOPNG_MANAGE_CONF="/usr/bin/ntopng-utils-manage-config" + + if [ ! -z $CONFIG_INSTALL_TARGET ]; then + if [ -f "$NTOPNG_MANAGE_CONF" ]; then + $NTOPNG_MANAGE_CONF -a ${CONFIG_INSTALL_TARGET} -i ${SERVICE_PARAM} + fi + fi +} + +# ####################################################### + +print_usage() { + echo "Usage: {n2disk|n2n} {start|stop|restart|enable|disable|status|is-active|is-enabled|has-service|log|set-license} " + exit 1 +} + +if hash systemctl 2>/dev/null; then + SYSTEMD=true +fi + +# Program check +case "$1" in + n2disk) + CONFIG_INSTALL_TARGET="install-n2disk-conf" + SERVICE_STATS=get_n2disk_stats + SERVICE_NAME="n2disk" + + if [ -z "$3" ]; then + print_usage + fi + + if [ "$2" = "set-license" ]; then + LICENSE="$3" + check_license + LICENSE_INSTALLER=set_n2disk_license + else + IFNAME="$3" + check_interface + SERVICE_PARAM="$IFNAME" + LOG_FILE="/var/log/n2disk/n2disk-$IFNAME.log" + fi + ;; + + n2n) + SERVICE_NAME="edge" + CONFIG_INSTALL_TARGET="install-n2n-conf" + ;; + + *) + print_usage +esac + +# Action check +case "$2" in + start) + install_service_conf + start_service; + ;; + + stop) + stop_service; + ;; + + restart) + install_service_conf + restart_service; + ;; + + enable) + install_service_conf + enable_service; + ;; + + disable) + disable_service; + ;; + + status) + get_service_status; + ;; + + is-active) + is_active_service; + ;; + + log) + print_service_log; + ;; + + is-enabled) + is_service_enabled; + ;; + + has-service) + has_service; + ;; + +# n2disk + stats) + if [ -z $SERVICE_STATS ]; then + echo "Unsupported command" + exit 1 + fi + $SERVICE_STATS; + ;; + + set-license) + if [ -z $LICENSE_INSTALLER ]; then + echo "Unsupported command" + exit 1 + fi + $LICENSE_INSTALLER; + ;; + + *) + print_usage +esac + +# ####################################################### + +exit 0 diff --git a/scripts/callbacks/system/hourly.lua b/scripts/callbacks/system/hourly.lua new file mode 100644 index 0000000000..d77704ae1a --- /dev/null +++ b/scripts/callbacks/system/hourly.lua @@ -0,0 +1,12 @@ +-- +-- (C) 2013-18 - ntop.org +-- + +local dirs = ntop.getDirs() +package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path + +local remote_assistance = require "remote_assistance" + +-- ######################################################## + +remote_assistance.checkExpiration() diff --git a/scripts/callbacks/system/startup.lua b/scripts/callbacks/system/startup.lua index 4633896c16..2edad82f57 100644 --- a/scripts/callbacks/system/startup.lua +++ b/scripts/callbacks/system/startup.lua @@ -108,6 +108,12 @@ presets_utils.reloadAllDevicePolicies() -- ################################################################## +-- Check remote assistance expiration +local remote_assistance = require "remote_assistance" +remote_assistance.checkExpiration() + +-- ################################################################## + initCustomnDPIProtoCategories() lists_utils.reloadLists() -- housekeeping will do the actual reload... diff --git a/scripts/locales/en.lua b/scripts/locales/en.lua index ce1b96b058..ed30ed2872 100644 --- a/scripts/locales/en.lua +++ b/scripts/locales/en.lua @@ -126,6 +126,7 @@ local lang = { ["remove"] = "Remove", ["reset"] = "Reset", ["restore"] = "Restore", + ["running"] = "Running", ["save"] = "Save", ["save_configuration"] = "Save Configuration", ["save_settings"] = "Save Settings", @@ -538,12 +539,12 @@ local lang = { }, ["discover"] = { ["device"] = "Device", + ["discovered_devices"] = "Discovered %{manuf} %{sys} %{dev} Devices", ["err_unable_to_arp_discovery"] = "Unable to start ARP network discovery", ["error_no_discovery_cached"] = "No discovery data has been cached yet.", ["error_unable_to_decode_json"] = "Unable to decode cache JSON discovery data.", ["ghost_icon_descr"] = "The %{ghost_icon} icon highlights ghost hosts (i.e. they do not belong to the interface IP address network)", ["network_discovery"] = "Network Discovery", - ["discovered_devices"] = "Discovered %{manuf} %{sys} %{dev} Devices", ["network_discovery_datetime"] = "Last Network Discovery", ["network_discovery_not_enabled"] = "Network discovery in progress", }, @@ -2482,6 +2483,19 @@ local lang = { ["traffic_sent"] = "Traffic Sent", ["type"] = "Type", }, + ["remote_assistance"] = { + ["admin_access"] = "Enable Admin Access", + ["admin_access_descr"] = "Allow the support team access as admin user to the %{product} gui.", + ["ask_admin"] = "Ask the network administrator permission before doing this.", + ["enable_remote_assistance"] = "Enable Remote Assistance", + ["key_descr"] = "This is the key to provide to the support team for assistance.", + ["note_sensitive"] = "The information above is sensitive. Only provide it to the ntopng support team.", + ["product_remote_assistance"] = "%{product} Remote Assistance", + ["remember_disable"] = "Remember to disable the remote assistance when not needed.", + ["remote_assistance"] = "Remote Assistance", + ["tos_notice"] = "I want to provide remote access to my host and my network security policies allow this. ntop is not responsible for any damage, security violation or vulnerability caused by enabling remote assistance.", + ["will_create_virtual_network"] = "When enabled, the remote assistance will create an encrypted virtual network to connect remotely to your device.", + }, ["report"] = { ["application_breakdown"] = "Application Breakdown", ["applications"] = "Applications", diff --git a/scripts/lua/admin/remote_assistance.lua b/scripts/lua/admin/remote_assistance.lua new file mode 100644 index 0000000000..271cb5f689 --- /dev/null +++ b/scripts/lua/admin/remote_assistance.lua @@ -0,0 +1,140 @@ +-- +-- (C) 2018 - ntop.org +-- + +local dirs = ntop.getDirs() +package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path +require "lua_utils" +local remote_assistance = require("remote_assistance") + +if((not isAdministrator()) or (not remote_assistance.isAvailable())) then + return +end + +local info = ntop.getInfo() + +if not table.empty(_POST) then + local enabled = (_POST["toggle_remote_assistance"] == "1") and (_POST["accept_tos"] == "1") + + if enabled then + local admin_access = _POST["allow_admin_access"] + local community = _POST["assistance_key"] + local key = community + + if admin_access == "1" then + remote_assistance.enableTempAdminAccess(key) + else + remote_assistance.disableTempAdminAccess() + end + + ntop.setPref("ntopng.prefs.remote_assistance.community", community) + ntop.setPref("ntopng.prefs.remote_assistance.key", key) + ntop.setPref("ntopng.prefs.remote_assistance.admin_access", admin_access or "0") + remote_assistance.createConfig(community, key) + remote_assistance.enableAndStart() + else + remote_assistance.disableTempAdminAccess() + remote_assistance.disableAndStop() + end +end + +sendHTTPContentTypeHeader('text/html') +ntop.dumpFile(dirs.installdir .. "/httpdocs/inc/header.inc") +dofile(dirs.installdir .. "/scripts/lua/inc/menu.lua") + +print("
") +print("

") print(i18n("remote_assistance.product_remote_assistance", {product=info.product})) print("

") +print("
") + +local assistace_checked = "" +local admin_checked = "" +local assist_enabled = remote_assistance.isEnabled() + +if assist_enabled then + assistace_checked = "checked" +end + +if ntop.getPref("ntopng.prefs.remote_assistance.admin_access") == "1" then + admin_checked = "checked" +end + +print [[ +
+ + +
+ + + + + + + + + + + + + +
]] print(i18n("remote_assistance.enable_remote_assistance")) print [[ +
+ +
+
]] print(remote_assistance.statusLabel()) print[[
+
]] print(i18n("key")) print[[
+ ]] print(i18n("remote_assistance.key_descr")) print[[ +
]] print(i18n("remote_assistance.admin_access")) print[[
+ ]] print(i18n("remote_assistance.admin_access_descr", {product = info.product})) print[[ +
+
+ +
+
+ +
+ ]] print(i18n("remote_assistance.tos_notice")) print[[ +
+ + +
+

+ + ]] +print(i18n("notes")) +print[[ + + + + +]] + +dofile(dirs.installdir .. "/scripts/lua/inc/footer.lua") diff --git a/scripts/lua/inc/footer.lua b/scripts/lua/inc/footer.lua index 771923bfce..47b4615461 100644 --- a/scripts/lua/inc/footer.lua +++ b/scripts/lua/inc/footer.lua @@ -401,6 +401,15 @@ print [[/lua/if_stats.lua\"> "; } + if(typeof rsp.remote_assistance !== "undefined") { + var status = rsp.remote_assistance.status; + var status_label = (status == "active") ? "success" : "danger"; + + msg += " "; + msg += ""; + } + if(typeof rsp.traffic_recording !== "undefined") { var status_label="primary"; var status_title="]] print(i18n("traffic_recording.recording")) print [["; diff --git a/scripts/lua/inc/menu.lua b/scripts/lua/inc/menu.lua index b311d8039b..990447caeb 100644 --- a/scripts/lua/inc/menu.lua +++ b/scripts/lua/inc/menu.lua @@ -7,6 +7,7 @@ package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path if((dirs.scriptdir ~= nil) and (dirs.scriptdir ~= "")) then package.path = dirs.scriptdir .. "/lua/modules/?.lua;" .. package.path end require "lua_utils" local recording_utils = require "recording_utils" +local remote_assistance = require "remote_assistance" print[[