Skip to content

Instantly share code, notes, and snippets.

@WMAL
Created December 12, 2024 13:33
Show Gist options
  • Save WMAL/7bff84229f6f7f3109f3f2a121bce12b to your computer and use it in GitHub Desktop.
Save WMAL/7bff84229f6f7f3109f3f2a121bce12b to your computer and use it in GitHub Desktop.
Managing DNS records can be a time-consuming task, especially when handling multiple subdomains. This Bash script simplifies the process using the Porkbun API, automating DNS record queries, subdomain creation, and deletion. While this example specifically works for Porkbun.com, the same concept can be adapted to any domain provider that offers …
#!/bin/bash
# =========================================
# Domain API Setup Script
# =========================================
#
# Version: 1.0.0
# Script written by Warith AL Maawali
#
# Discord channel: https://discord.gg/KEFErEx
# Twitter: http://twitter.com/warith2020
# Linkedin: http://www.linkedin.com/in/warith1977
# Website: https://www.digi77.com
# (c) 2024
#
# Description:
# This script automates the management of DNS records for a specified domain using the Porkbun API.
# It includes functionalities to query existing DNS records, add new subdomains with random names,
# and delete subdomains with specific criteria.
#
# This software is dual-licensed:
#
# Personal, non-commercial use: Apache License 2.0
# Commercial, corporate, or organizational use: Separate commercial license required.
# Contact me for licensing inquiries.
#
# Usage: ./domain-api-setup.sh [domain]
#
# Usage Examples:
# Run this script to manage DNS records for the default domain:
# ./domain-api-setup.sh
# Run this script to manage DNS records for a specified domain:
# ./domain-api-setup.sh example.com
# =========================================
# Global variables for API authentication and domain configuration
API_KEY="pk1_3xxxxxxxxxxxxxxxx"
SECRET_API_KEY="sk1_xxxxxxxxxxxxxxxxxxxxxxxxxx"
DOMAIN="xxx.com" # Default domain name
TYPE="A" # DNS record type
TARGET_IP="34.27.202.113" # Target IP address for subdomains
TTL="600" # Time to live for DNS records
NUM_SUBDOMAINS=4 # Number of subdomains to add
# Check if the user provided a domain as an argument and override the default if so
if [ ! -z "$1" ]; then
DOMAIN="$1"
fi
# Function to query DNS records for the specified domain
query_dns_records() {
echo "Fetching DNS records for: $DOMAIN, Type: $TYPE"
echo "------------------------------------------------"
# Query Porkbun API for DNS records by domain and type
RESPONSE=$(curl -s -X POST https://api.porkbun.com/api/json/v3/dns/retrieve/"$DOMAIN" \
-H "Content-Type: application/json" \
-d '{
"apikey": "'"$API_KEY"'",
"secretapikey": "'"$SECRET_API_KEY"'"
}')
# Check if the response was successful
STATUS=$(echo "$RESPONSE" | jq -r '.status')
if [[ "$STATUS" != "SUCCESS" ]]; then
echo "Error retrieving DNS records: $RESPONSE"
exit 1
fi
# Get the main domain IP address
MAIN_IP=$(dig +short "$DOMAIN" | head -n 1)
# List subdomains with their IDs and IP addresses, excluding those with the main domain IP and ensuring valid IP addresses
echo "Subdomains with different and valid IP Addresses:"
echo "-------------------------------------------------"
echo "$RESPONSE" | jq -r --arg MAIN_IP "$MAIN_IP" '.records[] | select(.name != "'"$DOMAIN"'") | select(.content != $MAIN_IP) | select(.content | test("^[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+$")) | "\(.id) - \(.name) - \(.content)"'
}
# Function to add a specified number of subdomains with random names
add_subdomain() {
for ((i = 0; i < NUM_SUBDOMAINS; i++)); do
# Generate a random subdomain string
RANDOM_SUBDOMAIN="$(openssl rand -hex 8)"
# Create the subdomain via Porkbun API
RESPONSE=$(curl -s -X POST https://api.porkbun.com/api/json/v3/dns/create/"$DOMAIN" \
-H "Content-Type: application/json" \
-d '{
"apikey": "'"$API_KEY"'",
"secretapikey": "'"$SECRET_API_KEY"'",
"name": "'"$RANDOM_SUBDOMAIN"'",
"type": "'"$TYPE"'",
"content": "'"$TARGET_IP"'",
"ttl": "'"$TTL"'"
}')
# Check if the subdomain was created successfully
STATUS=$(echo "$RESPONSE" | jq -r '.status')
if [[ "$STATUS" == "SUCCESS" ]]; then
echo "Subdomain created successfully!"
echo "Subdomain: $RANDOM_SUBDOMAIN.$DOMAIN -> $TARGET_IP"
else
echo "Error creating subdomain: $RESPONSE"
fi
done
}
# Function to delete subdomains with different and valid IP addresses
delete_subdomains() {
echo "Deleting subdomains with different and valid IP Addresses:"
echo "----------------------------------------------------------"
# Query Porkbun API for DNS records by domain and type
RESPONSE=$(curl -s -X POST https://api.porkbun.com/api/json/v3/dns/retrieve/"$DOMAIN" \
-H "Content-Type: application/json" \
-d '{
"apikey": "'"$API_KEY"'",
"secretapikey": "'"$SECRET_API_KEY"'"
}')
# Check if the response was successful
STATUS=$(echo "$RESPONSE" | jq -r '.status')
if [[ "$STATUS" != "SUCCESS" ]]; then
echo "Error retrieving DNS records: $RESPONSE"
exit 1
fi
# Get the main domain IP address
MAIN_IP=$(dig +short "$DOMAIN" | head -n 1)
# Delete subdomains with different and valid IP addresses
echo "$RESPONSE" | jq -r --arg MAIN_IP "$MAIN_IP" '.records[] | select(.name != "'"$DOMAIN"'") | select(.content != $MAIN_IP) | select(.content | test("^[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+$")) | .id' | while read -r ID; do
DELETE_RESPONSE=$(curl -s -X POST https://api.porkbun.com/api/json/v3/dns/delete/"$DOMAIN"/"$ID" \
-H "Content-Type: application/json" \
-d '{
"apikey": "'"$API_KEY"'",
"secretapikey": "'"$SECRET_API_KEY"'"
}')
DELETE_STATUS=$(echo "$DELETE_RESPONSE" | jq -r '.status')
if [[ "$DELETE_STATUS" == "SUCCESS" ]]; then
echo "Subdomain with ID $ID deleted successfully."
else
echo "Error deleting subdomain with ID $ID: $DELETE_RESPONSE"
fi
done
}
# Call the functions in sequence to manage DNS records
query_dns_records # Initial query to list current DNS records
add_subdomain # Add new subdomains
query_dns_records # Query again to verify new subdomains
delete_subdomains # Delete specific subdomains
query_dns_records # Final query to confirm deletions
exit 0 # Exit the script successfully
@WMAL
Copy link
Author

