Skip to content

Instantly share code, notes, and snippets.

@DfKimera
Created March 4, 2026 20:32
Show Gist options
  • Select an option

  • Save DfKimera/e3bc9cbf3d1a4febd960fa24e58253dc to your computer and use it in GitHub Desktop.

Select an option

Save DfKimera/e3bc9cbf3d1a4febd960fa24e58253dc to your computer and use it in GitHub Desktop.
<?php
function run($cmd) {
echo "Running: $cmd\n";
exec($cmd . " 2>&1", $out, $code);
echo implode("\n", $out) . "\n";
if ($code !== 0) {
echo "Command failed with code $code\n";
}
return $code === 0;
}
function write_file($path, $content) {
echo "Writing $path\n";
if (!file_put_contents($path, $content)) {
echo "Failed writing $path\n";
exit(1);
}
}
echo "=== EC2 Blocklist Bootstrap ===\n";
if (posix_geteuid() !== 0) {
echo "ERROR: Run this script as root\n";
exit(1);
}
echo "\nInstalling ipset if missing...\n";
run("apt-get update");
run("apt-get install -y ipset curl");
echo "\nCreating ipset directory...\n";
run("mkdir -p /etc/ipset");
echo "\nCreating ipset blocklist...\n";
run("ipset create blocklist hash:net -exist");
echo "\nSaving initial set...\n";
run("ipset save | tee /etc/ipset/blocklist.conf > /dev/null");
echo "\nConfiguring UFW hook...\n";
$ufwFile = "/etc/ufw/before.rules";
$rule = "-A ufw-before-input -m set --match-set blocklist src -j DROP";
$before = file_get_contents($ufwFile);
if (strpos($before, "match-set blocklist") === false) {
$before = preg_replace(
"/\\*filter/",
"*filter\n$rule",
$before
);
file_put_contents($ufwFile, $before);
echo "UFW rule inserted\n";
} else {
echo "UFW rule already exists\n";
}
run("ufw reload");
echo "\nWriting blocklist updater script...\n";
$script = <<<'BASH'
#!/usr/bin/env bash
URL="https://example.com/blocklist.txt"
TMP="/tmp/blocklist.txt"
SET="blocklist"
NEWSET="blocklist_new"
LOGTAG="blocklist-updater"
log() {
logger -t "$LOGTAG" "$1"
}
log "Starting blocklist update"
if ! curl -fsSL "$URL" -o "$TMP"; then
log "ERROR: failed to download blocklist"
exit 1
fi
COUNT=0
ipset create $NEWSET hash:net -exist
while read -r ip; do
case "$ip" in
""|\#*) continue ;;
esac
if ipset add $NEWSET "$ip" -exist 2>/dev/null; then
COUNT=$((COUNT+1))
fi
done < "$TMP"
ipset swap $SET $NEWSET
ipset destroy $NEWSET
ipset save > /etc/ipset/blocklist.conf
log "Blocklist update complete: $COUNT entries loaded"
BASH;
write_file("/usr/local/bin/update-blocklist.sh", $script);
run("chmod +x /usr/local/bin/update-blocklist.sh");
echo "\nWriting systemd restore service...\n";
$service = <<<UNIT
[Unit]
Description=Restore ipset blocklist
Before=ufw.service
[Service]
Type=oneshot
ExecStart=/sbin/ipset restore < /etc/ipset/blocklist.conf
[Install]
WantedBy=multi-user.target
UNIT;
write_file("/etc/systemd/system/ipset-restore.service", $service);
run("systemctl daemon-reload");
run("systemctl enable ipset-restore");
echo "\nAdding cron job...\n";
$cronLine = "0 * * * * /usr/local/bin/update-blocklist.sh";
$current = shell_exec("crontab -l 2>/dev/null");
if (strpos($current, "update-blocklist.sh") === false) {
file_put_contents("/tmp/cron.tmp", $current . "\n" . $cronLine . "\n");
run("crontab /tmp/cron.tmp");
unlink("/tmp/cron.tmp");
echo "Cron job installed\n";
} else {
echo "Cron job already present\n";
}
echo "\nRunning test update...\n";
if (!run("/usr/local/bin/update-blocklist.sh")) {
echo "Test update failed\n";
exit(1);
}
echo "\nVerifying ipset exists...\n";
exec("ipset list blocklist", $out, $code);
if ($code !== 0) {
echo "ERROR: ipset blocklist missing\n";
exit(1);
}
echo "ipset blocklist verified\n";
echo "\nChecking firewall rule...\n";
exec("iptables -L | grep blocklist", $out, $code);
if ($code !== 0) {
echo "WARNING: iptables rule not detected\n";
} else {
echo "iptables rule active\n";
}
echo "\nSetup complete.\n";
echo "View logs with:\n";
echo "journalctl -t blocklist-updater\n";
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment