From a8cd1c324c0541b0d26542168aeced085ec13201 Mon Sep 17 00:00:00 2001 From: doc Date: Mon, 30 Jun 2025 20:14:17 +0000 Subject: initial failzero commit --- functions/destroy_vps_by_label.sh | 28 +++++++ functions/disable_backups_by_label.sh | 23 ++++++ functions/disable_ip.sh | 18 +++++ functions/enable_backups_by_label.sh | 23 ++++++ functions/list_all_vps.sh | 9 +++ functions/provision.sh | 135 ++++++++++++++++++++++++++++++++++ functions/reboot_vps.sh | 7 ++ functions/resize_vps.sh | 27 +++++++ functions/safe_create_dataset.sh | 12 +++ functions/status_vps.sh | 8 ++ functions/usage.sh | 22 ++++++ functions/verify_ptr.sh | 29 ++++++++ 12 files changed, 341 insertions(+) create mode 100755 functions/destroy_vps_by_label.sh create mode 100755 functions/disable_backups_by_label.sh create mode 100644 functions/disable_ip.sh create mode 100755 functions/enable_backups_by_label.sh create mode 100755 functions/list_all_vps.sh create mode 100755 functions/provision.sh create mode 100755 functions/reboot_vps.sh create mode 100755 functions/resize_vps.sh create mode 100755 functions/safe_create_dataset.sh create mode 100755 functions/status_vps.sh create mode 100755 functions/usage.sh create mode 100755 functions/verify_ptr.sh (limited to 'functions') diff --git a/functions/destroy_vps_by_label.sh b/functions/destroy_vps_by_label.sh new file mode 100755 index 0000000..09d807e --- /dev/null +++ b/functions/destroy_vps_by_label.sh @@ -0,0 +1,28 @@ +destroy_vps_by_label() { + LABEL="$1" + echo "Looking for VPS with label '$LABEL'..." + LINODE_ID=$(curl -s -H "Authorization: Bearer $LINODE_API_TOKEN" \ + https://api.linode.com/v4/linode/instances | \ + jq -r --arg LABEL "$LABEL" '.data[] | select(.label == $LABEL) | .id') + + if [ -z "$LINODE_ID" ]; then + echo "Error: No Linode found with label '$LABEL'" + exit 1 + fi + + read -rp "Are you sure you want to destroy VPS '$LABEL' (ID: $LINODE_ID)? [y/N] " confirm + if [[ "$confirm" =~ ^[Yy]$ ]]; then + echo "Destroying Linode with ID $LINODE_ID (label: $LABEL)..." + HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE \ + https://api.linode.com/v4/linode/instances/$LINODE_ID \ + -H "Authorization: Bearer $LINODE_API_TOKEN") + + if [[ "$HTTP_STATUS" == "204" ]]; then + echo "✅ Linode $LABEL (ID $LINODE_ID) has been destroyed." + else + echo "❌ Failed to destroy VPS. HTTP status: $HTTP_STATUS" + fi + else + echo "Cancelled. VPS '$LABEL' not destroyed." + fi +} diff --git a/functions/disable_backups_by_label.sh b/functions/disable_backups_by_label.sh new file mode 100755 index 0000000..417bdb8 --- /dev/null +++ b/functions/disable_backups_by_label.sh @@ -0,0 +1,23 @@ +disable_backups_by_label() { + LABEL="$1" + LINODE_ID=$(curl -s -H "Authorization: Bearer $LINODE_API_TOKEN" \ + https://api.linode.com/v4/linode/instances | \ + jq -r --arg LABEL "$LABEL" '.data[] | select(.label == $LABEL) | .id') + + if [ -z "$LINODE_ID" ]; then + echo "❌ No Linode found with label '$LABEL'" + exit 1 + fi + + echo "Disabling backups for Linode '$LABEL' (ID: $LINODE_ID)..." + + HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X POST \ + https://api.linode.com/v4/linode/instances/$LINODE_ID/backups/disable \ + -H "Authorization: Bearer $LINODE_API_TOKEN") + + if [[ "$HTTP_STATUS" == "200" ]]; then + echo "✅ Backups disabled for Linode $LABEL." + else + echo "❌ Failed to disable backups (HTTP $HTTP_STATUS)" + fi +} diff --git a/functions/disable_ip.sh b/functions/disable_ip.sh new file mode 100644 index 0000000..0021b74 --- /dev/null +++ b/functions/disable_ip.sh @@ -0,0 +1,18 @@ +disable_ip() { + local ip="$1" + + if [[ -z "$ip" ]]; then + echo "[!] No IP specified." + exit 1 + fi + + echo "[*] Disabling access to VPS with IP: $ip" + + # Block all traffic to/from that IP via iptables + iptables -A INPUT -s "$ip" -j DROP + iptables -A OUTPUT -d "$ip" -j DROP + + echo "$ip - disabled on $(date)" >> /var/log/genesis-disabled.log + + echo "[✓] $ip has been blocked and logged." +} diff --git a/functions/enable_backups_by_label.sh b/functions/enable_backups_by_label.sh new file mode 100755 index 0000000..08fb31d --- /dev/null +++ b/functions/enable_backups_by_label.sh @@ -0,0 +1,23 @@ +enable_backups_by_label() { + LABEL="$1" + LINODE_ID=$(curl -s -H "Authorization: Bearer $LINODE_API_TOKEN" \ + https://api.linode.com/v4/linode/instances | \ + jq -r --arg LABEL "$LABEL" '.data[] | select(.label == $LABEL) | .id') + + if [ -z "$LINODE_ID" ]; then + echo "❌ No Linode found with label '$LABEL'" + exit 1 + fi + + echo "Enabling backups for Linode '$LABEL' (ID: $LINODE_ID)..." + + HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X POST \ + https://api.linode.com/v4/linode/instances/$LINODE_ID/backups/enable \ + -H "Authorization: Bearer $LINODE_API_TOKEN") + + if [[ "$HTTP_STATUS" == "200" ]]; then + echo "✅ Backups enabled for Linode $LABEL." + else + echo "❌ Failed to enable backups (HTTP $HTTP_STATUS)" + fi +} diff --git a/functions/list_all_vps.sh b/functions/list_all_vps.sh new file mode 100755 index 0000000..8ce99eb --- /dev/null +++ b/functions/list_all_vps.sh @@ -0,0 +1,9 @@ +list_all_vps() { + curl -s -H "Authorization: Bearer $LINODE_API_TOKEN" \ + https://api.linode.com/v4/linode/instances | \ + jq -r ' + .data[] | [.label, .id, .region, .type, .ipv4[0], .status] | + @tsv' | column -t -s $'\t' | \ + awk 'BEGIN { print "LABEL ID REGION TYPE IP STATUS" } + { printf "%-11s %-10s %-10s %-16s %-15s %s\n", $1, $2, $3, $4, $5, $6 }' +} diff --git a/functions/provision.sh b/functions/provision.sh new file mode 100755 index 0000000..f6e9d39 --- /dev/null +++ b/functions/provision.sh @@ -0,0 +1,135 @@ +provision_vps() { + LABEL="$1" + REGION="$2" + TYPE="$3" + IMAGE="$4" + ROOT_PASS="${5:-$(openssl rand -base64 16)}" + + if [[ "$LINODE_API_TOKEN" == "REPLACE_WITH_YOUR_LINODE_API_TOKEN" ]]; then + echo "❌ Error: You must set your LINODE_API_TOKEN at the top of this script." + exit 1 + fi + + CLOUD_INIT=$(cat </dev/null || true + systemctl disable linode-cloudinit 2>/dev/null || true + touch /etc/cloud/cloud-init.disabled + rm -rf /etc/cloud /var/lib/cloud /var/log/cloud-init.log + + rm -f /etc/motd /etc/update-motd.d/linode + rm -rf /usr/share/linode* + rm -f /etc/apt/sources.list.d/linode.list + apt remove --purge -y linode-cli linode-config 2>/dev/null || true + + echo "[genesisctl] Attempting to log to Krang via webhook..." >> /var/log/genesis-harden.log + curl -s -X POST -H "Content-Type: application/json" \ + -d "{\"host\": \"$GEN_HOSTNAME\", \"ip\": \"$IP_ADDR\", \"timestamp\": \"$(date)\"}" \ + http://krang.core.sshjunkie.com:8080/genesislog >> /var/log/genesis-harden.log 2>&1 || echo "[genesisctl] Krang webhook logging failed" >> /var/log/genesis-harden.log + + touch /var/log/genesis-hardened.ok + +runcmd: + - [ bash, /usr/local/bin/genesis_squeaky.sh ] +EOF +) + + USER_DATA=$(echo "$CLOUD_INIT" | base64 -w 0) + + echo "Provisioning VPS '$LABEL' in $REGION with type $TYPE and image $IMAGE..." + TMP_FILE=$(mktemp) + JSON_PAYLOAD=$(cat <> /home/doc/vpslogs/pending_rdns.log +} diff --git a/functions/reboot_vps.sh b/functions/reboot_vps.sh new file mode 100755 index 0000000..2741b9c --- /dev/null +++ b/functions/reboot_vps.sh @@ -0,0 +1,7 @@ +reboot_vps() { + LINODE_ID="$1" + echo "Rebooting Linode VPS ID $LINODE_ID..." + + curl -s -X POST https://api.linode.com/v4/linode/instances/$LINODE_ID/reboot \ + -H "Authorization: Bearer $LINODE_API_TOKEN" | jq +} diff --git a/functions/resize_vps.sh b/functions/resize_vps.sh new file mode 100755 index 0000000..c06ea91 --- /dev/null +++ b/functions/resize_vps.sh @@ -0,0 +1,27 @@ +resize_vps() { + LABEL="$1" + NEW_TYPE="$2" + + LINODE_ID=$(curl -s -H "Authorization: Bearer $LINODE_API_TOKEN" \ + https://api.linode.com/v4/linode/instances | \ + jq -r --arg LABEL "$LABEL" '.data[] | select(.label == $LABEL) | .id') + + if [ -z "$LINODE_ID" ]; then + echo "❌ No Linode found with label '$LABEL'" + exit 1 + fi + + echo "Resizing Linode '$LABEL' to type '$NEW_TYPE'..." + + HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X POST \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $LINODE_API_TOKEN" \ + -d '{"type": "'"$NEW_TYPE"'"}' \ + https://api.linode.com/v4/linode/instances/$LINODE_ID/resize) + + if [[ "$HTTP_STATUS" == "200" ]]; then + echo "✅ Linode $LABEL resized to $NEW_TYPE." + else + echo "❌ Failed to resize VPS. HTTP status: $HTTP_STATUS" + fi +} diff --git a/functions/safe_create_dataset.sh b/functions/safe_create_dataset.sh new file mode 100755 index 0000000..1960e55 --- /dev/null +++ b/functions/safe_create_dataset.sh @@ -0,0 +1,12 @@ +safe_create_dataset() { + FULLPATH="$1" + + # Remove any trailing slash + FULLPATH="${FULLPATH%/}" + + POOL="${FULLPATH%%/*}" + DATASET="${FULLPATH#*/}" + + echo "🛰 Connecting to Shredder to safely create '${POOL}/${DATASET}'..." + ssh shredder "/usr/local/bin/genesis-safe-zfs.sh $POOL $DATASET" +} diff --git a/functions/status_vps.sh b/functions/status_vps.sh new file mode 100755 index 0000000..91996e9 --- /dev/null +++ b/functions/status_vps.sh @@ -0,0 +1,8 @@ +status_vps() { + LABEL="$1" + curl -s -H "Authorization: Bearer $LINODE_API_TOKEN" \ + https://api.linode.com/v4/linode/instances | \ + jq -r --arg LABEL "$LABEL" ' + .data[] | select(.label == $LABEL) | + "Label: \(.label)\nID: \(.id)\nRegion: \(.region)\nType: \(.type)\nStatus: \(.status)\nIP: \(.ipv4[0])\nCreated: \(.created)"' +} diff --git a/functions/usage.sh b/functions/usage.sh new file mode 100755 index 0000000..25861b8 --- /dev/null +++ b/functions/usage.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +function usage() { + echo "Usage: genesisctl [command]" + echo "Commands:" + echo " watch-abuse Start abuse monitoring via IPTables" +} + +function watch_abuse() { + echo "[*] Launching abuse watch via screen..." + screen -dmS abusewatch /usr/local/bin/genesisctl-watch-abuse.sh + echo "[✓] Abuse watch running in detached screen session 'abusewatch'" +} + +case "$1" in + watch-abuse) + watch_abuse + ;; + *) + usage + ;; +esac diff --git a/functions/verify_ptr.sh b/functions/verify_ptr.sh new file mode 100755 index 0000000..8ce2f6c --- /dev/null +++ b/functions/verify_ptr.sh @@ -0,0 +1,29 @@ +verify_ptr() { + LABEL="$1" + IP=$(curl -s -H "Authorization: Bearer $LINODE_API_TOKEN" https://api.linode.com/v4/linode/instances \ + | jq -r --arg LABEL "$LABEL" '.data[] | select(.label == $LABEL) | .ipv4[0]') + LINODE_ID=$(curl -s -H "Authorization: Bearer $LINODE_API_TOKEN" https://api.linode.com/v4/linode/instances \ + | jq -r --arg LABEL "$LABEL" '.data[] | select(.label == $LABEL) | .id') + + if [[ -z "$IP" || -z "$LINODE_ID" ]]; then + echo "❌ Could not retrieve IP or Linode ID for label '$LABEL'" + return 1 + fi + + echo "Re-attempting rDNS update for $LABEL ($IP)..." + PTR_NAME="${LABEL}.doinkle.pro" + RDNS_PAYLOAD=$(cat <