WMAL commented Feb 20, 2025

In addition to the original script, I have developed an enhanced version that introduces new functionality. This updated script supports multiple target IP addresses, automatically deletes existing subdomains with a specific hex pattern, and generates a structured domains.yaml file mapping subdomains to their respective IPs. It also ensures that all required dependencies are installed before execution, further streamlining the DNS management process.

#!/bin/bash
# =========================================
# Domain API Setup Script
# =========================================
#
# Version: 1.0.1
# Script written by Warith AL Maawali
#
# Discord channel: https://discord.gg/KEFErEx
# Twitter: http://twitter.com/warith2020
# Linkedin: http://www.linkedin.com/in/warith1977
# Website: https://www.digi77.com
# (c) 2024
#
# Description:
# This script provides a command-line interface for managing DNS records through the Porkbun API.
# Key features include:
# - Installing required system packages (curl, jq, openssl, dnsutils)
# - Configuring API authentication and domain settings
# - Managing A records for multiple IP addresses
# - Creating random subdomains with configurable TTL
# - Tracking created subdomains per IP address
#
# This software is dual-licensed:
#
# Personal, non-commercial use: Apache License 2.0
# Commercial, corporate, or organizational use: Separate commercial license required.
# Contact me for licensing inquiries.
#
# Usage: ./domain-api-setup.sh [domain]
#
# Usage Examples:
#   Run with default domain from config:
#     ./domain-api-setup.sh
#   Run with custom domain:
#     ./domain-api-setup.sh example.com
#
# Note: Requires Porkbun API credentials to be configured
# =========================================

