BTW: Netgate will add support for this in pfSense 2.5.0 release.
Till waiting for 2.5.0 release I enchanted workaround by using of Filer plugin will slightly help to manage BASH scripts. One-line ECHO workaround in ShellCMD is ugly. So:
Install Filer plugin
Create script in pfSense Diagnostics=>Filer with name: /root/shellcmd_after_filter_changes.sh
2.1. Permissions 700 and Description Create AfterFilterChange Shellcmd script
2.2. File Contents: (all your scripts that must be run by AfterFilterChange Shellcmd script, change it to your need):
#!/bin/sh
echo "Launching AfterFilterChange Shellcmd script"
/bin/sh -c /root/shellcmd_ddns_sub1.example.com.sh
/bin/sh -c /root/shellcmd_ddns_sub2.example.com.sh
echo "AfterFilterChange Shellcmd script exited with status: OK"
2.3 Execute mode: Do not run this script
3. Create all scripts in Filer with names mentioned in AfterFilterChange Shellcmd script (tune it to your needs): /root/shellcmd_ddns_sub1.example.com
3.1. Permissions 700 and Description Create DDNS sub1.example.com script for Shellcmd
3.2. File Contents: (do not forget adjust your RECORD, ZONE and TOKEN. This sample for ipv4. To change it to ipv6 aaaa record you need change curl -4 to -6 and type a to type aaaa)
#!/bin/sh
RECORD="sub1.example.com"
ZONE="example.com"
TOKEN="change-me"
TTL="120"
PROXIED="false"
CHECK_IP_SERVICE="ifconfig.co"
ZONES=`curl -X GET "https://api.cloudflare.com/client/v4/zones?name=$ZONE&status=active&match=all" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json"`
ZONES_SUCCESS=`echo $ZONES | /usr/local/bin/jq -r ".success"`
if [ "$ZONES_SUCCESS" = "true" ]; then
ZONE_ID=`echo $ZONES | /usr/local/bin/jq -r ".result | .[0].id"`
DNS_RECORDS=`curl -X GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records?type=A&name=$RECORD&match=all" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json"`
DNS_RECORDS_SUCCESS=`echo $DNS_RECORDS | /usr/local/bin/jq -r ".success"`
if [ "$DNS_RECORDS_SUCCESS" = "true" ]; then
RECORD_ID=`echo $DNS_RECORDS | /usr/local/bin/jq -r ".result | .[0].id"`
IP=`curl -4 $CHECK_IP_SERVICE`
UPDDATE_DNS_RECORD=`curl -X PUT "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$RECORD_ID" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" --data "{\"type\":\"A\",\"name\":\"$RECORD\",\"content\":\"$IP\",\"ttl\":$TTL,\"proxied\":$PROXIED}"`
UPDDATE_DNS_RECORD_SUCCESS=`echo $UPDDATE_DNS_RECORD | /usr/local/bin/jq -r ".success"`
if [ "$UPDDATE_DNS_RECORD_SUCCESS" = "true" ]; then
echo "DynDNS updated: $RECORD to $IP"
else
echo "DynDNS update failed: $RECORD to $IP"
exit 1
fi
else
echo "Error while tried to get DNS records of Zone: $ZONE_ID"
exit 1
fi
else
echo "Error while tried to get Zones"
fi
echo "DDNS sub1.example.com exited with status: OK"
3.3 Execute mode: Do not run this script
4. In ShellCmd if you created previously other scripts by my how-to - remove them and leave only: /bin/sh /root/shellcmd_after_filter_changes.sh with type afterfilterchangeshellcmd and Description Run shellcmd_after_filter_changes.sh