This project implements multiple layers of security controls, ensuring that if one layer is bypassed, others still protect the system.
Location: Cloud perimeter (Azure network)
Rules:
- Priority 100: Allow SSH (22/tcp) from admin IP only (configured in terraform.tfvars)
- Priority 110: Allow Minecraft (25565/tcp) from Internet
- Priority 4000: Deny all other inbound traffic
Purpose: First line of defense, blocks traffic before it reaches the VM
Location: VM operating system
Rules:
- Default policy: DENY inbound, ALLOW outbound
- SSH (22/tcp): LIMIT (rate-limited to 6 connections per 30 seconds per IP)
- Minecraft (25565/tcp): ALLOW
- All other ports: BLOCKED
Purpose: Defense-in-depth redundancy with NSG, protects if NSG misconfigured
Location: VM user-space monitoring daemon
Configuration:
- Monitors: /var/log/auth.log via systemd journal
- Threshold: 5 failed SSH attempts in 10 minutes
- Action: Ban IP for 10 minutes via iptables
- Backend: systemd
Purpose: Active response to brute-force attacks, adapts to attacker behavior
Location: SSH daemon configuration (/etc/ssh/sshd_config)
Settings:
- PermitRootLogin: no
- PasswordAuthentication: no
- ChallengeResponseAuthentication: no
- PermitEmptyPasswords: no
- LoginGraceTime: 30 seconds
- MaxAuthTries: 3
- Protocol: 2
Purpose: Eliminates password-based attacks, reduces attack surface
Location: systemd timer (daily)
Configuration:
- Source: Ubuntu security and stable repositories
- Schedule: Daily via apt-daily-upgrade.timer
- Auto-reboot: Intelligent (based on server state and player count)
- Notifications: System log, MOTD, in-game chat (if players present)
Purpose: Closes known vulnerabilities before exploitation
Challenge: Cost-optimized VMs are deallocated during off-hours, can't reboot at fixed time.
Solution: Intelligent reboot manager that adapts to server state:
- No Minecraft running: Displays reboot required, exits (admin decision)
- Minecraft running, 0 players: Automatic immediate reboot
- Minecraft running, N players: 10-minute countdown with warnings every minute
Player Experience (in-game chat messages):
[SYSTEM] WARNING: Server will restart in 10 minutes
[SYSTEM] Reason: Critical security updates require reboot
[SYSTEM] Please save your progress and prepare to log out!
[SYSTEM] WARNING: Server restarting in 9 minutes!
[SYSTEM] WARNING: Server restarting in 8 minutes!
...
[SYSTEM] WARNING: 10 SECONDS UNTIL RESTART!
[SYSTEM] Restarting in 3... 2... 1...
Security:
- RCON bound to localhost only (127.0.0.1), not internet-accessible
- Strong 32-character random password
- UFW blocks external access to RCON port (25575)
- Password stored in root-only file (0600 permissions)
| Threat | Mitigation | Layer |
|---|---|---|
| SSH Brute-Force | fail2ban + key-only auth | Layer 3 & 4 |
| Credential Stuffing | Password auth disabled | Layer 4 |
| Unpatched CVEs | unattended-upgrades | Layer 5 |
| Port Scanning | NSG + UFW default-deny | Layer 1 & 2 |
| Root Compromise | Root login disabled, sudo only | Layer 4 |
| DoS (Connection Exhaustion) | SSH rate-limiting, reduced LoginGraceTime | Layer 2 & 4 |
| Lateral Movement | Single-purpose VM, minimal packages | Architecture |
| Risk | Impact | Likelihood | Mitigation Plan |
|---|---|---|---|
| Zero-day in SSH | HIGH | LOW | Monitor CVEs, update immediately |
| DDoS on Minecraft port | MEDIUM | MEDIUM | Accept (DDoS Protection Standard too expensive) |
| Azure platform compromise | HIGH | VERY LOW | Out of scope, trust Azure |
| Minecraft server exploit | MEDIUM | LOW | Keep server updated, whitelist if private |
Test SSH password auth blocked:
ssh -o PubkeyAuthentication=no mcadmin@<VM_PUBLIC_IP>
# Expected: Permission denied (publickey)
Test root login blocked:
ssh root@<VM_PUBLIC_IP>
# Expected: Permission denied (publickey)
Test UFW firewall active:
sudo ufw status verbose
# Expected: Status: active, SSH LIMIT, Minecraft ALLOW
Test fail2ban monitoring:
sudo fail2ban-client status sshd
# Expected: Jail enabled, filter active
Test unattended-upgrades configured:
cat /etc/apt/apt.conf.d/50unattended-upgrades | grep Automatic-Reboot
# Expected: "false" (manual reboot management)
Test reboot notification system (dry-run):
sudo touch /var/run/reboot-required
sudo /usr/local/bin/check-reboot-required
# Expected: Displays reboot warning, updates MOTD
Verify RCON is NOT accessible from internet:
nmap -p 25575 <VM_PUBLIC_IP>
# Expected: filtered or closed
Verify RCON works locally:
ssh mcadmin@<VM_PUBLIC_IP>
mcrcon -H 127.0.0.1 -P 25575 -p <password> "list"
# Expected: Player list displayed
- NSG rules match documented configuration
- UFW status shows correct rules
- SSH config matches hardened settings
- fail2ban jail active and monitoring
- unattended-upgrades configured (auto-reboot disabled)
- Intelligent reboot scripts present and executable
- No unnecessary services running
- All security services enabled on boot
- RCON bound to localhost only
- RCON password file has 0600 permissions
The security controls align with:
- CIS Ubuntu 22.04 Benchmark: SSH hardening, firewall configuration
- NIST Cybersecurity Framework: Identify, Protect, Detect (fail2ban), Respond
- Azure Security Benchmark: Network segmentation, access control, vulnerability management
- Check fail2ban status:
sudo fail2ban-client status sshd - Review banned IPs: Look for patterns (country, ASN)
- Check auth logs:
sudo grep 'Failed password' /var/log/auth.log - If massive attack: Consider changing SSH port (security by obscurity, but effective)
- Patches auto-install daily via unattended-upgrades
- Reboot handled by intelligent manager:
- No players: Auto-reboot
- Players online: 10-minute countdown
- For urgent CVE:
sudo apt update && sudo apt upgrade -y - Manual reboot:
sudo /usr/local/bin/check-reboot-required
- Immediately deallocate VM:
az vm deallocate --name vm-minecraft-dev-scus --resource-group rg-minecraft-dev-scus - Take snapshot of disk for forensics
- Review NSG flow logs (if enabled)
- Rebuild from Terraform/Ansible (infrastructure as code)
- Rotate SSH keys: Generate new keypair, update Terraform