From 8619d990bc26b55d92a8cd4d5e96f36e1ff6162c Mon Sep 17 00:00:00 2001 From: Blackwhitebear8 Date: Sun, 5 Oct 2025 13:05:21 +0200 Subject: [PATCH] Add gen.sh --- gen.sh | 207 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 207 insertions(+) create mode 100644 gen.sh diff --git a/gen.sh b/gen.sh new file mode 100644 index 0000000..50b0d2e --- /dev/null +++ b/gen.sh @@ -0,0 +1,207 @@ +#!/bin/bash +# +# IRR filter updater for the VyOS API +# + +VYOS_HOST="https://api-url" +API_KEY="api-key" +ASN_FILE="/opt/irr-update/asns.txt" +LOG_FILE="/opt/irr-update/irr_updater.log" + +log() { + local message="$1" + echo "$(date '+%Y-%m-%d %H:%M:%S') - $message" | tee -a "$LOG_FILE" +} + +log "==========================================================" +log "Starting IRR filter update process." +log "==========================================================" + +# fetching entries +declare -a current_entries +while read -r entry; do + if [[ ! "$entry" =~ ^# ]] && [[ -n "$entry" ]]; then + current_entries+=("$entry") + fi +done < "$ASN_FILE" + +# ----------------------------------- +# Removing orphaned prefix-lists +# ----------------------------------- +log "Checking for orphaned prefix-lists..." +has_orphaned_lists=false +commands_list_orphans="" + +# get iPv4 lists +ipv4_lists_json=$(curl -s -k --location --request POST "${VYOS_HOST}/retrieve" \ + --form data='{"op":"showConfig","path":["policy","prefix-list"]}' \ + --form key="${API_KEY}" --max-time 300) +ipv4_lists=$(echo "$ipv4_lists_json" | grep -o '"AS[0-9]*V4":' | sed 's/"://;s/"//g') + +for list_name in $ipv4_lists; do + original_asn=$(echo "$list_name" | sed 's/V4$//;s/^AS//') + is_orphaned=true + for entry in "${current_entries[@]}"; do + main_asn=$(echo "$entry" | cut -d':' -f1) + [[ "$main_asn" == "$original_asn" ]] && is_orphaned=false + done + if [ "$is_orphaned" = true ]; then + log "Found orphaned IPv4 prefix-list: $list_name. Adding delete command..." + commands_list_orphans+='{"op":"delete","path":["policy","prefix-list","'"$list_name"'"]},' + has_orphaned_lists=true + fi +done + +# Get iPv6 lists +ipv6_lists_json=$(curl -s -k --location --request POST "${VYOS_HOST}/retrieve" \ + --form data='{"op":"showConfig","path":["policy","prefix-list6"]}' \ + --form key="${API_KEY}" --max-time 300) +ipv6_lists=$(echo "$ipv6_lists_json" | grep -o '"AS[0-9]*V6":' | sed 's/"://;s/"//g') + +for list_name in $ipv6_lists; do + original_asn=$(echo "$list_name" | sed 's/V6$//;s/^AS//') + is_orphaned=true + for entry in "${current_entries[@]}"; do + main_asn=$(echo "$entry" | cut -d':' -f1) + [[ "$main_asn" == "$original_asn" ]] && is_orphaned=false + done + if [ "$is_orphaned" = true ]; then + log "Found orphaned IPv6 prefix-list: $list_name. Adding delete command..." + commands_list_orphans+='{"op":"delete","path":["policy","prefix-list6","'"$list_name"'"]},' + has_orphaned_lists=true + fi +done + +if [ "$has_orphaned_lists" = true ]; then + commands_list_orphans="[${commands_list_orphans::-1}]" + log "Sending delete commands for orphaned lists..." + api_response=$(curl -s -k --location --request POST "${VYOS_HOST}/configure" \ + --form data="${commands_list_orphans}" \ + --form key="${API_KEY}" --max-time 300) + echo "$api_response" | grep -q '"success":true' \ + && log "Deletion successful." \ + || log "Deletion failed. API response: $api_response" +else + log "No orphaned prefix-lists found." +fi + +# ----------------------------------- +# Retrieve prefixes for each entry and execute 'set' and 'delete' +# ----------------------------------- +for entry in "${current_entries[@]}"; do + log "--------------------------------------------------------" + log "Processing entry: $entry" + + declare -a ipv4_prefixes_to_add=() + declare -a ipv6_prefixes_to_add=() + declare -A seen_v4=() + declare -A seen_v6=() + ipv4_rules=10 + ipv6_rules=10 + + main_asn=$(echo "$entry" | cut -d':' -f1) + as_set=$(echo "$entry" | cut -s -d':' -f2-) + + declare -a asns_to_query=() + asns_to_query+=("AS${main_asn}") + if [ -n "$as_set" ]; then + log "Resolving members of AS-Set: $as_set" + resolved_asns=$(bgpq4 -j -t "$as_set" 2>/dev/null | jq -r '.[][]' | sed 's/^/AS/' | sort -u) + for resolved_asn in $resolved_asns; do + asns_to_query+=("$resolved_asn") + done + log "Resolved ASNs: ${asns_to_query[*]}" + fi + + # Make the list unique + asns_to_query=($(echo "${asns_to_query[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' ')) + log "Unique ASNs to query: ${asns_to_query[*]}" + + # Combine ipv4 and ipv6 in one go + for asn_to_query in "${asns_to_query[@]}"; do + log "Fetching prefixes for $asn_to_query..." + + # Retrieve IPv6 for this ASN + bgpq4_output_ipv6_raw=$(bgpq4 -6 -A "$asn_to_query" 2>&1) + if ! echo "$bgpq4_output_ipv6_raw" | grep -q "FATAL ERROR"; then + for prefix_with_length in $(echo "$bgpq4_output_ipv6_raw" | grep -oE '[0-9a-fA-F:]+/[0-9]+'); do + [[ "$prefix_with_length" == "::/0" ]] && continue + [[ -z "${seen_v6[$prefix_with_length]}" ]] && seen_v6[$prefix_with_length]=1 && ipv6_prefixes_to_add+=("$prefix_with_length") + done + fi + + # Retrieve IPv4 for this ASN + bgpq4_output_ipv4_raw=$(bgpq4 -4 -A "$asn_to_query" 2>&1) + if ! echo "$bgpq4_output_ipv4_raw" | grep -q "FATAL ERROR"; then + for prefix_with_length in $(echo "$bgpq4_output_ipv4_raw" | grep -oE '[0-9.]+/[0-9]+'); do + [[ "$prefix_with_length" == "0.0.0.0/0" ]] && continue + [[ -z "${seen_v4[$prefix_with_length]}" ]] && seen_v4[$prefix_with_length]=1 && ipv4_prefixes_to_add+=("$prefix_with_length") + done + fi + done + + # ----------------------------------- + # Retrieve current rules and determine rules to be removed + # ----------------------------------- + commands_list_atomic="" + prefix_list_name_ipv6="AS${main_asn}V6" + prefix_list_name_ipv4="AS${main_asn}V4" + local_has_changes=false + + # First, add the delete commands for the entire prefix list. + commands_list_atomic+='{"op":"delete","path":["policy","prefix-list","'"$prefix_list_name_ipv4"'"]},' + commands_list_atomic+='{"op":"delete","path":["policy","prefix-list6","'"$prefix_list_name_ipv6"'"]},' + local_has_changes=true + + # Then add the new IPv4 rules + for prefix_with_length in "${ipv4_prefixes_to_add[@]}"; do + log "Adding IPv4 rule ${ipv4_rules} for ${prefix_with_length}..." + prefix_len="${prefix_with_length#*/}" + commands_list_atomic+='{"op":"set","path":["policy","prefix-list","'"$prefix_list_name_ipv4"'","rule","'$ipv4_rules'","action","permit"]},' + commands_list_atomic+='{"op":"set","path":["policy","prefix-list","'"$prefix_list_name_ipv4"'","rule","'$ipv4_rules'","prefix","'$prefix_with_length'"]},' + commands_list_atomic+='{"op":"set","path":["policy","prefix-list","'"$prefix_list_name_ipv4"'","rule","'$ipv4_rules'","ge","'$prefix_len'"]},' + commands_list_atomic+='{"op":"set","path":["policy","prefix-list","'"$prefix_list_name_ipv4"'","rule","'$ipv4_rules'","le","24"]},' + ipv4_rules=$((ipv4_rules+10)) + done + + # Then add the new IPv6 rules + for prefix_with_length in "${ipv6_prefixes_to_add[@]}"; do + log "Adding IPv6 rule ${ipv6_rules} for ${prefix_with_length}..." + prefix_len="${prefix_with_length#*/}" + commands_list_atomic+='{"op":"set","path":["policy","prefix-list6","'"$prefix_list_name_ipv6"'","rule","'$ipv6_rules'","action","permit"]},' + commands_list_atomic+='{"op":"set","path":["policy","prefix-list6","'"$prefix_list_name_ipv6"'","rule","'$ipv6_rules'","prefix","'$prefix_with_length'"]},' + commands_list_atomic+='{"op":"set","path":["policy","prefix-list6","'"$prefix_list_name_ipv6"'","rule","'$ipv6_rules'","ge","'$prefix_len'"]},' + commands_list_atomic+='{"op":"set","path":["policy","prefix-list6","'"$prefix_list_name_ipv6"'","rule","'$ipv6_rules'","le","48"]},' + ipv6_rules=$((ipv6_rules+10)) + done + + if [ "$local_has_changes" = true ]; then + commands_list_atomic="[${commands_list_atomic::-1}]" + log "Sending new rules for $entry..." + api_response=$(curl -s -k --location --request POST "${VYOS_HOST}/configure" \ + --form data="${commands_list_atomic}" \ + --form key="${API_KEY}" --max-time 300) + if echo "$api_response" | grep -q '"success": true'; then + log "Update successful for $entry." + else + echo "$commands_list_atomic" > "/tmp/failed-${entry}-payload.json" + log "Update failed for $entry. Payload saved to /tmp/failed-${entry}-payload.json" + fi + else + log "No new prefixes or changes found for $entry." + fi +done + +# Save the config +log "--------------------------------------------------------" +log "Saving configuration..." +api_response=$(curl -s -k --location --request POST "${VYOS_HOST}/config-file" \ + --form data='{"op":"save"}' \ + --form key="${API_KEY}" --max-time 300) +echo "$api_response" | grep -q '"success": true' \ + && log "Configuration saved successfully." \ + || log "Failed to save configuration. API response: $api_response" + +log "==========================================================" +log "IRR filter update process finished." +log "==========================================================" \ No newline at end of file