#!/bin/sh
# ========================================
# FreeBSD 13.5 Hypervisor Hardening Script - FINAL
# Secure, POSIX-compliant, with interface checks and snapshot
# ========================================
echo "=== Advanced Hypervisor Hardening Started ==="
# ----------------------------
# Configuration - Change as needed
# ----------------------------
MGMT_NIC="em0"
MGMT_IP="192.168.1.100/24"
MGMT_GATEWAY="192.168.1.1"
BRIDGES="bridge0 bridge1 bridge2"
TAPS="tap0 tap1 tap2"
WAN_NICS="em1 em2 em3"
# ----------------------------
# Helper function for error checking
# ----------------------------
check() {
if [ $? -ne 0 ]; then
echo "Error: $1" >&2
fi
}
# ----------------------------
# 1️⃣ User and Access Management
# ----------------------------
echo "-> Configuring User and Access Management"
if ! id -u admin >/dev/null 2>&1; then
pw useradd admin -d /home/admin -s /bin/sh -m
echo "admin ALL=(ALL) NOPASSWD: ALL" > /usr/local/etc/sudoers.d/admin
chmod 440 /usr/local/etc/sudoers.d/admin
fi
passwd -l root
# ----------------------------
# 2️⃣ SSH Hardening
# ----------------------------
echo "-> Hardening SSH"
cat << EOF > /etc/ssh/sshd_config
Port 2222
Protocol 2
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
ChallengeResponseAuthentication no
PubkeyAuthentication yes
UsePAM yes
AllowUsers admin
EOF
service sshd restart
check "SSHD restart"
# ----------------------------
# 3️⃣ Network Hygiene
# ----------------------------
echo "-> Configuring Management LAN only"
ifconfig $MGMT_NIC inet $MGMT_IP up
for nic in $WAN_NICS $BRIDGES $TAPS; do
ifconfig $nic inet delete 2>/dev/null
done
# Disable routing
sysctl net.inet.ip.forwarding=0
sysctl net.inet6.ip6.forwarding=0
sysrc gateway_enable="NO"
# ----------------------------
# 4️⃣ PF Firewall
# ----------------------------
echo "-> Configuring PF Firewall"
cat << EOF > /etc/pf.conf
set block-policy drop
set skip on lo
block all
# Management SSH
pass in on $MGMT_NIC proto tcp to port 2222 keep state
# DNS and NTP outbound
pass out proto { tcp, udp } to port 53 keep state
pass out proto udp to port 123 keep state
# Optional: log blocked packets
block in log all
EOF
sysrc pf_enable="YES"
service pf restart
check "PF restart"
# ----------------------------
# 5️⃣ Kernel and Sysctl Hardening
# ----------------------------
echo "-> Applying sysctl hardening"
cat << EOF >> /etc/sysctl.conf
net.inet.ip.redirect=0
net.inet.ip.accept_sourceroute=0
net.inet.tcp.blackhole=2
net.inet.udp.blackhole=1
security.bsd.see_other_uids=0
security.bsd.see_other_gids=0
security.bsd.unprivileged_read_msgbuf=0
security.bsd.unprivileged_proc_debug=0
net.inet.icmp.drop_redirect=1
EOF
sysctl -f /etc/sysctl.conf
# ----------------------------
# 6️⃣ Disable unnecessary services
# ----------------------------
echo "-> Disabling unnecessary services"
sysrc sendmail_enable="NONE"
sysrc rpcbind_enable="NO"
sysrc ntpd_enable="NO"
service ntpd stop 2>/dev/null
service sendmail stop 2>/dev/null
service nfsd stop 2>/dev/null
# ----------------------------
# 7️⃣ Filesystem & ZFS
# ----------------------------
echo "-> Filesystem and permissions"
chmod 700 /root
chmod 750 /usr/local/etc
if zfs list >/dev/null 2>&1; then
zfs set atime=off zroot
echo "-> Creating ZFS snapshot"
zfs snapshot zroot/ROOT/default@hypervisor-clean
fi
# ----------------------------
# 8️⃣ Interface and Bridge Checks
# ----------------------------
echo "-> Checking bridge and tap interfaces"
for iface in $BRIDGES $TAPS $WAN_NICS $MGMT_NIC; do
if ifconfig $iface >/dev/null 2>&1; then
status=$(ifconfig $iface | grep "status: active")
if [ -n "$status" ]; then
echo "Interface $iface: ACTIVE"
else
echo "Warning: Interface $iface: INACTIVE"
fi
else
echo "Warning: Interface $iface: NOT FOUND"
fi
done
# ----------------------------
# 9️⃣ Load essential kernel modules
# ----------------------------
echo "-> Loading necessary kernel modules"
sysrc kld_list="vmm if_bridge if_tap nmdm"
# ----------------------------
# 10️⃣ Final Report
# ----------------------------
echo "=== Hypervisor Hardening Completed ==="
echo "- Check: No IP on WAN interfaces or bridges"
echo "- SSH only accessible from $MGMT_NIC"
echo "- PF active and blocking all other traffic"
echo "- Bridge/tap interfaces checked above"
echo "- Backup snapshot exists (if ZFS)"
# Reboot prompt
echo -n "Do you want to reboot now? (y/n): "
read REPLY
case "$REPLY" in [Yy]*) reboot;; *) echo "Reboot skipped. Please reboot manually later.";; esac