-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconchecker.sh
138 lines (117 loc) · 4.9 KB
/
conchecker.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#!/bin/bash
set -euo pipefail
IFS=$'\n\t'
# Constants
readonly NEW_SSH_PORT=2298
readonly ALLOWED_CONNECTIONS_FILE="allowed_ips.txt"
readonly LOG_FILE="/var/log/conchecker.log"
# Function to log messages with timestamps
log() {
local message="$1"
echo "$(date '+%Y-%m-%d %H:%M:%S'): $message" | tee -a "$LOG_FILE"
}
# Ensure log file is writable
if [[ ! -w "$(dirname "$LOG_FILE")" ]]; then
echo "Error: Log directory is not writable."
exit 1
fi
# Check if the script is run as root
if [[ $EUID -ne 0 ]]; then
log "Error: This script must be run as root."
exit 1
fi
# Validate the provided username parameter
if [[ $# -ne 1 ]]; then
log "Error: Please provide exactly one username as an argument."
log "Usage: $0 <username_to_exclude>"
exit 1
fi
readonly CURRENT_USER="$1"
# Verify the allowed_ips.txt file
if [[ ! -f "$ALLOWED_CONNECTIONS_FILE" || ! -s "$ALLOWED_CONNECTIONS_FILE" ]]; then
log "Error: The allowed_ips.txt file does not exist or is empty."
log "Please create the file and add allowed IP addresses, one per line."
exit 1
fi
# Get firewall tool
FIREWALL_TOOL=$(command -v ufw || command -v iptables || echo "none")
# Function to add firewall rules
add_firewall_rule() {
local local_ip="$1"
local remote_ip="$2"
case "$FIREWALL_TOOL" in
"ufw")
ufw deny from "$remote_ip" to "$local_ip"
log "Firewall rule added using ufw to block $remote_ip to $local_ip"
;;
"iptables")
iptables -A INPUT -s "$remote_ip" -d "$local_ip" -j DROP
log "Firewall rule added using iptables to block $remote_ip to $local_ip"
;;
*)
log "No firewall tool available to add rule."
;;
esac
}
# Function to kill a process by PID
kill_process() {
local pid="$1"
local signal="$2"
kill "-$signal" "$pid"
log "Process with PID $pid killed with signal $signal"
}
# Main function to check connections
check_connections() {
local current_ssh_connection
current_ssh_connection=$(who | awk -v user="$CURRENT_USER" '$1 == user {print $NF}' | sed 's/[()]//g')
log "Starting connection checks..."
while read -r line; do
if [[ "$line" =~ ^tcp.*ESTABLISHED$ ]]; then
local_ip=$(echo "$line" | awk '{print $4}')
remote_ip=$(echo "$line" | awk '{print $5}')
pid_program=$(echo "$line" | awk '{print $7}' | awk -F'/' '{print $1}')
program_name=$(echo "$line" | awk '{print $7}' | awk -F'/' '{print $2}')
local_port=$(echo "$local_ip" | awk -F':' '{print $NF}')
# Skip the connection if it belongs to the current user's SSH connection
if [[ "$program_name" == "sshd" && "$remote_ip" == *"$current_ssh_connection"* ]]; then
continue
fi
# Check if the connection is allowed based on the allowed_ips.txt file or if the local port matches NEW_SSH_PORT
if ! grep -qE "^$remote_ip\s*$local_port$" "$ALLOWED_CONNECTIONS_FILE" && [[ "$local_port" -ne "$NEW_SSH_PORT" ]]; then
log "Unauthorized connection: $local_ip <-> $remote_ip (Process: $program_name, PID: $pid_program)"
if $INTERACTIVE; then
# Prompt the user to kill the unauthorized process
read -r -p "Do you want to kill this process? (yes/no) " answer_kill
if [[ "$answer_kill" =~ ^(yes|y)$ ]]; then
log "User chose to kill the process with PID $pid_program"
kill_process "$pid_program" "15"
sleep 5
if ps -p "$pid_program" > /dev/null; then
log "Process with PID $pid_program is still running after SIGTERM, sending SIGKILL"
kill_process "$pid_program" "9"
fi
else
log "User chose not to kill the process with PID $pid_program"
fi
# Prompt the user to add a firewall rule to block the unauthorized connection
read -r -p "Do you want to block this connection using firewall? (yes/no) " answer_firewall
if [[ "$answer_firewall" =~ ^(yes|y)$ ]]; then
log "User chose to block the connection from $remote_ip to $local_ip using $FIREWALL_TOOL"
add_firewall_rule "$local_ip" "$remote_ip"
else
log "User chose not to block the connection from $remote_ip to $local_ip"
fi
else
log "Running in non-interactive mode. Not prompting user for actions."
fi
fi
fi
done < <(netstat -antp 2>/dev/null)
log "Connection checks completed."
}
# Main function to encapsulate script logic
main() {
check_connections
}
# Execute main function
main "$@"