| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438 |
- <?php
- namespace DDNS;
- if (!is_callable('curl_init'))
- die('ERROR: This PHP script requires cURL to be installed.');
- /*
- *
- * CUSTOM DYNAMIC DNS SOLUTION FOR USE WITH CLOUDFLARE
- * ===============================================================================================
- * ===============================================================================================
- *
- * Christopher Pei
- * ------------------------------------------
- * September 05, 2018 R1
- * November 27, 2018 R2
- * November 28, 2018 R3
- * ===============================================================================================
- *
- */
- // -------------------------------------------------------------------------------------------
- // SETTINGS
- // -------------------------------------------------------------------------------------------
- // API Credential Setup Instructions
- // ===========================================================================================
- //
- // Settings or organized in a tabular format with SETTING NAME on the left and VLUE on the right.
- // Please only edit the VALUE data/columns. When editing, please keep values inside the quotation-
- // marks ("") and do not remove any parentheses (()) or semi-colons (;).
- //
- // ------------------ Set Basic Options
- //
- // Since this script may be publicly accessible on your web server, you can use the "DDNS_PASSWORD"
- // setting so that this string must be provided in order to access this script.
- //
- // To access the script with the password, you use a web browser and access it as follows:
- //
- // /ddns.php?psswd=56789
- //
- // replacing "56789" with your DDNS Password. For example, if this script is located
- // on your webserver at "https://www.google.com/ddns.php" and your DDNS Password is
- // "4392", you would use your browser to access it as follows:
- //
- // https://www.google.com/ddns.php?passwd=4392
- //
- // Alternatively, if you wish to disable this security feature, leave the VALUE empty
- // (nothing between the quotation marks). Then you can access the script just via the
- // name itself. In the example above but without a DDNS Password, you would access it
- // as follows:
- //
- // https://www.google.com/ddns.php
- //
- //
- // -------------------------------------------------------------------------------------------
- // ------------------ SETTING NAME -------------------- VALUE --------------------------------
- // -------------------------------------------------------------------------------------------
- define(__NAMESPACE__ . '\DDNS_PASSWORD', '56789' );
- //
- //
- //
- // ------------------ Set Your API Credentials
- //
- // For many of these settings, you will have access to your CloudFlare account to acquire the
- // appropriate information.
- //
- // 1). Login to your CloudFlare account at: https://dash.cloudflare.com/login
- //
- // 2). If applicable, select your account.
- //
- // 3). If applicable, select the domain you wish to use.
- //
- // 4). Under the "Domain Summary" section, locate the "Zone ID". Copy this value and paste
- // this into the VALUE for the "CF_ZONE_ID" setting.
- //
- // 5). In the same section, click "Get your API Key". Scroll down the page and under the
- // "API Keys" locate the "Global API Key" and click "View". Copy this value and paste
- // this into the VALUE for the "CF_API_KEY" setting.
- //
- // 6). The e-mail address you use to login to CloudFlare is your API username. Provide
- // this into the VALUE for the "CF_API_USERNAME" setting.
- //
- // -------------------------------------------------------------------------------------------
- // ------------------ SETTING NAME -------------------- VALUE --------------------------------
- // -------------------------------------------------------------------------------------------
- define(__NAMESPACE__ . "\CF_ZONE_ID", "s40v9w8fbn0w49r84r8gw04954852784" );
- define(__NAMESPACE__ . "\CF_API_USERNAME", "your_email@domain.com" );
- define(__NAMESPACE__ . "\CF_API_KEY", "xk59gs4jg90d893i8560fg8wejdnci4869vvy" );
- //
- // ------------------ Create The DNS Record
- //
- // Now, if you have not already done so, it is time to create a subdomain on the domain
- // that you wish to use for the custom dynamic DNS:
- //
- // 1). Navigate to https://dash.cloudflare.com/websites and select the domain you wish to
- // use for the custom dynamic DNS service.
- //
- // 2). Go to the "DNS" section, and under the "Search" box, select "A" from the drop-down
- // menu, enter your desired subdomain in the "Name" field.
- //
- // 3). Copy and past the value of the "Name" field into the VALUE for the "FQDN" setting.
- // Do not include ANY trailing slashes and do NOT include either "http://" or "https://"
- // in the setting value.
- //
- // 4). Enter any IP address into the "IPv4 address" field (even "1.2.3.4" is okay; this will
- // be updated by the script automatically later, so its current value is not relevant).
- //
- // 5). If this dynamic DNS is going to be used for HTTP traffic (such as a website), then you
- // can leave the "Automatic TTL" and orange cloud enabled to benefit from CloudFlare's
- // reverse proxy security. However, if this will be used for something else (such as FTP,
- // SSH, Remote Desktop, etc) then modify the TTL to "2 minutes" and DISABLE the orange
- // cloud. Disabling the orange cloud will disable CloudFlare's reverse proxy, which is
- // required for non-HTTP protocols.
- //
- // 6). When finished, click the "Add Record" button.
- //
- // -------------------------------------------------------------------------------------------
- // ------------------ SETTING NAME -------------------- VALUE --------------------------------
- // -------------------------------------------------------------------------------------------
- define(__NAMESPACE__ . "\FQDN", "something.example.com" );
- //
- // ------------------ Get The DNS Record ID
- //
- // This is where it might seem funky. CloudFlare is somewhat "stupid" in the sense that it
- // provides no NORMAL way to get the ID of a DNS record, which is a unique ID that identifies
- // a particular DNS record for your website. The only way to do this is programmatically, via
- // their API.
- //
- // For simplicity, I have programmed this ability directly into this script:
- //
- // 1). Please be sure that all other settings are already provided--- otherwise this script
- // cannot authenticate with the CloudFlare API to find the ID of your DNS record. The
- // VALUE of CF_ZONE_ID, CF_API_KEY, and CF_API_USERNAME must be provided. (Please see
- // the [Set Your API Credentials] section above for help).
- //
- // 2). Using a web browser of your choice, access this PHP script in the URL as follows:
- //
- // /ddns.php?psswd=12345&dump=1
- //
- // replacing "12345" with your DDNS Password. For example, if this script is located
- // on your webserver at "https://www.google.com/ddns.php" and your DDNS Password is
- // "4392", you would use your browser to access it as follows:
- //
- // https://www.google.com/ddns.php?passwd=4392&dump=1
- //
- // If your DDNS Password is disabled, access this PHP script in the URL as follows:
- //
- // /ddns.php?dump=1
- //
- // For example:
- //
- // https://www.google.com/ddns.php?dump=1
- //
- //
- // 3). If successful, the script will output a long string. Please carefully copy and paste
- // the string into the VALUE for the "CF_DNS_RECORD_ID" setting.
- // -------------------------------------------------------------------------------------------
- // ------------------ SETTING NAME -------------------- VALUE --------------------------------
- // -------------------------------------------------------------------------------------------
- define(__NAMESPACE__ . "\CF_DNS_RECORD_ID", "e67898768a9859c859845898b7897f09" );
- //
- //
- // ------------------ Miscellaneous Settings
- //
- // If you wish to use CloudFlare's reverse proxy security, which will mask your your IP, set this
- // value to "true" (without quotations). Otherwise, set it to "false" (without quotations). Note
- // that the CloudFlare reverse proxy feature is currently for HTTP services only, and will not
- // work for other services, such as FTP, SSH, Remote Desktop, etc. A value of "true" is equivalent
- // to the "orange-cloud" DNS setting on your CloudFlare control panel, while a value of "false"
- // is equivalent of the "grey-cloud" DNS setting.
- // -------------------------------------------------------------------------------------------
- // ------------------ SETTING NAME -------------------- VALUE --------------------------------
- // -------------------------------------------------------------------------------------------
- define(__NAMESPACE__ . "\USE_CF_REV_PROXY", false );
- // --------------------------------------------------------------------------------------------
- // --------------------------------------------------------------------------------------------
- // --------------------------------------------------------------------------------------------
- // --------------------------------------------------------------------------------------------
- // ------------- END OF SETTINGS - BE CAREFUL CHANGING ANYTHING BEYOND THIS POINT -------------
- // --------------------------------------------------------------------------------------------
- // --------------------------------------------------------------------------------------------
- // --------------------------------------------------------------------------------------------
- // --------------------------------------------------------------------------------------------
- // VARS
- $visitor_ip = $_SERVER['HTTP_CF_CONNECTING_IP']??$_SERVER['REMOTE_ADDR'];
- $j = new \stdClass();
- // FUNCTIONS
- // @BRIEF Creates and outputs the JSON response.
- // @RETURNS Does not return a value.
- function CREATE_JSON_RESPONSE(&$r){
-
- header('Content-Type: application/json');
- echo json_encode($r, JSON_FORCE_OBJECT);
- }
- // @BRIEF Checks DDNS Password with provided password.
- // @RETURNS Returns true if correct or disabled, and false if incorrect.
- function CHECK_PASSWORD(){
-
- if (defined('DDNS\\DDNS_PASSWORD')){
-
- if (empty(DDNS_PASSWORD))
- return true;
- if (!strcmp($_REQUEST['passwd'], DDNS_PASSWORD))
- return true;
- return false;
- }
-
- return true;
- }
- // @BRIEF Checks if script is being called with a DUMP request.
- // @RETURNS Returns true if it is or false otherwise.
- function IS_DUMP_REQUEST(){
-
- if (isset($_REQUEST['dump']) &&
- !empty($_REQUEST['dump']) &&
- ($_REQUEST['dump'] == 1 ||
- $_REQUEST['dump'] == "1")
- ){
-
- if (!strcmp(FQDN, "something.example.com")){
-
- $j->success = false;
- $j->message = 'You must provide the domain you wish to use for the "FQDN" setting.';
-
- CREATE_JSON_RESPONSE($j);
-
- exit(0);
- }
-
- else return true;
- }
-
- return false;
- }
- // @BRIEF Creates and DUMP of the DNS data to output the DNS Record ID.
- // @RETURNS Does not return a value.
- function DUMP(){
-
- try{
-
- // Send the request.
- $ch = curl_init();
- curl_setopt($ch, CURLOPT_URL, "https://api.cloudflare.com/client/v4/zones/" . CF_ZONE_ID . "/dns_records?type=A&name=" . FQDN . "&match=all");
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
- curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
- $headers = array();
- $headers[] = "X-Auth-Email: " . CF_API_USERNAME;
- $headers[] = "X-Auth-Key: " . CF_API_KEY;
- $headers[] = "Content-Type: application/json";
- curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
- $response = curl_exec($ch);
- if (curl_errno($ch)){
-
- $j->success = false;
- $j->message = 'cURL encountered a problem.';
- $j->cURL_err = curl_error($ch);
-
- curl_close ($ch);
- CREATE_JSON_RESPONSE($j);
-
- exit(0);
- }
-
- curl_close ($ch);
-
- // Parse the DNS Record ID.
- $r = json_decode($response, true);
- if (isset($r['result'][0]['id'])){
-
- $j->success = true;
- $j->message = 'Please copy the "id" value below into the VALUE for the CF_DNS_RECORD_ID settings. Be sure to copy only the value below within the quotation marks.';
- $j->id = $r['result'][0]['id'];
- CREATE_JSON_RESPONSE($j);
-
- exit(0);
- }
-
- else{
-
- $j->success = false;
- $j->message = 'CloudFlare did not provide a valid response. Please ensure that you have provided correct details for all settings and try again.';
- CREATE_JSON_RESPONSE($j);
- exit(0);
- }
- }catch(Exception $e){
-
- $j->success = false;
- $j->message = 'A fatal exception occurred.';
- $j->exception = $e;
- $j->cURL_err = curl_error($ch);
- curl_close ($ch);
- }
- }
- // @BRIEF Updates the DNS record with the visitor's IP.
- // @RETURNS Does not return a value.
- function DNS_UPDATE($new_ip){
-
- try{
-
- // Send the request.
- $ch = curl_init();
- curl_setopt($ch, CURLOPT_URL, "https://api.cloudflare.com/client/v4/zones/" . CF_ZONE_ID . "/dns_records/" . CF_DNS_RECORD_ID);
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
- // CloudFlare is fucking retarded and bitches about this as "malformed JSON, error 6007".
- //curl_setopt($ch, CURLOPT_POSTFIELDS, "{\"type\":\"A\",\"name\":\"" . FQDN . "\",\"content\":\"" . $new_ip . "\",\"ttl\":120,\"proxied\":" . USE_CF_REV_PROXY . "}");
- if (USE_CF_REV_PROXY)
- curl_setopt($ch, CURLOPT_POSTFIELDS, "{\"type\":\"A\",\"name\":\"" . FQDN . "\",\"content\":\"" . $new_ip . "\",\"ttl\":120,\"proxied\":true}");
- else
- curl_setopt($ch, CURLOPT_POSTFIELDS, "{\"type\":\"A\",\"name\":\"" . FQDN . "\",\"content\":\"" . $new_ip . "\",\"ttl\":120,\"proxied\":false}");
- curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
- $headers = array();
- $headers[] = "X-Auth-Email: " . CF_API_USERNAME;
- $headers[] = "X-Auth-Key: " . CF_API_KEY;
- $headers[] = "Content-Type: application/json";
- curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
- $response = curl_exec($ch);
- if (curl_errno($ch)){
-
- $j->success = false;
- $j->message = 'cURL encountered a problem.';
- $j->cURL_err = curl_error($ch);
-
- curl_close ($ch);
- CREATE_JSON_RESPONSE($j);
-
- exit(0);
- }
-
- curl_close ($ch);
-
- // Parse the DNS Record ID.
- $r = json_decode($response, true);
- if (isset($r['success'])){
-
- // Uncomment these lines for debugging.
- // header('Content-Type: application/json');
- // echo json_encode($r, JSON_FORCE_OBJECT);
- // exit(0);
-
- if ($r['success'] == true){
-
- $j->success = true;
- $j->message = 'The [' . FQDN . '] DNS record was successfully updated to point to [' . $new_ip . '].';
- CREATE_JSON_RESPONSE($j);
-
- exit(0);
- }
-
- $j->success = false;
- $j->message = 'CloudFlare reported an error. Please ensure that you have provided correct details for all settings and try again.';
- // $j->id = $r['result'][0]['id'];
- CREATE_JSON_RESPONSE($j);
-
- exit(0);
- }
-
- else{
-
- $j->success = false;
- $j->message = 'CloudFlare did not provide a valid response. Please ensure that you have provided correct details for all settings and try again.';
- CREATE_JSON_RESPONSE($j);
- exit(0);
- }
- }catch(Exception $e){
-
- $j->success = false;
- $j->message = 'A fatal exception occurred.';
- $j->exception = $e;
- $j->cURL_err = curl_error($ch);
- curl_close ($ch);
- }
- }
- // SCRIPT
- // ---------------------------------------------------------
- if (CHECK_PASSWORD()){
-
-
- if (IS_DUMP_REQUEST()){
-
- DUMP();
- exit(0);
- }
-
- DNS_UPDATE($visitor_ip);
-
- exit(0);
- }
- $j->success = false;
- $j->message = 'The DDNS Password is incorrect. Check the "passwd" value and try again.';
- CREATE_JSON_RESPONSE($j);
- exit(0);
- // ---------------------------------------------------------
|