Files
CoM-ghost_protocol/opsec/scripts/opsec-harden.sh
T

378 lines
14 KiB
Bash
Executable File

#!/bin/bash
# /usr/local/bin/opsec-harden.sh — System hardening apply/revert
# Usage: sudo opsec-harden.sh apply|revert
#
# Reads settings from /etc/opsec/opsec.conf
# Handles: core dumps, swap, timezone, locale, screen lock, WebRTC,
# USB blocking, clipboard auto-clear, traffic jitter
## NOTE: Do NOT use "set -euo pipefail" — it causes silent crashes
## when commands like sysctl, dconf, tc, etc. return non-zero.
## Use explicit error handling instead (|| true).
if [ "$EUID" -ne 0 ]; then
echo "[-] Please run as root"
exit 1
fi
OPSEC_LIB="/usr/local/lib/opsec/opsec-lib.sh"
BACKUP_DIR="/etc/opsec/.harden-backup"
# Source shared library
if [ -f "$OPSEC_LIB" ]; then
. "$OPSEC_LIB"
else
# Minimal fallback
opsec_green() { echo -e "\033[38;5;49m[+] $*\033[0m"; }
opsec_red() { echo -e "\033[38;5;196m[-] $*\033[0m"; }
opsec_yellow() { echo -e "\033[38;5;214m[*] $*\033[0m"; }
opsec_info() { echo -e "\033[38;5;39m[~] $*\033[0m"; }
opsec_load_config() {
[ -f /etc/opsec/opsec.conf ] && . /etc/opsec/opsec.conf
}
fi
mkdir -p "$BACKUP_DIR"
opsec_load_config 2>/dev/null || true
# ─── CORE DUMPS ────────────────────────────────────────────────────────────────
apply_core_dumps() {
if [ "${HARDEN_CORE_DUMPS:-1}" = "1" ]; then
opsec_info "Disabling core dumps..."
# sysctl
sysctl -w kernel.core_pattern='|/bin/false' >/dev/null 2>&1
sysctl -w fs.suid_dumpable=0 >/dev/null 2>&1
# limits.d
cat > /etc/security/limits.d/opsec-coredump.conf << 'EOF'
# OPSEC: Disable core dumps
* hard core 0
* soft core 0
EOF
# systemd coredump
mkdir -p /etc/systemd/coredump.conf.d
cat > /etc/systemd/coredump.conf.d/opsec.conf << 'EOF'
[Coredump]
Storage=none
ProcessSizeMax=0
EOF
opsec_green "Core dumps disabled"
fi
}
revert_core_dumps() {
sysctl -w kernel.core_pattern='core' >/dev/null 2>&1
sysctl -w fs.suid_dumpable=1 >/dev/null 2>&1
rm -f /etc/security/limits.d/opsec-coredump.conf
rm -f /etc/systemd/coredump.conf.d/opsec.conf
opsec_green "Core dumps restored"
}
# ─── SWAP ──────────────────────────────────────────────────────────────────────
apply_swap() {
if [ "${HARDEN_SWAP:-1}" = "1" ]; then
opsec_info "Disabling swap..."
swapoff -a 2>/dev/null || true
# Comment out swap entries in fstab (backup first)
if [ ! -f "$BACKUP_DIR/fstab.swap" ]; then
grep -E '^\s*[^#].*\sswap\s' /etc/fstab > "$BACKUP_DIR/fstab.swap" 2>/dev/null || true
fi
sed -i '/\sswap\s/s/^/#OPSEC# /' /etc/fstab 2>/dev/null || true
opsec_green "Swap disabled"
fi
}
revert_swap() {
sed -i 's/^#OPSEC# //' /etc/fstab 2>/dev/null || true
swapon -a 2>/dev/null || true
opsec_green "Swap restored"
}
# ─── IPv6 ──────────────────────────────────────────────────────────────────────
apply_ipv6() {
if [ "${HARDEN_IPV6:-1}" = "1" ]; then
opsec_info "Disabling IPv6..."
sysctl -w net.ipv6.conf.all.disable_ipv6=1 >/dev/null
sysctl -w net.ipv6.conf.default.disable_ipv6=1 >/dev/null
opsec_green "IPv6 disabled"
fi
}
revert_ipv6() {
sysctl -w net.ipv6.conf.all.disable_ipv6=0 >/dev/null
sysctl -w net.ipv6.conf.default.disable_ipv6=0 >/dev/null
opsec_green "IPv6 restored"
}
# ─── TIMEZONE SPOOF ────────────────────────────────────────────────────────────
apply_timezone() {
if [ "${HARDEN_TIMEZONE_SPOOF:-0}" = "1" ]; then
local tz="${HARDEN_TIMEZONE_VALUE:-UTC}"
opsec_info "Spoofing timezone to ${tz}..."
# Backup current timezone
timedatectl show -p Timezone --value > "$BACKUP_DIR/timezone.orig" 2>/dev/null || true
timedatectl set-timezone "$tz" 2>/dev/null || {
ln -sf "/usr/share/zoneinfo/${tz}" /etc/localtime
}
opsec_green "Timezone set to ${tz}"
fi
}
revert_timezone() {
if [ -f "$BACKUP_DIR/timezone.orig" ]; then
local orig_tz
orig_tz=$(cat "$BACKUP_DIR/timezone.orig")
timedatectl set-timezone "$orig_tz" 2>/dev/null || true
rm -f "$BACKUP_DIR/timezone.orig"
opsec_green "Timezone restored to ${orig_tz}"
fi
}
# ─── LOCALE SPOOF ─────────────────────────────────────────────────────────────
apply_locale() {
if [ "${HARDEN_LOCALE_SPOOF:-0}" = "1" ]; then
local loc="${HARDEN_LOCALE_VALUE:-en_US.UTF-8}"
opsec_info "Spoofing locale to ${loc}..."
# Backup
locale > "$BACKUP_DIR/locale.orig" 2>/dev/null || true
export LANG="$loc"
export LC_ALL="$loc"
echo "LANG=${loc}" > /etc/default/locale.opsec
opsec_green "Locale set to ${loc}"
fi
}
revert_locale() {
rm -f /etc/default/locale.opsec
if [ -f "$BACKUP_DIR/locale.orig" ]; then
rm -f "$BACKUP_DIR/locale.orig"
fi
opsec_green "Locale restored"
}
# ─── SCREEN LOCK ───────────────────────────────────────────────────────────────
apply_screen_lock() {
if [ "${HARDEN_SCREEN_LOCK:-1}" = "1" ]; then
local timeout="${HARDEN_SCREEN_LOCK_TIMEOUT:-300}"
opsec_info "Setting screen lock timeout to ${timeout}s..."
# Try GNOME dconf (runs as user via sudo)
local real_user="${SUDO_USER:-$USER}"
if command -v dconf >/dev/null 2>&1; then
su - "$real_user" -c "
dconf write /org/gnome/desktop/session/idle-delay 'uint32 ${timeout}' 2>/dev/null
dconf write /org/gnome/desktop/screensaver/lock-enabled 'true' 2>/dev/null
dconf write /org/gnome/desktop/screensaver/lock-delay 'uint32 0' 2>/dev/null
" 2>/dev/null || true
fi
opsec_green "Screen lock set to ${timeout}s"
fi
}
revert_screen_lock() {
local real_user="${SUDO_USER:-$USER}"
if command -v dconf >/dev/null 2>&1; then
su - "$real_user" -c "
dconf write /org/gnome/desktop/session/idle-delay 'uint32 900' 2>/dev/null
" 2>/dev/null || true
fi
opsec_green "Screen lock restored to default"
}
# ─── WEBRTC BLOCKING ──────────────────────────────────────────────────────────
apply_webrtc() {
if [ "${LEAK_WEBRTC_BLOCK:-1}" = "1" ]; then
opsec_info "Blocking WebRTC..."
local real_user="${SUDO_USER:-$USER}"
local user_home
user_home=$(eval echo "~${real_user}")
# Firefox profiles
for profile_dir in "${user_home}"/.mozilla/firefox/*.default* "${user_home}"/.mozilla/firefox/*.opsec*; do
[ -d "$profile_dir" ] || continue
cat >> "${profile_dir}/user.js" << 'EOF'
// OPSEC: Disable WebRTC IP leak
user_pref("media.peerconnection.enabled", false);
user_pref("media.peerconnection.turn.disable", true);
user_pref("media.peerconnection.use_document_iceservers", false);
user_pref("media.peerconnection.video.enabled", false);
user_pref("media.peerconnection.identity.timeout", 1);
EOF
done
# Brave/Chromium policies
mkdir -p /etc/brave/policies/managed /etc/chromium/policies/managed
cat > /etc/brave/policies/managed/opsec-webrtc.json << 'EOF'
{ "WebRtcIPHandling": "disable_non_proxied_udp" }
EOF
cp /etc/brave/policies/managed/opsec-webrtc.json /etc/chromium/policies/managed/ 2>/dev/null || true
opsec_green "WebRTC blocked (Firefox + Brave/Chromium)"
fi
}
revert_webrtc() {
local real_user="${SUDO_USER:-$USER}"
local user_home
user_home=$(eval echo "~${real_user}")
for profile_dir in "${user_home}"/.mozilla/firefox/*.default* "${user_home}"/.mozilla/firefox/*.opsec*; do
[ -d "$profile_dir" ] || continue
sed -i '/OPSEC: Disable WebRTC/,/peerconnection\.identity/d' "${profile_dir}/user.js" 2>/dev/null || true
done
rm -f /etc/brave/policies/managed/opsec-webrtc.json
rm -f /etc/chromium/policies/managed/opsec-webrtc.json
opsec_green "WebRTC restrictions removed"
}
# ─── USB BLOCKING ─────────────────────────────────────────────────────────────
apply_usb_block() {
if [ "${LEAK_USB_BLOCK:-0}" = "1" ]; then
opsec_info "Blocking new USB devices..."
echo 0 > /sys/bus/usb/drivers_autoprobe 2>/dev/null || true
opsec_green "USB auto-probe disabled (new devices blocked)"
fi
}
revert_usb_block() {
echo 1 > /sys/bus/usb/drivers_autoprobe 2>/dev/null || true
opsec_green "USB auto-probe restored"
}
# ─── CLIPBOARD AUTO-CLEAR ─────────────────────────────────────────────────────
apply_clipboard_clear() {
if [ "${HARDEN_CLIPBOARD_CLEAR:-0}" = "1" ]; then
opsec_info "Starting clipboard auto-clear..."
# Launch background clearer (clears clipboard every 30 seconds)
local pidfile="/var/run/opsec-clipboard.pid"
if [ -f "$pidfile" ] && kill -0 "$(cat "$pidfile")" 2>/dev/null; then
opsec_yellow "Clipboard cleaner already running"
return
fi
(
while true; do
sleep 30
# Clear X clipboard
if command -v xclip >/dev/null 2>&1; then
echo -n "" | xclip -selection clipboard 2>/dev/null || true
echo -n "" | xclip -selection primary 2>/dev/null || true
elif command -v xsel >/dev/null 2>&1; then
xsel --clipboard --clear 2>/dev/null || true
xsel --primary --clear 2>/dev/null || true
fi
done
) &
echo $! > "$pidfile"
opsec_green "Clipboard auto-clear active (every 30s)"
fi
}
revert_clipboard_clear() {
local pidfile="/var/run/opsec-clipboard.pid"
if [ -f "$pidfile" ]; then
kill "$(cat "$pidfile")" 2>/dev/null || true
rm -f "$pidfile"
fi
opsec_green "Clipboard auto-clear stopped"
}
# ─── TRAFFIC JITTER ───────────────────────────────────────────────────────────
apply_traffic_jitter() {
if [ "${TRAFFIC_JITTER_ENABLED:-0}" = "1" ]; then
local ms="${TRAFFIC_JITTER_MS:-50}"
opsec_info "Adding ${ms}ms traffic jitter..."
# Find primary outbound interface
local iface
iface=$(ip route get 1.1.1.1 2>/dev/null | awk '{for(i=1;i<=NF;i++) if($i=="dev") print $(i+1)}' | head -1)
if [ -n "$iface" ]; then
# Remove existing qdisc first
tc qdisc del dev "$iface" root 2>/dev/null || true
tc qdisc add dev "$iface" root netem delay "${ms}ms" "${ms}ms" distribution normal 2>/dev/null || {
opsec_yellow "tc not available — jitter skipped"
return
}
echo "$iface" > "$BACKUP_DIR/jitter-iface"
opsec_green "Traffic jitter active on ${iface} (${ms}ms)"
else
opsec_yellow "No outbound interface found for jitter"
fi
fi
}
revert_traffic_jitter() {
if [ -f "$BACKUP_DIR/jitter-iface" ]; then
local iface
iface=$(cat "$BACKUP_DIR/jitter-iface")
tc qdisc del dev "$iface" root 2>/dev/null || true
rm -f "$BACKUP_DIR/jitter-iface"
opsec_green "Traffic jitter removed from ${iface}"
fi
}
# ─── MAIN ──────────────────────────────────────────────────────────────────────
do_apply() {
echo ""
opsec_hdr "APPLYING SYSTEM HARDENING"
echo ""
apply_core_dumps
apply_swap
apply_ipv6
apply_timezone
apply_locale
apply_screen_lock
apply_webrtc
# Ghost-mode-only features — skip when called from mode_base (OPSEC_BASE_ONLY=1)
if [ "${OPSEC_BASE_ONLY:-0}" != "1" ]; then
apply_usb_block
apply_clipboard_clear
apply_traffic_jitter
else
opsec_info "Base-only mode — skipping USB block, clipboard clear, traffic jitter"
fi
echo ""
opsec_green "All hardening measures applied"
}
do_revert() {
echo ""
opsec_hdr "REVERTING SYSTEM HARDENING"
echo ""
revert_core_dumps
revert_swap
revert_ipv6
revert_timezone
revert_locale
revert_screen_lock
revert_webrtc
revert_usb_block
revert_clipboard_clear
revert_traffic_jitter
echo ""
opsec_green "All hardening measures reverted"
}
case "${1:-}" in
apply) do_apply ;;
revert) do_revert ;;
*)
echo "Usage: $(basename "$0") apply|revert"
exit 1
;;
esac