From d102b513e2ae01ffc462e103e9ebd5168ac55d35 Mon Sep 17 00:00:00 2001 From: Tomasz Kapias Date: Tue, 7 Feb 2023 16:10:46 +0700 Subject: [PATCH] first commit --- 00-motdfetch | 121 ++++++++++++++++++++ docs/img/preview.jpg | Bin 0 -> 118866 bytes install.sh | 157 ++++++++++++++++++++++++++ motdfetch.d/00-header | 81 ++++++++++++++ motdfetch.d/01-sysinfo | 149 +++++++++++++++++++++++++ motdfetch.d/02-services | 143 ++++++++++++++++++++++++ motdfetch.d/03-filesystem | 227 ++++++++++++++++++++++++++++++++++++++ motdfetch.d/04-tls | 119 ++++++++++++++++++++ motdfetch.d/05-postqueue | 74 +++++++++++++ motdfetch.d/06-fail2ban | 77 +++++++++++++ motdfetch.d/99-userslog | 77 +++++++++++++ motdfetch.sample.conf | 70 ++++++++++++ readme.md | 112 +++++++++++++++++++ 13 files changed, 1407 insertions(+) create mode 100755 00-motdfetch create mode 100644 docs/img/preview.jpg create mode 100755 install.sh create mode 100644 motdfetch.d/00-header create mode 100644 motdfetch.d/01-sysinfo create mode 100644 motdfetch.d/02-services create mode 100644 motdfetch.d/03-filesystem create mode 100644 motdfetch.d/04-tls create mode 100644 motdfetch.d/05-postqueue create mode 100644 motdfetch.d/06-fail2ban create mode 100644 motdfetch.d/99-userslog create mode 100644 motdfetch.sample.conf create mode 100644 readme.md diff --git a/00-motdfetch b/00-motdfetch new file mode 100755 index 0000000..768f98f --- /dev/null +++ b/00-motdfetch @@ -0,0 +1,121 @@ +#!/usr/bin/env bash +# +# MOTDfetch is a modular and dynamic MOTD replacement +# and a very nice command line information tool for Debian/Ubuntu systems. +# +# repository: https://git.tkapias.net/tkapias/MOTDfetch +# author: Tomasz Kapias +# email: tomasz@tkapias.net +# +# modules path: ./motdfetch.d/ +# config paths: $HOME/.config/motdfetch/motdfetch.conf +# /etc/motdfetch/motdfetch.conf +# +# requirements (modules apart): sudo apt install coreutils bc + +# locale env +unset LC_ALL +export LC_MESSAGES=C + +# GLOBAL COLORS ###################################################### + +c_txt="39" +c_txt_emphase="35" +c_txt_deco="97" +c_txt_invert="30" +c_bg="47" +c_danger="31" +c_warning="33" +c_success="32" +c_title="${c_bg};1;${c_txt_invert}m" + +# RUN OPTIONS ####################################################### + +# MODTfetch directory path +SCRIPT_DIR=$(dirname "$(realpath "$0")") + +Help() +{ + echo -e "\e[1;${c_txt_emphase}mMOTDfetch\e[1;${c_txt}m is a modular and dynamic MOTD replacement and a very" + echo -e "nice command line information tool for Debian/Ubuntu systems.\e[0m" + echo + echo "Syntax: bash $SCRIPT_DIR/00-motdfetch [-h] [-f] [-t ARG] [-l]" + echo + echo "options: -h Print this Help" + echo " -f force execution under heavy load" + echo " -t execute a standalone module with internal sample conf" + echo " -l list available modules files names" +} + +unset option_force_load + +# command options and arguments +while getopts "hft:l" option; do + case $option in + h) Help + exit ;; + f) option_force_load=1;; + t) # standalone module option + if [[ -f "$SCRIPT_DIR/motdfetch.d/$OPTARG" ]]; then + (. "$SCRIPT_DIR/motdfetch.d/$OPTARG") + exit 0 + else + echo -e "\e[1;${c_danger}mError\e[0m: Invalid module filename, check the -l option.\n" + Help + exit 1 + fi;; + l) # List modules option + for file in $SCRIPT_DIR/motdfetch.d/* + do + echo -e "$(basename $file) $(head -3 $file|tail -1)" + done | column -t -s '#' + exit 0;; + \?) # Invalid option + echo -e "\e[1;${c_danger}mError\e[0m: Invalid option" + Help + exit 1;; + esac +done + +# CONFIG LOADING ################################################### + +userconf="$HOME/.config/motdfetch/motdfetch.conf" +sysconf="/etc/motdfetch/motdfetch.conf" + +if [[ -f "$userconf" ]];then + . "$userconf" +elif [[ -f "$sysconf" ]];then + . "$sysconf" +else + echo -e "\e[1;${c_danger}mError\e[0m: no configuration available.\n" + Help + exit 1 +fi + +# EXECUTION ######################################################### + +## load check +cores=$(/usr/bin/grep -ioPc 'processor\t:' /proc/cpuinfo 2>/dev/null) +if [[ "$cores" -eq "0" ]]; then + cores=1 +fi +threshold="${cores:-1}.5" + +echo -e "\n\e[${c_title} MOTDFETCH \e[0m\n" +if [[ $(echo "`cut -f1 -d ' ' /proc/loadavg` < $threshold" | /usr/bin/bc) -eq 1 || $option_force_load -eq 1 ]]; then + ### output modules + for file in $SCRIPT_DIR/motdfetch.d/* + do + (. "$file") + done + echo +else + ### too much load for modules, run only 00 & 99 + msg + module_header_disable=0 + (. $SCRIPT_DIR/motdfetch.d/00-*) + module_userslog_disable=0 + (. $SCRIPT_DIR/motdfetch.d/99-*) + echo -e "\n\e[${c_title} WE SKIPPED SOME MODULES \e[0m\n" + echo -e " MOTDfetch skipped some modules because of\n this \e[1;${c_danger}msystem load\e[0m being higher than \e[1;${c_danger}m$threshold\e[0;${c_warning}m.\e[0m\n" + echo -e " \e[1;${c_txt}mBAD ADVICE\e[0m: you can force execution with the option [-f]:\n # bash $SCRIPT_DIR/00-motdfetch -f\n" +fi diff --git a/docs/img/preview.jpg b/docs/img/preview.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b0202a63dbe2c20ac1a3c89b467477d8d89357ec GIT binary patch literal 118866 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

