-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathportdiff
More file actions
executable file
·103 lines (87 loc) · 2.81 KB
/
Copy pathportdiff
File metadata and controls
executable file
·103 lines (87 loc) · 2.81 KB
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
#!/bin/bash
# Snapshot open ports and compare against the last snapshot.
# Usage: portdiff (snapshot and diff)
# portdiff --show (show current snapshot without diffing)
# portdiff --reset (delete saved snapshot and start fresh)
SNAPSHOT_DIR="${PORTDIFF_DIR:-$HOME/.portdiff}"
CURRENT="$SNAPSHOT_DIR/current.txt"
PREVIOUS="$SNAPSHOT_DIR/previous.txt"
if [ "$(id -u)" -ne 0 ]; then
echo "Error: Must run as root (use sudo)."
exit 1
fi
mkdir -p "$SNAPSHOT_DIR"
# Emit one line per listening socket: proto, port, address, process NAME only
# (no PID), so a service restart is not reported as a change.
collect_ports() {
ss -tulnp 2>/dev/null | tail -n +2 | awk '{
proto = $1
addr = $5
n = split($5, a, ":")
port = a[n]
proc = $7
if (match(proc, /"[^"]+"/)) {
proc = substr(proc, RSTART + 1, RLENGTH - 2)
} else {
proc = "-"
}
printf "%-6s %-8s %-25s %s\n", proto, port, addr, proc
}'
}
print_block() {
local title="$1" data="$2"
echo "$title"
echo ""
printf " %-6s %-8s %-25s %s\n" "PROTO" "PORT" "ADDRESS" "PROCESS"
printf " %-6s %-8s %-25s %s\n" "-----" "----" "-------" "-------"
printf '%s\n' "$data" | while IFS= read -r line; do
echo " $line"
done
}
if [ "$1" = "--reset" ]; then
rm -f "$CURRENT" "$PREVIOUS"
echo "Snapshots cleared."
exit 0
fi
if [ "$1" = "--show" ]; then
echo "Current listening ports:"
echo ""
printf "%-6s %-8s %-25s %s\n" "PROTO" "PORT" "ADDRESS" "PROCESS"
printf "%-6s %-8s %-25s %s\n" "-----" "----" "-------" "-------"
collect_ports | sort -k2 -n
exit 0
fi
# Take a new snapshot in a canonical (byte) order so comm can compare it.
snapshot=$(collect_ports | LC_ALL=C sort)
if [ -z "$snapshot" ]; then
echo "Error: could not read listening ports (is 'ss' available?)."
exit 1
fi
# Rotate current -> previous, then write the new current.
if [ -f "$CURRENT" ]; then
mv "$CURRENT" "$PREVIOUS"
fi
printf '%s\n' "$snapshot" > "$CURRENT"
# No previous snapshot yet: just show what we captured.
if [ ! -f "$PREVIOUS" ]; then
echo "First snapshot saved. Run again later to see changes."
echo ""
printf "%-6s %-8s %-25s %s\n" "PROTO" "PORT" "ADDRESS" "PROCESS"
printf "%-6s %-8s %-25s %s\n" "-----" "----" "-------" "-------"
printf '%s\n' "$snapshot" | sort -k2 -n
exit 0
fi
# Both files are LC_ALL=C-sorted, so comm compares them correctly.
new_ports=$(LC_ALL=C comm -13 "$PREVIOUS" "$CURRENT" | sort -k2 -n)
closed_ports=$(LC_ALL=C comm -23 "$PREVIOUS" "$CURRENT" | sort -k2 -n)
if [ -z "$new_ports" ] && [ -z "$closed_ports" ]; then
echo "No changes since last snapshot."
exit 0
fi
if [ -n "$new_ports" ]; then
print_block "NEW ports since last snapshot:" "$new_ports"
echo ""
fi
if [ -n "$closed_ports" ]; then
print_block "CLOSED ports since last snapshot:" "$closed_ports"
fi