Forked from tuklusan/openvms-telnet-spam-blocklist.sh
Created
April 19, 2021 17:39
-
-
Save sskras/45f140128c2ae7b945a28e3fa54c7527 to your computer and use it in GitHub Desktop.
Linux Bash Script to Parse OpenVMS Operator Log forwarded to Unix-Style SYSLOG on Linux, Generating auth failure audit events for fail2ban reporting to Blocklist.de. See http://supratim-sanyal.blogspot.com/2016/12/mitigate-openvms-telnet-port-brute.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# | |
# -------------------------------- | |
# openvms-telnet-spam-blocklist.sh | |
# -------------------------------- | |
# | |
# READS LINUX (CENTOS) SYSTEM LOG FILE, LOOKING FOR REMOTELY LOGGED OPENVMS VAX INTRUSIONS. | |
# FOR EACH OPENVMS INTRUDER FOUND, LOGS AN EQUIVALENT PAM AUTHENTICATION FAILURE LOG LINE. | |
# FAIL2BAN PICKS UP THE PAM AUTHENTCATION FAILURES AS USUAL AND REPORTS TO BLOCKLIST.DE. | |
# ALSO WRITES AN INFORMATIONAL SUMMARY REPORT OF BRUTE-FORCE ATTACK SOURCES. | |
# | |
# SEE http://sanyal.blogspot.com/2016/12/mitigate-openvms-telnet-port-brute.html FOR | |
# MORE INFORMATION | |
# | |
# | |
# REVISION HISTORY | |
# REV 1.0 04-DEC-2016 INITIAL RELEASE | |
# | |
# | |
# (C) 2016 SUPRATIM SANYAL <SUPRATIM AT RISEUP DOT NET> | |
# FREELY USABLE AND REDISTRIBUTABLE UNDER GNU AGPLv3 | |
# LICENSE: http://tuklusan.decsystem.org/agpl-3.0-standalone.html | |
# ----------------------- | |
# | |
# | |
# ----------------------- | |
# EXAMPLE OF OPENVMS INTRUSION LOGGED IN /var/log/messages BY REMOTE VAXserver RUNNING OpenVMS and VAX SYSLOGD.EXE tool | |
# ----------------------- | |
# Nov 23 16:11:31 sanyalnet-vax [OPCOM] %%%%%%%%%%% OPCOM 23-NOV-2016 16:11:31.06 %%%%%%%%%%% | |
# Nov 23 16:11:31 sanyalnet-vax [OPCOM] Message from user INTERnet on QCOCAL | |
# Nov 23 16:11:31 sanyalnet-vax [OPCOM] TELNET Login from Host: 120.59.231.133 Port: 4783 | |
# Nov 23 16:11:32 sanyalnet-vax [OPCOM] %%%%%%%%%%% OPCOM 23-NOV-2016 16:11:32.34 %%%%%%%%%%% | |
# Nov 23 16:11:32 sanyalnet-vax [OPCOM] Message from user AUDIT$SERVER on QCOCAL | |
# Nov 23 16:11:32 sanyalnet-vax [OPCOM] Security alarm (SECURITY) and security audit (SECURITY) on QCOCAL, system id: 1574 | |
# Nov 23 16:11:32 sanyalnet-vax [OPCOM] Auditable event: Remote interactive breakin detection | |
# Nov 23 16:11:32 sanyalnet-vax [OPCOM] Event time: 23-NOV-2016 16:11:32.33 | |
# Nov 23 16:11:32 sanyalnet-vax [OPCOM] PID: 0000023E | |
# Nov 23 16:11:32 sanyalnet-vax [OPCOM] Process name: _TNA29: | |
# Nov 23 16:11:32 sanyalnet-vax [OPCOM] Username: ROOT | |
# Nov 23 16:11:32 sanyalnet-vax [OPCOM] Terminal name: TNA29:, _TNA29:, Host: 120.59.231.133 Port: 4783 | |
# Nov 23 16:11:32 sanyalnet-vax [OPCOM] Remote node id: 2246523768 (14.888) | |
# Nov 23 16:11:32 sanyalnet-vax [OPCOM] Remote node fullname: 120.59.231.133 | |
# Nov 23 16:11:32 sanyalnet-vax [OPCOM] Remote username: TELNET_783BE785 | |
# Nov 23 16:11:32 sanyalnet-vax [OPCOM] Status: %LOGIN-F-NOSUCHUSER, no such user | |
# ----------------------- | |
# | |
# ----------------------- | |
# EXAMPLE OF OPENVMS INTRUSION LOG CONVERTED TO LOOK LIKE PAM AUTHENTICATION FAILURE IN /var/log/secure | |
# ----------------------- | |
# Dec 4 16:07:35 dormarth sshd[00002457]: pam_unix(sshd:auth): authentication failure; logname=SYS$MANAGER:OPERATOR.LOG uid=0 euid=0 tty=TELNET_BD1AB4A8:38942 ruser=ROOT rhost=189.26.180.168.dynamic.adsl.gvt.net.br user=TELNET_BD1AB4A8 rport=38942 time="4-DEC-2016 15:46:59.08 UTC" event="%LOGIN-F-NOSUCHUSER, no such user;[OPCOM] Auditable event: Remote interactive breakin detection" reporter="Digital-VAXserver-3900-OpenVMS-7.3;DECnet:QCOCAL(1.550);inet:http://sanyalnet-openvms-vax.freeddns.org:82/" | |
# ----------------------- | |
# dec2ip() takes parameter integer IP like 3994475481 (in OpenVMS Byte Order) and | |
# returns dotted IP like 217.219.22.238 | |
# Usage example: dottedip=$(dec2ip "3994475481") | |
dec2ip(){ | |
local a=$((~(-1<<8))) b=$1; | |
set -- "$((b&a))" "$((b>>8&a))" "$((b>>16&a))" "$((b>>24&a))"; | |
local IFS=.; | |
echo "$*"; | |
} | |
# Duplicate execution check | |
# PIDFILE is deleted at script end | |
PIDFILE=/var/run/openvms-telnet-spam-blocklist.pid | |
if [ -f $PIDFILE ] | |
then | |
PID=$(cat $PIDFILE) | |
ps -p $PID > /dev/null 2>&1 | |
if [ $? -eq 0 ] | |
then | |
echo "Process already running" | |
exit 1 | |
else | |
## Process not found assume not running | |
echo $$ > $PIDFILE | |
if [ $? -ne 0 ] | |
then | |
echo "Could not create PID file" | |
exit 1 | |
fi | |
fi | |
else | |
echo $$ > $PIDFILE | |
if [ $? -ne 0 ] | |
then | |
echo "Could not create PID file" | |
exit 1 | |
fi | |
fi | |
# --- | |
DEBUG=0 | |
if [ "$1" == "-v" ] ; then DEBUG=1; echo "$0: ******** VERBOSE MODE ACTIVE ********"; fi | |
TEMPFILE="/tmp/vmsbreakins.tmp" | |
TEMPFILE2="/tmp/vmsbreakins-singlelines.tmp" | |
TEMPFILE3="/tmp/vmsbreakins-sorted-uniqued.tmp" | |
nice -n 19 ionice -c3 egrep -B6 -A9 "\[OPCOM\] Auditable event: Remote interactive breakin detection" /var/log/messages* | nice -n 19 ionice -c3 egrep -v "^--" | cut -f 6- -d " " > $TEMPFILE | |
:>$TEMPFILE2 | |
while IFS='' read -r l_evt || [[ -n "$l_evt" ]]; do # %%%%%%%%%%% OPCOM 23-NOV-2016 16:35:40.67 %%%%%%%%%%% | |
if [[ $l_evt != *" OPCOM "* ]]; then continue; fi | |
read -r l_msgfrominternet # Message from user INTERnet on QCOCAL | |
if [[ $l_msgfrominternet != *"Message from user INTERnet on "* ]]; then continue; fi | |
read -r l_login_info # TELNET Login from Host: 217.219.22.238 Port: 32817 | |
if [[ $l_login_info != *"TELNET Login from Host: "* ]]; then continue; fi | |
# ++ | |
# Ignore certain domains and IPs from being reported | |
# -- | |
if [[ $l_login_info == *"uptimerobot.com"* ]]; then continue; fi | |
if [[ $l_login_info == *" localhost "* ]]; then continue; fi | |
if [[ $l_login_info == *" localhost.localdomain "* ]]; then continue; fi | |
if [[ $l_login_info == *" 127.0.0.1 "* ]]; then continue; fi | |
if [[ $l_login_info == *" 0.0.0.0 "* ]]; then continue; fi | |
if [[ $l_login_info == *" 10.42.2.2 "* ]]; then continue; fi | |
if [[ $l_login_info == *"sanyalnet-cloud-vps.freeddns.org"* ]]; then continue; fi | |
if [[ $l_login_info == *"sanyalnet-cloud-vps2.freeddns.org"* ]]; then continue; fi | |
if [[ $l_login_info == *"cloudatcost.com "* ]]; then continue; fi | |
if [[ $l_login_info == *" 103.25.58.8 "* ]]; then continue; fi # proxy-au.ftelnet.ca web telnet proxy | |
if [[ $l_login_info == *" proxy-au.ftelnet.ca "* ]]; then continue; fi # proxy-au.ftelnet.ca web telnet proxy | |
# -- | |
read -r l_evt2 # %%%%%%%%%%% OPCOM 23-NOV-2016 16:35:41.35 %%%%%%%%%%% | |
if [[ $l_evt2 != *" OPCOM "* ]]; then continue; fi | |
read -r l_msgfromauditsvr # Message from user AUDIT$SERVER on QCOCAL | |
if [[ $l_msgfromauditsvr != *"Message from user AUDIT\$SERVER on "* ]]; then continue; fi | |
read -r l_secalarm # Security alarm (SECURITY) and security audit (SECURITY) on QCOCAL, system id: 1574 | |
if [[ $l_secalarm != *"Security alarm (SECURITY) and security audit (SECURITY) on "* ]]; then continue; fi | |
read -r l_auditevt # Auditable event: Remote interactive breakin detection | |
if [[ $l_auditevt != *"Auditable event: Remote interactive breakin detection"* ]]; then continue; fi | |
read -r l_evttm # Event time: 23-NOV-2016 16:35:41.34 | |
if [[ $l_evttm != *"Event time: "* ]]; then continue; fi | |
read -r l_pid # PID: 00000260 | |
if [[ $l_pid != *"PID: "* ]]; then continue; fi | |
read -r l_pname # Process name: _TNA63: | |
if [[ $l_pname != *"Process name: "* ]]; then continue; fi | |
read -r l_user # Username: ROOT | |
if [[ $l_user != *"Username: "* ]]; then continue; fi | |
read -r l_termname # Terminal name: TNA29:, _TNA29:, Host: 120.59.231.133 Port: 4783 | |
# This one sometimes contains only a "Port: xxxx" string | |
# Or even worse, just a single digit | |
# Read it but don't use it! | |
#if [[ $l_termname != *"Port: "* ]]; then continue; fi | |
read -r l_remnodeid # Remote node id: 3994475481 (54.985) | |
if [[ $l_remnodeid != *"Remote node id: "* ]]; then continue; fi | |
read -r l_remnode # Remote node fullname: 217.219.22.238 | |
if [[ $l_remnode != *"Remote node fullname: "* ]]; then continue; fi | |
read -r l_remuser # Remote username: TELNET_D9DB16EE | |
if [[ $l_remuser != *"Remote username: "* ]]; then continue; fi | |
read -r l_remstatus # Status: %LOGIN-F-NOSUCHUSER, no such user | |
if [[ $l_remstatus != *"Status: "* ]]; then continue; fi | |
l_evt="$(echo -e "${l_evt##*:}" | sed -e 's/^[[:space:]]*//')" | |
l_evttm="$(echo -e "${l_evttm##*time:}" | sed -e 's/^[[:space:]]*//')" | |
l_user="$(echo -e "${l_user##*:}" | sed -e 's/^[[:space:]]*//')" | |
l_remoteip="$(echo -e "${l_remnodeid##*:}" | sed -e 's/^[[:space:]]*//')" | |
l_remoteip=${l_remoteip%% *} | |
l_remoteip=$(dec2ip "$l_remoteip") | |
l_remnode="$(echo -e "${l_remnode##*fullname:}" | sed -e 's/^[[:space:]]*//')" | |
l_remport="$(echo -e "${l_login_info##*Port: }" | sed -e 's/^[[:space:]]*//')" | |
l_remuser="$(echo -e "${l_remuser##*:}" | sed -e 's/^[[:space:]]*//')" | |
l_remstatus="$(echo -e "${l_remstatus##*:}" | sed -e 's/^[[:space:]]*//')" | |
l_pid="$(echo -e "${l_pid##*:}" | sed -e 's/^[[:space:]]*//')" | |
if [ "$DEBUG" -eq 1 ]; then | |
echo "Event: [$l_auditevt]" | |
echo "Time: [$l_evttm]" | |
echo "Username: [$l_user]" | |
echo "IP: [$l_remoteip]" | |
echo "Host: [$l_remnode]" | |
echo "Port: [$l_remport]" | |
echo "RemUsr: [$l_remuser]" | |
echo "PID: [$l_pid]" | |
echo "Status: [$l_remstatus]" | |
echo "-------------------" | |
fi | |
# -- | |
# Add to line-summary report file | |
# 194.140.233.79|194-140-233-79.luksus.net.pl|44395|12-DEC-2016 05:37:51.16|SHSTEM|%LOGIN-F-NOSUCHUSER, no such user|Auditable event: Remote interactive breakin detection | |
# -- | |
oneline="$l_remoteip|$l_remnode|$l_remport|$l_evttm|$l_user|$l_remstatus|$l_auditevt" | |
echo $oneline >> $TEMPFILE2 | |
if [ "$DEBUG" -eq 1 ]; then | |
echo $oneline | |
echo "-------------------" | |
fi | |
# --- | |
# generate pam-lookalike message for fail2ban to pick up | |
# fail2ban filter template: | |
# ^%(__prefix_line)spam_unix\(sshd:auth\):\s+authentication failure;\s*logname=\S*\s*uid=\d*\s*euid=\d*\s*tty=\S*\s*ruser=\S*\s*rhost=<HOST>\s.*$ | |
# | |
# generated line looks like follows: | |
# pam_unix(sshd:auth): authentication failure; logname=SYS$MANAGER:OPERATOR.LOG uid=0 euid=0 tty=TELNET_58F97EB9:46428 ruser=ROOT rhost=88.249.126.185 user=TELNET_58F97EB9 rport=46428 time="12-DEC-2016 05:45:34.27 UTC" event="88.249.126.185.dynamic.ttnet.com.tr;%LOGIN-F-NOSUCHUSER, no such user;Auditable event: Remote interactive breakin detection" reporter="Digital-VAXserver-3900-OpenVMS-7.3;DECnet:QCOCAL(1.550);inet:http://sanyalnet-openvms-vax.freeddns.org:82/" | |
# --- | |
logline="pam_unix(sshd:auth): authentication failure; logname=SYS\$MANAGER:OPERATOR.LOG uid=0 euid=0 tty=$l_remuser:$l_remport ruser=$l_user rhost=$l_remoteip user=$l_remuser rport=$l_remport time=\"$l_evttm UTC\" event=\"$l_remnode;$l_remstatus;$l_auditevt\" reporter=\"Digital-VAXserver-3900-OpenVMS-7.3;DECnet:QCOCAL(1.550);inet:http://sanyalnet-openvms-vax.freeddns.org:82/\"" | |
if [ "$DEBUG" -eq 1 ]; then | |
echo $logline | |
echo "-------------------" | |
fi | |
logger -p authpriv.info -t "sshd[$l_pid]" $logline | |
sleep 1 | |
done < $TEMPFILE | |
if [ "$DEBUG" -eq 1 ]; then | |
cat $TEMPFILE2 | |
echo "-------------------" | |
fi | |
# ++ | |
# Generate a sorted file with unique IP per line (may be useful later), move it to /var/log/QCOCAL-openvms-vax-attacks.txt | |
# Each line looks like | |
# 114-32-206-181.HINET-IP.hinet.net|39097|24-NOV-2016 08:16:03.61|SHSTEM|%LOGIN-F-NOSUCHUSER, no such user|Auditable event: Remote interactive breakin detection | |
# ++ | |
: > $TEMPFILE3 | |
echo "# ++" >> $TEMPFILE3 | |
echo "# QCOCAL-openvms-vax-attacks.txt" >> $TEMPFILE3 | |
echo "#" >> $TEMPFILE3 | |
echo "# ACTIVE BRUTEFORCE ATTACKS ON SANYALNET QCOCAL OPENVMS 7.3 VAX VAXserver-3900 SERVER (http://sanyalnet-openvms-vax.freeddns.org:82/)" >> $TEMPFILE3 | |
echo "# Generated: `date`" >> $TEMPFILE3 | |
echo "#" >> $TEMPFILE3 | |
echo "# (C) SUPRATIM SANYAL - Contact me at QCOCAL::SANYAL OVER HECnet OR http://mcaf.ee/sdlg9f OVER INTERNET" >> $TEMPFILE3 | |
echo "#" >> $TEMPFILE3 | |
echo "# ++" >> $TEMPFILE3 | |
sort $TEMPFILE2 | awk -F"[. ]" '!a[$1]++' >> $TEMPFILE3 | |
mv $TEMPFILE3 /var/log/QCOCAL-openvms-vax-attacks.txt | |
if [ "$DEBUG" -eq 1 ]; then | |
cat /var/log/QCOCAL-openvms-vax-attacks.txt | |
echo "-------------------" | |
fi | |
rm -f $PIDFILE | |
exit |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment