mirror of
https://github.com/kuhyx/scripts.git
synced 2026-07-04 15:03:09 +02:00
Add integrity checks and VirtualBox hosts enforcement to pacman wrapper
Co-authored-by: kuhyx <147418882+kuhyx@users.noreply.github.com>
This commit is contained in:
parent
54155aac5f
commit
538b83c753
@ -28,6 +28,11 @@ WORDS_DEST="${INSTALL_DIR}/words.txt"
|
|||||||
BLOCKED_DEST="${INSTALL_DIR}/pacman_blocked_keywords.txt"
|
BLOCKED_DEST="${INSTALL_DIR}/pacman_blocked_keywords.txt"
|
||||||
WHITELIST_DEST="${INSTALL_DIR}/pacman_whitelist.txt"
|
WHITELIST_DEST="${INSTALL_DIR}/pacman_whitelist.txt"
|
||||||
GREYLIST_DEST="${INSTALL_DIR}/pacman_greylist.txt"
|
GREYLIST_DEST="${INSTALL_DIR}/pacman_greylist.txt"
|
||||||
|
INTEGRITY_DIR="/var/lib/pacman-wrapper"
|
||||||
|
INTEGRITY_FILE="${INTEGRITY_DIR}/policy.sha256"
|
||||||
|
VBOX_ENFORCE_SOURCE="$(dirname "$0")/../virtualbox/enforce_vbox_hosts.sh"
|
||||||
|
VBOX_INSTALL_DIR="/usr/local/share/digital_wellbeing/virtualbox"
|
||||||
|
VBOX_ENFORCE_DEST="${VBOX_INSTALL_DIR}/enforce_vbox_hosts.sh"
|
||||||
# Check if script is run as root
|
# Check if script is run as root
|
||||||
if [ "$EUID" -ne 0 ]; then
|
if [ "$EUID" -ne 0 ]; then
|
||||||
echo -e "${RED}Please run as root${NC}"
|
echo -e "${RED}Please run as root${NC}"
|
||||||
@ -78,8 +83,51 @@ fi
|
|||||||
# Update the PACMAN_BIN variable in the wrapper to point to the original
|
# Update the PACMAN_BIN variable in the wrapper to point to the original
|
||||||
sed -i 's|PACMAN_BIN="\/usr\/bin\/pacman"|PACMAN_BIN="\/usr\/bin\/pacman.orig"|g' "$WRAPPER_DEST"
|
sed -i 's|PACMAN_BIN="\/usr\/bin\/pacman"|PACMAN_BIN="\/usr\/bin\/pacman.orig"|g' "$WRAPPER_DEST"
|
||||||
|
|
||||||
|
# Create integrity directory if it doesn't exist
|
||||||
|
mkdir -p "$INTEGRITY_DIR"
|
||||||
|
chmod 755 "$INTEGRITY_DIR"
|
||||||
|
|
||||||
|
# Generate checksums of policy files for integrity verification
|
||||||
|
echo -e "${BLUE}Generating integrity checksums for policy files...${NC}"
|
||||||
|
{
|
||||||
|
sha256sum "$BLOCKED_DEST" 2>/dev/null || true
|
||||||
|
sha256sum "$GREYLIST_DEST" 2>/dev/null || true
|
||||||
|
sha256sum "$WHITELIST_DEST" 2>/dev/null || true
|
||||||
|
} > "$INTEGRITY_FILE"
|
||||||
|
|
||||||
|
# Make integrity file immutable
|
||||||
|
chmod 400 "$INTEGRITY_FILE"
|
||||||
|
if command -v chattr > /dev/null 2>&1; then
|
||||||
|
chattr +i "$INTEGRITY_FILE" 2>/dev/null || echo -e "${YELLOW}Warning: Could not make integrity file immutable${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Make policy files immutable to prevent easy tampering
|
||||||
|
echo -e "${BLUE}Protecting policy files from modification...${NC}"
|
||||||
|
if command -v chattr > /dev/null 2>&1; then
|
||||||
|
chattr +i "$BLOCKED_DEST" 2>/dev/null || echo -e "${YELLOW}Warning: Could not make blocked list immutable${NC}"
|
||||||
|
chattr +i "$GREYLIST_DEST" 2>/dev/null || echo -e "${YELLOW}Warning: Could not make greylist immutable${NC}"
|
||||||
|
# Note: whitelist is intentionally left modifiable for user convenience
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}Warning: chattr not available, policy files will not be immutable${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Install VirtualBox enforcement script if available
|
||||||
|
if [ -f "$VBOX_ENFORCE_SOURCE" ]; then
|
||||||
|
echo -e "${BLUE}Installing VirtualBox hosts enforcement script...${NC}"
|
||||||
|
mkdir -p "$VBOX_INSTALL_DIR"
|
||||||
|
cp "$VBOX_ENFORCE_SOURCE" "$VBOX_ENFORCE_DEST"
|
||||||
|
chmod +x "$VBOX_ENFORCE_DEST"
|
||||||
|
echo -e "${GREEN}VirtualBox enforcement script installed to ${VBOX_ENFORCE_DEST}${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}VirtualBox enforcement script not found, skipping...${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
# Create symbolic link
|
# Create symbolic link
|
||||||
echo -e "${BLUE}Creating symbolic link...${NC}"
|
echo -e "${BLUE}Creating symbolic link...${NC}"
|
||||||
ln -sf "$WRAPPER_DEST" /usr/bin/pacman
|
ln -sf "$WRAPPER_DEST" /usr/bin/pacman
|
||||||
echo -e "${GREEN}Installation complete!${NC}"
|
echo -e "${GREEN}Installation complete!${NC}"
|
||||||
echo -e "Pacman is now wrapped. The original pacman is available at ${CYAN}/usr/bin/pacman.orig${NC}"
|
echo -e "Pacman is now wrapped. The original pacman is available at ${CYAN}/usr/bin/pacman.orig${NC}"
|
||||||
|
echo -e "${CYAN}Policy files are now protected with immutable attributes.${NC}"
|
||||||
|
if [ -f "$VBOX_ENFORCE_DEST" ]; then
|
||||||
|
echo -e "${CYAN}VirtualBox VMs will automatically be configured to use host's /etc/hosts.${NC}"
|
||||||
|
fi
|
||||||
|
|||||||
@ -17,6 +17,50 @@ declare -a BLOCKED_KEYWORDS_LIST=()
|
|||||||
declare -a WHITELISTED_NAMES_LIST=()
|
declare -a WHITELISTED_NAMES_LIST=()
|
||||||
declare -a GREYLISTED_KEYWORDS_LIST=()
|
declare -a GREYLISTED_KEYWORDS_LIST=()
|
||||||
POLICY_LISTS_LOADED=0
|
POLICY_LISTS_LOADED=0
|
||||||
|
INTEGRITY_DIR="/var/lib/pacman-wrapper"
|
||||||
|
INTEGRITY_FILE="${INTEGRITY_DIR}/policy.sha256"
|
||||||
|
|
||||||
|
# Verify integrity of policy files
|
||||||
|
verify_policy_integrity() {
|
||||||
|
if [[ ! -f $INTEGRITY_FILE ]]; then
|
||||||
|
echo -e "${RED}SECURITY WARNING: Policy integrity file missing!${NC}" >&2
|
||||||
|
echo -e "${RED}The pacman wrapper may have been tampered with.${NC}" >&2
|
||||||
|
echo -e "${RED}Please reinstall the wrapper using: sudo install_pacman_wrapper.sh${NC}" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local script_dir
|
||||||
|
script_dir="$(dirname "$(readlink -f "$0")")"
|
||||||
|
local blocked_file="$script_dir/pacman_blocked_keywords.txt"
|
||||||
|
local greylist_file="$script_dir/pacman_greylist.txt"
|
||||||
|
local whitelist_file="$script_dir/pacman_whitelist.txt"
|
||||||
|
|
||||||
|
# Verify checksums
|
||||||
|
local failed=0
|
||||||
|
while IFS= read -r line; do
|
||||||
|
local expected_hash expected_file
|
||||||
|
expected_hash=$(echo "$line" | awk '{print $1}')
|
||||||
|
expected_file=$(echo "$line" | awk '{print $2}')
|
||||||
|
|
||||||
|
if [[ -f $expected_file ]]; then
|
||||||
|
local actual_hash
|
||||||
|
actual_hash=$(sha256sum "$expected_file" 2>/dev/null | awk '{print $1}')
|
||||||
|
if [[ $actual_hash != "$expected_hash" ]]; then
|
||||||
|
echo -e "${RED}SECURITY WARNING: Policy file integrity check failed for $expected_file${NC}" >&2
|
||||||
|
failed=1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done < "$INTEGRITY_FILE"
|
||||||
|
|
||||||
|
if [[ $failed -eq 1 ]]; then
|
||||||
|
echo -e "${RED}CRITICAL: Policy files have been tampered with!${NC}" >&2
|
||||||
|
echo -e "${RED}This could be an attempt to bypass security restrictions.${NC}" >&2
|
||||||
|
echo -e "${RED}Wrapper operation DENIED. Please reinstall using: sudo install_pacman_wrapper.sh${NC}" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
load_policy_lists() {
|
load_policy_lists() {
|
||||||
if [[ $POLICY_LISTS_LOADED -eq 1 ]]; then
|
if [[ $POLICY_LISTS_LOADED -eq 1 ]]; then
|
||||||
@ -409,11 +453,22 @@ function is_steam_package() {
|
|||||||
[[ $1 == "steam" ]]
|
[[ $1 == "steam" ]]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Helper to check if a package name is VirtualBox (hardcoded, cannot be bypassed by editing policy files)
|
||||||
|
function is_virtualbox_package() {
|
||||||
|
local pkg_lower="${1,,}"
|
||||||
|
[[ $pkg_lower == *"virtualbox"* || $pkg_lower == *"vbox"* ]]
|
||||||
|
}
|
||||||
|
|
||||||
# Function to check if user is trying to install steam (challenge-eligible package)
|
# Function to check if user is trying to install steam (challenge-eligible package)
|
||||||
function check_for_steam() {
|
function check_for_steam() {
|
||||||
check_install_for is_steam_package "$@"
|
check_install_for is_steam_package "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Function to check if user is trying to install VirtualBox (hardcoded enforcement)
|
||||||
|
function check_for_virtualbox() {
|
||||||
|
check_install_for is_virtualbox_package "$@"
|
||||||
|
}
|
||||||
|
|
||||||
# Function to check if current day is a weekday (after 4PM Friday until midnight Sunday)
|
# Function to check if current day is a weekday (after 4PM Friday until midnight Sunday)
|
||||||
function is_weekday() {
|
function is_weekday() {
|
||||||
local day_of_week
|
local day_of_week
|
||||||
@ -581,12 +636,38 @@ function prompt_for_greylist_challenge() {
|
|||||||
run_word_challenge "Greylist" 6 120 90 30 15 20
|
run_word_challenge "Greylist" 6 120 90 30 15 20
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Function to prompt for VirtualBox installation (enhanced security, hardcoded)
|
||||||
|
function prompt_for_virtualbox_challenge() {
|
||||||
|
echo -e "${RED}═══════════════════════════════════════════════════════${NC}"
|
||||||
|
echo -e "${RED} VIRTUALBOX INSTALLATION ATTEMPT DETECTED ${NC}"
|
||||||
|
echo -e "${RED}═══════════════════════════════════════════════════════${NC}"
|
||||||
|
echo -e "${YELLOW}WARNING: You are trying to install VirtualBox.${NC}"
|
||||||
|
echo -e "${YELLOW}This package can be used to bypass /etc/hosts restrictions.${NC}"
|
||||||
|
echo -e ""
|
||||||
|
echo -e "${CYAN}Security measures will be automatically applied:${NC}"
|
||||||
|
echo -e " 1. VMs will use host's DNS resolution"
|
||||||
|
echo -e " 2. Host's /etc/hosts will be shared with VMs (read-only)"
|
||||||
|
echo -e " 3. Policy enforcement cannot be disabled via file editing"
|
||||||
|
echo -e ""
|
||||||
|
echo -e "${YELLOW}This is a HARDCODED restriction that cannot be bypassed by${NC}"
|
||||||
|
echo -e "${YELLOW}modifying policy files or reinstalling the wrapper.${NC}"
|
||||||
|
echo -e ""
|
||||||
|
|
||||||
|
# More difficult challenge: word_length=7, words_count=150, timeout=120s, initial_delay=45, post_delay=30-50
|
||||||
|
run_word_challenge "VirtualBox Security" 7 150 120 45 30 20
|
||||||
|
}
|
||||||
|
|
||||||
# Check for wrapper-specific commands
|
# Check for wrapper-specific commands
|
||||||
if [[ $1 == "--help-wrapper" ]]; then
|
if [[ $1 == "--help-wrapper" ]]; then
|
||||||
show_help
|
show_help
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# CRITICAL: Verify policy file integrity before any operations
|
||||||
|
if ! verify_policy_integrity; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# Before any pacman action, ensure maintenance services exist
|
# Before any pacman action, ensure maintenance services exist
|
||||||
ensure_periodic_maintenance
|
ensure_periodic_maintenance
|
||||||
|
|
||||||
@ -606,6 +687,13 @@ if check_for_steam "$@"; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Check for VirtualBox (HARDCODED - cannot be bypassed by editing policy files)
|
||||||
|
if check_for_virtualbox "$@"; then
|
||||||
|
if ! prompt_for_virtualbox_challenge; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# Check for greylisted packages (challenge-eligible)
|
# Check for greylisted packages (challenge-eligible)
|
||||||
if check_for_greylisted "$@"; then
|
if check_for_greylisted "$@"; then
|
||||||
if ! prompt_for_greylist_challenge; then
|
if ! prompt_for_greylist_challenge; then
|
||||||
@ -656,6 +744,52 @@ remove_installed_blocked_packages "$@"
|
|||||||
# Also remove installed greylisted packages
|
# Also remove installed greylisted packages
|
||||||
remove_installed_greylisted_packages "$@"
|
remove_installed_greylisted_packages "$@"
|
||||||
|
|
||||||
|
# If VirtualBox was involved in this operation, enforce hosts file sharing
|
||||||
|
enforce_vbox_hosts_if_needed() {
|
||||||
|
# Only check after install operations
|
||||||
|
if [[ ${1:-} != "-S"* && ${1:-} != "-U"* ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if VirtualBox is installed
|
||||||
|
if ! "$PACMAN_BIN" -Qq virtualbox > /dev/null 2>&1; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Locate the enforcement script
|
||||||
|
local script_dir
|
||||||
|
script_dir="$(dirname "$(readlink -f "$0")")"
|
||||||
|
local vbox_enforce_script=""
|
||||||
|
|
||||||
|
# Try to find the enforcement script
|
||||||
|
if [[ -f "$script_dir/../virtualbox/enforce_vbox_hosts.sh" ]]; then
|
||||||
|
vbox_enforce_script="$script_dir/../virtualbox/enforce_vbox_hosts.sh"
|
||||||
|
elif [[ -f "$HOME/linux-configuration/scripts/digital_wellbeing/virtualbox/enforce_vbox_hosts.sh" ]]; then
|
||||||
|
vbox_enforce_script="$HOME/linux-configuration/scripts/digital_wellbeing/virtualbox/enforce_vbox_hosts.sh"
|
||||||
|
elif [[ -f "/usr/local/share/digital_wellbeing/virtualbox/enforce_vbox_hosts.sh" ]]; then
|
||||||
|
vbox_enforce_script="/usr/local/share/digital_wellbeing/virtualbox/enforce_vbox_hosts.sh"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z $vbox_enforce_script ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if enforcement is already applied
|
||||||
|
if bash "$vbox_enforce_script" check > /dev/null 2>&1; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# VirtualBox is installed but enforcement not applied
|
||||||
|
echo -e "${YELLOW}VirtualBox detected. Applying /etc/hosts enforcement to VMs...${NC}" >&2
|
||||||
|
if [[ $EUID -ne 0 ]]; then
|
||||||
|
sudo bash "$vbox_enforce_script" enforce || echo -e "${RED}Failed to enforce hosts on VirtualBox VMs${NC}" >&2
|
||||||
|
else
|
||||||
|
bash "$vbox_enforce_script" enforce || echo -e "${RED}Failed to enforce hosts on VirtualBox VMs${NC}" >&2
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
enforce_vbox_hosts_if_needed "$@"
|
||||||
|
|
||||||
# Display some helpful tips depending on the operation
|
# Display some helpful tips depending on the operation
|
||||||
if [[ $1 == "-S" || $1 == "-S "* ]] && [ $exit_code -eq 0 ]; then
|
if [[ $1 == "-S" || $1 == "-S "* ]] && [ $exit_code -eq 0 ]; then
|
||||||
echo -e "${CYAN}Tip:${NC} You may need to log out or restart to use some newly installed software."
|
echo -e "${CYAN}Tip:${NC} You may need to log out or restart to use some newly installed software."
|
||||||
|
|||||||
279
scripts/digital_wellbeing/virtualbox/enforce_vbox_hosts.sh
Normal file
279
scripts/digital_wellbeing/virtualbox/enforce_vbox_hosts.sh
Normal file
@ -0,0 +1,279 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# filepath: enforce_vbox_hosts.sh
|
||||||
|
# Enforce host machine's /etc/hosts file on all VirtualBox VMs
|
||||||
|
# This prevents VMs from bypassing host-level content filtering
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Colors
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[0;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
CYAN='\033[0;36m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# Auto-sudo functionality
|
||||||
|
if [ "$EUID" -ne 0 ]; then
|
||||||
|
echo -e "${YELLOW}Executing with sudo...${NC}"
|
||||||
|
exec sudo "$0" "$@"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if VBoxManage is available
|
||||||
|
if ! command -v VBoxManage > /dev/null 2>&1; then
|
||||||
|
echo -e "${RED}VBoxManage not found. VirtualBox may not be installed.${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
VBOX_SHARED_FOLDER_NAME="host_etc"
|
||||||
|
HOSTS_ENFORCEMENT_MARKER="/var/lib/vbox-hosts-enforced"
|
||||||
|
|
||||||
|
# Get list of all VMs
|
||||||
|
get_all_vms() {
|
||||||
|
VBoxManage list vms | awk -F'"' '{print $2}'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get list of running VMs
|
||||||
|
get_running_vms() {
|
||||||
|
VBoxManage list runningvms | awk -F'"' '{print $2}'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Configure a VM to use host DNS (NAT network)
|
||||||
|
configure_vm_dns() {
|
||||||
|
local vm_name="$1"
|
||||||
|
echo -e "${BLUE}Configuring DNS for VM: ${vm_name}${NC}"
|
||||||
|
|
||||||
|
# Enable DNS proxy for NAT adapter (adapter 1 by default)
|
||||||
|
# This makes the VM use the host's DNS resolution
|
||||||
|
VBoxManage modifyvm "$vm_name" --natdnshostresolver1 on 2>/dev/null || true
|
||||||
|
VBoxManage modifyvm "$vm_name" --natdnsproxy1 on 2>/dev/null || true
|
||||||
|
|
||||||
|
echo -e "${GREEN}DNS configuration applied to ${vm_name}${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Add shared folder for /etc directory (read-only)
|
||||||
|
configure_hosts_shared_folder() {
|
||||||
|
local vm_name="$1"
|
||||||
|
echo -e "${BLUE}Setting up /etc/hosts sharing for VM: ${vm_name}${NC}"
|
||||||
|
|
||||||
|
# Remove existing shared folder if present
|
||||||
|
VBoxManage sharedfolder remove "$vm_name" --name "$VBOX_SHARED_FOLDER_NAME" 2>/dev/null || true
|
||||||
|
|
||||||
|
# Add /etc as a shared folder (read-only)
|
||||||
|
VBoxManage sharedfolder add "$vm_name" \
|
||||||
|
--name "$VBOX_SHARED_FOLDER_NAME" \
|
||||||
|
--hostpath "/etc" \
|
||||||
|
--readonly \
|
||||||
|
--automount 2>/dev/null || {
|
||||||
|
echo -e "${YELLOW}Could not add shared folder to ${vm_name} (VM may be running)${NC}"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
echo -e "${GREEN}Shared folder configured for ${vm_name}${NC}"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create a startup script that can be placed in VMs
|
||||||
|
generate_vm_startup_script() {
|
||||||
|
local output_file="${1:-/tmp/vbox_hosts_sync.sh}"
|
||||||
|
|
||||||
|
cat > "$output_file" << 'EOF'
|
||||||
|
#!/bin/bash
|
||||||
|
# VirtualBox VM startup script to sync /etc/hosts from host machine
|
||||||
|
# This should be placed in the VM and run at startup
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SHARED_FOLDER_MOUNT="/mnt/host_etc"
|
||||||
|
HOST_HOSTS_FILE="${SHARED_FOLDER_MOUNT}/hosts"
|
||||||
|
VM_HOSTS_FILE="/etc/hosts"
|
||||||
|
BACKUP_HOSTS_FILE="/etc/hosts.pre-vbox-sync"
|
||||||
|
|
||||||
|
# Function to check if running in VirtualBox
|
||||||
|
is_virtualbox() {
|
||||||
|
if command -v dmidecode > /dev/null 2>&1; then
|
||||||
|
if sudo dmidecode -s system-product-name 2>/dev/null | grep -qi "VirtualBox"; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v systemd-detect-virt > /dev/null 2>&1; then
|
||||||
|
if systemd-detect-virt | grep -qi "oracle"; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Only run if we're in VirtualBox
|
||||||
|
if ! is_virtualbox; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create mount point if it doesn't exist
|
||||||
|
mkdir -p "$SHARED_FOLDER_MOUNT"
|
||||||
|
|
||||||
|
# Try to mount the shared folder (if Guest Additions are installed)
|
||||||
|
if ! mountpoint -q "$SHARED_FOLDER_MOUNT"; then
|
||||||
|
if command -v mount.vboxsf > /dev/null 2>&1; then
|
||||||
|
mount -t vboxsf -o ro host_etc "$SHARED_FOLDER_MOUNT" 2>/dev/null || {
|
||||||
|
echo "Could not mount VirtualBox shared folder"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
else
|
||||||
|
echo "VirtualBox Guest Additions not installed, cannot sync hosts file"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Sync hosts file if the shared one exists
|
||||||
|
if [ -f "$HOST_HOSTS_FILE" ]; then
|
||||||
|
# Backup current hosts file if not already backed up
|
||||||
|
if [ ! -f "$BACKUP_HOSTS_FILE" ]; then
|
||||||
|
cp "$VM_HOSTS_FILE" "$BACKUP_HOSTS_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Copy host's hosts file to VM
|
||||||
|
cp "$HOST_HOSTS_FILE" "$VM_HOSTS_FILE"
|
||||||
|
echo "Synced /etc/hosts from host machine"
|
||||||
|
|
||||||
|
# Make it harder to modify (though not impossible in VM)
|
||||||
|
chmod 444 "$VM_HOSTS_FILE"
|
||||||
|
fi
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod +x "$output_file"
|
||||||
|
echo -e "${GREEN}Generated VM startup script at ${output_file}${NC}"
|
||||||
|
echo -e "${CYAN}Copy this script to your VMs and add it to their startup (e.g., /etc/rc.local or systemd)${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Apply enforcement to all VMs
|
||||||
|
enforce_all_vms() {
|
||||||
|
local -a vms
|
||||||
|
mapfile -t vms < <(get_all_vms)
|
||||||
|
|
||||||
|
if [[ ${#vms[@]} -eq 0 ]]; then
|
||||||
|
echo -e "${YELLOW}No VirtualBox VMs found.${NC}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${CYAN}Found ${#vms[@]} VM(s). Applying /etc/hosts enforcement...${NC}"
|
||||||
|
|
||||||
|
local success=0
|
||||||
|
local failed=0
|
||||||
|
|
||||||
|
for vm in "${vms[@]}"; do
|
||||||
|
echo -e "\n${BLUE}Processing VM: ${vm}${NC}"
|
||||||
|
|
||||||
|
# Configure DNS settings (works even when VM is running)
|
||||||
|
configure_vm_dns "$vm"
|
||||||
|
|
||||||
|
# Try to configure shared folder (only works when VM is stopped)
|
||||||
|
if configure_hosts_shared_folder "$vm"; then
|
||||||
|
((success++))
|
||||||
|
else
|
||||||
|
((failed++))
|
||||||
|
echo -e "${YELLOW}Note: Stop the VM and run this script again to add shared folder${NC}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo -e "\n${GREEN}Enforcement complete!${NC}"
|
||||||
|
echo -e "Successfully configured: ${success} VM(s)"
|
||||||
|
[[ $failed -gt 0 ]] && echo -e "${YELLOW}Needs VM shutdown for full config: ${failed} VM(s)${NC}"
|
||||||
|
|
||||||
|
# Mark that enforcement has been applied
|
||||||
|
touch "$HOSTS_ENFORCEMENT_MARKER"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if enforcement is needed
|
||||||
|
check_enforcement_status() {
|
||||||
|
local -a vms
|
||||||
|
mapfile -t vms < <(get_all_vms)
|
||||||
|
|
||||||
|
if [[ ${#vms[@]} -eq 0 ]]; then
|
||||||
|
echo -e "${GREEN}No VMs to enforce.${NC}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -f $HOSTS_ENFORCEMENT_MARKER ]]; then
|
||||||
|
echo -e "${YELLOW}Hosts enforcement has not been applied to VMs.${NC}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${GREEN}Hosts enforcement marker found.${NC}"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Show status
|
||||||
|
show_status() {
|
||||||
|
echo -e "${CYAN}VirtualBox Hosts Enforcement Status${NC}"
|
||||||
|
echo -e "${CYAN}====================================${NC}\n"
|
||||||
|
|
||||||
|
local -a all_vms running_vms
|
||||||
|
mapfile -t all_vms < <(get_all_vms)
|
||||||
|
mapfile -t running_vms < <(get_running_vms)
|
||||||
|
|
||||||
|
echo -e "Total VMs: ${#all_vms[@]}"
|
||||||
|
echo -e "Running VMs: ${#running_vms[@]}"
|
||||||
|
|
||||||
|
if [[ -f $HOSTS_ENFORCEMENT_MARKER ]]; then
|
||||||
|
echo -e "Enforcement status: ${GREEN}Applied${NC}"
|
||||||
|
else
|
||||||
|
echo -e "Enforcement status: ${RED}Not applied${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "\n${CYAN}VMs:${NC}"
|
||||||
|
for vm in "${all_vms[@]}"; do
|
||||||
|
local running=""
|
||||||
|
if printf '%s\n' "${running_vms[@]}" | grep -qx "$vm"; then
|
||||||
|
running=" ${GREEN}[RUNNING]${NC}"
|
||||||
|
fi
|
||||||
|
echo -e " - ${vm}${running}"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main function
|
||||||
|
main() {
|
||||||
|
local action="${1:-enforce}"
|
||||||
|
|
||||||
|
case "$action" in
|
||||||
|
enforce|apply)
|
||||||
|
enforce_all_vms
|
||||||
|
;;
|
||||||
|
check)
|
||||||
|
if check_enforcement_status; then
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
status)
|
||||||
|
show_status
|
||||||
|
;;
|
||||||
|
generate-script)
|
||||||
|
local output="${2:-/tmp/vbox_hosts_sync.sh}"
|
||||||
|
generate_vm_startup_script "$output"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo -e "${CYAN}VirtualBox /etc/hosts Enforcement Tool${NC}"
|
||||||
|
echo ""
|
||||||
|
echo "Usage: $0 [command]"
|
||||||
|
echo ""
|
||||||
|
echo "Commands:"
|
||||||
|
echo " enforce Apply /etc/hosts enforcement to all VMs (default)"
|
||||||
|
echo " check Check if enforcement has been applied"
|
||||||
|
echo " status Show current enforcement status"
|
||||||
|
echo " generate-script [path] Generate a script to place in VMs for hosts sync"
|
||||||
|
echo ""
|
||||||
|
echo "This tool configures VirtualBox VMs to:"
|
||||||
|
echo " 1. Use host's DNS resolution (via NAT DNS proxy)"
|
||||||
|
echo " 2. Share /etc from host (read-only) for hosts file access"
|
||||||
|
echo ""
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
Loading…
Reference in New Issue
Block a user