|
630 | 630 | #!/bin/bash |
631 | 631 | set -e |
632 | 632 |
|
633 | | - # Fetch current IP list |
634 | | - NEW_IPS=$(curl -s https://forwardemail.net/ips/v4.txt?comments=false | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$') |
635 | | -
|
636 | | - # Get current UFW rules for Redis TLS port |
| 633 | + # Configuration |
637 | 634 | REDIS_PORT="${REDIS_PORT:-6380}" |
638 | | - CURRENT_IPS=$(ufw status | grep "${REDIS_PORT}/tcp" | grep "ALLOW" | awk '{print $3}' | sort -u) |
| 635 | + IP_LIST_URL="https://forwardemail.net/ips/v4.txt?comments=false" |
| 636 | + COMMENT="Auto-whitelist Redis TLS" |
| 637 | + SERVICE_NAME="Redis" |
| 638 | + POSTFIX_RCPTS="${POSTFIX_RCPTS:[email protected]}" |
| 639 | +
|
| 640 | + echo "[$(date -Iseconds)] Fetching IP whitelist..." |
| 641 | + NEW_IPS=$(curl -s "$IP_LIST_URL" | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' | sort -u) |
| 642 | +
|
| 643 | + if [ -z "$NEW_IPS" ]; then |
| 644 | + echo "[$(date -Iseconds)] ERROR: Failed to fetch IP list or list is empty" |
| 645 | + exit 1 |
| 646 | + fi |
| 647 | +
|
| 648 | + # Get current IPs from UFW |
| 649 | + CURRENT_IPS=$(ufw status | grep "${REDIS_PORT}/tcp" | grep "$COMMENT" | awk '{print $3}' | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' | sort -u) |
| 650 | +
|
| 651 | + # Calculate diff |
| 652 | + TO_ADD=$(comm -13 <(echo "$CURRENT_IPS") <(echo "$NEW_IPS")) |
| 653 | + TO_REMOVE=$(comm -23 <(echo "$CURRENT_IPS") <(echo "$NEW_IPS")) |
| 654 | +
|
| 655 | + # Check if changes needed |
| 656 | + if [ -z "$TO_ADD" ] && [ -z "$TO_REMOVE" ]; then |
| 657 | + echo "[$(date -Iseconds)] No changes needed" |
| 658 | + exit 0 |
| 659 | + fi |
639 | 660 |
|
640 | | - # Track if changes were made |
641 | | - CHANGED=0 |
| 661 | + echo "[$(date -Iseconds)] Changes detected - updating UFW rules..." |
| 662 | +
|
| 663 | + # Remove old IPs (delete from highest rule number to lowest) |
| 664 | + REMOVED_COUNT=0 |
| 665 | + if [ -n "$TO_REMOVE" ]; then |
| 666 | + for ip in $TO_REMOVE; do |
| 667 | + RULE_NUMS=$(ufw status numbered | grep "${REDIS_PORT}/tcp" | grep "$ip" | grep "$COMMENT" | grep -oP '^\[\s*\K[0-9]+' | sort -rn) |
| 668 | + for rule_num in $RULE_NUMS; do |
| 669 | + echo "y" | ufw delete "$rule_num" > /dev/null 2>&1 |
| 670 | + REMOVED_COUNT=$((REMOVED_COUNT + 1)) |
| 671 | + done |
| 672 | + done |
| 673 | + fi |
642 | 674 |
|
643 | 675 | # Add new IPs |
644 | | - for ip in $NEW_IPS; do |
645 | | - if ! echo "$CURRENT_IPS" | grep -q "^${ip}$"; then |
646 | | - ufw allow from "$ip" to any port "$REDIS_PORT" proto tcp comment "Auto-whitelist Redis TLS" |
647 | | - CHANGED=1 |
648 | | - fi |
649 | | - done |
| 676 | + ADDED_COUNT=0 |
| 677 | + if [ -n "$TO_ADD" ]; then |
| 678 | + for ip in $TO_ADD; do |
| 679 | + ufw allow from "$ip" to any port "$REDIS_PORT" proto tcp comment "$COMMENT" > /dev/null 2>&1 |
| 680 | + ADDED_COUNT=$((ADDED_COUNT + 1)) |
| 681 | + done |
| 682 | + fi |
650 | 683 |
|
651 | | - # Remove old IPs (not in new list) |
652 | | - for ip in $CURRENT_IPS; do |
653 | | - if ! echo "$NEW_IPS" | grep -q "^${ip}$"; then |
654 | | - # Find and delete the rule |
655 | | - RULE_NUM=$(ufw status numbered | grep "${REDIS_PORT}/tcp" | grep "$ip" | grep -oP '^\[\s*\K[0-9]+' | head -1) |
656 | | - if [ -n "$RULE_NUM" ]; then |
657 | | - echo "y" | ufw delete "$RULE_NUM" |
658 | | - CHANGED=1 |
659 | | - fi |
660 | | - fi |
661 | | - done |
| 684 | + # Reload UFW |
| 685 | + ufw reload > /dev/null 2>&1 |
662 | 686 |
|
663 | | - # Reload UFW if changes were made |
664 | | - if [ $CHANGED -eq 1 ]; then |
665 | | - ufw reload |
| 687 | + # Build email report |
| 688 | + TOTAL_IPS=$(echo "$NEW_IPS" | wc -l) |
| 689 | + ADDED_LIST=$(echo "$TO_ADD" | sed 's/^/ - /' | head -20) |
| 690 | + REMOVED_LIST=$(echo "$TO_REMOVE" | sed 's/^/ - /' | head -20) |
| 691 | + |
| 692 | + if [ $(echo "$TO_ADD" | wc -l) -gt 20 ]; then |
| 693 | + ADDED_LIST="$ADDED_LIST\n ... and $(($(echo "$TO_ADD" | wc -l) - 20)) more" |
666 | 694 | fi |
| 695 | + |
| 696 | + if [ $(echo "$TO_REMOVE" | wc -l) -gt 20 ]; then |
| 697 | + REMOVED_LIST="$REMOVED_LIST\n ... and $(($(echo "$TO_REMOVE" | wc -l) - 20)) more" |
| 698 | + fi |
| 699 | +
|
| 700 | + REPORT="UFW Whitelist Changes for $SERVICE_NAME |
| 701 | + Timestamp: $(date -Iseconds) |
| 702 | + |
| 703 | + Added IPs ($ADDED_COUNT): |
| 704 | + $ADDED_LIST |
| 705 | + |
| 706 | + Removed IPs ($REMOVED_COUNT): |
| 707 | + $REMOVED_LIST |
| 708 | + |
| 709 | + Summary: |
| 710 | + - Total added: $ADDED_COUNT |
| 711 | + - Total removed: $REMOVED_COUNT |
| 712 | + - Current total: $TOTAL_IPS IPs whitelisted |
| 713 | + |
| 714 | + Server: $(hostname) |
| 715 | + Port: $REDIS_PORT/tcp |
| 716 | + |
| 717 | + View logs: sudo journalctl -u redis-ufw-whitelist-update.service -n 50" |
| 718 | +
|
| 719 | + # Send email report |
| 720 | + /usr/local/bin/send-rate-limited-email.sh \ |
| 721 | + "ufw-whitelist-redis" \ |
| 722 | + "[UFW] Whitelist Updated: $SERVICE_NAME (Port $REDIS_PORT)" \ |
| 723 | + "$REPORT" |
| 724 | +
|
| 725 | + echo "[$(date -Iseconds)] UFW whitelist updated (added: $ADDED_COUNT, removed: $REMOVED_COUNT)" |
667 | 726 |
|
668 | 727 | # Create systemd timer for UFW whitelist updates |
669 | 728 | - name: Create UFW whitelist update systemd service |
|
0 commit comments