Chk5%nqmyDQO^?1Rx8L2Pgqv0Vn{*09Sw|zy{y~ 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/dev/null) + if [[ $resultsshno == "" ]]; then + echo -e "${E}FAIL - check manually \"PrintMotd no\" & \"PrintLastLog no\"${N}\n" + ((ERRORCOUNT++)) + else + echo -e "$resultsshno" | /usr/bin/grep --color=auto "no" + echo -e "${S}DONE${N}\n" + fi + echo -e "${T}# setup ssh server (/etc/ssh/sshd_config) to accept custom SSH_MOTD env variable${N}" + sed -ri '/SSH_MOTD/! s/^(\#?)(AcceptEnv)(.+)/\2\3 SSH_MOTD/' /etc/ssh/sshd_config + resultsshmotd=$(/usr/bin/grep -E "^AcceptEnv.+SSH_MOTD" /etc/ssh/sshd_config 2>/dev/null) + if [[ $resultsshmotd == "" ]]; then + echo -e "${E}FAIL - check manually \"AcceptEnv SSH_MOTD\"${N}\n" + ((ERRORCOUNT++)) + else + echo -e "$resultsshmotd" | /usr/bin/grep --color=auto "SSH_MOTD" + echo -e "${S}DONE${N}\n" + fi +else + echo -e "${E}/etc/ssh/sshd_config DOES NOT EXIST${N}\n" + ((ERRORCOUNT++)) +fi + +echo -e "${T}# setup PAM's sshd (/etc/pam.d/sshd) to not print MOTD and MAIL${N}" +if [[ -f "/etc/pam.d/sshd" ]]; then + sed -ri 's/^(\#?)(session[[:space:]]+optional[[:space:]]+)(pam_motd.so|pam_mail.so)(.+)/#\2\3\4/' /etc/pam.d/sshd + resultpamcom=$(/usr/bin/grep -E "^\#.+pam_motd.so|^\#.+pam_mail.so" /etc/pam.d/sshd 2>/dev/null) + if [[ $resultpamcom == "" ]]; then + echo -e "${E}FAIL - comment manually lines with \"pam_motd.so\" & \"pam_mail.so\"${N}\n" + ((ERRORCOUNT++)) + else + echo -e "$resultpamcom" | /usr/bin/grep --color=auto -E "^\#" + echo -e "${S}DONE${N}\n" + fi +else + echo -e "${E}FAIL - /etc/pam.d/sshd DOES NOT EXIST${N}\n" + ((ERRORCOUNT++)) +fi + +echo -e "${T}# restart ssh server if it's active${N}" +if [[ $(systemctl is-active ssh 2>/dev/null) == "active" ]]; then + systemctl restart ssh.service + echo -e "${S}DONE${N}\n" +else + echo -e "${E}SSHD NOT ACTIVE${N}\n" +fi + +echo -e "${T}# install minimal dependencies${N}" +apt install -f figlet coreutils bc wget nano dnsutils openssl s-nail +echo + +echo -e "${T}# install ANSI_Shadow figlet font${N}" +downloadfigletfont=$(wget -nv -O "/usr/share/figlet/ANSI Shadow.flf" https://raw.githubusercontent.com/xero/figlet-fonts/master/ANSI%20Shadow.flf) +if $downloadfigletfont ; then + echo -e "${S}DONE${N}\n" +else + echo -e "${E}FAIL${N}\n" + ((ERRORCOUNT++)) +fi + +echo -e "${T}# check directories & backup old & obsolete files${N}" +if [[ ! -d "/etc/update-motd.d/backup" ]]; then + mkdir -vp /etc/update-motd.d/backup +fi +if [[ ! -d "/etc/motdfetch" ]]; then + mkdir -vp /etc/motdfetch +fi +chmod -v 755 /etc/update-motd.d/ /etc/update-motd.d/backup/ 2>/dev/null +echo -e "${S}CHMOD DONE${N}\n" +if [[ -d "/etc/update-motd.d/motdfetch.d" ]]; then + cp -p -Rv /etc/update-motd.d/*motdfetch* /etc/update-motd.d/backup/ 2>/dev/null + echo -e "${S}MOTDfetch BACKUP DONE${N}" +fi +if [[ -d "/etc/motd" ]]; then + mkdir -vp /etc/update-motd.d/backup/etc + mv -vf /etc/motd /etc/update-motd.d/backup/etc/motd 2>/dev/null + echo -e "${S}Static MOTD BACKUP DONE${N}" +fi +if [[ -d "/etc/update-motd.d/10-uname" ]]; then + mv -vf /etc/update-motd.d/10-uname /etc/update-motd.d/backup/10-uname 2>/dev/null + echo -e "${S}Debian uname MOTD BACKUP DONE${N}" +fi +echo + +echo -e "${T}# install/update MOTDfetch${N}" +downloadmotd=$(wget -c -nv https://git.tkapias.net/tkapias/MOTDfetch/archive/master.tar.gz -O - \ + | tar -xz --strip-components=1 -C /etc/update-motd.d/ MOTDfetch-master/motdfetch.d/ MOTDfetch-master/00-motdfetch MOTDfetch-master/motdfetch.sample.conf 2>/dev/null) +if $downloadmotd ; then + mv -vf /etc/update-motd.d/motdfetch.sample.conf /etc/motdfetch/motdfetch.sample.conf + if [[ -f "/etc/motdfetch/motdfetch.conf" ]]; then + echo -e "${S}SUCCESSFUL UPDATE${N}\n" + else + cp -p -Rv /etc/motdfetch/motdfetch.sample.conf /etc/motdfetch/motdfetch.conf + echo -e "${S}SUCCESSFUL INSTALLATION${N}\n" + fi + if (( $ERRORCOUNT == 1 )); then + echo -e "${W}But CAUTION, $ERRORCOUNT configuration steps have failed.${N} Please check if you need to adjust manually.\n" + elif (( $ERRORCOUNT > 1 )); then + echo -e "${W}But CAUTION, $ERRORCOUNT configuration step has failed.${N} Please check if you need to adjust manually.\n" + fi + echo -e " - ${S}edit the config file${N}: + # sudo nano /etc/motdfetch/motdfetch.conf + ${S}or create a new user config${N}: + # userdir=~/.config/motdfetch \\ + && mkdir \$userdir \\ + && cp /etc/motdfetch/motdfetch.sample.conf \$userdir/motdfetch.conf \\ + && nano \$userdir/motdfetch.conf\n" + echo -e " - ${S}add an alias \"motd\" command to your .bashrc${N}:\n alias motd='/etc/update-motd.d/00-motdfetch'\n" + echo -e " - ${S}how to use MOTDfetch as an alternative MOTD for SSH sessions${N}: + + ${S}on the ssh server, add the new \"motd\" alias at the end of the ssh user .bashrc${N}: + if [[ -n \$SSH_CONNECTION ]]; then\n motd\n fi + + ${S}on the ssh client, add an alias \"sshmotd\" to your .bashrc${N}:\n alias sshmotd='ssh -o SetEnv=SSH_MOTD=1'\n" +else + echo -e "${E}INSTALLATION FAILED - please retry${N}\n" +fi diff --git a/motdfetch.d/00-header b/motdfetch.d/00-header new file mode 100644 index 0000000..1a1e247 --- /dev/null +++ b/motdfetch.d/00-header @@ -0,0 +1,81 @@ +#!/usr/bin/env bash +# +# display a custom decorative text (default to username) +# + welcome the username + date, time and timezone +# + inform of mail presence for user (if s-nail is installed) +# +# requirements: sudo apt install figlet +# sudo wget --no-check-certificate -O "/usr/share/figlet/ansi-shadow.flf" https://raw.githubusercontent.com/xero/figlet-fonts/master/ANSI%20Shadow.flf +# optionnal: sudo apt install s-nail + +# GENERAL ########################################################### + +# locale env +unset LC_ALL +export LC_MESSAGES=C + +# check if module was disabled +module_disable=${module_header_disable:=0} +if (($module_disable == 1)); then + exit 1 +fi + +# colors +c_txt=${c_txt:="39"} +c_txt_emphase=${c_txt_emphase:="35"} +c_txt_deco=${c_txt_deco:="97"} +c_txt_invert=${c_txt_invert:="30"} +c_bg=${c_bg_sec:="47"} +c_danger=${c_danger:="31"} +c_warning=${c_warning:="33"} +c_success=${c_success:="32"} +c_title=${c_title:="${c_bg};1;${c_txt_invert}m"} + +# OPTIONS ########################################################### + +# banner custom text or username +username=$(/usr/bin/id -un) +header_text=${module_header_text:="$username"} + +# PREPARATIONS ###################################################### + +# check if s-nail is available and if you have mail +if command -v s-nail 1>/dev/null; then + # check mail for user + if /usr/bin/s-nail -e; then + hasmail=$(echo -e " You have \e[1;${c_success}mmessages\e[0m.") + + else + hasmail=$(echo -e " You have no messages.") + fi +else + hasmail="" +fi + +# trim banner text +header_text_width=${#header_text} +figlet_width=$(/usr/bin/env figlet -f "ANSI Shadow" "$header_text" | wc -L) +while [[ $figlet_width -ge 73 ]]; do + let "header_text_width-=1" + header_text=$(echo -e "${header_text:0:$header_text_width}...") + figlet_width=$(/usr/bin/env figlet -f "ANSI Shadow" "$header_text" | wc -L) +done + +# OUTPUT ############################################################ + +if [[ $module_header_text != "$username" ]]; then + /usr/bin/env figlet -f "ANSI Shadow" "$header_text" \ + | sed "$d" \ + | sed "s/^/ /" \ + | echo -e "$(sed "1 s/^/\\\e[${c_txt_emphase}m/")" \ + | echo -e "$(sed "$ s/$/\\\e[0m/")" + echo -e " \e[1;${c_txt}mWelcome \e[${c_txt_emphase}m${username}\e[${c_txt}m, it is \e[${c_txt_emphase}m$(date +"%Y-%m-%d %H:%M:%S %z")\e[${c_txt}m.\e[0m\n${hasmail}" +else + echo -e " Welcome" + /usr/bin/env figlet -f "ANSI Shadow" "$header_text" \ + | sed "$d" \ + | sed "s/^/ /" \ + | echo -e "$(sed "1 s/^/\\\e[${c_txt_emphase}m/")" \ + | echo -e "$(sed "$ s/$/\\\e[0m/")" + echo -e " \e[1;${c_txt}mIt is \e[${c_txt_emphase}m$(date +"%Y-%m-%d %H:%M:%S %z")\e[${c_txt}m.\e[0m\n${hasmail}" +fi diff --git a/motdfetch.d/01-sysinfo b/motdfetch.d/01-sysinfo new file mode 100644 index 0000000..fbe9c51 --- /dev/null +++ b/motdfetch.d/01-sysinfo @@ -0,0 +1,149 @@ +#!/usr/bin/env bash +# +# display a list of system informations +# + dig and curl have shorts timeouts to not hang the script +# +# requirements: sudo apt install dnsutils + +# GENERAL ########################################################### + +# locale env +unset LC_ALL +export LC_MESSAGES=C + +# check if module was disabled +module_disable=${module_sysinfo_disable:=0} +if (($module_disable == 1)); then + exit 1 +fi + +# colors +c_txt=${c_txt:="39"} +c_txt_emphase=${c_txt_emphase:="35"} +c_txt_deco=${c_txt_deco:="97"} +c_txt_invert=${c_txt_invert:="30"} +c_bg=${c_bg_sec:="47"} +c_danger=${c_danger:="31"} +c_warning=${c_warning:="33"} +c_success=${c_success:="32"} +c_title=${c_title:="${c_bg};1;${c_txt_invert}m"} + +# api website name for plain public IP4/6 check +publicip_api=${global_publicip_api:="icanhazip.com"} + +# PREPARATIONS ###################################################### + +# output header +echo -e "\nWaiting for DNS and IP checks\e[5m...\e[0m" + +# get hostname +HOSTNAME=`hostname -f` +# get distribution name +DISTRO=`/usr/bin/cat /etc/*release | /usr/bin/grep "PRETTY_NAME" | cut -d "=" -f 2- | sed 's/"//g'` +# get name of main interface with a route for internet +INTERNETIFACE="$(ip -o route get 8/32 2>/dev/null)" +if [[ "$INTERNETIFACE" ]]; then + INTERNETIFACE=`echo -e "$INTERNETIFACE" | sed -e 's/.*dev //' -e 's/ .*//'` +else + INTERNETIFACE="\e[1;${c_warning}mno interface with a route to 8/32\e[0;${c_txt}m" +fi +# get DNS servers ips from resolv.conf +DNSSERVERS=`/usr/bin/grep '^nameserver' /etc/resolv.conf | cut -d' ' -f2 | paste -sd ','` +if [[ ! $DNSSERVERS ]];then + DNSSERVERS="\e[1;${c_warning}mno ns in resolv.conf\e[0;${c_txt}m" +fi +# get current output public IPs and their revers DNS record +PUBLICIP4=`timeout 6 curl -s -4 $publicip_api 2>/dev/null` +if [[ $PUBLICIP4 ]];then + IP4PTR=`timeout 4 dig +short -x $PUBLICIP4 @1.1.1.1 2>/dev/null` + if [[ ! $IP4PTR ]];then + IP4PTR="\e[0;${c_txt}mno data" + fi + else + IP4PTR="\e[0;${c_txt}mno data" + PUBLICIP4="\e[1;5;${c_warning}mno IPv4 internet\e[0;${c_txt}m" + INTERNET_IP4=0 +fi +PUBLICIP6=`timeout 6 curl -s -6 $publicip_api 2>/dev/null` +if [[ $PUBLICIP6 ]];then + IP6PTR=`timeout 4 dig +short -x $PUBLICIP6 @1.1.1.1 2>/dev/null` + if [[ ! $IP6PTR ]];then + IP6PTR="\e[0;${c_txt}mno data" + fi +else + IP6PTR="\e[0;${c_txt}mno data" + PUBLICIP6="\e[1;${c_warning}mno ipv6 internet\e[0;${c_txt}m" + INTERNET_IP6=0 +fi +INTERNET_OUT=0 +if [[ $INTERNET_IP4 && $INTERNET_IP6 ]]; then + INTERNET_OUT=1 +fi +# get DNS records of the FQDN +HOSTNAMEIP4=`timeout 4 dig +short A $HOSTNAME @1.1.1.1 2>/dev/null` +if [[ ! $HOSTNAMEIP4 ]];then + HOSTNAMEIP4="\e[0;${c_txt}mno data" +fi +HOSTNAMEIP6=`timeout 4 dig +short AAAA $HOSTNAME @1.1.1.1 2>/dev/null` +if [[ ! $HOSTNAMEIP6 ]];then + HOSTNAMEIP6="\e[0;${c_txt}mno data" +fi +# get processes +PROCESS=`/usr/bin/ps -eo user= | sort | uniq -c | awk '{ print $2 " " $1 }'` +PROCESS_ALL=`echo "$PROCESS" | awk {'print $2'} | awk '{ SUM += $1} END { print SUM }'` +PROCESS_ROOT=`echo "$PROCESS" | /usr/bin/grep root | awk {'print $2'}` +PROCESS_USER=`echo "$PROCESS" | /usr/bin/grep -v root | awk {'print $2'} | awk '{ SUM += $1} END { print SUM }'` +# get processors +PROCESSOR_NAME=`/usr/bin/grep "model name" /proc/cpuinfo | cut -d ' ' -f3- | awk {'print $0'} | head -1 | sed -e 's/([^()]*)/ /g' -e 's/\s\+/ /g'` +PROCESSOR_COUNT=`/usr/bin/grep -ioPc 'processor\t:' /proc/cpuinfo 2>/dev/null` +# get load averages +IFS=" " read LOAD1 LOAD5 LOAD15 <<<$(cat /proc/loadavg | awk '{ print $1,$2,$3 }') +if [[ $(echo "$LOAD1 > $(echo "$PROCESSOR_COUNT + ($PROCESSOR_COUNT / 3)" | bc -l )" | bc) == 1 ]]; then + LOAD1="\e[1;5;${c_danger}m$LOAD1\e[0;${c_txt}m" +elif [[ $(echo "$LOAD1 > $(echo "$PROCESSOR_COUNT - ($PROCESSOR_COUNT / 3)" | bc -l )" | bc) == 1 ]]; then + LOAD1="\e[1;5;${c_warning}m$LOAD1\e[0;${c_txt}m" +fi +if [[ $(echo "$LOAD5 > $(echo "$PROCESSOR_COUNT * 2" | bc -l )" | bc) == 1 ]]; then + LOAD2="\e[1;5;${c_warning}m$LOAD5\e[0;${c_txt}m" +fi +if [[ $(echo "$LOAD15 > $(echo "$PROCESSOR_COUNT * 2" | bc -l )" | bc) == 1 ]]; then + LOAD3="\e[1;5;${c_warning}m$LOAD15\e[0;${c_txt}m" +fi +# get free memory +IFS=" " read USED AVAIL TOTAL <<<$(free -htm | /usr/bin/grep "Mem" | awk {'print $3,$7,$2'}) +# get free swap +IFS=" " read SUSED SAVAIL STOTAL <<<$(free -htm | /usr/bin/grep "Swap" | awk {'print $3,$4,$2'}) + +# OUTPUT ############################################################ + +W="\e[0;${c_txt}m" +X="\e[1;${c_txt}m" +G="\e[1;${c_txt_emphase}m" +N="\e[0m" +echo -e "\e[1A\e[${c_title} System information $N + +$X Distro$W..........: $DISTRO +$X Kernel$W..........: `uname -sr` +$X Uptime$W..........: $G`uptime -p`$W + +$X CPU$W.............: $PROCESSOR_NAME +$X CPU cores$W.......: $G$PROCESSOR_COUNT$W +$X Load$W............: $G$LOAD1$W (1m), $G$LOAD5$W (5m), $G$LOAD15$W (15m) +$X Processes$W.......: $G$PROCESS_ROOT$W (root), $G$PROCESS_USER$W (user), $G$PROCESS_ALL$W (total) +$X Memory$W..........: $G$USED$W used, $G$AVAIL$W avail, $G$TOTAL$W total$N" +if [[ ${SUSED} ]]; then + echo -e "$X Swap$W............: $G$SUSED$W used, $G$SAVAIL$W avail, $G$STOTAL$W total$W" +else + echo -e "$X Swap$W............: \e[1;${c_warning}mno Swap$W" +fi +echo -e " +$X Hostname/FQDN$W...: $G$(hostname)$W / $G$(hostname -f)$W +$X Internet Iface$W..: $G$INTERNETIFACE$W +$X DNS servers$W.....: $G$(echo -e "${DNSSERVERS}" | sed "s/,/\\\e[0m, \\\e[1;${c_txt_emphase}m/g")$N" +if [[ ${INTERNET_OUT} == 0 ]]; then + echo -e "$X Public IP4/IP6$W..: $G$PUBLICIP4$W / $G$PUBLICIP6$N" +else + echo -e "$X Public IP4/IP6$W..: \e[1;${c_warning}mno internet or "${publicip_api}" timeout$N" +fi +echo -e "$X PTR IP4/IP6$W.....: $G$IP4PTR$W / $G$IP6PTR$W +$X FQDN A/AAAA$W.....: $G$HOSTNAMEIP4$W / $G$HOSTNAMEIP6$N" \ No newline at end of file diff --git a/motdfetch.d/02-services b/motdfetch.d/02-services new file mode 100644 index 0000000..4d7c6f1 --- /dev/null +++ b/motdfetch.d/02-services @@ -0,0 +1,143 @@ +#!/usr/bin/env bash +# +# check status of a list of systemd service units +# + accept service name with or without extension (.service) +# + default to system wide services but accept --user services with the :uid +# + alarm by bullet coloration and blinking +# +# requirements: systemd + +# GENERAL ########################################################### + +# locale env +unset LC_ALL +export LC_MESSAGES=C + +# check if module was disabled +module_disable=${module_services_disable:=0} +if (($module_disable == 1)); then + exit 1 +fi + +# colors +c_txt=${c_txt:="39"} +c_txt_emphase=${c_txt_emphase:="35"} +c_txt_deco=${c_txt_deco:="97"} +c_txt_invert=${c_txt_invert:="30"} +c_bg=${c_bg_sec:="47"} +c_danger=${c_danger:="31"} +c_warning=${c_warning:="33"} +c_success=${c_success:="32"} +c_title=${c_title:="${c_bg};1;${c_txt_invert}m"} + +# OPTIONS ########################################################### + +# array of services +if [[ $module_services ]]; then + services=(${module_services[@]}) +else + services=("cron.service" "dbus.service:1000" "user2service:1002") +fi +IFS=$'\n' services=($(sort <<<"${services[*]}")) +unset IFS + +# column max-width +width=${module_services_width:="80"} + +# PREPARATIONS ###################################################### + +# get status +# + dim status if the service does not exist or if the user is not root and the service has another uid +serviceStatus=() +for service in "${services[@]}"; do + uid=${service/*:/} + # script executed as root and the service to check is from a user + if [[ $service = *:* ]] && [[ "$(id -u)" == "0" ]]; then + service=${service/.service/} + service=${service/:[0-9]*/} + serviceexist=$(machinectl -q shell --uid="$uid" .host /usr/bin/systemctl list-units --user -q --plain --no-pager --full --all -t service 2>/dev/null \ + | awk '$1 ~ /\.service$/ { sub("\\.service$", "", $1); print $1 }' \ + | /usr/bin/grep "$service") + if [[ "$serviceexist" ]] ;then + status=$(machinectl -q shell --uid="$uid" .host /usr/bin/systemctl is-active --user "$service") + if [[ $status = inactive* ]]; then + serviceStatus+=("inactive") + elif [[ $status = active* ]]; then + serviceStatus+=("active") + else + serviceStatus+=("hidden") + fi + else + serviceStatus+=("hidden") + fi + # script executed by the same user as the service user + elif [[ $service = *:* ]] && [[ "$(id -u)" == "$uid" ]]; then + service=${service/.service/} + service=${service/:[0-9]*/} + serviceexist=$(/usr/bin/systemctl list-units --user -q --plain --no-pager --full --all -t service 2>/dev/null \ + | awk '$1 ~ /\.service$/ { sub("\\.service$", "", $1); print $1 }' \ + | /usr/bin/grep "$service") + if [[ "$serviceexist" ]] ;then + serviceStatus+=($(/usr/bin/systemctl --user is-active "$service")) + else + serviceStatus+=("hidden") + fi + # script executed by another user than root and than the service user + elif [[ $service = *:* ]]; then + serviceStatus+=("hidden") + # system service + else + service=${service/.service/} + service=${service/:[0-9]*/} + serviceexist=$(/usr/bin/systemctl list-units -q --plain --no-pager --full --all -t service 2>/dev/null \ + | awk '$1 ~ /\.service$/ { sub("\\.service$", "", $1); print $1 }' \ + | /usr/bin/grep "$service") + if [[ "$serviceexist" ]] ;then + serviceStatus+=($(/usr/bin/systemctl is-active "$service")) + else + serviceStatus+=("hidden") + fi + fi +done + +# OUTPUT ############################################################ + +# output header +echo -e "\n\e[${c_title} Services checks \e[0m\n" + +# output checklist +line=" " +lineLen=1 +for i in "${!serviceStatus[@]}" +do + service=${services[$i]/.service/} + service=${service^} + + # Next line and next line length + next=" $service " + nextLen=$((1+${#next})) + + # If the current line will exceed the max column with then echo and start a new line + if [[ $((lineLen+nextLen)) -gt $width ]]; then + echo -e "$line" + lineLen=1 + line=" " + fi + + lineLen=$((lineLen+nextLen)) + + # Color the next line green if it's active, red if inactive, else orange + if [[ "${serviceStatus[$i]}" == "active" ]] + then + line+=" \e[${c_success}m●\e[0m \e[${c_txt}m$service\e[0m " + elif [[ "${serviceStatus[$i]}" == "inactive" ]] + then + line+=" \e[1;5;${c_danger}m▲\e[0m \e[1;${c_txt}m$service\e[0m " + else + line+=" \e[1;2;${c_warning}m▲\e[0m \e[1;2;${c_txt}m$service\e[0m " + fi +done + +# echo what is left +echo -e "$line" + diff --git a/motdfetch.d/03-filesystem b/motdfetch.d/03-filesystem new file mode 100644 index 0000000..9214065 --- /dev/null +++ b/motdfetch.d/03-filesystem @@ -0,0 +1,227 @@ +#!/usr/bin/env bash +# +# status of mounted filesystems in 2 steps +# 1. use "df" for general fs except zfs, squashfs, tmpfs, devtmpfs and overlay +# 2. use "zpool" for ZFS pools +# + displays name, filesystem type, used blocks and inodes or pool health when relevant +# + custom warn threshold for blocks +# + warn threshold for inodes (80%), flashing danger threshold for health, blocks (95%) and inodes (90%) +# +# requirements: sudo apt install coreutils +# optionnal: sudo apt install zfsutils-linux + +# GENERAL ########################################################### + +# locale env +unset LC_ALL +export LC_MESSAGES=C + +# check if module was disabled +module_disable=${module_filesystem_disable:=0} +if (($module_disable == 1)); then + exit 1 +fi + +# colors +c_txt=${c_txt:="39"} +c_txt_emphase=${c_txt_emphase:="35"} +c_txt_deco=${c_txt_deco:="97"} +c_txt_invert=${c_txt_invert:="30"} +c_bg=${c_bg_sec:="47"} +c_danger=${c_danger:="31"} +c_warning=${c_warning:="33"} +c_success=${c_success:="32"} +c_title=${c_title:="${c_bg};1;${c_txt_invert}m"} + +# OPTIONS ########################################################### + +# max usage warning threshold +max_usage=${module_filesystem_max_usage:="85"} + +# disable ZFS section +zfs_disable=${module_filesystem_zfs_disable:=0} + +# PREPARATIONS ###################################################### + +# disk usage: ignore zfs, squashfs & tmpfs, standard error output because of a bug with /run/user/1000/doc +dfcmd=$(/usr/bin/df -H -x zfs -x squashfs -x tmpfs -x devtmpfs -x overlay --output 2>/dev/null) +mapfile -t dfoutput < <(echo "$dfcmd" | tail -n+2) + +# determine best width for the bar +largesttarget=$(echo "$dfcmd" | awk '{if (length ($12)>max) max=length($12)} END {print max}') +if [[ $((largesttarget+30)) -gt 50 ]]; then + bar_width=$((largesttarget+30)) +else + bar_width="50" +fi + +# OUTPUT ############################################################ + +# general filesystems +linecounter=0 +if [[ "${dfoutput[@]}" ]]; then + # output header + echo -e "\n\e[${c_title} Filesystem usage \e[0m\n" + # output filesystem status except ZFS + for line in "${dfoutput[@]}"; do + # parse df output + diskid=$(echo "$line" | awk '{print $12}') + diskused=$(echo "$line" | awk '{print $10}'| sed 's/%//') + disktotal=$(echo "$line" | awk '{print $7}') + fsformat=$(echo "$line" | awk '{print $2}') + inodesused=$(echo "$line" | awk '{print $6}'| sed 's/%//') + inodestotal=$(echo "$line" | awk '{print $3}') + + # bar & blocks coloration, danger red above 95% + if [[ "${diskused}" -ge "95" ]]; then + barcolor="\e[1;${c_danger}m" + blockscolor="\e[1;${c_danger}m" + flashing="\e[5m" + elif [ "${diskused}" -ge "${max_usage}" ]; then + barcolor="\e[1;${c_warning}m" + blockscolor="\e[1;${c_warning}m" + flashing="" + else + barcolor="\e[1;${c_success}m" + blockscolor="\e[${c_txt}m" + flashing="" + fi + # print colored bar until used_width + used_width=$(((diskused*$bar_width)/100)) + bar="[${barcolor}" + for ((i=0; i<$used_width; i++)); do + bar+="=" + done + # print dimmmed bar until end + bar+="\e[${c_txt}m\e[0m" + for ((i=$used_width; i<$bar_width; i++)); do + bar+="=" + done + bar+="\e[0m]" + + # print blocks usage line & bar + padding=$((bar_width-28)) + if [[ $linecounter -ge 1 ]] + then + echo -e "\n" + fi + echo "${line}" | printf "\e[1;${c_txt_emphase}m%-${padding}s\e[0m${blockscolor}%+3s%% used ${flashing}blocks\e[0m out of %+4s\n" $diskid $diskused $disktotal | sed 's/^/ /' + echo -e "${bar}" | sed 's/^/ /' + + # print filesystem type & inodes usage line + if [[ ! "$inodesused" == "-" ]] + then + padding=$((bar_width-34)) + # inodes coloration, danger red above 90% + if [[ "${inodesused}" -ge "90" ]]; then + inodescolor="\e[1;${c_danger}m" + flashing="\e[5m" + elif [[ "${inodesused}" -ge "80" ]]; then + inodescolor="\e[1;${c_warning}m" + flashing="" + else + inodescolor="\e[${c_txt}m" + flashing="" + fi + echo "${line}" | printf "Type: %-${padding}s${inodescolor}%+3s%% used ${flashing}inodes\e[0m out of %+4s\n" $fsformat $inodesused $inodestotal | sed 's/^/ /' + else + echo "${line}" | printf "Type: %-10s\n" $fsformat | sed 's/^/ /' + fi + linecounter=$((linecounter+1)) + done +else + echo " no general filesystem available, ZFS expected in next section" +fi + +# check if ZFS section was disabled +if [[ $zfs_disable == 1 ]]; then + exit 1 +fi + +# output ZFS header +echo -e "\n\e[${c_title} Zpool usage \e[0m\n" + +# check if zpool is available +if ! command -v zpool 1> /dev/null; then + echo " no ZFS tools available" + exit 1 +fi + +# ZFS zpool usage & health status +zlistcmd=$(zpool list -o name,cap,size,health 2> /dev/null) +if [[ $zlistcmd == "no pools available" ]]; then + echo " no ZFS pool available" +else + mapfile -t zpools < <(echo "$zlistcmd" | tail -n+2) + + # determine best width for the bar + largesttarget=$(echo "zlistcmd" | awk '{if (length ($1)>max) max=length($1)} END {print max}') + if [[ $((largesttarget+30)) -gt 50 ]]; then + bar_width=$((largesttarget+30)) + else + bar_width="50" + fi + + linecounter=0 + for line in "${zpools[@]}"; do + # parse zpool list output + poolid=$(echo "$line" | awk '{print $1}') + poolused=$(echo "$line" | awk '{print $2}'| sed 's/%//') + pooltotal=$(echo "$line" | awk '{print $3}') + poolhealth=$(echo "$line" | awk '{print $4}') + + # bar & pools coloration, danger red above 95% + if [[ "${poolused}" -ge "95" ]]; then + barcolor="\e[1;${c_danger}m" + poolscolor="\e[1;${c_danger}m" + flashing="\e[5m" + elif [[ "${poolused}" -ge "${max_usage}" ]]; then + barcolor="\e[1;${c_warning}m" + poolscolor="\e[1;${c_warning}m" + flashing="" + else + barcolor="\e[1;${c_success}m" + poolscolor="\e[${c_txt}m" + flashing="" + fi + # print colored bar until used_width + used_width=$(((poolused*$bar_width)/100)) + bar="[${barcolor}" + for ((i=0; i<$used_width; i++)); do + bar+="=" + done + # print dimmmed bar until end + bar+="\e[${c_txt}m\e[0m" + for ((i=$used_width; i<$bar_width; i++)); do + bar+="=" + done + bar+="\e[0m]" + + # print pool usage line & bar + padding=$((bar_width-29)) + if [[ $linecounter -ge 1 ]] + then + echo -e "\n" + fi + echo "${line}" | printf "\e[1;${c_txt_emphase}m%-${padding}s\e[0m${poolscolor}%+3s%% used ${flashing}blocks\e[0m out of %+5s\n" $poolid $poolused $pooltotal | sed 's/^/ /' + echo -e "${bar}" | sed 's/^/ /' + + # print pool health line + padding=$((bar_width-34)) + # health coloration, danger red for FAULTED + if [[ "${poolhealth}" == "FAULTED" ]]; then + healthcolor="\e[1;${c_danger}m" + flashing="\e[5m" + elif [[ "${poolhealth}" == "OFFLINE" ]] || [[ "${poolhealth}" == "UNAVAIL" ]] || [[ "${poolhealth}" == "REMOVED" ]] || [[ "${poolhealth}" == "DEGRADED" ]]; then + healthcolor="\e[1;${c_warning}m" + flashing="" + else + healthcolor="\e[${c_txt}m" + flashing="" + fi + padding=$((bar_width-17)) + text="health" + echo "${line}" | printf "%+${padding}s status: ${healthcolor}${flashing}%+8s\e[0m\n" $text ${poolhealth,,} | sed 's/^/ /' + linecounter=$((linecounter+1)) + done +fi diff --git a/motdfetch.d/04-tls b/motdfetch.d/04-tls new file mode 100644 index 0000000..a08aa7d --- /dev/null +++ b/motdfetch.d/04-tls @@ -0,0 +1,119 @@ +#!/usr/bin/env bash +# +# check X.509 cert for a domain:port with openssl, for correspondance and expiration +# + by default the port is 443 +# + there is a timeout of 6 sec and is there is no connectivity the check is skipped +# +# requirements: sudo apt install openssl + +# GENERAL ########################################################### + +# locale env +unset LC_ALL +export LC_MESSAGES=C + +# check if module was disabled +module_disable=${module_tls_disable:=0} +if (($module_disable == 1)); then + exit 1 +fi + +# colors +c_txt=${c_txt:="39"} +c_txt_emphase=${c_txt_emphase:="35"} +c_txt_deco=${c_txt_deco:="97"} +c_txt_invert=${c_txt_invert:="30"} +c_bg=${c_bg_sec:="47"} +c_danger=${c_danger:="31"} +c_warning=${c_warning:="33"} +c_success=${c_success:="32"} +c_title=${c_title:="${c_bg};1;${c_txt_invert}m"} + +# api website name for plain public IP4/6 check +publicip_api=${global_publicip_api:="icanhazip.com"} + +# OPTIONS ########################################################### + +# domains:ports input +if [[ $module_tls_domains ]] +then + tls_domains=(${module_tls_domains[@]}) +else + tls_domains=("www.google.com" "smtp.gmail.com:465") +fi +IFS=$'\n' tls_domains=($(sort <<<"${tls_domains[*]}")) +unset IFS + +# PREPARATIONS ###################################################### + +# print loading message +echo -e "\nWaiting for TLS checks\e[5m...\e[0m" + +# parse output +output=" \e[1;4;${c_txt}mDomain\e[24m|\e[4mPort\e[24m|\e[4mValid until\e[0m" +currentTime=$(date +%s) + +# check if there is internet connectivity +INTERNET_OUT=0 +PUBLICIP="$(timeout 6 curl -s $publicip_api 2>/dev/null)" +if [[ ! $PUBLICIP ]]; then + INTERNET_OUT=1 +fi + +# OUTPUT ############################################################ + +for domain in "${tls_domains[@]}" +do + if [[ $domain == *:* ]] + then + port=${domain/*:/} + domain=${domain/:*/} + else + port="443" + fi + if [[ $INTERNET_OUT == 0 ]]; then + # fetch cert + cert="" + cert=$(timeout 6 openssl s_client -servername ${domain} -connect ${domain}:${port} < /dev/null 2>/dev/null) + # fetch subject name with a 3 sec timeout + certSubj=$(echo -e "$cert" | openssl x509 -noout -subject 2>/dev/null) + # fetch expiration time + certTime=$(echo -e "$cert" | openssl x509 -noout -enddate 2>/dev/null | cut -d= -f2) + certLineTime=$(date -d "${certTime}" +"%F") + certTimestamp=$(date -d "${certTime}" +%s) + port="\e[${c_txt}m${port}\e[0m" + # check subject name with a 3 sec timeout + if [[ $certSubj == *${domain} ]] + then + domain="\e[${c_txt}m${domain}\e[0m" + # check expiration time - 3 days + if [[ "$((${certTimestamp} - 259200 ))" -ge "${currentTime}" ]] + then + sign="\e[${c_success}m●\e[0m" + result="\e[1;${c_success}m$certLineTime\e[0m" + # check expiration time today + elif [[ "${certTimestamp}" -ge "${currentTime}" ]] + then + sign="\e[1;${c_warning}m▲\e[0m" + result="\e[1;${c_warning}m${certLineTime}\e[0m" + else + sign="\e[1;5;${c_danger}m▲\e[0m" + result="\e[1;${c_danger}m$certLineTime\e[0m" + fi + else + domain="\e[${c_txt}m${domain}\e[0m" + sign="\e[1;2;${c_warning}m\U25B2\e[0m" + result="\e[1;2;${c_warning}mtimeout or misnamed\e[0m" + fi + elif [[ $INTERNET_OUT == 1 ]]; then + domain="\e[${c_txt}m${domain}\e[0m" + sign="\e[1;2;${c_txt}m▲\e[0m" + result="\e[1;2;${c_txt}mno internet, skipped\e[0m" + fi + output+="\n ${sign} ${domain}|${port}|$result" +done + +# output header and table content +echo -e "\e[1A\e[${c_title} TLS checks \e[0m " +echo -e +echo -e "$output" | column -t -s '|' diff --git a/motdfetch.d/05-postqueue b/motdfetch.d/05-postqueue new file mode 100644 index 0000000..45e89d8 --- /dev/null +++ b/motdfetch.d/05-postqueue @@ -0,0 +1,74 @@ +#!/usr/bin/env bash +# +# check if there is some mails in the deferred queue of postfix +# + danger color if >= 100 messages +# + warning color if >= 1 messages +# +# requirements: sudo apt install postfix + +# GENERAL ########################################################### + +# locale env +unset LC_ALL +export LC_MESSAGES=C + +# check if module was disabled +module_disable=${module_postqueue_disable:=0} +if (($module_disable == 1)); then + exit 1 +fi + +# colors +c_txt=${c_txt:="39"} +c_txt_emphase=${c_txt_emphase:="35"} +c_txt_deco=${c_txt_deco:="97"} +c_txt_invert=${c_txt_invert:="30"} +c_bg=${c_bg_sec:="47"} +c_danger=${c_danger:="31"} +c_warning=${c_warning:="33"} +c_success=${c_success:="32"} +c_title=${c_title:="${c_bg};1;${c_txt_invert}m"} + +# PREPARATIONS ###################################################### + +# print loading message +echo -e "\nWaiting for Postqueue checks\e[5m...\e[0m" + +# check if postfix is available, with qshape +if ! command -v qshape 1>/dev/null; then + # output module header + echo -e "\e[1A\e[${c_title} Postfix deferred queue status \e[0m\n" + echo -e " no Postfix server available" + exit 1 +fi + +# parse deferred messages qty with qshape +deferredcmd=$(timeout 5 qshape -b 6 deferred 2>/dev/null) + +# OUTPUT ############################################################ + +# if qshape timeout 5sec +if [[ "$deferredcmd" == "" ]]; then + # output module header + echo -e "\e[1A\e[${c_title} Postfix deferred \e[0m\n" + echo -e " \e[1;${c_warning}mqshape needs more than 5 sec to parse the deferred Mails list,\n you should investigate!\e[0m" + exit 1 +fi + +# if total deferred is 0 +deferredtotal=$(echo -e "$deferredcmd" | grep TOTAL | awk '{print $2}') +if [[ "$deferredtotal" == "0" ]]; then + # output module header + echo -e "\e[1A\e[${c_title} Postfix deferred queue status \e[0m\n" + echo -e " There is \e[1;${c_success}m${deferredtotal}\e[0m deferred Mails." + exit 1 +fi + +# else print qshape output +# output module header +echo -e "\e[1A\e[${c_title} Postfix deferred queue status \e[0m\n" +if [[ "$deferredtotal" -gt 100 ]]; then + echo -e " There is \e[1;${c_danger}m${deferredtotal}\e[0m deferred Mails in queue." +else + echo -e " There is \e[1;${c_warning}m${deferredtotal}\e[0m deferred Mails in queue." +fi diff --git a/motdfetch.d/06-fail2ban b/motdfetch.d/06-fail2ban new file mode 100644 index 0000000..682b1aa --- /dev/null +++ b/motdfetch.d/06-fail2ban @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +# +# parse Fail2ban jail status, display failed and banned counts +# + Warning if currently more than 0 +# + Danger if currently more than 20 +# +# /!\ need root to display status, display warning for other user +# +# requirements: sudo apt install fail2ban + +# GENERAL ########################################################### + +# locale env +unset LC_ALL +export LC_MESSAGES=C + +# check if module was disabled +module_disable=${module_fail2ban_disable:=0} +if (($module_disable == 1)); then + exit 1 +fi + +# colors +c_txt=${c_txt:="39"} +c_txt_emphase=${c_txt_emphase:="35"} +c_txt_deco=${c_txt_deco:="97"} +c_txt_invert=${c_txt_invert:="30"} +c_bg=${c_bg_sec:="47"} +c_danger=${c_danger:="31"} +c_warning=${c_warning:="33"} +c_success=${c_success:="32"} +c_title=${c_title:="${c_bg};1;${c_txt_invert}m"} + +# PREPARATIONS ###################################################### + +# check if fail2ban is available +if ! command -v fail2ban-client 1>/dev/null; then + # output module header + echo -e "\n\e[${c_title} Fail2Ban status \e[0m\n" + echo -e " no Fail2Ban server available" + exit 1 +elif [[ ! `id -un` == "root" ]]; then + echo -e "\n\e[${c_title} Fail2Ban status \e[0m\n" + echo -e " you must be root to get Fail2Ban status" + exit 1 +fi + +# OUTPUT ############################################################ + +echo -e "\n\e[${c_title} Fail2Ban status \e[0m\n" + +# fail2ban-client status to get all jails, takes about ~70ms +jails=($(fail2ban-client status | grep "Jail list:" | sed "s/ //g" | awk '{split($2,a,",");for(i in a) print a[i]}')) + +out="\e[1;4;${c_txt}mJail name\e[24m,\e[4mFailed\e[24m,\e[4mTotal\e[24m,\e[4mBanned\e[24m,\e[4mTotal\e[24m\n" + +for jail in ${jails[@]}; do + # slow because fail2ban-client has to be called for every jail (~70ms per jail) + status=$(fail2ban-client status ${jail}) + failed=$(echo "$status" | grep -ioP '(?<=Currently failed:\t)[[:digit:]]+') + if [[ $failed -ge 20 ]]; then + failed="\e[1;5;${c_danger}m${failed}\e[0m" + elif [[ $failed -ge 1 ]]; then + failed="\e[1;${c_warning}m${failed}\e[0m" + fi + totalfailed=$(echo "$status" | grep -ioP '(?<=Total failed:\t)[[:digit:]]+') + banned=$(echo "$status" | grep -ioP '(?<=Currently banned:\t)[[:digit:]]+') + if [[ $banned -ge 20 ]]; then + banned="\e[1;5;${c_danger}m${banned}\e[0m" + elif [[ $banned -ge 1 ]]; then + banned="\e[1;${c_warning}m${banned}\e[0m" + fi + totalbanned=$(echo "$status" | grep -ioP '(?<=Total banned:\t)[[:digit:]]+') + out+="\e[1;${c_txt_emphase}m${jail}\e[0m,$failed,$totalfailed,$banned,$totalbanned\n" +done + +echo -e "$out" | column -ts $',' | sed 's/^/ /' diff --git a/motdfetch.d/99-userslog b/motdfetch.d/99-userslog new file mode 100644 index 0000000..a3ae77d --- /dev/null +++ b/motdfetch.d/99-userslog @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +# +# check last user logged in (with host ip and period) and currently logged in users +# + if the last logged in is not the current user, add a section about the last login of the curent user + +# GENERAL ########################################################### + +# locale env +unset LC_ALL +export LC_MESSAGES=C + +# check if module was disabled +module_disable=${module_userslog_disable:=0} +if (($module_disable == 1)); then + exit 1 +fi + +# colors +c_txt=${c_txt:="39"} +c_txt_emphase=${c_txt_emphase:="35"} +c_txt_deco=${c_txt_deco:="97"} +c_txt_invert=${c_txt_invert:="30"} +c_bg=${c_bg_sec:="47"} +c_danger=${c_danger:="31"} +c_warning=${c_warning:="33"} +c_success=${c_success:="32"} +c_title=${c_title:="${c_bg};1;${c_txt_invert}m"} + +# PREPARATIONS ###################################################### + +lastuserlog=$(last -i -F -n 2 | head -2 | tail -1) +lastusername=$(echo -e "$lastuserlog" | awk '{print $1}') +lastuserhost=$(echo -e "$lastuserlog" | awk '{print $3}') +if [[ "$lastuserhost" == "0.0.0.0" ]]; then + lastuserhost="localhost" +fi +lastusertime=$(echo -e "$lastuserlog" | awk '{$1=$2=$3=""; print $0}' | sed 's/^ //') + +lastcurrentuserlog=$(last $(id -un) -i -F -n 2 | head -2 | tail -1) +lastcurrentusername=$(echo -e "$lastcurrentuserlog" | awk '{print $1}') +lastcurrentuserhost=$(echo -e "$lastcurrentuserlog" | awk '{print $3}') +if [[ "$lastcurrentuserhost" == "0.0.0.0" ]]; then + lastcurrentuserhost="localhost" +fi +lastcurrentusertime=$(echo -e "$lastcurrentuserlog" | awk '{$1=$2=$3=""; print $0}' | sed 's/^ //') + +loggedusers=$(last -i -F -p now | /usr/bin/grep "logged in" | awk '{print $1}') +loggedusersnames=$(echo -e "$loggedusers" | uniq -c | sed 's/^\s\+/|/' | tr ' ' '|') +loggeduserscount=$(echo -e "$loggedusers" | wc -l) + +# OUTPUT ############################################################ + +# header +echo -e "\n\e[${c_title} Users log \e[0m\n" + +W="\e[0;${c_txt}m" +X="\e[1;${c_txt}m" +F="\e[0;${c_txt_emphase}m" +G="\e[1;${c_txt_emphase}m" +S="\e[1;4;${c_txt}m" +N="\e[0m" + +# last logins +if [[ "$lastusername" == "$lastcurrentusername" ]]; then + echo -e "$X Last user logged in$W: $G$lastcurrentusername$W, from $F$lastcurrentuserhost$W +$X | Login - out$W (duration): $F$lastcurrentusertime$N" +else + echo -e "$X Last user logged in$W: $G$lastusername$W, from $F$lastuserhost$W +$X | Login - out$W (duration): $F$lastusertime$W + +$X Last time$W $G$lastcurrentusername$W$X logged in$W, was from $F$lastcurrentuserhost$W +$X | Login - out$W (duration): $F$lastcurrentusertime$N" +fi + +# logged users +echo +echo -e "$G"$loggeduserscount"$W ${X}session$W(s)$X are logged in$W:|${S}Session(s)${W}|${S}User$W${G}\n`echo -e "$loggedusersnames"`$N" | column -t -s '|' | sed 's/^/ /' diff --git a/motdfetch.sample.conf b/motdfetch.sample.conf new file mode 100644 index 0000000..7704cd0 --- /dev/null +++ b/motdfetch.sample.conf @@ -0,0 +1,70 @@ +#!/usr/bin/env bash +# +# user configuration file for MOTDfetch + +# GLOBAL COLORS ###################################################### + +c_txt="39" +c_txt_emphase="35" +c_txt_deco="97" +c_txt_invert="30" +c_bg="47" +c_danger="31" +c_warning="33" +c_success="32" +c_title="${c_bg};1;${c_txt_invert}m" + +# GLOBAL OPTIONS #################################################### + +## api website name for plain public IP4/6 check +global_publicip_api="icanhazip.com" + +# MODULES OPTIONS #################################################### + +## HEADER module +module_header_disable=0 +### custom text (comment to use username, trim > 80 char) +module_header_text="BANNER" + +## SYSINFO module +module_sysinfo_disable=0 + +## SERVICES module +module_services_disable=0 +### services to check +### + lookup system & current user services running with these 2 commands: +### systemctl --type=service --no-pager -q --state running +### systemctl --type=service --user --no-pager -q --state running +### + to add user services you need to provide the uid of the user ("service:uid"), find the uid with: +### id -u +module_services=( + "cron" + "unattended-upgrades.service" + "dbus:1000" +) +### column max-width +module_services_width="80" + +## FILESYSTEM module +module_filesystem_disable=0 +### disable the ZFS section of the module +module_filesystem_zfs_disable=0 +### max blocks usage percentage warning threshold +module_filesystem_max_usage="85" + +## TLS module +module_tls_disable=0 +### Domains and ports (default:433) for TLS certification check +module_tls_domains=( + "www.google.com" + "w.fakedomain.com" +) + +## POSTQUEUE module +module_postqueue_disable=0 + +## FAIL2BAN module +module_fail2ban_disable=0 + +## USERLOG module +module_userslog_disable=0 \ No newline at end of file diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..356a031 --- /dev/null +++ b/readme.md @@ -0,0 +1,112 @@ +# [MOTDfetch][motdfetch_repo] + +![Bash](https://img.shields.io/badge/bash-1f425f.svg?style=for-the-badge&logo=image%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw%2FeHBhY2tldCBiZWdpbj0i77u%2FIiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8%2BIDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTExIDc5LjE1ODMyNSwgMjAxNS8wOS8xMC0wMToxMDoyMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkE3MDg2QTAyQUZCMzExRTVBMkQxRDMzMkJDMUQ4RDk3IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkE3MDg2QTAzQUZCMzExRTVBMkQxRDMzMkJDMUQ4RDk3Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QTcwODZBMDBBRkIzMTFFNUEyRDFEMzMyQkMxRDhEOTciIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QTcwODZBMDFBRkIzMTFFNUEyRDFEMzMyQkMxRDhEOTciLz4gPC9yZGY6RGVzY3JpcHRpb24%2BIDwvcmRmOlJERj4gPC94OnhtcG1ldGE%2BIDw%2FeHBhY2tldCBlbmQ9InIiPz6lm45hAAADkklEQVR42qyVa0yTVxzGn7d9Wy03MS2ii8s%2BeokYNQSVhCzOjXZOFNF4jx%2BMRmPUMEUEqVG36jo2thizLSQSMd4N8ZoQ8RKjJtooaCpK6ZoCtRXKpRempbTv5ey83bhkAUphz8fznvP8znn%2B%2F3NeEEJgNBoRRSmz0ub%2FfuxEacBg%2FDmYtiCjgo5NG2mBXq%2BH5I1ogMRk9Zbd%2BQU2e1ML6VPLOyf5tvBQ8yT1lG10imxsABm7SLs898GTpyYynEzP60hO3trHDKvMigUwdeaceacqzp7nOI4n0SSIIjl36ao4Z356OV07fSQAk6xJ3XGg%2BLCr1d1OYlVHp4eUHPnerU79ZA%2F1kuv1JQMAg%2BE4O2P23EumF3VkvHprsZKMzKwbRUXFEyTvSIEmTVbrysp%2BWr8wfQHGK6WChVa3bKUmdWou%2BjpArdGkzZ41c1zG%2Fu5uGH4swzd561F%2BuhIT4%2BLnSuPsv9%2BJKIpjNr9dXYOyk7%2FBZrcjIT4eCnoKgedJP4BEqhG77E3NKP31FO7cfQA5K0dSYuLgz2TwCWJSOBzG6crzKK%2BohNfni%2Bx6OMUMMNe%2Fgf7ocbw0v0acKg6J8Ql0q%2BT%2FAXR5PNi5dz9c71upuQqCKFAD%2BYhrZLEAmpodaHO3Qy6TI3NhBpbrshGtOWKOSMYwYGQM8nJzoFJNxP2HjyIQho4PewK6hBktoDcUwtIln4PjOWzflQ%2Be5yl0yCCYgYikTclGlxadio%2BBQCSiW1UXoVGrKYwH4RgMrjU1HAB4vR6LzWYfFUCKxfS8Ftk5qxHoCUQAUkRJaSEokkV6Y%2F%2BJUOC4hn6A39NVXVBYeNP8piH6HeA4fPbpdBQV5KOx0QaL1YppX3Jgk0TwH2Vg6S3u%2BdB91%2B%2FpuNYPYFl5uP5V7ZqvsrX7jxqMXR6ff3gCQSTzFI0a1TX3wIs8ul%2Bq4HuWAAiM39vhOuR1O1fQ2gT%2F26Z8Z5vrl2OHi9OXZn995nLV9aFfS6UC9JeJPfuK0NBohWpCHMSAAsFe74WWP%2BvT25wtP9Bpob6uGqqyDnOtaeumjRu%2ByFu36VntK%2FPA5umTJeUtPWZSU9BCgud661odVp3DZtkc7AnYR33RRC708PrVi1larW7XwZIjLnd7R6SgSqWSNjU1B3F72pz5TZbXmX5vV81Yb7Lg7XT%2FUXriu8XLVqw6c6XqWnBKiiYU%2BMt3wWF7u7i91XlSEITwSAZ%2FCzAAHsJVbwXYFFEAAAAASUVORK5CYII%3D) +![Debian](https://img.shields.io/badge/Debian-D70A53?style=for-the-badge&logo=debian&logoColor=white) +![Ubuntu](https://img.shields.io/badge/Ubuntu-E95420?style=for-the-badge&logo=ubuntu&logoColor=white) + +**MOTDfetch** is a modular & dynamic **MOTD replacement** written in Bash and a nice **command line information tool** for Debian/Ubuntu systems. + +>*MOTD - "message of the day" +>Feature used on Unix-like CLI systems to send a common message to all users after a successful login, and just before it executes the login shell. +>Newer Unix-like systems may generate the message dynamically when the host boots or a user logs in.* + +**Drawbacks** with the current implementation of **MOTD with PAM on Debian and Ubuntu** are at least 3: + 1. The **SSH client does not decide** whether to activate the MOTD. +As it is loaded before the shell login is opened: + 2. User has to **wait blindly** for the end of the execution if there is a dynamic script. + 3. Scripts **can not check the user sessions** status. + +MOTDfetch **avoids** and partially **disable the original MOTD implementation**, but **remains compatible** with it for PAM login. + +--- + +>###### Table of contents +>**[FEATURES](#features)** +>**[INSTALLATION](#installation)** +>**[USAGE](#usage)** + +[![Preview of MOTDfetch][preview_image]][preview_image_url] + +--- + +## Features + +- Usable as a **command**, a **login MOTD** or **SSH MOTD**. +- **[8 Core modules](#8_core_modules)**. +- Uniform and **easily customizable**. +- **Emphasis** of important elements and status by **colors, symbols or flashing**. +- **Notice message** upon missing dependencies +- **Reduced operation mode fot high load** (enforceable). +- Separate **system and users configuration** files. +- **Scripted installation** and updates. +- **Modules or sections can be disabled**. +- Standalone **executable modules**. + +### 8 Core modules + +#### **HEADER module** + +- decorative banner (custom text or username) +- welcome message with username, date and time +- user mail inbox status + +#### **SYSYINFO module** + +- distribution name, kernel version, uptime +- CPU, cores, load, processes, memory, swap +- hostname, network interface, DNS servers, public IPs/DNS/rDNS records +- custom external API for public IP check +- skip connectivity related tests if the API check fail +- short timeout on dig & curl commands to keep the script snappy + +#### **SERVICES module** + +- check systemd services status +- by service name and user UID if not system +- :warning: user cannot check other user's services + +#### **FILESYSTEM module** + +- 2 sections: general filesystems, ZFS filesystems +- name, fs type, usage and size of disk or ZFS pool +- inodes usage and size when relevant +- health status for ZFS +- custom usage threshold for warning hints + +#### **TLS module** + +- check X.509 certificates status with openssl +- accept domain and optional port (443 by default) +- validate name correspondence and expiration date +- skip the test if there is no internet connectivity +- short timeout on openssl command to keep the script snappy + +#### **POSTQUEUE module** + +- postfix deferred queue status +- short timeout on the parsing to keep the script snappy if there is thousands of mails + +#### **FAIL2BAN module** + +- display fail2ban jails status +- :warning: need to be executed with root or sudo + +#### **USERSLOG module** + + - display last user logged in + - name, IP and connection range + - if the current user is different, display his last log too + - display currently logged sessions with usernames + +## Installation + +### Requirements + +## Usage + +--- + +[//]: # (LINKS) +[motdfetch_repo]: https://git.tkapias.net/tkapias/MOTDfetch +[preview_image]: docs/img/preview.jpg "Preview of MOTDfetch" +[preview_image_url]: https://git.tkapias.net/tkapias/MOTDfetch/raw/master/docs/img/preview.jpg