Netgate Discussion Forum
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Search
    • Register
    • Login

    DDNS Cloudflare

    Scheduled Pinned Locked Moved DHCP and DNS
    8 Posts 2 Posters 2.0k Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • dragoangelD
      dragoangel
      last edited by dragoangel

      Currently to use DDNS with Cloudflare users need provide Global API key witch is give to many unwanted permissions.
      Is it possible to implement Cloudflare APIv4 for DDNS over Authorization Bearer API Tokens which can be limited by zone and permissions type? Like here: https://api.cloudflare.com/#dns-records-for-a-zone-update-dns-record.
      As workaround: maybe there a way to trigger custom user script on WAN IP change in pfSense?
      If I understand correct Shellcmd plugin provide such possibility > afterfilterchangeshellcmd is what I need as filter_configure() run every rc.newwanip?
      If yes, then I can solve this by running custom bash script =)

      Updated, link to FR:
      https://redmine.pfsense.org/issues/9639

      Latest stable pfSense on 2x XG-7100 and 1x Intel Xeon Server, running mutiWAN, he.net IPv6, pfBlockerNG-devel, HAProxy-devel, Syslog-ng, Zabbix-agent, OpenVPN, IPsec site-to-site, DNS-over-TLS...
      Unifi AP-AC-LR with EAP RADIUS, US-24

      1 Reply Last reply Reply Quote 0
      • dragoangelD
        dragoangel
        last edited by dragoangel

        After testing, workaround with afterfilterchangeshellcmd working.
        But it will be cool if pfSense will support Cloudflare APIv4 by native DDNS & store API token as a secret, not plaintext.
        Maybe for someone my findings will be useful:
        To create API tocket go to https://dash.cloudflare.com/profile/api-tokens
        You need configure permissions for your token.

        Permission:
            Account -> Access: Organizations, Identity Providers, and Groups: Read
            Zone -> Zone: Read
            Zone -> DNS: Edit
        Account Resources:
            Include -> Your Account
        Zone Resources:
            Include -> Specific zone: Your DNS Zone
        

        After this you need install ShellCmd plugin & pfBlockerNG-devel (needed to have JQ package) in pfSense.
        afterfilterchangeshellcmd can be used only once in this plugin, so I created structure that can be scaled in future:

        1. type afterfilterchangeshellcmd to run script
        /bin/sh -c /root/shellcmd_after_filterchanges.sh
        
        1. type earlyshellcmd to create script itself. If you need in future run more then one script - add it HERE:
        echo -e "#!/bin/sh \n/bin/sh -c /root/shellcmd_after_ddns.sh \n" > /root/shellcmd_after_filterchanges.sh; chmod 700 /root/shellcmd_after_filterchanges.sh
        
        1. type earlyshellcmd to create ddns script. NOTE Before use this part modify variables RECORD, ZONE and TOKEN, TTL & PROXIED to your needs! Proxied true mean hide IP behind Cloudflare, false by default.
        echo -e '#!/bin/sh \n \nRECORD="dyn-ipv4.example.com" \nZONE="example.com" \nTOKEN="Get it from https://dash.cloudflare.com/profile/api-tokens" \nTTL="120" \nPROXIED="false" \nCHECK_IP_SERVICE="ifconfig.co" \nZONES=`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"` \nZONES_SUCCESS=`echo $ZONES | /usr/local/bin/jq -r ".success"` \nif [ "$ZONES_SUCCESS" = "true" ]; then \nZONE_ID=`echo $ZONES | /usr/local/bin/jq -r ".result | .[0].id"` \nDNS_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"` \nDNS_RECORDS_SUCCESS=`echo $DNS_RECORDS | /usr/local/bin/jq -r ".success"` \nif [ "$DNS_RECORDS_SUCCESS" = "true" ]; then \nRECORD_ID=`echo $DNS_RECORDS | /usr/local/bin/jq -r ".result | .[0].id"` \nIP=`curl -4 $CHECK_IP_SERVICE` \nUPDDATE_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}"` \nUPDDATE_DNS_RECORD_SUCCESS=`echo $UPDDATE_DNS_RECORD | /usr/local/bin/jq -r ".success"` \nif [ "$UPDDATE_DNS_RECORD_SUCCESS" = "true" ]; then \necho "DynDNS updated: $RECORD to $IP" \nelse \necho "DynDNS update failed: $RECORD to $IP" \nexit 1 \nfi \nelse \necho "Error while tried to get DNS records of Zone: $ZONE_ID" \nexit 1 \nfi \nelse \necho "Error while tried to get Zones" \nfi \n' > /root/shellcmd_after_ddns.sh; chmod 700 /root/shellcmd_after_ddns.sh
        

        Latest stable pfSense on 2x XG-7100 and 1x Intel Xeon Server, running mutiWAN, he.net IPv6, pfBlockerNG-devel, HAProxy-devel, Syslog-ng, Zabbix-agent, OpenVPN, IPsec site-to-site, DNS-over-TLS...
        Unifi AP-AC-LR with EAP RADIUS, US-24

        1 Reply Last reply Reply Quote 2
        • J
          jkm
          last edited by

          @dragoangel /usr/local/bin/jq doesn't appear to be installed by default, at least on my box. Where did you install it from?

          /root/shellcmd_after_ddns.sh: /usr/local/bin/jq: not found
          echo: write error on stdout
          Error while tried to get Zones

          dragoangelD 2 Replies Last reply Reply Quote 0
          • dragoangelD
            dragoangel @jkm
            last edited by dragoangel

            @jkm hm, need look to my installed packages =) will reply soon

            Latest stable pfSense on 2x XG-7100 and 1x Intel Xeon Server, running mutiWAN, he.net IPv6, pfBlockerNG-devel, HAProxy-devel, Syslog-ng, Zabbix-agent, OpenVPN, IPsec site-to-site, DNS-over-TLS...
            Unifi AP-AC-LR with EAP RADIUS, US-24

            1 Reply Last reply Reply Quote 0
            • dragoangelD
              dragoangel @jkm
              last edited by dragoangel

              @jkm to have JQ you need install pfBlockerNG-devel, this package needed to parse JSON reply from Cloudflare API as object. I has it on all of my pfSense instances as must have package. Thanks for note, I updated How-to.

              Latest stable pfSense on 2x XG-7100 and 1x Intel Xeon Server, running mutiWAN, he.net IPv6, pfBlockerNG-devel, HAProxy-devel, Syslog-ng, Zabbix-agent, OpenVPN, IPsec site-to-site, DNS-over-TLS...
              Unifi AP-AC-LR with EAP RADIUS, US-24

              J 1 Reply Last reply Reply Quote 1
              • J
                jkm @dragoangel
                last edited by

                @dragoangel Thank you! This is working perfectly!

                dragoangelD 1 Reply Last reply Reply Quote 1
                • dragoangelD
                  dragoangel @jkm
                  last edited by

                  @jkm glad that it can help somebody 👍

                  Latest stable pfSense on 2x XG-7100 and 1x Intel Xeon Server, running mutiWAN, he.net IPv6, pfBlockerNG-devel, HAProxy-devel, Syslog-ng, Zabbix-agent, OpenVPN, IPsec site-to-site, DNS-over-TLS...
                  Unifi AP-AC-LR with EAP RADIUS, US-24

                  1 Reply Last reply Reply Quote 0
                  • dragoangelD
                    dragoangel
                    last edited by dragoangel

                    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:

                    1. Install Filer plugin
                    2. 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

                    Latest stable pfSense on 2x XG-7100 and 1x Intel Xeon Server, running mutiWAN, he.net IPv6, pfBlockerNG-devel, HAProxy-devel, Syslog-ng, Zabbix-agent, OpenVPN, IPsec site-to-site, DNS-over-TLS...
                    Unifi AP-AC-LR with EAP RADIUS, US-24

                    1 Reply Last reply Reply Quote 0
                    • First post
                      Last post
                    Copyright 2025 Rubicon Communications LLC (Netgate). All rights reserved.