# Required packages
packages=(curl jq openssl)

# Check if dnsutils is installed, if not add it to required packages
if ! command -v dig &>/dev/null; then
  packages+=(dnsutils)
fi

# Global variables for API authentication and domain configuration
API_KEY="YOUR_PORKBUN_API_KEY"
SECRET_API_KEY="YOUR_PORKBUN_SECRET_API_KEY"
DOMAIN="example.com"                                                                         # Default domain name
TYPE="A"                                                                                     # DNS record type
TARGET_IPS=("1.2.3.4" "2.3.4.5" "3.4.5.6" "4.5.6.7" "5.6.7.8")                            # Array of target IP addresses for subdomains
TTL="600"                                                                                    # Time to live for DNS records
NUM_SUBDOMAINS=2                                                                             # Number of subdomains to add per IP

# Array to store subdomains created in this session
declare -A IP_SUBDOMAINS

# Function to check and install required packages
function install_required_packages() {
  for package in "${packages[@]}"; do
    echo "Checking if $package is installed..."
    if ! command -v $package &>/dev/null; then
      echo "$package not found, installing..."
      sudo apt update
      sudo apt install -y "$package"
    else
      echo "$package is already installed."
    fi
  done
}

# Check if the user provided a domain as an argument and override the default if so
if [ ! -z "$1" ]; then
  DOMAIN="$1"
fi

# Function to query DNS records for the specified domain
query_dns_records() {
  echo "Fetching DNS records for: $DOMAIN, Type: $TYPE"
  echo "------------------------------------------------"

  # Query Porkbun API for DNS records by domain and type
  RESPONSE=$(curl -s -X POST https://api.porkbun.com/api/json/v3/dns/retrieve/"$DOMAIN" \
    -H "Content-Type: application/json" \
    -d '{
      "apikey": "'"$API_KEY"'",
      "secretapikey": "'"$SECRET_API_KEY"'"
  }')

  # Check if the response was successful
  STATUS=$(echo "$RESPONSE" | jq -r '.status')

  if [[ "$STATUS" != "SUCCESS" ]]; then
    echo "Error retrieving DNS records: $RESPONSE"
    exit 1
  fi

  # Get the main domain IP address
  MAIN_IP=$(dig +short "$DOMAIN" | head -n 1)

  # List subdomains with their IDs and IP addresses, excluding those with the main domain IP and ensuring valid IP addresses
  echo "Subdomains with different and valid IP Addresses:"
  echo "-------------------------------------------------"
  echo "$RESPONSE" | jq -r --arg MAIN_IP "$MAIN_IP" '.records[] | select(.name != "'"$DOMAIN"'") | select(.content != $MAIN_IP) | select(.content | test("^[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+$")) | "\(.id) - \(.name) - \(.content)"'
}

