first commit
This commit is contained in:
BIN
install/XRDP/new.bmp
Normal file
BIN
install/XRDP/new.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 98 KiB |
230
install/XRDP/xrdp.ini
Normal file
230
install/XRDP/xrdp.ini
Normal file
@ -0,0 +1,230 @@
|
||||
[Globals]
|
||||
; xrdp.ini file version number
|
||||
ini_version=1
|
||||
|
||||
; fork a new process for each incoming connection
|
||||
fork=true
|
||||
|
||||
; ports to listen on, number alone means listen on all interfaces
|
||||
; 0.0.0.0 or :: if ipv6 is configured
|
||||
; space between multiple occurrences
|
||||
;
|
||||
; Examples:
|
||||
; port=3389
|
||||
; port=unix://./tmp/xrdp.socket
|
||||
; port=tcp://.:3389 127.0.0.1:3389
|
||||
; port=tcp://:3389 *:3389
|
||||
; port=tcp://<any ipv4 format addr>:3389 192.168.1.1:3389
|
||||
; port=tcp6://.:3389 ::1:3389
|
||||
; port=tcp6://:3389 *:3389
|
||||
; port=tcp6://{<any ipv6 format addr>}:3389 {FC00:0:0:0:0:0:0:1}:3389
|
||||
; port=vsock://<cid>:<port>
|
||||
port=3389
|
||||
|
||||
; 'port' above should be connected to with vsock instead of tcp
|
||||
; use this only with number alone in port above
|
||||
; prefer use vsock://<cid>:<port> above
|
||||
use_vsock=false
|
||||
|
||||
; regulate if the listening socket use socket option tcp_nodelay
|
||||
; no buffering will be performed in the TCP stack
|
||||
tcp_nodelay=true
|
||||
|
||||
; regulate if the listening socket use socket option keepalive
|
||||
; if the network connection disappear without close messages the connection will be closed
|
||||
tcp_keepalive=true
|
||||
|
||||
; set tcp send/recv buffer (for experts)
|
||||
#tcp_send_buffer_bytes=32768
|
||||
#tcp_recv_buffer_bytes=32768
|
||||
|
||||
; security layer can be 'tls', 'rdp' or 'negotiate'
|
||||
; for client compatible layer
|
||||
security_layer=negotiate
|
||||
|
||||
; minimum security level allowed for client for classic RDP encryption
|
||||
; use tls_ciphers to configure TLS encryption
|
||||
; can be 'none', 'low', 'medium', 'high', 'fips'
|
||||
crypt_level=None
|
||||
|
||||
; X.509 certificate and private key
|
||||
; openssl req -x509 -newkey rsa:2048 -nodes -keyout key.pem -out cert.pem -days 365
|
||||
; note this needs the user xrdp to be a member of the ssl-cert group, do with e.g.
|
||||
;$ sudo adduser xrdp ssl-cert
|
||||
certificate=
|
||||
key_file=
|
||||
|
||||
; set SSL protocols
|
||||
; can be comma separated list of 'SSLv3', 'TLSv1', 'TLSv1.1', 'TLSv1.2', 'TLSv1.3'
|
||||
ssl_protocols=TLSv1.2, TLSv1.3
|
||||
; set TLS cipher suites
|
||||
#tls_ciphers=HIGH
|
||||
|
||||
; Section name to use for automatic login if the client sends username
|
||||
; and password. If empty, the domain name sent by the client is used.
|
||||
; If empty and no domain name is given, the first suitable section in
|
||||
; this file will be used.
|
||||
autorun=
|
||||
|
||||
allow_channels=true
|
||||
allow_multimon=true
|
||||
bitmap_cache=true
|
||||
bitmap_compression=true
|
||||
bulk_compression=true
|
||||
#hidelogwindow=true
|
||||
max_bpp=32
|
||||
new_cursors=true
|
||||
; fastpath - can be 'input', 'output', 'both', 'none'
|
||||
use_fastpath=both
|
||||
; when true, userid/password *must* be passed on cmd line
|
||||
#require_credentials=true
|
||||
; You can set the PAM error text in a gateway setup (MAX 256 chars)
|
||||
#pamerrortxt=change your password according to policy at http://url
|
||||
|
||||
;
|
||||
; colors used by windows in RGB format
|
||||
;
|
||||
blue=009cb5
|
||||
grey=dedede
|
||||
#black=000000
|
||||
#dark_grey=808080
|
||||
#blue=08246b
|
||||
#dark_blue=08246b
|
||||
#white=ffffff
|
||||
#red=ff0000
|
||||
#green=00ff00
|
||||
#background=626c72
|
||||
|
||||
|
||||
|
||||
;
|
||||
; configure login screen
|
||||
;
|
||||
|
||||
; Login Screen Window Title
|
||||
ls_title=Discord-Linux RDP Login
|
||||
|
||||
; top level window background color in RGB format
|
||||
ls_top_window_bg_color=000000
|
||||
|
||||
; width and height of login screen
|
||||
ls_width=350
|
||||
ls_height=430
|
||||
|
||||
; login screen background color in RGB format
|
||||
ls_bg_color=dedede
|
||||
|
||||
; optional background image filename (bmp format).
|
||||
#ls_background_image=
|
||||
|
||||
; logo
|
||||
; full path to bmp-file or file in shared folder
|
||||
#ls_logo_filename=/etc/xrdp/codingworldf.bmp
|
||||
ls_logo_filename=/etc/xrdp/new.bmp
|
||||
ls_logo_x_pos=55
|
||||
ls_logo_y_pos=50
|
||||
|
||||
; for positioning labels such as username, password etc
|
||||
ls_label_x_pos=30
|
||||
ls_label_width=65
|
||||
|
||||
; for positioning text and combo boxes next to above labels
|
||||
ls_input_x_pos=110
|
||||
ls_input_width=210
|
||||
|
||||
; y pos for first label and combo box
|
||||
ls_input_y_pos=220
|
||||
|
||||
; OK button
|
||||
ls_btn_ok_x_pos=142
|
||||
ls_btn_ok_y_pos=370
|
||||
ls_btn_ok_width=85
|
||||
ls_btn_ok_height=30
|
||||
|
||||
; Cancel button
|
||||
ls_btn_cancel_x_pos=237
|
||||
ls_btn_cancel_y_pos=370
|
||||
ls_btn_cancel_width=85
|
||||
ls_btn_cancel_height=30
|
||||
|
||||
[Logging]
|
||||
LogFile=xrdp.log
|
||||
LogLevel=DEBUG
|
||||
EnableSyslog=true
|
||||
SyslogLevel=DEBUG
|
||||
; LogLevel and SysLogLevel could by any of: core, error, warning, info or debug
|
||||
|
||||
[Channels]
|
||||
; Channel names not listed here will be blocked by XRDP.
|
||||
; You can block any channel by setting its value to false.
|
||||
; IMPORTANT! All channels are not supported in all use
|
||||
; cases even if you set all values to true.
|
||||
; You can override these settings on each session type
|
||||
; These settings are only used if allow_channels=true
|
||||
rdpdr=true
|
||||
rdpsnd=true
|
||||
drdynvc=true
|
||||
cliprdr=true
|
||||
rail=true
|
||||
xrdpvr=true
|
||||
tcutils=true
|
||||
|
||||
; for debugging xrdp, in section xrdp1, change port=-1 to this:
|
||||
#port=/tmp/.xrdp/xrdp_display_10
|
||||
|
||||
; for debugging xrdp, add following line to section xrdp1
|
||||
#chansrvport=/tmp/.xrdp/xrdp_chansrv_socket_7210
|
||||
|
||||
|
||||
;
|
||||
; Session types
|
||||
;
|
||||
|
||||
; Some session types such as Xorg, X11rdp and Xvnc start a display server.
|
||||
; Startup command-line parameters for the display server are configured
|
||||
; in sesman.ini. See and configure also sesman.ini.
|
||||
[Xorg]
|
||||
name=Discord-Linux Personal
|
||||
lib=libxup.so
|
||||
username=ask
|
||||
password=ask
|
||||
ip=127.0.0.1
|
||||
port=-1
|
||||
code=20
|
||||
#[Xvnc]
|
||||
#name=Xvnc
|
||||
#lib=libvnc.so
|
||||
#username=ask
|
||||
#password=ask
|
||||
#ip=127.0.0.1
|
||||
#port=-1
|
||||
##xserverbpp=24
|
||||
#delay_ms=2000
|
||||
|
||||
#[vnc-any]
|
||||
#name=vnc-any
|
||||
#lib=libvnc.so
|
||||
#ip=ask
|
||||
#port=ask5900
|
||||
#username=na
|
||||
#password=ask
|
||||
#pamusername=asksame
|
||||
#pampassword=asksame
|
||||
#pamsessionmng=127.0.0.1
|
||||
#delay_ms=2000
|
||||
|
||||
#[neutrinordp-any]
|
||||
#name=neutrinordp-any
|
||||
#lib=libxrdpneutrinordp.so
|
||||
#ip=ask
|
||||
#port=ask3389
|
||||
#username=ask
|
||||
#password=ask
|
||||
|
||||
#; You can override the common channel settings for each session type
|
||||
#channel.rdpdr=true
|
||||
#channel.rdpsnd=true
|
||||
#channel.drdynvc=true
|
||||
#channel.cliprdr=true
|
||||
#channel.rail=true
|
||||
#channel.xrdpvr=true
|
4
install/code-server/config.yaml
Normal file
4
install/code-server/config.yaml
Normal file
@ -0,0 +1,4 @@
|
||||
bind-addr: 127.0.0.1:8080
|
||||
auth: password
|
||||
password: replaceme
|
||||
cert: false
|
9
install/code-server/startCodeServer.json
Normal file
9
install/code-server/startCodeServer.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"apps": [
|
||||
{
|
||||
"name": "Code-Server",
|
||||
"script": "/var/tools/startCodeServer.sh",
|
||||
"args" : ""
|
||||
}
|
||||
]
|
||||
}
|
2
install/code-server/startCodeServer.sh
Normal file
2
install/code-server/startCodeServer.sh
Normal file
@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
code-server
|
9
install/hastebin
Normal file
9
install/hastebin
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"apps": [
|
||||
{
|
||||
"name": "HasteBin",
|
||||
"script": "node server.js",
|
||||
"args" : ""
|
||||
}
|
||||
]
|
||||
}
|
3
install/mc/eula
Normal file
3
install/mc/eula
Normal file
@ -0,0 +1,3 @@
|
||||
#By changing the setting below to TRUE you are indicating your agreement to our EULA (https://account.mojang.com/documents/minecraft_eula).
|
||||
#Mon Mar 20 21:15:37 PDT 2017
|
||||
eula=true
|
9
install/mc/minecraft-server.json
Normal file
9
install/mc/minecraft-server.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"apps": [
|
||||
{
|
||||
"name": "MineCraft Server",
|
||||
"script": "java -Xms960M -Xmx960M -jar server.jar --nogui",
|
||||
"args" : ""
|
||||
}
|
||||
]
|
||||
}
|
8
install/mysql/mysql.list
Normal file
8
install/mysql/mysql.list
Normal file
@ -0,0 +1,8 @@
|
||||
### THIS FILE IS AUTOMATICALLY CONFIGURED ###
|
||||
# You may comment out entries below, but any other modifications may be lost.
|
||||
# Use command 'dpkg-reconfigure mysql-apt-config' as root for modifications.
|
||||
deb http://repo.mysql.com/apt/debian/ bullseye mysql-apt-config
|
||||
deb http://repo.mysql.com/apt/debian/ bullseye mysql-8.0
|
||||
deb http://repo.mysql.com/apt/debian/ bullseye mysql-tools
|
||||
#deb http://repo.mysql.com/apt/debian/ bullseye mysql-tools-preview
|
||||
deb-src http://repo.mysql.com/apt/debian/ bullseye mysql-8.0
|
9
install/osjs/osjsStart.json
Normal file
9
install/osjs/osjsStart.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"apps": [
|
||||
{
|
||||
"name": "OSjs",
|
||||
"script": "npm run serve",
|
||||
"args" : ""
|
||||
}
|
||||
]
|
||||
}
|
65
install/osjs/osjs_client_config.js
Normal file
65
install/osjs/osjs_client_config.js
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* OS.js - JavaScript Cloud/Web Desktop Platform
|
||||
*
|
||||
* Copyright (c) 2011-2020, Anders Evenrud <andersevenrud@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, t$
|
||||
* list of conditions and the following disclaimer
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"$
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLI$
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE$
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMA$
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF TH$
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* @author Anders Evenrud <andersevenrud@gmail.com>
|
||||
* @licence Simplified BSD License
|
||||
*/
|
||||
|
||||
//
|
||||
// This is the client configuration tree.
|
||||
// Guide: https://manual.os-js.org/v3/config/#client
|
||||
// Complete config tree: https://github.com/os-js/osjs-client/blob/master/src/$
|
||||
//
|
||||
import wallpaper from './wallpaper.jpg';
|
||||
|
||||
export default {
|
||||
auth: {
|
||||
ui: {
|
||||
title: 'Discord-Linux Web OS',
|
||||
stamp: 'Discord-Linux-OSJS v-2.4'
|
||||
}
|
||||
},
|
||||
|
||||
desktop: {
|
||||
settings: {
|
||||
background: {
|
||||
src: wallpaper,
|
||||
color: '#000',
|
||||
style: 'cover'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
// module.exports = {
|
||||
// /// ws: {
|
||||
// /// uri: '/ws'
|
||||
// /// }
|
||||
|
||||
// };
|
28
install/osjs/osjs_server_config.js
Normal file
28
install/osjs/osjs_server_config.js
Normal file
@ -0,0 +1,28 @@
|
||||
//
|
||||
// This is the server configuration tree.
|
||||
// Guide: https://manual.os-js.org/v3/config/#server
|
||||
// Complete config tree: https://github.com/os-js/osjs-server/blob/master/sr$
|
||||
//
|
||||
|
||||
const path = require('path');
|
||||
const root = path.resolve(__dirname, '../../');
|
||||
|
||||
module.exports = {
|
||||
root,
|
||||
port: CUSTOM,
|
||||
public: path.resolve(root, 'dist'),
|
||||
vfs: { root: '/home' },
|
||||
|
||||
xterm: {
|
||||
ssh: {
|
||||
// Custom hostname
|
||||
hostname: 'localhost',
|
||||
|
||||
// Custom port
|
||||
args: '-p 22'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
79
install/osjs/osjs_server_index.js
Normal file
79
install/osjs/osjs_server_index.js
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* OS.js - JavaScript Cloud/Web Desktop Platform
|
||||
*
|
||||
* Copyright (c) 2011-2020, Anders Evenrud <andersevenrud@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* @author Anders Evenrud <andersevenrud@gmail.com>
|
||||
* @licence Simplified BSD License
|
||||
*/
|
||||
|
||||
//
|
||||
// This is the server bootstrapping script.
|
||||
// This is where you can register service providers or set up
|
||||
// your libraries etc.
|
||||
//
|
||||
// https://manual.os-js.org/v3/guide/provider/
|
||||
// https://manual.os-js.org/v3/install/
|
||||
// https://manual.os-js.org/v3/resource/official/
|
||||
//
|
||||
|
||||
// In the top of the file load the library
|
||||
const pamAuth = require('@osjs/pam-auth');
|
||||
|
||||
const {
|
||||
Core,
|
||||
CoreServiceProvider,
|
||||
PackageServiceProvider,
|
||||
VFSServiceProvider,
|
||||
AuthServiceProvider,
|
||||
SettingsServiceProvider
|
||||
} = require('@osjs/server');
|
||||
|
||||
const config = require('./config.js');
|
||||
const osjs = new Core(config, {});
|
||||
|
||||
osjs.register(CoreServiceProvider, {before: true});
|
||||
osjs.register(PackageServiceProvider);
|
||||
osjs.register(VFSServiceProvider);
|
||||
osjs.register(AuthServiceProvider, {
|
||||
args: {
|
||||
adapter: pamAuth
|
||||
}
|
||||
});
|
||||
osjs.register(SettingsServiceProvider);
|
||||
|
||||
|
||||
const shutdown = signal => (error) => {
|
||||
if (error instanceof Error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
osjs.destroy(() => process.exit(signal));
|
||||
};
|
||||
|
||||
process.on('SIGTERM', shutdown(0));
|
||||
process.on('SIGINT', shutdown(0));
|
||||
process.on('exit', shutdown(0));
|
||||
|
||||
osjs.boot().catch(shutdown(1));
|
2
install/s2l/input.sh
Normal file
2
install/s2l/input.sh
Normal file
@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
screen -S s2l -X stuff "${*}^M"
|
12
install/s2l/s2l-pm2.json
Normal file
12
install/s2l/s2l-pm2.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"apps": [
|
||||
{
|
||||
"name": "s2l",
|
||||
"script": "ttyd -R -p changeme screen -x s2l",
|
||||
"args" : "",
|
||||
"error_file": "/dev/null",
|
||||
"log_file": "/dev/null"
|
||||
|
||||
}
|
||||
]
|
||||
}
|
13
install/s2l/s2l-service.service
Normal file
13
install/s2l/s2l-service.service
Normal file
@ -0,0 +1,13 @@
|
||||
[Unit]
|
||||
Description=Screen2Log Backend for CMDBOT.Service
|
||||
After=network.target
|
||||
StartLimitIntervalSec=0
|
||||
[Service]
|
||||
Type=simple
|
||||
Restart=always
|
||||
RestartSec=1
|
||||
User=root
|
||||
ExecStart=/bin/bash -c 'screen -mdS s2l -s bash'
|
||||
RemainAfterExit=yes
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
229
install/secu/apache2.conf
Normal file
229
install/secu/apache2.conf
Normal file
@ -0,0 +1,229 @@
|
||||
# This is the main Apache server configuration file. It contains the
|
||||
# configuration directives that give the server its instructions.
|
||||
# See http://httpd.apache.org/docs/2.4/ for detailed information about
|
||||
# the directives and /usr/share/doc/apache2/README.Debian about Debian specific
|
||||
# hints.
|
||||
#
|
||||
#
|
||||
# Summary of how the Apache 2 configuration works in Debian:
|
||||
# The Apache 2 web server configuration in Debian is quite different to
|
||||
# upstream's suggested way to configure the web server. This is because Debian's
|
||||
# default Apache2 installation attempts to make adding and removing modules,
|
||||
# virtual hosts, and extra configuration directives as flexible as possible, in
|
||||
# order to make automating the changes and administering the server as easy as
|
||||
# possible.
|
||||
|
||||
# It is split into several files forming the configuration hierarchy outlined
|
||||
# below, all located in the /etc/apache2/ directory:
|
||||
#
|
||||
# /etc/apache2/
|
||||
# |-- apache2.conf
|
||||
# | `-- ports.conf
|
||||
# |-- mods-enabled
|
||||
# | |-- *.load
|
||||
# | `-- *.conf
|
||||
# |-- conf-enabled
|
||||
# | `-- *.conf
|
||||
# `-- sites-enabled
|
||||
# `-- *.conf
|
||||
#
|
||||
#
|
||||
# * apache2.conf is the main configuration file (this file). It puts the pieces
|
||||
# together by including all remaining configuration files when starting up the
|
||||
# web server.
|
||||
#
|
||||
# * ports.conf is always included from the main configuration file. It is
|
||||
# supposed to determine listening ports for incoming connections which can be
|
||||
# customized anytime.
|
||||
#
|
||||
# * Configuration files in the mods-enabled/, conf-enabled/ and sites-enabled/
|
||||
# directories contain particular configuration snippets which manage modules,
|
||||
# global configuration fragments, or virtual host configurations,
|
||||
# respectively.
|
||||
#
|
||||
# They are activated by symlinking available configuration files from their
|
||||
# respective *-available/ counterparts. These should be managed by using our
|
||||
# helpers a2enmod/a2dismod, a2ensite/a2dissite and a2enconf/a2disconf. See
|
||||
# their respective man pages for detailed information.
|
||||
#
|
||||
# * The binary is called apache2. Due to the use of environment variables, in
|
||||
# the default configuration, apache2 needs to be started/stopped with
|
||||
# /etc/init.d/apache2 or apache2ctl. Calling /usr/bin/apache2 directly will not
|
||||
# work with the default configuration.
|
||||
|
||||
|
||||
# Global configuration
|
||||
#
|
||||
|
||||
#
|
||||
# ServerRoot: The top of the directory tree under which the server's
|
||||
# configuration, error, and log files are kept.
|
||||
#
|
||||
# NOTE! If you intend to place this on an NFS (or otherwise network)
|
||||
# mounted filesystem then please read the Mutex documentation (available
|
||||
# at <URL:http://httpd.apache.org/docs/2.4/mod/core.html#mutex>);
|
||||
# you will save yourself a lot of trouble.
|
||||
#
|
||||
# Do NOT add a slash at the end of the directory path.
|
||||
#
|
||||
#ServerRoot "/etc/apache2"
|
||||
|
||||
#
|
||||
# The accept serialization lock file MUST BE STORED ON A LOCAL DISK.
|
||||
#
|
||||
#Mutex file:${APACHE_LOCK_DIR} default
|
||||
|
||||
#
|
||||
# The directory where shm and other runtime files will be stored.
|
||||
#
|
||||
|
||||
DefaultRuntimeDir ${APACHE_RUN_DIR}
|
||||
|
||||
#
|
||||
# PidFile: The file in which the server should record its process
|
||||
# identification number when it starts.
|
||||
# This needs to be set in /etc/apache2/envvars
|
||||
#
|
||||
PidFile ${APACHE_PID_FILE}
|
||||
|
||||
#
|
||||
# Timeout: The number of seconds before receives and sends time out.
|
||||
#
|
||||
Timeout 300
|
||||
|
||||
#
|
||||
# KeepAlive: Whether or not to allow persistent connections (more than
|
||||
# one request per connection). Set to "Off" to deactivate.
|
||||
#
|
||||
KeepAlive On
|
||||
|
||||
#
|
||||
# MaxKeepAliveRequests: The maximum number of requests to allow
|
||||
# during a persistent connection. Set to 0 to allow an unlimited amount.
|
||||
# We recommend you leave this number high, for maximum performance.
|
||||
#
|
||||
MaxKeepAliveRequests 100
|
||||
|
||||
#
|
||||
# KeepAliveTimeout: Number of seconds to wait for the next request from the
|
||||
# same client on the same connection.
|
||||
#
|
||||
KeepAliveTimeout 5
|
||||
|
||||
|
||||
# These need to be set in /etc/apache2/envvars
|
||||
User ${APACHE_RUN_USER}
|
||||
Group ${APACHE_RUN_GROUP}
|
||||
|
||||
#
|
||||
# HostnameLookups: Log the names of clients or just their IP addresses
|
||||
# e.g., www.apache.org (on) or 204.62.129.132 (off).
|
||||
# The default is off because it'd be overall better for the net if people
|
||||
# had to knowingly turn this feature on, since enabling it means that
|
||||
# each client request will result in AT LEAST one lookup request to the
|
||||
# nameserver.
|
||||
#
|
||||
HostnameLookups Off
|
||||
|
||||
# ErrorLog: The location of the error log file.
|
||||
# If you do not specify an ErrorLog directive within a <VirtualHost>
|
||||
# container, error messages relating to that virtual host will be
|
||||
# logged here. If you *do* define an error logfile for a <VirtualHost>
|
||||
# container, that host's errors will be logged there and not here.
|
||||
#
|
||||
ErrorLog ${APACHE_LOG_DIR}/error.log
|
||||
|
||||
#
|
||||
# LogLevel: Control the severity of messages logged to the error_log.
|
||||
# Available values: trace8, ..., trace1, debug, info, notice, warn,
|
||||
# error, crit, alert, emerg.
|
||||
# It is also possible to configure the log level for particular modules, e.g.
|
||||
# "LogLevel info ssl:warn"
|
||||
#
|
||||
LogLevel warn
|
||||
|
||||
# Include module configuration:
|
||||
IncludeOptional mods-enabled/*.load
|
||||
IncludeOptional mods-enabled/*.conf
|
||||
|
||||
# Include list of ports to listen on
|
||||
Include ports.conf
|
||||
|
||||
|
||||
# Sets the default security model of the Apache2 HTTPD server. It does
|
||||
# not allow access to the root filesystem outside of /usr/share and /var/www.
|
||||
# The former is used by web applications packaged in Debian,
|
||||
# the latter may be used for local directories served by the web server. If
|
||||
# your system is serving content from a sub-directory in /srv you must allow
|
||||
# access here, or in any related virtual host.
|
||||
<Directory />
|
||||
Options FollowSymLinks
|
||||
AllowOverride All
|
||||
Require all denied
|
||||
</Directory>
|
||||
|
||||
<Directory /usr/share>
|
||||
AllowOverride All
|
||||
Require all granted
|
||||
</Directory>
|
||||
|
||||
<Directory /var/www/>
|
||||
Options Indexes FollowSymLinks
|
||||
AllowOverride All
|
||||
Require all granted
|
||||
</Directory>
|
||||
|
||||
#<Directory /srv/>
|
||||
# Options Indexes FollowSymLinks
|
||||
# AllowOverride All
|
||||
# Require all granted
|
||||
#</Directory>
|
||||
|
||||
|
||||
|
||||
|
||||
# AccessFileName: The name of the file to look for in each directory
|
||||
# for additional configuration directives. See also the AllowOverride
|
||||
# directive.
|
||||
#
|
||||
AccessFileName .htaccess
|
||||
|
||||
#
|
||||
# The following lines prevent .htaccess and .htpasswd files from being
|
||||
# viewed by Web clients.
|
||||
#
|
||||
<FilesMatch "^\.ht">
|
||||
Require all denied
|
||||
</FilesMatch>
|
||||
|
||||
|
||||
#
|
||||
# The following directives define some format nicknames for use with
|
||||
# a CustomLog directive.
|
||||
#
|
||||
# These deviate from the Common Log Format definitions in that they use %O
|
||||
# (the actual bytes sent including headers) instead of %b (the size of the
|
||||
# requested file), because the latter makes it impossible to detect partial
|
||||
# requests.
|
||||
#
|
||||
# Note that the use of %{X-Forwarded-For}i instead of %h is not recommended.
|
||||
# Use mod_remoteip instead.
|
||||
#
|
||||
LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined
|
||||
#LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
|
||||
LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
|
||||
LogFormat "%h %l %u %t \"%r\" %>s %O" common
|
||||
LogFormat "%{Referer}i -> %U" referer
|
||||
LogFormat "%{User-agent}i" agent
|
||||
|
||||
# Include of directories ignores editors' and dpkg's backup files,
|
||||
# see README.Debian for details.
|
||||
|
||||
# Include generic snippets of statements
|
||||
IncludeOptional conf-enabled/*.conf
|
||||
|
||||
# Include the virtual host configurations:
|
||||
IncludeOptional sites-enabled/*.conf
|
||||
|
||||
# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
|
||||
serverName secuNotifyHTTP
|
160
install/secu/build
Normal file
160
install/secu/build
Normal file
@ -0,0 +1,160 @@
|
||||
// Lets use some libs to help us out.
|
||||
const fs = require('fs')
|
||||
Tail = require('tail').Tail;
|
||||
|
||||
sshTail = new Tail("/var/log/auth.log");
|
||||
wpTail = new Tail("/var/log/apache2/access.log");
|
||||
const cmd = require('cmd-promise')
|
||||
|
||||
// Setting up our main storage logic - for now this program does not use a database system.
|
||||
let serverStatusCount = 0;
|
||||
let attackData = []
|
||||
let blockedIPs = []
|
||||
let ipToBlock
|
||||
|
||||
console.log("Welcome to the security notification system secuNotify by Discord-Linux!");
|
||||
console.log("We currently will notify you about login events, such as failed logins and successful logins.");
|
||||
|
||||
// Setting up our notification function - This allows us to direct message our user.
|
||||
function notify(message) {
|
||||
const { spawn } = require('child_process');
|
||||
const notif = spawn('notif', [message]);
|
||||
|
||||
notif.stdout.on('data', (data) => {
|
||||
console.log(`stdout: ${data}`);
|
||||
});
|
||||
|
||||
notif.stderr.on('data', (data) => {
|
||||
console.error(`stderr: ${data}`);
|
||||
});
|
||||
|
||||
notif.on('close', (code) => {
|
||||
console.log(`Code: ${code} - Continuing to monitor`);
|
||||
});
|
||||
}
|
||||
|
||||
function listenAuthLog(logLocation) {
|
||||
sshTail.on("line", function (info) {
|
||||
let infoString = info.toString();
|
||||
|
||||
if (infoString.includes("Failed password for root")) {
|
||||
console.log(info);
|
||||
notify("secuNotify Service Alert: \n" + info);
|
||||
}
|
||||
|
||||
if (infoString.includes("Accepted password for")) {
|
||||
console.log(info);
|
||||
notify("secuNotify Service Alert: \n" + info + "This does mean that someone (Maybe you) has logged in successfully!");
|
||||
}
|
||||
if (infoString.includes("Invalid user")) {
|
||||
console.log(info);
|
||||
notify("secuNotify Service Alert: \n" + info + "This means that someone (Maybe you) has tried to login with an invalid username!");
|
||||
}
|
||||
})
|
||||
|
||||
;
|
||||
}
|
||||
|
||||
function listenWPLog(logLocation) {
|
||||
// Check to see if we are a wordpress user, if so, activate the wordpress notification service
|
||||
const wpLog = '/var/www/html/wp-config.php'
|
||||
if (fs.existsSync(wpLog)) console.log("We are a wordpress user, activating wordpress notification service");
|
||||
try {
|
||||
if (fs.existsSync(wpLog)) {
|
||||
// Tail Logs section, if we have a lot, it will have a listeniner below.
|
||||
wpTail.on("line", function (info) {
|
||||
|
||||
// Convert Data to String
|
||||
let requestInfo = info.toString()
|
||||
// FIND IP Address from this request
|
||||
var ipRegEx = /\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/; // RegEx IPAddress Format
|
||||
var ipRegExMatched = requestInfo.match(ipRegEx); // Set up our match
|
||||
let remoteIP = ipRegExMatched[0] // Set our var
|
||||
|
||||
// // Grab the whitelist
|
||||
// let whitelistData = process.env.WHITELIST
|
||||
// let whitelist = whitelistData.split(",")
|
||||
|
||||
// // If an IP is found to be in the whitelist, return as to do nothing.
|
||||
// for (const [key, value] of Object.entries(whitelist)) {
|
||||
// if (value === remoteIP) return
|
||||
// }
|
||||
|
||||
// Filtering out any server-status requests - These are annoying.
|
||||
if (requestInfo.includes("server-status")) {
|
||||
// Add to the server status count so we may keep track of these requests.
|
||||
serverStatusCount++
|
||||
// Lets return the data as no not proceed with any further code, as it is not needed.
|
||||
// We return to stdout here to update the cli without adding a new line line a clock
|
||||
return process.stdout.write("Server Status Count: " + serverStatusCount + "\r");
|
||||
}
|
||||
|
||||
// If request contans wp-login lets process its request
|
||||
if (requestInfo.includes("wp-login.php")) {
|
||||
// Lets start the process of logging attack attempts to determine request intent.
|
||||
// Over the threshhold here will automatically CSF D the IP Address.
|
||||
// In this simple version, we will just log each IP Address as they come in within an array
|
||||
// We will then roll and count this array after each detection to determine the IPs intent.
|
||||
console.log("---------\nWP LOGIN REQUEST DETECTED!\n---------")
|
||||
console.log(info + "\n----------");
|
||||
attackData.push(remoteIP)
|
||||
|
||||
// Lets count the attack data per IP Address to ensure its logged properly.
|
||||
var counts = {};
|
||||
|
||||
// For each IP Address recorded into the main attackData array, count them and see outmany bad requests they have made.
|
||||
attackData.forEach(function (x) {
|
||||
// Add a point for each entry
|
||||
counts[x] = (counts[x] || 0) + 1;
|
||||
//
|
||||
for ([key, value] of Object.entries(counts)) {
|
||||
// If the count has hit the blockON Count we start the blocking process
|
||||
|
||||
if (counts[x] == 5) {
|
||||
// Preserve the key for later blocklist addition
|
||||
ipToBlock = key
|
||||
|
||||
// Check the already blocked IPs - If the remoteIP is in the list do nothing
|
||||
if (blockedIPs.includes(key)) {
|
||||
return
|
||||
|
||||
} else {
|
||||
// The remoteIP is not listed, lets add it.
|
||||
blockedIPs.push(ipToBlock)
|
||||
// Let the log know we are blocking the IP
|
||||
console.log("Starting to block bad IP")
|
||||
// Run the block, wait for the promise - Requests are still going on
|
||||
cmd(`/var/tools/firewallctl 123.123.123.123 ` + key + " WP-Login Brute Force Blocked Via secuNotify").then(out => {
|
||||
notify("secuNotify Service Alert: \n " + key + " has been blocked for 5 bad wordpress login attempts!");
|
||||
|
||||
// The block has finished - remoteIP no longer has access
|
||||
}).catch(err => {
|
||||
// IF we see an error, give its output
|
||||
console.log('CSF Error: ', err)
|
||||
}).then(out2 => {
|
||||
// Set IPBLOCK to null for a reset and start scanning for new attacks
|
||||
ipToBlock = null;
|
||||
console.log("Attack Stopped, Looking for new attacks....")
|
||||
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// Live view of the counts
|
||||
console.log(counts)
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
listenAuthLog("/var/log/auth.log")
|
||||
listenWPLog("/var/log/apache2/access.log")
|
BIN
install/secu/csf
Executable file
BIN
install/secu/csf
Executable file
Binary file not shown.
BIN
install/secu/make/new
Executable file
BIN
install/secu/make/new
Executable file
Binary file not shown.
180
install/secu/make/new.js
Normal file
180
install/secu/make/new.js
Normal file
@ -0,0 +1,180 @@
|
||||
// Lets use some libs to help us out.
|
||||
const fs = require('fs')
|
||||
Tail = require('tail').Tail;
|
||||
|
||||
sshTail = new Tail("/var/log/auth.log");
|
||||
const cmd = require('cmd-promise')
|
||||
|
||||
// Setting up our main storage logic - for now this program does not use a database system.
|
||||
let serverStatusCount = 0;
|
||||
let attackData = []
|
||||
let blockedIPs = []
|
||||
let ipToBlock
|
||||
|
||||
console.log("Welcome to the security notification system secuNotify by Discord-Linux!");
|
||||
console.log("We currently will notify you about login events, such as failed logins and successful logins.");
|
||||
|
||||
// Setting up our notification function - This allows us to direct message our user.
|
||||
function notify(message) {
|
||||
const { spawn } = require('child_process');
|
||||
const notif = spawn('notif', [message]);
|
||||
|
||||
notif.stdout.on('data', (data) => {
|
||||
console.log(`stdout: ${data}`);
|
||||
});
|
||||
|
||||
notif.stderr.on('data', (data) => {
|
||||
console.error(`stderr: ${data}`);
|
||||
});
|
||||
|
||||
notif.on('close', (code) => {
|
||||
console.log(`Code: ${code} - Continuing to monitor`);
|
||||
});
|
||||
}
|
||||
|
||||
function listenAuthLog(logLocation) {
|
||||
sshTail.on("line", function (info) {
|
||||
let infoString = info.toString();
|
||||
|
||||
if (infoString.includes("Failed password for root")) {
|
||||
console.log(info);
|
||||
notify("secuNotify Service Alert: \n" + info);
|
||||
}
|
||||
|
||||
if (infoString.includes("Accepted password for")) {
|
||||
console.log(info);
|
||||
notify("secuNotify Service Alert: \n" + info + "This does mean that someone (Maybe you) has logged in successfully!");
|
||||
}
|
||||
if (infoString.includes("Invalid user")) {
|
||||
console.log(info);
|
||||
notify("secuNotify Service Alert: \n" + info + "This means that someone (Maybe you) has tried to login with an invalid username!");
|
||||
}
|
||||
})
|
||||
|
||||
;
|
||||
}
|
||||
|
||||
function listenWPLog(logLocation) {
|
||||
// Check to see if we are a wordpress user, if so, activate the wordpress notification service
|
||||
try {
|
||||
if (fs.existsSync("/var/www/html/wp-config.php")) {
|
||||
console.log("We are a wordpress user, activating wordpress notification service");
|
||||
|
||||
// Tail Logs section, if we have a lot, it will have a listeniner below.
|
||||
wpTail.on("line", function (info) {
|
||||
|
||||
// Convert Data to String
|
||||
let requestInfo = info.toString()
|
||||
// FIND IP Address from this request
|
||||
var ipRegEx = /\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/; // RegEx IPAddress Format
|
||||
var ipRegExMatched = requestInfo.match(ipRegEx); // Set up our match
|
||||
let remoteIP = ipRegExMatched[0] // Set our var
|
||||
|
||||
// // Grab the whitelist
|
||||
// let whitelistData = process.env.WHITELIST
|
||||
// let whitelist = whitelistData.split(",")
|
||||
|
||||
// // If an IP is found to be in the whitelist, return as to do nothing.
|
||||
// for (const [key, value] of Object.entries(whitelist)) {
|
||||
// if (value === remoteIP) return
|
||||
// }
|
||||
|
||||
// Filtering out any server-status requests - These are annoying.
|
||||
if (requestInfo.includes("server-status")) {
|
||||
// Add to the server status count so we may keep track of these requests.
|
||||
serverStatusCount++
|
||||
// Lets return the data as no not proceed with any further code, as it is not needed.
|
||||
// We return to stdout here to update the cli without adding a new line line a clock
|
||||
return process.stdout.write("Server Status Count: " + serverStatusCount + "\r");
|
||||
}
|
||||
|
||||
// If request contans wp-login lets process its request
|
||||
if (requestInfo.includes("wp-login.php") && requestInfo.includes("POST")) {
|
||||
// Lets start the process of logging attack attempts to determine request intent.
|
||||
// Over the threshhold here will automatically CSF D the IP Address.
|
||||
// In this simple version, we will just log each IP Address as they come in within an array
|
||||
// We will then roll and count this array after each detection to determine the IPs intent.
|
||||
console.log("---------\nWP LOGIN REQUEST DETECTED!\n---------")
|
||||
console.log(info + "\n----------");
|
||||
attackData.push(remoteIP)
|
||||
|
||||
// Lets count the attack data per IP Address to ensure its logged properly.
|
||||
var counts = {};
|
||||
|
||||
// For each IP Address recorded into the main attackData array, count them and see outmany bad requests they have made.
|
||||
attackData.forEach(function (x) {
|
||||
// Add a point for each entry
|
||||
counts[x] = (counts[x] || 0) + 1;
|
||||
//
|
||||
for ([key, value] of Object.entries(counts)) {
|
||||
// If the count has hit the blockON Count we start the blocking process
|
||||
|
||||
if (counts[x] === 5) {
|
||||
console.log("counts: " + counts[x])
|
||||
counts = {}
|
||||
|
||||
|
||||
// Preserve the key for later blocklist addition
|
||||
ipToBlock = key
|
||||
|
||||
// Check the already blocked IPs - If the remoteIP is in the list do nothing
|
||||
if (blockedIPs.includes(key)) {
|
||||
return
|
||||
|
||||
} else {
|
||||
// The remoteIP is not listed, lets add it.
|
||||
blockedIPs.push(ipToBlock)
|
||||
// Let the log know we are blocking the IP
|
||||
console.log("Starting to block bad IP")
|
||||
// Run the block, wait for the promise - Requests are still going on
|
||||
cmd(`/var/tools/firewallctl ` + key + " WP-Login Brute Force Blocked Via secuNotify").then(out => {
|
||||
notify("secuNotify Service Alert:\n " + key + " has been blocked for 5 bad wordpress login attempts!");
|
||||
|
||||
// The block has finished - remoteIP no longer has access
|
||||
}).catch(err => {
|
||||
// IF we see an error, give its output
|
||||
console.log('CSF Error: ', err)
|
||||
}).then(out2 => {
|
||||
// Set IPBLOCK to null for a reset and start scanning for new attacks
|
||||
ipToBlock = null;
|
||||
console.log("Attack Stopped, Looking for new attacks....")
|
||||
// Live view of the counts
|
||||
})
|
||||
|
||||
|
||||
if (blockedIPs.length == 0) {
|
||||
console.log("No IPs have been blocked yet.")
|
||||
} else {
|
||||
console.log("Blocked IP List (Since Service start): " + blockedIPs)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
listenAuthLog("/var/log/auth.log")
|
||||
|
||||
fs.exists("/var/log/apache2/access.log", function (isExist) {
|
||||
if (isExist) {
|
||||
wpTail = new Tail("/var/log/apache2/access.log");
|
||||
listenWPLog("/var/log/apache2/access.log")
|
||||
} else {
|
||||
console.log("ApacheHTTP Server is not installed, not enabling WP protection.");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
20
install/secu/make/node_modules/.package-lock.json
generated
vendored
Normal file
20
install/secu/make/node_modules/.package-lock.json
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "make",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"node_modules/cmd-promise": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/cmd-promise/-/cmd-promise-1.2.0.tgz",
|
||||
"integrity": "sha1-PPUTIiAZi1HBbakt44ag03Q9u1w="
|
||||
},
|
||||
"node_modules/tail": {
|
||||
"version": "2.2.4",
|
||||
"resolved": "https://registry.npmjs.org/tail/-/tail-2.2.4.tgz",
|
||||
"integrity": "sha512-PX8klSxW1u3SdgDrDeewh5GNE+hkJ4h02JvHfV6YrHqWOVJ88nUdSQqtsUf/gWhgZlPAws3fiZ+F1f8euspcuQ==",
|
||||
"engines": {
|
||||
"node": ">= 6.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
6
install/secu/make/node_modules/cmd-promise/.npmignore
generated
vendored
Normal file
6
install/secu/make/node_modules/cmd-promise/.npmignore
generated
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
node_modules/
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
Desktop.ini
|
||||
$RECYCLE.BIN/
|
164
install/secu/make/node_modules/cmd-promise/README.md
generated
vendored
Normal file
164
install/secu/make/node_modules/cmd-promise/README.md
generated
vendored
Normal file
@ -0,0 +1,164 @@
|
||||
|
||||
# CMD Promise
|
||||
|
||||
Node command line interface with a simple Promise based API.
|
||||
|
||||
[](http://standardjs.com/)
|
||||
[](https://www.npmjs.com/package/cmd-promise)
|
||||
[](https://www.npmjs.com/package/cmd-promise)
|
||||
|
||||
Inspired by [node-cmd](https://github.com/RIAEvangelist/node-cmd).
|
||||
|
||||
## Features
|
||||
|
||||
- Simple Promise based API.
|
||||
- Single or multiple commands in one call.
|
||||
- Passes the [`exec()`](https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback) node options through.
|
||||
- Returns an `object` containing both `stdout` and `stderr`.
|
||||
- Optionally return the [child process](https://nodejs.org/api/child_process.html#child_process_class_childprocess) instead of the output.
|
||||
- Zero dependencies.
|
||||
|
||||
## Requirments
|
||||
|
||||
Uses native node promises (including `Promise.all` with generic iterables) so requires at least node version 4.0.0. See [http://node.green/](http://node.green/#ES2015-built-ins-Promise).
|
||||
|
||||
## Install
|
||||
|
||||
`npm install cmd-promise`
|
||||
|
||||
## Examples
|
||||
|
||||
### Single command
|
||||
|
||||
```js
|
||||
const cmd = require('cmd-promise')
|
||||
|
||||
cmd(`node -v`).then(out => {
|
||||
console.log('out =', out)
|
||||
}).catch(err => {
|
||||
console.log('err =', err)
|
||||
})
|
||||
|
||||
// out = { stdout: 'v4.2.2\r\n', stderr: '' }
|
||||
```
|
||||
|
||||
### Multiple commands
|
||||
|
||||
```js
|
||||
const cmd = require('cmd-promise')
|
||||
|
||||
const commands = `
|
||||
node -v
|
||||
npm -v
|
||||
`
|
||||
|
||||
cmd(commands).then(out => {
|
||||
console.log('out =', out)
|
||||
}).catch(err => {
|
||||
console.log('err =', err)
|
||||
})
|
||||
|
||||
// out = [ { stdout: 'v4.2.2\r\n', stderr: '' }, { stdout: '4.4.1\n', stderr: '' } ]
|
||||
// out[0].stdout = v4.2.2
|
||||
```
|
||||
|
||||
### More involved example
|
||||
|
||||
```js
|
||||
const semver = require('semver') // https://github.com/npm/node-semver
|
||||
const cmd = require('cmd-promise')
|
||||
|
||||
const commands = `
|
||||
npm view npm version
|
||||
npm -v
|
||||
`
|
||||
|
||||
cmd(commands).then(out => {
|
||||
return {
|
||||
npm: out[0].stdout.replace(/\n/g, ''),
|
||||
me: out[1].stdout.replace(/\n/g, '')
|
||||
}
|
||||
}).then(versions => {
|
||||
if (semver.lt(versions.me, versions.npm)) {
|
||||
console.log(`My npm version is out of date (npm install npm@latest -g).`)
|
||||
} else {
|
||||
console.log(`My npm version is up to date! :-)`)
|
||||
}
|
||||
}).catch(err => {
|
||||
console.log('err =', err)
|
||||
})
|
||||
```
|
||||
|
||||
### Return the child process instead
|
||||
|
||||
```js
|
||||
const cmd = require('../cmd-promise')
|
||||
|
||||
const options = { returnProcess: true }
|
||||
|
||||
cmd(`node -v`, options).then(childProcess => {
|
||||
console.log('pid =', childProcess.pid)
|
||||
childProcess.stdout.on('data', stdout => {
|
||||
console.log('stdout =', stdout)
|
||||
})
|
||||
childProcess.stderr.on('data', stderr => {
|
||||
console.log('stderr =', stderr)
|
||||
})
|
||||
}).catch(err => {
|
||||
console.log('err =', err)
|
||||
})
|
||||
```
|
||||
|
||||
### Pass exec() options
|
||||
|
||||
Pass [`child_process.exec()`](https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback) options as defined in the node docs.
|
||||
|
||||
```js
|
||||
const cmd = require('../cmd-promise')
|
||||
|
||||
const execOptions = { timeout: 1000 }
|
||||
|
||||
cmd(`node -v`, {}, execOptions).then(out => {
|
||||
console.log('out =', out)
|
||||
}).catch(err => {
|
||||
console.log('err =', err)
|
||||
})
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
`cmd(commands [,options] [,execOptions]) -> Promise`
|
||||
|
||||
- **commands** (string) Single or multiple line string of commands to execute.
|
||||
- **options** (object)
|
||||
- `returnProcess` (boolean) Return the child process instead of waiting on and returning the outcome. Default is `false`.
|
||||
- **execOptions** (object) Options as passed to the [`exec()`](https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback) method of the [child_process](https://nodejs.org/api/child_process.html) node module.
|
||||
|
||||
Returns a Promise.
|
||||
|
||||
For **single** commands the promises return value is an `object` containing `stdout` and `stderr` properties. If `options.returnProcess` is set to `true` the return value is the [child process](https://nodejs.org/api/child_process.html#child_process_class_childprocess) instead.
|
||||
|
||||
```js
|
||||
const cmd = require('cmd-promise')
|
||||
|
||||
cmd(`node -v`).then(out => {
|
||||
console.log('out.stdout =', out.stdout) // v4.2.2
|
||||
console.log('out.stderr =', out.stderr)
|
||||
})
|
||||
```
|
||||
|
||||
For **multiple line** command calls the promises return value is an array of `object`'s containing `stdout` and `stderr` properties. If `options.returnProcess` is set to `true` the return value is an array of [child processes](https://nodejs.org/api/child_process.html#child_process_class_childprocess) instead.
|
||||
|
||||
```js
|
||||
const cmd = require('cmd-promise')
|
||||
|
||||
const commands = `
|
||||
node -v
|
||||
npm -v
|
||||
`
|
||||
|
||||
cmd(commands).then(out => {
|
||||
console.log('out[0] =', out[0]) // result from 'node -v'
|
||||
console.log('out[1] =', out[1]) // result from 'npm -v'
|
||||
})
|
||||
```
|
88
install/secu/make/node_modules/cmd-promise/cmd-promise.js
generated
vendored
Normal file
88
install/secu/make/node_modules/cmd-promise/cmd-promise.js
generated
vendored
Normal file
@ -0,0 +1,88 @@
|
||||
|
||||
const exec = require('child_process').exec
|
||||
|
||||
/**
|
||||
* does the given object have the given property
|
||||
* @param {object} obj object to check.
|
||||
* @param {string} prop property to check for.
|
||||
* @return Boolean
|
||||
*/
|
||||
function hasProp (obj, prop) {
|
||||
return obj.hasOwnProperty(prop)
|
||||
}
|
||||
|
||||
/**
|
||||
* is this a string please sir?
|
||||
* @param {string} str string (or is it?) to check.
|
||||
* @return Boolean
|
||||
*/
|
||||
function isString (str) {
|
||||
return (typeof str === 'string' || str instanceof String)
|
||||
}
|
||||
|
||||
/**
|
||||
* wrapper for child_process.exec()
|
||||
* @param {string} command command line command to run.
|
||||
* @param {object} options cmd-promise options.
|
||||
* @param {object} execOptions exec() options object as outlined in the node docs.
|
||||
* @return Promise
|
||||
*/
|
||||
function runCommand (command, options, execOptions) {
|
||||
// defaults
|
||||
if (!options) { options = {} }
|
||||
if (!execOptions) { execOptions = {} }
|
||||
|
||||
// resolve to the child process?
|
||||
const returnProcess = hasProp(options, 'returnProcess') ? options.returnProcess : false
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
if (returnProcess) {
|
||||
// resolve to the child process, don't wait for the output
|
||||
resolve(exec(command, execOptions))
|
||||
} else {
|
||||
// resolve to the output, using the callback
|
||||
exec(command, execOptions, (error, stdout, stderr) => {
|
||||
if (error) { return reject(error) }
|
||||
resolve({ stdout, stderr })
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* run one or many commands
|
||||
* @param {string} commands command line command(s) string to run.
|
||||
* @param {object} options options object as outlined in the node docs.
|
||||
* @return Promise
|
||||
*/
|
||||
function cmdPromise (commands, options, execOptions) {
|
||||
// make sure the command is a string
|
||||
if (!isString(commands)) {
|
||||
return Promise.reject(new Error('Command not a string.'))
|
||||
}
|
||||
|
||||
// do we have multiple lines?
|
||||
if (commands.indexOf('\n') > -1) {
|
||||
// split by new lines
|
||||
const arrSplit = commands.split(/\n/g)
|
||||
|
||||
// remove empty array elements
|
||||
const arrFiltered = arrSplit.filter(ele => ele.length)
|
||||
|
||||
// trim each array element
|
||||
const arrTrimmed = arrFiltered.map(ele => ele.trim())
|
||||
|
||||
// array of command promises
|
||||
const arrOut = arrTrimmed.map(command => {
|
||||
return runCommand(command, options, execOptions)
|
||||
})
|
||||
|
||||
// multiple lines, return an array of outs
|
||||
return Promise.all(arrOut)
|
||||
} else {
|
||||
// one line, run it
|
||||
return runCommand(commands, options, execOptions)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = cmdPromise
|
21
install/secu/make/node_modules/cmd-promise/package.json
generated
vendored
Normal file
21
install/secu/make/node_modules/cmd-promise/package.json
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "cmd-promise",
|
||||
"version": "1.2.0",
|
||||
"description": "Node command line interface with a simple Promise based API.",
|
||||
"main": "cmd-promise.js",
|
||||
"scripts": {
|
||||
"test": ""
|
||||
},
|
||||
"author": {
|
||||
"name": "Stephen Last",
|
||||
"email": "stephen.last@gmail.com"
|
||||
},
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"semver": "^5.3.0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/stephen-last/cmd-promise.git"
|
||||
}
|
||||
}
|
25
install/secu/make/node_modules/cmd-promise/test/my-npm-version.js
generated
vendored
Normal file
25
install/secu/make/node_modules/cmd-promise/test/my-npm-version.js
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
const semver = require('semver')
|
||||
const cmd = require('../cmd-promise')
|
||||
|
||||
console.log('cmd-promise: More involved example.')
|
||||
|
||||
const commands = `
|
||||
npm view npm version
|
||||
npm -v
|
||||
`
|
||||
|
||||
cmd(commands).then(out => {
|
||||
return {
|
||||
npm: out[0].stdout.replace(/\n/g, ''),
|
||||
me: out[1].stdout.replace(/\n/g, '')
|
||||
}
|
||||
}).then(versions => {
|
||||
if (semver.lt(versions.me, versions.npm)) {
|
||||
console.log(`My npm version is out of date (npm install npm@latest -g).`)
|
||||
} else {
|
||||
console.log(`My npm version is up to date! :-)`)
|
||||
}
|
||||
}).catch(err => {
|
||||
console.log('err =', err)
|
||||
})
|
18
install/secu/make/node_modules/cmd-promise/test/process.js
generated
vendored
Normal file
18
install/secu/make/node_modules/cmd-promise/test/process.js
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
const cmd = require('../cmd-promise')
|
||||
|
||||
console.log('cmd-promise: Return child process instead of output.')
|
||||
|
||||
const options = { returnProcess: true }
|
||||
|
||||
cmd(`node -v`, options).then(childProcess => {
|
||||
console.log('pid =', childProcess.pid)
|
||||
childProcess.stdout.on('data', stdout => {
|
||||
console.log('stdout =', stdout)
|
||||
})
|
||||
childProcess.stderr.on('data', stderr => {
|
||||
console.log('stderr =', stderr)
|
||||
})
|
||||
}).catch(err => {
|
||||
console.log('err =', err)
|
||||
})
|
17
install/secu/make/node_modules/cmd-promise/test/simple.js
generated
vendored
Normal file
17
install/secu/make/node_modules/cmd-promise/test/simple.js
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
const cmd = require('../cmd-promise')
|
||||
|
||||
console.log('cmd-promise: One or multiple commands.')
|
||||
|
||||
// const single = `node -v`
|
||||
|
||||
const multiple = `
|
||||
node -v
|
||||
npm -v
|
||||
`
|
||||
|
||||
cmd(multiple).then(out => {
|
||||
console.log('out =', out)
|
||||
}).catch(err => {
|
||||
console.log('err =', err)
|
||||
})
|
3
install/secu/make/node_modules/tail/.github/FUNDING.yml
generated
vendored
Normal file
3
install/secu/make/node_modules/tail/.github/FUNDING.yml
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: lucagrulla
|
7
install/secu/make/node_modules/tail/.github/dependabot.yml
generated
vendored
Normal file
7
install/secu/make/node_modules/tail/.github/dependabot.yml
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: npm
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: monthly
|
||||
open-pull-requests-limit: 10
|
67
install/secu/make/node_modules/tail/.github/workflows/codeql-analysis.yml
generated
vendored
Normal file
67
install/secu/make/node_modules/tail/.github/workflows/codeql-analysis.yml
generated
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ master ]
|
||||
schedule:
|
||||
- cron: '16 13 * * 3'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'javascript' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
|
||||
# Learn more:
|
||||
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v1
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
|
||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||
# and modify them (or add more) to build your code if your project
|
||||
# uses a compiled language
|
||||
|
||||
#- run: |
|
||||
# make bootstrap
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
21
install/secu/make/node_modules/tail/LICENSE
generated
vendored
Normal file
21
install/secu/make/node_modules/tail/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2011 2012 2013 Forward
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
122
install/secu/make/node_modules/tail/README.md
generated
vendored
Normal file
122
install/secu/make/node_modules/tail/README.md
generated
vendored
Normal file
@ -0,0 +1,122 @@
|
||||
# Tail
|
||||
|
||||
The **zero** dependency Node.js module for tailing a file
|
||||
|
||||
[](https://nodei.co/npm/tail.png?downloads=true&downloadRank=true)
|
||||
|
||||
[](https://github.com/lucagrulla/node-tail/blob/master/LICENSE)
|
||||
[](https://www.npmjs.com/package/tail)
|
||||

|
||||
|
||||
Made with ❤️ by [Luca Grulla](https://www.lucagrulla.com)
|
||||
|
||||
1. TOC
|
||||
{:toc}
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install tail
|
||||
```
|
||||
|
||||
## Use
|
||||
|
||||
```javascript
|
||||
Tail = require('tail').Tail;
|
||||
|
||||
tail = new Tail("fileToTail");
|
||||
|
||||
tail.on("line", function(data) {
|
||||
console.log(data);
|
||||
});
|
||||
|
||||
tail.on("error", function(error) {
|
||||
console.log('ERROR: ', error);
|
||||
});
|
||||
```
|
||||
|
||||
If you want to stop tail:
|
||||
|
||||
```javascript
|
||||
tail.unwatch()
|
||||
```
|
||||
|
||||
To start watching again:
|
||||
|
||||
```javascript
|
||||
tail.watch()
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
The only mandatory parameter is the path to the file to tail.
|
||||
|
||||
```javascript
|
||||
var fileToTail = "/path/to/fileToTail.txt";
|
||||
new Tail(fileToTail)
|
||||
```
|
||||
|
||||
If the file is **missing or invalid** ```Tail``` constructor will throw an Exception and won't initialize.
|
||||
|
||||
```javascript
|
||||
try {
|
||||
new Tail('missingFile.txt')
|
||||
} catch (ex) {
|
||||
console.log(ex)
|
||||
}
|
||||
```
|
||||
|
||||
Optional parameters can be passed via a hash:
|
||||
|
||||
```javascript
|
||||
var options= {separator: /[\r]{0,1}\n/, fromBeginning: false, fsWatchOptions: {}, follow: true, logger: console}
|
||||
new Tail(fileToTail, options)
|
||||
```
|
||||
|
||||
### Constructor parameters
|
||||
|
||||
* `separator`: the line separator token (default: `/[\r]{0,1}\n/` to handle linux/mac (9+)/windows). Pass `null` for is binary files with no line separator.
|
||||
* `fsWatchOptions`: the full set of options that can be passed to `fs.watch` as per node documentation (default: {}).
|
||||
* `fromBeginning`: tail from the beginning of the file (default: `false`). If `fromBeginning` is true `nLines` will be ignored.
|
||||
* `follow`: simulate `tail -F` option. In the case the file is moved/renamed/logrotated, if set to `true` will start tailing again after a 1 second delay; if set to `false` it will emit an error event (default: `true`).
|
||||
* `logger`: a logger object(default: no logger). The passed logger should follow the folliwing signature:
|
||||
* `info([data][, ...])`
|
||||
* `error([data][, ...])`
|
||||
* `nLines`: tail from the last n lines. (default: `undefined`). Ignored if `fromBeginning` is set to `true`.
|
||||
* `useWatchFile`: if set to `true` will force the use of `fs.watchFile` over delegating to the library the choice between `fs.watch` and `fs.watchFile` (default: `false`).
|
||||
* `encoding`: the file encoding (default:`utf-8`).
|
||||
* `flushAtEOF`: set to `true` to force flush of content when end of file is reached. Useful when there's no separator character at the end of the file (default: `false`).
|
||||
|
||||
## Emitted events
|
||||
|
||||
`Tail` emits two events:
|
||||
|
||||
* line
|
||||
|
||||
```javascript
|
||||
tail.on('line', (data) => {
|
||||
console.log(data)
|
||||
})
|
||||
```
|
||||
|
||||
* error
|
||||
|
||||
```javascript
|
||||
tail.on('error', (err) => {
|
||||
console.log(err)
|
||||
})
|
||||
```
|
||||
The error emitted is either the underline exception or a descriptive string.
|
||||
|
||||
## How to contribute
|
||||
Node Tail code repo is [here](https://github.com/lucagrulla/node-tail/)
|
||||
Tail is written in ES6. Pull Requests are welcome.
|
||||
|
||||
## History
|
||||
|
||||
Tail was born as part of a data firehose. Read more about that project [here](https://www.lucagrulla.com/posts/building-a-firehose-with-nodejs/).
|
||||
Tail originally was written in [CoffeeScript](https://coffeescript.org/). Since December 2020 it's pure ES6.
|
||||
|
||||
## License
|
||||
|
||||
MIT. Please see [License](https://github.com/lucagrulla/node-tail/blob/master/LICENSE) file for more details.
|
233
install/secu/make/node_modules/tail/lib/tail.js
generated
vendored
Normal file
233
install/secu/make/node_modules/tail/lib/tail.js
generated
vendored
Normal file
@ -0,0 +1,233 @@
|
||||
let events = require(`events`)
|
||||
let fs = require('fs')
|
||||
let path = require('path')
|
||||
|
||||
// const environment = process.env['NODE_ENV'] || 'development'
|
||||
|
||||
class devNull {
|
||||
info() { };
|
||||
error() { };
|
||||
};
|
||||
|
||||
class Tail extends events.EventEmitter {
|
||||
|
||||
constructor(filename, options = {}) {
|
||||
super();
|
||||
this.filename = filename;
|
||||
this.absPath = path.dirname(this.filename);
|
||||
this.separator = (options.separator !== undefined) ? options.separator : /[\r]{0,1}\n/;// null is a valid param
|
||||
this.fsWatchOptions = options.fsWatchOptions || {};
|
||||
this.follow = options['follow'] != undefined ? options['follow'] : true;
|
||||
this.logger = options.logger || new devNull();
|
||||
this.useWatchFile = options.useWatchFile || false;
|
||||
this.flushAtEOF = options.flushAtEOF || false;
|
||||
this.encoding = options.encoding || 'utf-8';
|
||||
const fromBeginning = options.fromBeginning || false;
|
||||
this.nLines = options.nLines || undefined;
|
||||
|
||||
this.logger.info(`Tail starting...`)
|
||||
this.logger.info(`filename: ${this.filename}`);
|
||||
this.logger.info(`encoding: ${this.encoding}`);
|
||||
|
||||
try {
|
||||
fs.accessSync(this.filename, fs.constants.F_OK);
|
||||
} catch (err) {
|
||||
if (err.code == 'ENOENT') {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
this.buffer = '';
|
||||
this.internalDispatcher = new events.EventEmitter();
|
||||
this.queue = [];
|
||||
this.isWatching = false;
|
||||
this.pos = 0;
|
||||
|
||||
// this.internalDispatcher.on('next',this.readBlock);
|
||||
this.internalDispatcher.on('next', () => {
|
||||
this.readBlock();
|
||||
});
|
||||
|
||||
this.logger.info(`fromBeginning: ${fromBeginning}`);
|
||||
let startingCursor;
|
||||
if (fromBeginning) {
|
||||
startingCursor = 0;
|
||||
} else if (this.nLines !== undefined) {
|
||||
const data = fs.readFileSync(this.filename, {
|
||||
flag: 'r',
|
||||
encoding: this.encoding
|
||||
});
|
||||
const tokens = data.split(this.separator);
|
||||
const dropLastToken = (tokens[tokens.length - 1] === '') ? 1 : 0;//if the file ends with empty line ignore line NL
|
||||
if (tokens.length - this.nLines - dropLastToken <= 0) {
|
||||
//nLines is bigger than avaiable tokens: tail from the begin
|
||||
startingCursor = 0;
|
||||
} else {
|
||||
const match = data.match(new RegExp(`(?:[^\r\n]*[\r]{0,1}\n){${tokens.length - this.nLines - dropLastToken}}`));
|
||||
startingCursor = (match && match.length) ? Buffer.byteLength(match[0], this.encoding) : this.latestPosition();
|
||||
}
|
||||
} else {
|
||||
startingCursor = this.latestPosition();
|
||||
}
|
||||
if (startingCursor === undefined) throw new Error("Tail can't initialize.");
|
||||
const flush = fromBeginning || (this.nLines != undefined);
|
||||
try {
|
||||
this.watch(startingCursor, flush);
|
||||
} catch (err) {
|
||||
this.logger.error(`watch for ${this.filename} failed: ${err}`);
|
||||
this.emit("error", `watch for ${this.filename} failed: ${err}`);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
latestPosition() {
|
||||
try {
|
||||
return fs.statSync(this.filename).size;
|
||||
} catch (err) {
|
||||
this.logger.error(`size check for ${this.filename} failed: ${err}`);
|
||||
this.emit("error", `size check for ${this.filename} failed: ${err}`);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
readBlock() {
|
||||
if (this.queue.length >= 1) {
|
||||
const block = this.queue[0];
|
||||
if (block.end > block.start) {
|
||||
let stream = fs.createReadStream(this.filename, { start: block.start, end: block.end - 1, encoding: this.encoding });
|
||||
stream.on('error', (error) => {
|
||||
this.logger.error(`Tail error: ${error}`);
|
||||
this.emit('error', error);
|
||||
});
|
||||
stream.on('end', () => {
|
||||
let _ = this.queue.shift();
|
||||
if (this.queue.length > 0) {
|
||||
this.internalDispatcher.emit('next');
|
||||
}
|
||||
if (this.flushAtEOF && this.buffer.length > 0) {
|
||||
this.emit('line', this.buffer);
|
||||
this.buffer = "";
|
||||
}
|
||||
});
|
||||
stream.on('data', (d) => {
|
||||
if (this.separator === null) {
|
||||
this.emit("line", d);
|
||||
} else {
|
||||
this.buffer += d;
|
||||
let parts = this.buffer.split(this.separator);
|
||||
this.buffer = parts.pop();
|
||||
for (const chunk of parts) {
|
||||
this.emit("line", chunk);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
change() {
|
||||
let p = this.latestPosition()
|
||||
if (p < this.currentCursorPos) {//scenario where text is not appended but it's actually a w+
|
||||
this.currentCursorPos = p
|
||||
} else if (p > this.currentCursorPos) {
|
||||
this.queue.push({ start: this.currentCursorPos, end: p });
|
||||
this.currentCursorPos = p
|
||||
if (this.queue.length == 1) {
|
||||
this.internalDispatcher.emit("next");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
watch(startingCursor, flush) {
|
||||
if (this.isWatching) return;
|
||||
this.logger.info(`filesystem.watch present? ${fs.watch != undefined}`);
|
||||
this.logger.info(`useWatchFile: ${this.useWatchFile}`);
|
||||
|
||||
this.isWatching = true;
|
||||
this.currentCursorPos = startingCursor;
|
||||
//force a file flush is either fromBegining or nLines flags were passed.
|
||||
if (flush) this.change();
|
||||
|
||||
if (!this.useWatchFile && fs.watch) {
|
||||
this.logger.info(`watch strategy: watch`);
|
||||
this.watcher = fs.watch(this.filename, this.fsWatchOptions, (e, filename) => { this.watchEvent(e, filename); });
|
||||
} else {
|
||||
this.logger.info(`watch strategy: watchFile`);
|
||||
fs.watchFile(this.filename, this.fsWatchOptions, (curr, prev) => { this.watchFileEvent(curr, prev) });
|
||||
}
|
||||
}
|
||||
|
||||
rename(filename) {
|
||||
//TODO
|
||||
//MacOS sometimes throws a rename event for no reason.
|
||||
//Different platforms might behave differently.
|
||||
//see https://nodejs.org/api/fs.html#fs_fs_watch_filename_options_listener
|
||||
//filename might not be present.
|
||||
//https://nodejs.org/api/fs.html#fs_filename_argument
|
||||
//Better solution would be check inode but it will require a timeout and
|
||||
// a sync file read.
|
||||
if (filename === undefined || filename !== this.filename) {
|
||||
this.unwatch();
|
||||
if (this.follow) {
|
||||
this.filename = path.join(this.absPath, filename);
|
||||
this.rewatchId = setTimeout((() => {
|
||||
try {
|
||||
this.watch(this.currentCursorPos);
|
||||
} catch (ex) {
|
||||
this.logger.error(`'rename' event for ${this.filename}. File not available anymore.`);
|
||||
this.emit("error", ex);
|
||||
}
|
||||
}), 1000);
|
||||
} else {
|
||||
this.logger.error(`'rename' event for ${this.filename}. File not available anymore.`);
|
||||
this.emit("error", `'rename' event for ${this.filename}. File not available anymore.`);
|
||||
}
|
||||
} else {
|
||||
// this.logger.info("rename event but same filename")
|
||||
}
|
||||
}
|
||||
|
||||
watchEvent(e, evtFilename) {
|
||||
try {
|
||||
if (e === 'change') {
|
||||
this.change();
|
||||
} else if (e === 'rename') {
|
||||
this.rename(evtFilename);
|
||||
}
|
||||
} catch (err) {
|
||||
this.logger.error(`watchEvent for ${this.filename} failed: ${err}`);
|
||||
this.emit("error", `watchEvent for ${this.filename} failed: ${err}`);
|
||||
}
|
||||
}
|
||||
|
||||
watchFileEvent(curr, prev) {
|
||||
if (curr.size > prev.size) {
|
||||
this.currentCursorPos = curr.size; //Update this.currentCursorPos so that a consumer can determine if entire file has been handled
|
||||
this.queue.push({ start: prev.size, end: curr.size });
|
||||
if (this.queue.length == 1) {
|
||||
this.internalDispatcher.emit("next");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unwatch() {
|
||||
if (this.watcher) {
|
||||
this.watcher.close();
|
||||
} else {
|
||||
fs.unwatchFile(this.filename);
|
||||
}
|
||||
if (this.rewatchId) {
|
||||
clearTimeout(this.rewatchId);
|
||||
this.rewatchId = undefined;
|
||||
}
|
||||
this.isWatching = false;
|
||||
this.queue = [];// TODO: is this correct behaviour?
|
||||
if (this.logger) {
|
||||
this.logger.info(`Unwatch ${this.filename}`);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
exports.Tail = Tail
|
40
install/secu/make/node_modules/tail/package.json
generated
vendored
Normal file
40
install/secu/make/node_modules/tail/package.json
generated
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
{
|
||||
"author": {
|
||||
"name": "Luca Grulla",
|
||||
"url": "https://www.lucagrulla.com"
|
||||
},
|
||||
"contributors": [
|
||||
"Luca Grulla",
|
||||
"Tom Hall"
|
||||
],
|
||||
"name": "tail",
|
||||
"description": "tail a file in node",
|
||||
"keywords": [
|
||||
"tail",
|
||||
"file",
|
||||
"logs"
|
||||
],
|
||||
"version": "2.2.4",
|
||||
"homepage": "https://www.lucagrulla.com/node-tail",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/lucagrulla/node-tail.git"
|
||||
},
|
||||
"main": "lib/tail",
|
||||
"engines": {
|
||||
"node": ">= 6.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "rm -f ./lib/** && cp src/tail.js ./lib/",
|
||||
"prepare": "npm run build",
|
||||
"prepublishOnly": "npm run test",
|
||||
"test": "mocha",
|
||||
"coverage": "nyc npm run test"
|
||||
},
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"chai": "4.x",
|
||||
"mocha": "9.x",
|
||||
"nyc": "^15.1.0"
|
||||
}
|
||||
}
|
38
install/secu/make/package-lock.json
generated
Normal file
38
install/secu/make/package-lock.json
generated
Normal file
@ -0,0 +1,38 @@
|
||||
{
|
||||
"name": "make",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
"cmd-promise": "^1.2.0",
|
||||
"tail": "^2.2.4"
|
||||
}
|
||||
},
|
||||
"node_modules/cmd-promise": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/cmd-promise/-/cmd-promise-1.2.0.tgz",
|
||||
"integrity": "sha1-PPUTIiAZi1HBbakt44ag03Q9u1w="
|
||||
},
|
||||
"node_modules/tail": {
|
||||
"version": "2.2.4",
|
||||
"resolved": "https://registry.npmjs.org/tail/-/tail-2.2.4.tgz",
|
||||
"integrity": "sha512-PX8klSxW1u3SdgDrDeewh5GNE+hkJ4h02JvHfV6YrHqWOVJ88nUdSQqtsUf/gWhgZlPAws3fiZ+F1f8euspcuQ==",
|
||||
"engines": {
|
||||
"node": ">= 6.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"cmd-promise": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/cmd-promise/-/cmd-promise-1.2.0.tgz",
|
||||
"integrity": "sha1-PPUTIiAZi1HBbakt44ag03Q9u1w="
|
||||
},
|
||||
"tail": {
|
||||
"version": "2.2.4",
|
||||
"resolved": "https://registry.npmjs.org/tail/-/tail-2.2.4.tgz",
|
||||
"integrity": "sha512-PX8klSxW1u3SdgDrDeewh5GNE+hkJ4h02JvHfV6YrHqWOVJ88nUdSQqtsUf/gWhgZlPAws3fiZ+F1f8euspcuQ=="
|
||||
}
|
||||
}
|
||||
}
|
6
install/secu/make/package.json
Normal file
6
install/secu/make/package.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"cmd-promise": "^1.2.0",
|
||||
"tail": "^2.2.4"
|
||||
}
|
||||
}
|
173
install/secu/make/v1.1.js
Normal file
173
install/secu/make/v1.1.js
Normal file
@ -0,0 +1,173 @@
|
||||
// Lets use some libs to help us out.
|
||||
const fs = require('fs')
|
||||
Tail = require('tail').Tail;
|
||||
|
||||
sshTail = new Tail("/var/log/auth.log");
|
||||
wpTail = new Tail("/var/log/apache2/access.log");
|
||||
const cmd = require('cmd-promise')
|
||||
|
||||
// Setting up our main storage logic - for now this program does not use a database system.
|
||||
let serverStatusCount = 0;
|
||||
let attackData = []
|
||||
let blockedIPs = []
|
||||
let ipToBlock
|
||||
|
||||
console.log("Welcome to the security notification system secuNotify by Discord-Linux!");
|
||||
console.log("We currently will notify you about login events, such as failed logins and successful logins.");
|
||||
|
||||
// Setting up our notification function - This allows us to direct message our user.
|
||||
function notify(message) {
|
||||
const { spawn } = require('child_process');
|
||||
const notif = spawn('notif', [message]);
|
||||
|
||||
notif.stdout.on('data', (data) => {
|
||||
console.log(`stdout: ${data}`);
|
||||
});
|
||||
|
||||
notif.stderr.on('data', (data) => {
|
||||
console.error(`stderr: ${data}`);
|
||||
});
|
||||
|
||||
notif.on('close', (code) => {
|
||||
console.log(`Code: ${code} - Continuing to monitor`);
|
||||
});
|
||||
}
|
||||
|
||||
function listenAuthLog(logLocation) {
|
||||
sshTail.on("line", function (info) {
|
||||
let infoString = info.toString();
|
||||
|
||||
if (infoString.includes("Failed password for root")) {
|
||||
console.log(info);
|
||||
notify("secuNotify Service Alert: \n" + info);
|
||||
}
|
||||
|
||||
if (infoString.includes("Accepted password for")) {
|
||||
console.log(info);
|
||||
notify("secuNotify Service Alert: \n" + info + "This does mean that someone (Maybe you) has logged in successfully!");
|
||||
}
|
||||
if (infoString.includes("Invalid user")) {
|
||||
console.log(info);
|
||||
notify("secuNotify Service Alert: \n" + info + "This means that someone (Maybe you) has tried to login with an invalid username!");
|
||||
}
|
||||
})
|
||||
|
||||
;
|
||||
}
|
||||
|
||||
function listenWPLog(logLocation) {
|
||||
// Check to see if we are a wordpress user, if so, activate the wordpress notification service
|
||||
const wpLog = '/var/www/html/wp-config.php'
|
||||
try {
|
||||
if (fs.existsSync(wpLog)) {
|
||||
console.log("We are a wordpress user, activating wordpress notification service");
|
||||
|
||||
// Tail Logs section, if we have a lot, it will have a listeniner below.
|
||||
wpTail.on("line", function (info) {
|
||||
|
||||
// Convert Data to String
|
||||
let requestInfo = info.toString()
|
||||
// FIND IP Address from this request
|
||||
var ipRegEx = /\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/; // RegEx IPAddress Format
|
||||
var ipRegExMatched = requestInfo.match(ipRegEx); // Set up our match
|
||||
let remoteIP = ipRegExMatched[0] // Set our var
|
||||
|
||||
// // Grab the whitelist
|
||||
// let whitelistData = process.env.WHITELIST
|
||||
// let whitelist = whitelistData.split(",")
|
||||
|
||||
// // If an IP is found to be in the whitelist, return as to do nothing.
|
||||
// for (const [key, value] of Object.entries(whitelist)) {
|
||||
// if (value === remoteIP) return
|
||||
// }
|
||||
|
||||
// Filtering out any server-status requests - These are annoying.
|
||||
if (requestInfo.includes("server-status")) {
|
||||
// Add to the server status count so we may keep track of these requests.
|
||||
serverStatusCount++
|
||||
// Lets return the data as no not proceed with any further code, as it is not needed.
|
||||
// We return to stdout here to update the cli without adding a new line line a clock
|
||||
return process.stdout.write("Server Status Count: " + serverStatusCount + "\r");
|
||||
}
|
||||
|
||||
// If request contans wp-login lets process its request
|
||||
if (requestInfo.includes("wp-login.php")) {
|
||||
// Lets start the process of logging attack attempts to determine request intent.
|
||||
// Over the threshhold here will automatically CSF D the IP Address.
|
||||
// In this simple version, we will just log each IP Address as they come in within an array
|
||||
// We will then roll and count this array after each detection to determine the IPs intent.
|
||||
console.log("---------\nWP LOGIN REQUEST DETECTED!\n---------")
|
||||
console.log(info + "\n----------");
|
||||
attackData.push(remoteIP)
|
||||
|
||||
// Lets count the attack data per IP Address to ensure its logged properly.
|
||||
var counts = {};
|
||||
|
||||
// For each IP Address recorded into the main attackData array, count them and see outmany bad requests they have made.
|
||||
attackData.forEach(function (x) {
|
||||
// Add a point for each entry
|
||||
counts[x] = (counts[x] || 0) + 1;
|
||||
//
|
||||
for ([key, value] of Object.entries(counts)) {
|
||||
// If the count has hit the blockON Count we start the blocking process
|
||||
|
||||
if (counts[x] == 5) {
|
||||
// Preserve the key for later blocklist addition
|
||||
ipToBlock = key
|
||||
|
||||
// Check the already blocked IPs - If the remoteIP is in the list do nothing
|
||||
if (blockedIPs.includes(key)) {
|
||||
return
|
||||
|
||||
} else {
|
||||
// The remoteIP is not listed, lets add it.
|
||||
blockedIPs.push(ipToBlock)
|
||||
// Let the log know we are blocking the IP
|
||||
console.log("Starting to block bad IP")
|
||||
// Run the block, wait for the promise - Requests are still going on
|
||||
cmd(`/var/tools/firewallctl 123.123.123.123 ` + key + " WP-Login Brute Force Blocked Via secuNotify").then(out => {
|
||||
notify("secuNotify Service Alert: \n " + key + " has been blocked for 5 bad wordpress login attempts!");
|
||||
|
||||
// The block has finished - remoteIP no longer has access
|
||||
}).catch(err => {
|
||||
// IF we see an error, give its output
|
||||
console.log('CSF Error: ', err)
|
||||
}).then(out2 => {
|
||||
// Set IPBLOCK to null for a reset and start scanning for new attacks
|
||||
ipToBlock = null;
|
||||
console.log("Attack Stopped, Looking for new attacks....")
|
||||
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// Live view of the counts
|
||||
console.log(counts)
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
listenAuthLog("/var/log/auth.log")
|
||||
|
||||
const fs = require('fs')
|
||||
|
||||
const path = '/var/log/apache2/access.log'
|
||||
|
||||
try {
|
||||
if (fs.existsSync(path)) {
|
||||
listenWPLog("/var/log/apache2/access.log")
|
||||
}
|
||||
} catch(err) {
|
||||
console.log("I could not find any WP instaltion within the /var/www/html directory\nNOT loading the WP Log listener")
|
||||
}
|
||||
|
161
install/secu/make/v1.js
Normal file
161
install/secu/make/v1.js
Normal file
@ -0,0 +1,161 @@
|
||||
// Lets use some libs to help us out.
|
||||
const fs = require('fs')
|
||||
Tail = require('tail').Tail;
|
||||
|
||||
sshTail = new Tail("/var/log/auth.log");
|
||||
wpTail = new Tail("/var/log/apache2/access.log");
|
||||
const cmd = require('cmd-promise')
|
||||
|
||||
// Setting up our main storage logic - for now this program does not use a database system.
|
||||
let serverStatusCount = 0;
|
||||
let attackData = []
|
||||
let blockedIPs = []
|
||||
let ipToBlock
|
||||
|
||||
console.log("Welcome to the security notification system secuNotify by Discord-Linux!");
|
||||
console.log("We currently will notify you about login events, such as failed logins and successful logins.");
|
||||
|
||||
// Setting up our notification function - This allows us to direct message our user.
|
||||
function notify(message) {
|
||||
const { spawn } = require('child_process');
|
||||
const notif = spawn('notif', [message]);
|
||||
|
||||
notif.stdout.on('data', (data) => {
|
||||
console.log(`stdout: ${data}`);
|
||||
});
|
||||
|
||||
notif.stderr.on('data', (data) => {
|
||||
console.error(`stderr: ${data}`);
|
||||
});
|
||||
|
||||
notif.on('close', (code) => {
|
||||
console.log(`Code: ${code} - Continuing to monitor`);
|
||||
});
|
||||
}
|
||||
|
||||
function listenAuthLog(logLocation) {
|
||||
sshTail.on("line", function (info) {
|
||||
let infoString = info.toString();
|
||||
|
||||
if (infoString.includes("Failed password for root")) {
|
||||
console.log(info);
|
||||
notify("secuNotify Service Alert: \n" + info);
|
||||
}
|
||||
|
||||
if (infoString.includes("Accepted password for")) {
|
||||
console.log(info);
|
||||
notify("secuNotify Service Alert: \n" + info + "This does mean that someone (Maybe you) has logged in successfully!");
|
||||
}
|
||||
if (infoString.includes("Invalid user")) {
|
||||
console.log(info);
|
||||
notify("secuNotify Service Alert: \n" + info + "This means that someone (Maybe you) has tried to login with an invalid username!");
|
||||
}
|
||||
})
|
||||
|
||||
;
|
||||
}
|
||||
|
||||
function listenWPLog(logLocation) {
|
||||
// Check to see if we are a wordpress user, if so, activate the wordpress notification service
|
||||
const wpLog = '/var/www/html/wp-config.php'
|
||||
try {
|
||||
if (fs.existsSync(wpLog)) {
|
||||
console.log("We are a wordpress user, activating wordpress notification service");
|
||||
|
||||
// Tail Logs section, if we have a lot, it will have a listeniner below.
|
||||
wpTail.on("line", function (info) {
|
||||
|
||||
// Convert Data to String
|
||||
let requestInfo = info.toString()
|
||||
// FIND IP Address from this request
|
||||
var ipRegEx = /\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/; // RegEx IPAddress Format
|
||||
var ipRegExMatched = requestInfo.match(ipRegEx); // Set up our match
|
||||
let remoteIP = ipRegExMatched[0] // Set our var
|
||||
|
||||
// // Grab the whitelist
|
||||
// let whitelistData = process.env.WHITELIST
|
||||
// let whitelist = whitelistData.split(",")
|
||||
|
||||
// // If an IP is found to be in the whitelist, return as to do nothing.
|
||||
// for (const [key, value] of Object.entries(whitelist)) {
|
||||
// if (value === remoteIP) return
|
||||
// }
|
||||
|
||||
// Filtering out any server-status requests - These are annoying.
|
||||
if (requestInfo.includes("server-status")) {
|
||||
// Add to the server status count so we may keep track of these requests.
|
||||
serverStatusCount++
|
||||
// Lets return the data as no not proceed with any further code, as it is not needed.
|
||||
// We return to stdout here to update the cli without adding a new line line a clock
|
||||
return process.stdout.write("Server Status Count: " + serverStatusCount + "\r");
|
||||
}
|
||||
|
||||
// If request contans wp-login lets process its request
|
||||
if (requestInfo.includes("wp-login.php")) {
|
||||
// Lets start the process of logging attack attempts to determine request intent.
|
||||
// Over the threshhold here will automatically CSF D the IP Address.
|
||||
// In this simple version, we will just log each IP Address as they come in within an array
|
||||
// We will then roll and count this array after each detection to determine the IPs intent.
|
||||
console.log("---------\nWP LOGIN REQUEST DETECTED!\n---------")
|
||||
console.log(info + "\n----------");
|
||||
attackData.push(remoteIP)
|
||||
|
||||
// Lets count the attack data per IP Address to ensure its logged properly.
|
||||
var counts = {};
|
||||
|
||||
// For each IP Address recorded into the main attackData array, count them and see outmany bad requests they have made.
|
||||
attackData.forEach(function (x) {
|
||||
// Add a point for each entry
|
||||
counts[x] = (counts[x] || 0) + 1;
|
||||
//
|
||||
for ([key, value] of Object.entries(counts)) {
|
||||
// If the count has hit the blockON Count we start the blocking process
|
||||
|
||||
if (counts[x] == 5) {
|
||||
// Preserve the key for later blocklist addition
|
||||
ipToBlock = key
|
||||
|
||||
// Check the already blocked IPs - If the remoteIP is in the list do nothing
|
||||
if (blockedIPs.includes(key)) {
|
||||
return
|
||||
|
||||
} else {
|
||||
// The remoteIP is not listed, lets add it.
|
||||
blockedIPs.push(ipToBlock)
|
||||
// Let the log know we are blocking the IP
|
||||
console.log("Starting to block bad IP")
|
||||
// Run the block, wait for the promise - Requests are still going on
|
||||
cmd(`/var/tools/firewallctl 123.123.123.123 ` + key + " WP-Login Brute Force Blocked Via secuNotify").then(out => {
|
||||
notify("secuNotify Service Alert: \n " + key + " has been blocked for 5 bad wordpress login attempts!");
|
||||
|
||||
// The block has finished - remoteIP no longer has access
|
||||
}).catch(err => {
|
||||
// IF we see an error, give its output
|
||||
console.log('CSF Error: ', err)
|
||||
}).then(out2 => {
|
||||
// Set IPBLOCK to null for a reset and start scanning for new attacks
|
||||
ipToBlock = null;
|
||||
console.log("Attack Stopped, Looking for new attacks....")
|
||||
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// Live view of the counts
|
||||
console.log(counts)
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
listenAuthLog("/var/log/auth.log")
|
||||
listenWPLog("/var/log/apache2/access.log")
|
BIN
install/secu/make/vs
Executable file
BIN
install/secu/make/vs
Executable file
Binary file not shown.
172
install/secu/make/vs.js
Normal file
172
install/secu/make/vs.js
Normal file
@ -0,0 +1,172 @@
|
||||
// Lets use some libs to help us out.
|
||||
const fs = require('fs')
|
||||
Tail = require('tail').Tail;
|
||||
|
||||
sshTail = new Tail("/var/log/auth.log");
|
||||
const cmd = require('cmd-promise')
|
||||
|
||||
// Setting up our main storage logic - for now this program does not use a database system.
|
||||
let serverStatusCount = 0;
|
||||
let attackData = []
|
||||
let blockedIPs = []
|
||||
let ipToBlock
|
||||
|
||||
console.log("Welcome to the security notification system secuNotify by Discord-Linux!");
|
||||
console.log("We currently will notify you about login events, such as failed logins and successful logins.");
|
||||
|
||||
// Setting up our notification function - This allows us to direct message our user.
|
||||
function notify(message) {
|
||||
const { spawn } = require('child_process');
|
||||
const notif = spawn('notif', [message]);
|
||||
|
||||
notif.stdout.on('data', (data) => {
|
||||
console.log(`stdout: ${data}`);
|
||||
});
|
||||
|
||||
notif.stderr.on('data', (data) => {
|
||||
console.error(`stderr: ${data}`);
|
||||
});
|
||||
|
||||
notif.on('close', (code) => {
|
||||
console.log(`Code: ${code} - Continuing to monitor`);
|
||||
});
|
||||
}
|
||||
|
||||
function listenAuthLog(logLocation) {
|
||||
sshTail.on("line", function (info) {
|
||||
let infoString = info.toString();
|
||||
|
||||
if (infoString.includes("Failed password for root")) {
|
||||
console.log(info);
|
||||
notify("secuNotify Service Alert: \n" + info);
|
||||
}
|
||||
|
||||
if (infoString.includes("Accepted password for")) {
|
||||
console.log(info);
|
||||
notify("secuNotify Service Alert: \n" + info + "This does mean that someone (Maybe you) has logged in successfully!");
|
||||
}
|
||||
if (infoString.includes("Invalid user")) {
|
||||
console.log(info);
|
||||
notify("secuNotify Service Alert: \n" + info + "This means that someone (Maybe you) has tried to login with an invalid username!");
|
||||
}
|
||||
})
|
||||
|
||||
;
|
||||
}
|
||||
|
||||
function listenWPLog(logLocation) {
|
||||
// Check to see if we are a wordpress user, if so, activate the wordpress notification service
|
||||
try {
|
||||
if (fs.existsSync("/var/www/html/wp-config.php")) {
|
||||
console.log("We are a wordpress user, activating wordpress notification service");
|
||||
|
||||
// Tail Logs section, if we have a lot, it will have a listeniner below.
|
||||
wpTail.on("line", function (info) {
|
||||
|
||||
// Convert Data to String
|
||||
let requestInfo = info.toString()
|
||||
// FIND IP Address from this request
|
||||
var ipRegEx = /\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/; // RegEx IPAddress Format
|
||||
var ipRegExMatched = requestInfo.match(ipRegEx); // Set up our match
|
||||
let remoteIP = ipRegExMatched[0] // Set our var
|
||||
|
||||
// // Grab the whitelist
|
||||
// let whitelistData = process.env.WHITELIST
|
||||
// let whitelist = whitelistData.split(",")
|
||||
|
||||
// // If an IP is found to be in the whitelist, return as to do nothing.
|
||||
// for (const [key, value] of Object.entries(whitelist)) {
|
||||
// if (value === remoteIP) return
|
||||
// }
|
||||
|
||||
// Filtering out any server-status requests - These are annoying.
|
||||
if (requestInfo.includes("server-status")) {
|
||||
// Add to the server status count so we may keep track of these requests.
|
||||
serverStatusCount++
|
||||
// Lets return the data as no not proceed with any further code, as it is not needed.
|
||||
// We return to stdout here to update the cli without adding a new line line a clock
|
||||
return process.stdout.write("Server Status Count: " + serverStatusCount + "\r");
|
||||
}
|
||||
|
||||
// If request contans wp-login lets process its request
|
||||
if (requestInfo.includes("wp-login.php") && requestInfo.includes("POST")) {
|
||||
// Lets start the process of logging attack attempts to determine request intent.
|
||||
// Over the threshhold here will automatically CSF D the IP Address.
|
||||
// In this simple version, we will just log each IP Address as they come in within an array
|
||||
// We will then roll and count this array after each detection to determine the IPs intent.
|
||||
console.log("---------\nWP LOGIN REQUEST DETECTED!\n---------")
|
||||
console.log(info + "\n----------");
|
||||
attackData.push(remoteIP)
|
||||
|
||||
// Lets count the attack data per IP Address to ensure its logged properly.
|
||||
var counts = {};
|
||||
|
||||
// For each IP Address recorded into the main attackData array, count them and see outmany bad requests they have made.
|
||||
attackData.forEach(function (x) {
|
||||
// Add a point for each entry
|
||||
counts[x] = (counts[x] || 0) + 1;
|
||||
//
|
||||
for ([key, value] of Object.entries(counts)) {
|
||||
// If the count has hit the blockON Count we start the blocking process
|
||||
|
||||
if (counts[x] == 5) {
|
||||
// Preserve the key for later blocklist addition
|
||||
ipToBlock = key
|
||||
|
||||
// Check the already blocked IPs - If the remoteIP is in the list do nothing
|
||||
if (blockedIPs.includes(key)) {
|
||||
return
|
||||
|
||||
} else {
|
||||
// The remoteIP is not listed, lets add it.
|
||||
blockedIPs.push(ipToBlock)
|
||||
// Let the log know we are blocking the IP
|
||||
console.log("Starting to block bad IP")
|
||||
// Run the block, wait for the promise - Requests are still going on
|
||||
cmd(`/var/tools/firewallctl ` + key + " WP-Login Brute Force Blocked Via secuNotify").then(out => {
|
||||
notify("secuNotify Service Alert:\n " + key + " has been blocked for 5 bad wordpress login attempts!");
|
||||
|
||||
// The block has finished - remoteIP no longer has access
|
||||
}).catch(err => {
|
||||
// IF we see an error, give its output
|
||||
console.log('CSF Error: ', err)
|
||||
}).then(out2 => {
|
||||
// Set IPBLOCK to null for a reset and start scanning for new attacks
|
||||
ipToBlock = null;
|
||||
console.log("Attack Stopped, Looking for new attacks....")
|
||||
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// Live view of the counts
|
||||
console.log(counts)
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
listenAuthLog("/var/log/auth.log")
|
||||
|
||||
fs.exists("/var/log/apache2/access.log", function (isExist) {
|
||||
if (isExist) {
|
||||
wpTail = new Tail("/var/log/apache2/access.log");
|
||||
listenWPLog("/var/log/apache2/access.log")
|
||||
} else {
|
||||
console.log("ApacheHTTP Server is not installed, not enabling WP protection.");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
172
install/secu/make/vs_.js
Normal file
172
install/secu/make/vs_.js
Normal file
@ -0,0 +1,172 @@
|
||||
// Lets use some libs to help us out.
|
||||
const fs = require('fs')
|
||||
Tail = require('tail').Tail;
|
||||
|
||||
sshTail = new Tail("/var/log/auth.log");
|
||||
const cmd = require('cmd-promise')
|
||||
|
||||
// Setting up our main storage logic - for now this program does not use a database system.
|
||||
let serverStatusCount = 0;
|
||||
let attackData = []
|
||||
let blockedIPs = []
|
||||
let ipToBlock
|
||||
|
||||
console.log("Welcome to the security notification system secuNotify by Discord-Linux!");
|
||||
console.log("We currently will notify you about login events, such as failed logins and successful logins.");
|
||||
|
||||
// Setting up our notification function - This allows us to direct message our user.
|
||||
function notify(message) {
|
||||
const { spawn } = require('child_process');
|
||||
const notif = spawn('notif', [message]);
|
||||
|
||||
notif.stdout.on('data', (data) => {
|
||||
console.log(`stdout: ${data}`);
|
||||
});
|
||||
|
||||
notif.stderr.on('data', (data) => {
|
||||
console.error(`stderr: ${data}`);
|
||||
});
|
||||
|
||||
notif.on('close', (code) => {
|
||||
console.log(`Code: ${code} - Continuing to monitor`);
|
||||
});
|
||||
}
|
||||
|
||||
function listenAuthLog(logLocation) {
|
||||
sshTail.on("line", function (info) {
|
||||
let infoString = info.toString();
|
||||
|
||||
if (infoString.includes("Failed password for root")) {
|
||||
console.log(info);
|
||||
notify("secuNotify Service Alert: \n" + info);
|
||||
}
|
||||
|
||||
if (infoString.includes("Accepted password for")) {
|
||||
console.log(info);
|
||||
notify("secuNotify Service Alert: \n" + info + "This does mean that someone (Maybe you) has logged in successfully!");
|
||||
}
|
||||
if (infoString.includes("Invalid user")) {
|
||||
console.log(info);
|
||||
notify("secuNotify Service Alert: \n" + info + "This means that someone (Maybe you) has tried to login with an invalid username!");
|
||||
}
|
||||
})
|
||||
|
||||
;
|
||||
}
|
||||
|
||||
function listenWPLog(logLocation) {
|
||||
// Check to see if we are a wordpress user, if so, activate the wordpress notification service
|
||||
try {
|
||||
if (fs.existsSync("/var/www/html/wp-config.php")) {
|
||||
console.log("We are a wordpress user, activating wordpress notification service");
|
||||
|
||||
// Tail Logs section, if we have a lot, it will have a listeniner below.
|
||||
wpTail.on("line", function (info) {
|
||||
|
||||
// Convert Data to String
|
||||
let requestInfo = info.toString()
|
||||
// FIND IP Address from this request
|
||||
var ipRegEx = /\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/; // RegEx IPAddress Format
|
||||
var ipRegExMatched = requestInfo.match(ipRegEx); // Set up our match
|
||||
let remoteIP = ipRegExMatched[0] // Set our var
|
||||
|
||||
// // Grab the whitelist
|
||||
// let whitelistData = process.env.WHITELIST
|
||||
// let whitelist = whitelistData.split(",")
|
||||
|
||||
// // If an IP is found to be in the whitelist, return as to do nothing.
|
||||
// for (const [key, value] of Object.entries(whitelist)) {
|
||||
// if (value === remoteIP) return
|
||||
// }
|
||||
|
||||
// Filtering out any server-status requests - These are annoying.
|
||||
if (requestInfo.includes("server-status")) {
|
||||
// Add to the server status count so we may keep track of these requests.
|
||||
serverStatusCount++
|
||||
// Lets return the data as no not proceed with any further code, as it is not needed.
|
||||
// We return to stdout here to update the cli without adding a new line line a clock
|
||||
return process.stdout.write("Server Status Count: " + serverStatusCount + "\r");
|
||||
}
|
||||
|
||||
// If request contans wp-login lets process its request
|
||||
if (requestInfo.includes("wp-login.php")) {
|
||||
// Lets start the process of logging attack attempts to determine request intent.
|
||||
// Over the threshhold here will automatically CSF D the IP Address.
|
||||
// In this simple version, we will just log each IP Address as they come in within an array
|
||||
// We will then roll and count this array after each detection to determine the IPs intent.
|
||||
console.log("---------\nWP LOGIN REQUEST DETECTED!\n---------")
|
||||
console.log(info + "\n----------");
|
||||
attackData.push(remoteIP)
|
||||
|
||||
// Lets count the attack data per IP Address to ensure its logged properly.
|
||||
var counts = {};
|
||||
|
||||
// For each IP Address recorded into the main attackData array, count them and see outmany bad requests they have made.
|
||||
attackData.forEach(function (x) {
|
||||
// Add a point for each entry
|
||||
counts[x] = (counts[x] || 0) + 1;
|
||||
//
|
||||
for ([key, value] of Object.entries(counts)) {
|
||||
// If the count has hit the blockON Count we start the blocking process
|
||||
|
||||
if (counts[x] == 5) {
|
||||
// Preserve the key for later blocklist addition
|
||||
ipToBlock = key
|
||||
|
||||
// Check the already blocked IPs - If the remoteIP is in the list do nothing
|
||||
if (blockedIPs.includes(key)) {
|
||||
return
|
||||
|
||||
} else {
|
||||
// The remoteIP is not listed, lets add it.
|
||||
blockedIPs.push(ipToBlock)
|
||||
// Let the log know we are blocking the IP
|
||||
console.log("Starting to block bad IP")
|
||||
// Run the block, wait for the promise - Requests are still going on
|
||||
cmd(`/var/tools/firewallctl ` + key + " WP-Login Brute Force Blocked Via secuNotify").then(out => {
|
||||
notify("secuNotify Service Alert:\n " + key + " has been blocked for 5 bad wordpress login attempts!");
|
||||
|
||||
// The block has finished - remoteIP no longer has access
|
||||
}).catch(err => {
|
||||
// IF we see an error, give its output
|
||||
console.log('CSF Error: ', err)
|
||||
}).then(out2 => {
|
||||
// Set IPBLOCK to null for a reset and start scanning for new attacks
|
||||
ipToBlock = null;
|
||||
console.log("Attack Stopped, Looking for new attacks....")
|
||||
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// Live view of the counts
|
||||
console.log(counts)
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
listenAuthLog("/var/log/auth.log")
|
||||
|
||||
fs.exists("/var/log/apache2/access.log", function (isExist) {
|
||||
if (isExist) {
|
||||
wpTail = new Tail("/var/log/apache2/access.log");
|
||||
listenWPLog("/var/log/apache2/access.log")
|
||||
} else {
|
||||
console.log("ApacheHTTP Server is not installed, not enabling WP protection.");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
BIN
install/secu/secuNotify
Executable file
BIN
install/secu/secuNotify
Executable file
Binary file not shown.
15
install/secu/secuNotify.service
Normal file
15
install/secu/secuNotify.service
Normal file
@ -0,0 +1,15 @@
|
||||
[Unit]
|
||||
Description=secunotify service
|
||||
After=network.target
|
||||
StartLimitIntervalSec=0
|
||||
[Service]
|
||||
EnvironmentFile=
|
||||
WorkingDirectory=/var/tools/
|
||||
Type=simple
|
||||
Restart=always
|
||||
RestartSec=1
|
||||
User=root
|
||||
ExecStart=/var/tools/secuNotify
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
BIN
install/secu/secuNotifyold
Executable file
BIN
install/secu/secuNotifyold
Executable file
Binary file not shown.
26
install/startfiles/base
Normal file
26
install/startfiles/base
Normal file
@ -0,0 +1,26 @@
|
||||
#!/bin/sh
|
||||
export CID=$(basename $(cat /proc/1/cpuset))
|
||||
service ssh start
|
||||
sh /var/tools/getsystemctl.sh
|
||||
|
||||
#DISCORD-LINUX AUTOINSTALLER
|
||||
#DONOTREMOVE
|
||||
#webmin
|
||||
#osjs
|
||||
#wp
|
||||
#ENDDONOTREMOVE
|
||||
|
||||
#ADD ANY SERVICES YOU NEED TO BOOT ON START UP BELOW
|
||||
#DO NOT ADD ANY LINES BELOW THE TAIL -F /DEV/NULL
|
||||
#DOING SO WILL BREAK YOUR CONTAINER.
|
||||
|
||||
#CUSTOM SERVICES START
|
||||
|
||||
|
||||
|
||||
|
||||
#CUSTOM SERVICES END
|
||||
|
||||
#DONOTREMOVEEVER
|
||||
tail -f /dev/null
|
||||
#DONOTPUTANYTHINGBELOWTHISLINEEVER
|
15
install/startfiles/dlinux-service.service
Normal file
15
install/startfiles/dlinux-service.service
Normal file
@ -0,0 +1,15 @@
|
||||
[Unit]
|
||||
Description=dlinux service
|
||||
After=network.target
|
||||
StartLimitIntervalSec=0
|
||||
[Service]
|
||||
EnvironmentFile=
|
||||
WorkingDirectory=/root/.service
|
||||
Type=simple
|
||||
Restart=always
|
||||
RestartSec=1
|
||||
User=root
|
||||
ExecStart=/usr/bin/node /root/.service/dlinux
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
6
install/startfiles/webmin
Normal file
6
install/startfiles/webmin
Normal file
@ -0,0 +1,6 @@
|
||||
#!/bin/sh
|
||||
export CID=$(basename $(cat /proc/1/cpuset))
|
||||
service ssh start
|
||||
sh /var/tools/getsystemctl.sh
|
||||
service webmin start
|
||||
tail -f /dev/null
|
71
install/whoogle/config
Normal file
71
install/whoogle/config
Normal file
@ -0,0 +1,71 @@
|
||||
# ----------------------------------
|
||||
# Rename to "whoogle.env" before use
|
||||
# ----------------------------------
|
||||
# You can set Whoogle environment variables here, but must
|
||||
# modify your deployment to enable these values:
|
||||
# - Local: Set WHOOGLE_DOTENV=1
|
||||
# - docker-compose: Uncomment the env_file option
|
||||
# - docker: Add "--env-file ./whoogle.env" to your build command
|
||||
|
||||
|
||||
|
||||
|
||||
#WHOOGLE_CSP=1
|
||||
#HTTPS_ONLY=1
|
||||
|
||||
# Restrict results to only those near a particular city
|
||||
#WHOOGLE_CONFIG_NEAR=denver
|
||||
|
||||
# See app/static/settings/countries.json for values
|
||||
WHOOGLE_CONFIG_COUNTRY=US
|
||||
|
||||
# See app/static/settings/languages.json for values
|
||||
WHOOGLE_CONFIG_LANGUAGE=lang_en
|
||||
|
||||
# See app/static/settings/languages.json for values
|
||||
WHOOGLE_CONFIG_SEARCH_LANGUAGE=lang_en
|
||||
|
||||
# Disable changing of config from client
|
||||
WHOOGLE_CONFIG_DISABLE=0
|
||||
|
||||
# Block websites from search results (comma-separated list)
|
||||
#WHOOGLE_CONFIG_BLOCK=pinterest.com,whitehouse.gov
|
||||
|
||||
# Theme (light, dark, or system)
|
||||
WHOOGLE_CONFIG_THEME=dark
|
||||
|
||||
# Safe search mode
|
||||
#WHOOGLE_CONFIG_SAFE=1
|
||||
|
||||
# Use social media site alternatives (nitter, bibliogram, etc)
|
||||
#WHOOGLE_CONFIG_ALTS=1
|
||||
|
||||
# Use Tor if available
|
||||
WHOOGLE_CONFIG_TOR=1
|
||||
|
||||
# Open results in new tab
|
||||
#WHOOGLE_CONFIG_NEW_TAB=1
|
||||
|
||||
# Enable View Image option
|
||||
WHOOGLE_CONFIG_VIEW_IMAGE=1
|
||||
|
||||
# Search using GET requests only (exposes query in logs)
|
||||
#WHOOGLE_CONFIG_GET_ONLY=1
|
||||
|
||||
# Remove everything except basic result cards from all search queries
|
||||
#WHOOGLE_MINIMAL=0
|
||||
|
||||
# Set the number of results per page
|
||||
#WHOOGLE_RESULTS_PER_PAGE=10
|
||||
|
||||
# Controls visibility of autocomplete/search suggestions
|
||||
#WHOOGLE_AUTOCOMPLETE=1
|
||||
|
||||
# The port where Whoogle will be exposed
|
||||
EXPOSE_PORT=5000
|
||||
|
||||
# Set instance URL
|
||||
#WHOOGLE_CONFIG_URL=https://<whoogle url>/
|
||||
|
||||
# Set custom CSS styling/theming
|
||||
#WHOOGLE_CONFIG_STYLE=":root { /* LIGHT THEME COLORS */ --whoogle-background: #d8dee9; --whoogle-accent: #2e3440; --whoogle-text: #3B4252; --whoogle-contrast-text: #eceff4; --whoogle-secondary-text: #70757a; --whoogle-result-bg: #fff; --whoogle-result-title: #4c566a; --whoogle-result-url: #81a1c1; --whoogle-result-visited: #a3be8c; /* DARK THEME COLORS */ --whoogle-dark-background: #222; --whoogle-dark-accent: #685e79; --whoogle-dark-text: #fff; --whoogle-dark-contrast-text: #000; --whoogle-dark-secondary-text: #bbb; --whoogle-dark-result-bg: #000; --whoogle-dark-result-title: #1967d2; --whoogle-dark-result-url: #4b11a8; --whoogle-dark-result-visited: #bbbbff; }"
|
9
install/whoogle/whoogleStart.json
Normal file
9
install/whoogle/whoogleStart.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"apps": [
|
||||
{
|
||||
"name": "Whoogle",
|
||||
"script": "bash -c ./run",
|
||||
"args" : ""
|
||||
}
|
||||
]
|
||||
}
|
Reference in New Issue
Block a user