|  | #!/bin/sh | 
        
          |  |  | 
        
          |  | # ============================================================================== | 
        
          |  | # VPN Director - Cloudflare CIDR Updater | 
        
          |  | # | 
        
          |  | # This script automatically fetches the latest Cloudflare IPv4 CIDRs, | 
        
          |  | # compares them against the currently configured rules in VPN Director, | 
        
          |  | # and updates the rule list if any changes are detected. | 
        
          |  | # | 
        
          |  | # It correctly parses and generates the concatenated rule format. | 
        
          |  | # Designed for POSIX-compliant shells (e.g., ash on BusyBox). | 
        
          |  | # ============================================================================== | 
        
          |  |  | 
        
          |  | # --- Configuration --- | 
        
          |  | readonly RULE_PREFIX="Cloudflare v4_" | 
        
          |  | readonly VPN_CLIENT_ID="WGC1" | 
        
          |  | readonly RULES_FILE="/jffs/openvpn/vpndirector_rulelist" | 
        
          |  | readonly LOCAL_SUBNET=""  # (Optional) Specify a subnet (e.g., 192.168.1.0/24) or a single IP address to restrict the Cloudflare rules to a specific local network segment or client. | 
        
          |  | # Leave empty ("") to apply the rules to ALL clients on the router. | 
        
          |  | # Example: LOCAL_SUBNET="192.168.1.0/24" will only route traffic from this subnet through the VPN for Cloudflare IPs. | 
        
          |  | # Use for testing | 
        
          |  | #readonly RULES_FILE="./vpndirector_rulelist" | 
        
          |  |  | 
        
          |  | # --- Script Logic --- | 
        
          |  | set -e | 
        
          |  | set -u | 
        
          |  | set -o pipefail | 
        
          |  |  | 
        
          |  | readonly TEMP_DIR="/tmp/cf_updater_$$" | 
        
          |  | mkdir "$TEMP_DIR" | 
        
          |  | trap 'rm -rf -- "$TEMP_DIR"' EXIT | 
        
          |  |  | 
        
          |  | readonly NEW_CIDRS_FILE="$TEMP_DIR/cloudflare_cidrs_new.txt" | 
        
          |  | readonly OLD_CIDRS_FILE="$TEMP_DIR/cloudflare_cidrs_old.txt" | 
        
          |  | readonly NEW_CF_RULES_FILE="$TEMP_DIR/cloudflare_rules_new.txt" | 
        
          |  | readonly OLD_CF_RULES_FILE="$TEMP_DIR/cloudflare_rules_old.txt" | 
        
          |  |  | 
        
          |  | logger -sc -t "Cloudflare CIDR VPN Director Updater" -p user.notice "INFO: Starting Cloudflare CIDR update process." | 
        
          |  |  | 
        
          |  | # Step 1: Fetch the latest Cloudflare IPv4 CIDRs. | 
        
          |  | intrfce=$(echo "$VPN_CLIENT_ID" | awk '{print tolower($0)}') | 
        
          |  | logger -sc -t "Cloudflare CIDR VPN Director Updater" -p user.notice "INFO: Fetching latest Cloudflare IPv4 CIDRs..." | 
        
          |  | if ! curl --interface "$intrfce" -s "https://api.cloudflare.com/client/v4/ips" | jq -r '.result.ipv4_cidrs[]' > "$NEW_CIDRS_FILE"; then | 
        
          |  | logger -sc -t "Cloudflare CIDR VPN Director Updater" -p user.error "ERROR: Failed to fetch or parse Cloudflare IPs. Exiting." | 
        
          |  | exit 1 | 
        
          |  | fi | 
        
          |  |  | 
        
          |  | if [ ! -s "$NEW_CIDRS_FILE" ]; then | 
        
          |  | logger -sc -t "Cloudflare CIDR VPN Director Updater" -p user.error "ERROR: Fetched CIDR list is empty. Exiting." | 
        
          |  | exit 1 | 
        
          |  | fi | 
        
          |  |  | 
        
          |  | # Step 2: Extract currently configured Cloudflare rules block. | 
        
          |  | logger -sc -t "Cloudflare CIDR VPN Director Updater" -p user.notice "INFO: Extracting existing Cloudflare rules from $RULES_FILE..." | 
        
          |  | if [ -f "$RULES_FILE" ] && [ -s "$RULES_FILE" ]; then | 
        
          |  | # Extract the full Cloudflare rules block (not just CIDRs) | 
        
          |  | awk -F'>' -v prefix="^${RULE_PREFIX}" 'BEGIN{RS="<"; ORS=""} NF>0 && $2 ~ prefix {print "<"$0}' "$RULES_FILE" > "$OLD_CF_RULES_FILE" | 
        
          |  | else | 
        
          |  | logger -sc -t "Cloudflare CIDR VPN Director Updater" -p user.notice "INFO: Rules file does not exist or is empty. Will create it." | 
        
          |  | : > "$OLD_CF_RULES_FILE" | 
        
          |  | fi | 
        
          |  |  | 
        
          |  | # Step 3: Generate the new block of Cloudflare rules. | 
        
          |  | NEW_CLOUDFLARE_RULES_BLOCK="" | 
        
          |  | counter=0 | 
        
          |  | while IFS= read -r cidr; do | 
        
          |  | label="${RULE_PREFIX}${counter}" | 
        
          |  | NEW_CLOUDFLARE_RULES_BLOCK="${NEW_CLOUDFLARE_RULES_BLOCK}<1>${label}>${LOCAL_SUBNET}>${cidr}>${VPN_CLIENT_ID}" | 
        
          |  | counter=$((counter + 1)) | 
        
          |  | done < "$NEW_CIDRS_FILE" | 
        
          |  | echo -n "$NEW_CLOUDFLARE_RULES_BLOCK" > "$NEW_CF_RULES_FILE" | 
        
          |  |  | 
        
          |  | # Step 4: Compare the new and existing Cloudflare rules blocks. | 
        
          |  | logger -sc -t "Cloudflare CIDR VPN Director Updater" -p user.notice "INFO: Comparing new and existing Cloudflare rules block..." | 
        
          |  | if cmp -s "$OLD_CF_RULES_FILE" "$NEW_CF_RULES_FILE"; then | 
        
          |  | logger -sc -t "Cloudflare CIDR VPN Director Updater" -p user.notice "INFO: No changes detected in Cloudflare rules. No update necessary. Exiting." | 
        
          |  | exit 0 | 
        
          |  | fi | 
        
          |  |  | 
        
          |  | logger -sc -t "Cloudflare CIDR VPN Director Updater" -p user.notice "INFO: Changes detected. Proceeding with rule update." | 
        
          |  |  | 
        
          |  | # Step 5: Extract all non-Cloudflare rules. | 
        
          |  | CUSTOM_RULES_BLOCK="" | 
        
          |  | if [ -f "$RULES_FILE" ] && [ -s "$RULES_FILE" ]; then | 
        
          |  | CUSTOM_RULES_BLOCK=$(awk -F'>' -v prefix="^${RULE_PREFIX}" 'BEGIN{RS="<"; ORS=""} NF>0 && $2 !~ prefix {print "<"$0}' "$RULES_FILE") | 
        
          |  | fi | 
        
          |  |  | 
        
          |  | # Step 6: Combine custom rules with the new Cloudflare rules by simple concatenation. | 
        
          |  | FINAL_RULE_LIST="${CUSTOM_RULES_BLOCK}${NEW_CLOUDFLARE_RULES_BLOCK}" | 
        
          |  |  | 
        
          |  | # Step 7: Atomically update the rule list and apply changes. | 
        
          |  | logger -sc -t "Cloudflare CIDR VPN Director Updater" -p user.notice "INFO: Writing new rules to $RULES_FILE and applying changes." | 
        
          |  | echo -n "$FINAL_RULE_LIST" > "$RULES_FILE.tmp" | 
        
          |  | mv "$RULES_FILE.tmp" "$RULES_FILE" | 
        
          |  | service restart_vpndirector | 
        
          |  |  | 
        
          |  | logger -sc -t "Cloudflare CIDR VPN Director Updater" -p user.notice "SUCCESS: VPN Director rules updated successfully." | 
        
          |  | exit 0 | 
  
Полезное для тех, кто хочет настроить роутинг трафика через VPN для определённых сайтов для всех устройств сети
Как настроить роутинг трафика через VPN по доменному имени