# Function to delete existing hex subdomains
delete_hex_subdomains() {
  echo "Deleting existing hex-pattern subdomains:"
  echo "----------------------------------------"

  # Query Porkbun API for DNS records
  RESPONSE=$(curl -s -X POST https://api.porkbun.com/api/json/v3/dns/retrieve/"$DOMAIN" \
    -H "Content-Type: application/json" \
    -d '{
      "apikey": "'"$API_KEY"'",
      "secretapikey": "'"$SECRET_API_KEY"'"
  }')

  # Check if the response was successful
  STATUS=$(echo "$RESPONSE" | jq -r '.status')

  if [[ "$STATUS" != "SUCCESS" ]]; then
    echo "Error retrieving DNS records: $RESPONSE"
    exit 1
  fi

  # Process each DNS record, looking for hex pattern subdomains (16 hex characters)
  echo "$RESPONSE" | jq -r '.records[] | select(.name | test("^[0-9a-f]{16}\\.'$DOMAIN'$")) | "\(.id) \(.name)"' | while read -r ID NAME; do
    DELETE_RESPONSE=$(curl -s -X POST https://api.porkbun.com/api/json/v3/dns/delete/"$DOMAIN"/"$ID" \
      -H "Content-Type: application/json" \
      -d '{
        "apikey": "'"$API_KEY"'",
        "secretapikey": "'"$SECRET_API_KEY"'"
    }')

    DELETE_STATUS=$(echo "$DELETE_RESPONSE" | jq -r '.status')

    if [[ "$DELETE_STATUS" == "SUCCESS" ]]; then
      echo "Deleted hex subdomain: $NAME (ID: $ID)"
    else
      echo "Error deleting subdomain $NAME: $DELETE_RESPONSE"
    fi
  done
}

# Function to add a specified number of subdomains with random names
add_subdomain() {
  # Iterate through each target IP
  for IP in "${TARGET_IPS[@]}"; do
    echo "Creating $NUM_SUBDOMAINS subdomains for IP: $IP"
    IP_SUBDOMAINS[$IP]=""

    # Create NUM_SUBDOMAINS for this IP
    for ((i = 0; i < NUM_SUBDOMAINS; i++)); do
      # Generate a random subdomain string
      RANDOM_SUBDOMAIN="$(openssl rand -hex 8)"

      # Create the subdomain via Porkbun API
      RESPONSE=$(curl -s -X POST https://api.porkbun.com/api/json/v3/dns/create/"$DOMAIN" \
        -H "Content-Type: application/json" \
        -d '{
          "apikey": "'"$API_KEY"'",
          "secretapikey": "'"$SECRET_API_KEY"'",
          "name": "'"$RANDOM_SUBDOMAIN"'",
          "type": "'"$TYPE"'",
          "content": "'"$IP"'",
          "ttl": "'"$TTL"'"
      }')

      # Check if the subdomain was created successfully
      STATUS=$(echo "$RESPONSE" | jq -r '.status')

      if [[ "$STATUS" == "SUCCESS" ]]; then
        echo "Subdomain created successfully!"
        echo "Subdomain: $RANDOM_SUBDOMAIN.$DOMAIN -> $IP"
        # Append the subdomain to the IP's list
        IP_SUBDOMAINS[$IP]+="$RANDOM_SUBDOMAIN.$DOMAIN "
      else
        echo "Error creating subdomain: $RESPONSE"
      fi
    done
  done

  # Generate YAML output
  echo "Generating domains.yaml file..."
  {
    echo "domains:"
    for IP in "${TARGET_IPS[@]}"; do
      echo "  $IP:"
      for SUBDOMAIN in ${IP_SUBDOMAINS[$IP]}; do
        echo "    - $SUBDOMAIN"
      done
    done
  } >domains.yaml

  echo "YAML file generated successfully at domains.yaml"
}

# Install required packages first
install_required_packages

# Call the functions in sequence to manage DNS records
query_dns_records     # Initial query to list current DNS records
delete_hex_subdomains # Delete existing hex pattern subdomains
add_subdomain         # Add new subdomains and generate YAML
query_dns_records     # Final query to confirm changes

exit 0 # Exit the script successfully

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment