1. Jeroen Steenhuis Member

    Dyndns Script voor versio gebruikers

    Topic geplaatst op: 25-04-2014 om 09:30

    Als je gebruik wilt maken van dyndns heb ik onderstaande script gevonden en aangepast voor gebruik bij versio. Zet deze in een directory op je website en zet daarin ook een .htaccess en een .htpasswd file (http://www.htaccesstools.com/htpasswd-generator/) om te zorgen dat alleen jij dit script met een gebruikersnaam en wachtwoord kan aanroepen en zo niet iemand anders kan gaan rommelen met je domein records.

    Je kunt nu met een dyndns client of met 'wget -q -O- --http-user='htpasswdgebruikersnaam' --http-password='htpasswdwachtwoord' 'http://jouwdomein/jouwpath/update.php?hostname=hostname.joudomein' een update uitvoeren.

    De teruggegeven error codes zijn conform de dyndns standaard. (nochg=ip niet veranderd; dnserr=er is iets fout gegaan; good=dns is geupdate)

    FILE:.htaccess
    ______________________________________________________________________________________

    AuthName "Beveiligd gedeelte"
    AuthUserFile /home/JOUWGEBRUIKERSNAAM/domains/JOUWDOMEINNAAM/public_html/dyndns/.htpasswd
    AuthType Basic

    require valid-user
    ______________________________________________________________________________________

    FILE:update.php
    ______________________________________________________________________________________

    <?php
    $DIRECTADMINUSER="jouwdirectadmingebruikersnaam";
    $DIRECTADMINPASSWORD="jouwdirectadminwachtwoord";

     

    // Dit is de PHP class voor de DirectAdmin.
    // http://forum.directadmin.com/showthread.php?t=258
    include("HTTPSocket.php");

    if (isset($_GET["hostname"])) {

      // Bewaar het IP
      $IP = $_SERVER[REMOTE_ADDR];
      $HOSTNAMEARRAY = explode(".", $_GET["hostname"]);
      $DOMAIN = $HOSTNAMEARRAY[1].".".$HOSTNAMEARRAY[2];
      $HOSTNAME = $HOSTNAMEARRAY[0];

      $ERROR=0;
      // Controleer of het IP
      if ($IP !== gethostbyname($HOSTNAME)) {
     
        // Maak een instantie aan van het HTTPSocket object.
        $sock = new HTTPSocket;
     
        // Stel de hostnaam en de poort in van het DirectAdmin panel.
        $sock->connect("127.0.0.1",2222);
     
        // Stel de gebruikersnaam, het wachtwoord en kies voor de POST of GET methode.
        $sock->set_login($DIRECTADMINUSER,$DIRECTADMINPASSWORD);
        $sock->set_method('POST');
     
        // Set ttl to 60 seconds
        $sock->query("/CMD_API_DNS_CONTROL?domain=".$DOMAIN."&action=ttl&ttl_select=custom&ttl=60");
        if (!strstr($sock->fetch_body(),"error=0")) $ERROR=1;
        
        // Een update is niet mogelijk dus eerst het oude record verwijderen.
        $sock->query("/CMD_API_DNS_CONTROL?domain=".$DOMAIN."&action=select&arecs0=name=".$HOSTNAME."&value=".gethostbyname("$HOSTNAME"));
        if (!strstr($sock->fetch_body(),"error=0")) $ERROR=1;
     
        // Maak vervolgens een nieuw record aan in de DNS met het nieuwe IP.
        $sock->query("/CMD_API_DNS_CONTROL?domain=".$DOMAIN."&action=add&type=A&name=".$HOSTNAME."&value=".$IP);
        if (!strstr($sock->fetch_body(),"error=0")) $ERROR=1;

        if (ERROR == 0) print("good\\n"); else print ("dnserr\\n");
      }
      else print("nochg\\n");
    }
    else print("notfqdn\\n");

    ______________________________________________________________________________________

    File HTTPSocket.php

    ______________________________________________________________________________________

    <?php

    /**
     * Socket communication class.
     *
     * Originally designed for use with DirectAdmin's API, this class will fill any HTTP socket need.
     *
     * Very, very basic usage:
     *   $Socket = new HTTPSocket;
     *   echo $Socket->get('http://user:pass@somesite.com/somedir/some.file?query=string&this=that');
     *
     * @author Phi1 'l0rdphi1' Stier <l0rdphi1@liquenox.net>
     * @package HTTPSocket
     * @version 2.7
     */
    class HTTPSocket {

        var $version = '2.7';

        /* all vars are private except $error, $query_cache, and $doFollowLocationHeader */

        var $method = 'GET';

        var $remote_host;
        var $remote_port;
        var $remote_uname;
        var $remote_passwd;

        var $result;
        var $result_header;
        var $result_body;
        var $result_status_code;

        var $lastTransferSpeed;

        var $bind_host;

        var $error = array();
        var $warn = array();
        var $query_cache = array();

        var $doFollowLocationHeader = TRUE;
        var $redirectURL;

        var $extra_headers = array();

        /**
         * Create server "connection".
         *
         */
        function connect($host, $port = '' )
        {
            if (!is_numeric($port))
            {
                $port = 80;
            }

            $this->remote_host = $host;
            $this->remote_port = $port;
        }

        function bind( $ip = '' )
        {
            if ( $ip == '' )
            {
                $ip = $_SERVER['SERVER_ADDR'];
            }

            $this->bind_host = $ip;
        }

        /**
         * Change the method being used to communicate.
         *
         * @param string|null request method. supports GET, POST, and HEAD. default is GET
         */
        function set_method( $method = 'GET' )
        {
            $this->method = strtoupper($method);
        }

        /**
         * Specify a username and password.
         *
         * @param string|null username. defualt is null
         * @param string|null password. defualt is null
         */
        function set_login( $uname = '', $passwd = '' )
        {
            if ( strlen($uname) > 0 )
            {
                $this->remote_uname = $uname;
            }

            if ( strlen($passwd) > 0 )
            {
                $this->remote_passwd = $passwd;
            }

        }

        /**
         * Query the server
         *
         * @param string containing properly formatted server API. See DA API docs and examples. Http:// URLs O.K. too.
         * @param string|array query to pass to url
         * @param int if connection KB/s drops below value here, will drop connection
         */
        function query( $request, $content = '', $doSpeedCheck = 0 )
        {
            $this->error = $this->warn = array();
            $this->result_status_code = NULL;

            // is our request a http:// ... ?
            if (preg_match('!^http://!i',$request))
            {
                $location = parse_url($request);
                $this->connect($location['host'],$location['port']);
                $this->set_login($location['user'],$location['pass']);

                $request = $location['path'];
                $content = $location['query'];

                if ( strlen($request) < 1 )
                {
                    $request = '/';
                }

            }

            $array_headers = array(
                'User-Agent' => "HTTPSocket/$this->version",
                'Host' => ( $this->remote_port == 80 ? $this->remote_host : "$this->remote_host:$this->remote_port" ),
                'Accept' => '*/*',
                'Connection' => 'Close' );

            foreach ( $this->extra_headers as $key => $value )
            {
                $array_headers[$key] = $value;
            }

            $this->result = $this->result_header = $this->result_body = '';

            // was content sent as an array? if so, turn it into a string
            if (is_array($content))
            {
                $pairs = array();

                foreach ( $content as $key => $value )
                {
                    $pairs[] = "$key=".urlencode($value);
                }

                $content = join('&',$pairs);
                unset($pairs);
            }

            $OK = TRUE;

            // instance connection
            if ($this->bind_host)
            {
                $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
                socket_bind($socket,$this->bind_host);

                if (!@socket_connect($socket,$this->remote_host,$this->remote_port))
                {
                    $OK = FALSE;
                }

            }
            else
            {
                $socket = @fsockopen( $this->remote_host, $this->remote_port, $sock_errno, $sock_errstr, 10 );
            }

            if ( !$socket || !$OK )
            {
                $this->error[] = "Can't create socket connection to $this->remote_host:$this->remote_port.";
                return 0;
            }

            // if we have a username and password, add the header
            if ( isset($this->remote_uname) && isset($this->remote_passwd) )
            {
                $array_headers['Authorization'] = 'Basic '.base64_encode("$this->remote_uname:$this->remote_passwd");
            }

            // for DA skins: if $this->remote_passwd is NULL, try to use the login key system
            if ( isset($this->remote_uname) && $this->remote_passwd == NULL )
            {
                $array_headers['Cookie'] = "session={$_SERVER['SESSION_ID']}; key={$_SERVER['SESSION_KEY']}";
            }

            // if method is POST, add content length & type headers
            if ( $this->method == 'POST' )
            {
                $array_headers['Content-type'] = 'application/x-www-form-urlencoded';
                $array_headers['Content-length'] = strlen($content);
            }
            // else method is GET or HEAD. we don't support anything else right now.
            else
            {
                if ($content)
                {
                    $request .= "?$content";
                }
            }

            // prepare query
            $query = "$this->method $request HTTP/1.0\\r\\n";
            foreach ( $array_headers as $key => $value )
            {
                $query .= "$key: $value\\r\\n";
            }
            $query .= "\\r\\n";

            // if POST we need to append our content
            if ( $this->method == 'POST' && $content )
            {
                $query .= "$content\\r\\n\\r\\n";
            }

            // query connection
            if ($this->bind_host)
            {
                socket_write($socket,$query);

                // now load results
                while ( $out = socket_read($socket,2048) )
                {
                    $this->result .= $out;
                }
            }
            else
            {
                fwrite( $socket, $query, strlen($query) );

                // now load results
                $this->lastTransferSpeed = 0;
                $status = socket_get_status($socket);
                $startTime = time();
                $length = 0;
                $prevSecond = 0;
                while ( !feof($socket) && !$status['timed_out'] )
                {
                    $chunk = fgets($socket,1024);
                    $length += strlen($chunk);
                    $this->result .= $chunk;

                    $elapsedTime = time() - $startTime;

                    if ( $elapsedTime > 0 )
                    {
                        $this->lastTransferSpeed = ($length/1024)/$elapsedTime;
                    }

                    if ( $doSpeedCheck > 0 && $elapsedTime > 5 && $this->lastTransferSpeed < $doSpeedCheck )
                    {
                        $this->warn[] = "kB/s for last 5 seconds is below 50 kB/s (~".( ($length/1024)/$elapsedTime )."), dropping connection...";
                        $this->result_status_code = 503;
                        break;
                    }

                }

                if ( $this->lastTransferSpeed == 0 )
                {
                    $this->lastTransferSpeed = $length/1024;
                }

            }

            list($this->result_header,$this->result_body) = preg_split("/\\r\\n\\r\\n/",$this->result,2);

            if ($this->bind_host)
            {
                socket_close($socket);
            }
            else
            {
                fclose($socket);
            }

            $this->query_cache[] = $query;


            $headers = $this->fetch_header();

            // what return status did we get?
            if (!$this->result_status_code)
            {
                preg_match("#HTTP/1\\.. (\\d+)#",$headers[0],$matches);
                $this->result_status_code = $matches[1];
            }

            // did we get the full file?
            if ( !empty($headers['content-length']) && $headers['content-length'] != strlen($this->result_body) )
            {
                $this->result_status_code = 206;
            }

            // now, if we're being passed a location header, should we follow it?
            if ($this->doFollowLocationHeader)
            {
                if (!empty($headers['location']))
                {
                    $this->redirectURL = $headers['location'];
                    $this->query($headers['location']);
                }
            }

        }

        function getTransferSpeed()
        {
            return $this->lastTransferSpeed;
        }

        /**
         * The quick way to get a URL's content :)
         *
         * @param string URL
         * @param boolean return as array? (like PHP's file() command)
         * @return string result body
         */
        function get($location, $asArray = FALSE )
        {
            $this->query($location);

            if ( $this->get_status_code() == 200 )
            {
                if ($asArray)
                {
                    return preg_split("/\\n/",$this->fetch_body());
                }

                return $this->fetch_body();
            }

            return FALSE;
        }

        /**
         * Returns the last status code.
         * 200 = OK;
         * 403 = FORBIDDEN;
         * etc.
         *
         * @return int status code
         */
        function get_status_code()
        {
            return $this->result_status_code;
        }

        /**
         * Adds a header, sent with the next query.
         *
         * @param string header name
         * @param string header value
         */
        function add_header($key,$value)
        {
            $this->extra_headers[$key] = $value;
        }

        /**
         * Clears any extra headers.
         *
         */
        function clear_headers()
        {
            $this->extra_headers = array();
        }

        /**
         * Return the result of a query.
         *
         * @return string result
         */
        function fetch_result()
        {
            return $this->result;
        }

        /**
         * Return the header of result (stuff before body).
         *
         * @param string (optional) header to return
         * @return array result header
         */
        function fetch_header( $header = '' )
        {
            $array_headers = preg_split("/\\r\\n/",$this->result_header);

            $array_return = array( 0 => $array_headers[0] );
            unset($array_headers[0]);

            foreach ( $array_headers as $pair )
            {
                list($key,$value) = preg_split("/: /",$pair,2);
                $array_return[strtolower($key)] = $value;
            }

            if ( $header != '' )
            {
                return $array_return[strtolower($header)];
            }

            return $array_return;
        }

        /**
         * Return the body of result (stuff after header).
         *
         * @return string result body
         */
        function fetch_body()
        {
            return $this->result_body;
        }

        /**
         * Return parsed body in array format.
         *
         * @return array result parsed
         */
        function fetch_parsed_body()
        {
            parse_str($this->result_body,$x);
            return $x;
        }

    }

    ______________________________________________________________________________________

  2. Jeroen Steenhuis Member
    Reactie geplaatst op: 25-04-2014 om 10:58

    Nog even een update, het onderstaande script kan ook omgaan als je niet een subdomein maar het hoofddomein wilt aanpassen. Verder zit er een betere detectie in van het clientip.

    FILE: update.php
    _____________________________________________________

     

    <?php
     
    // Dit is de PHP class voor de DirectAdmin.
    // http://forum.directadmin.com/showthread.php?t=258
    include("HTTPSocket.php");

    $DIRECTADMINUSER="username";
    $DIRECTADMINPASSWORD="password";
     
    if (isset($_GET["hostname"])) {
       
      // Bewaar het IP
      if (!empty($_SERVER['HTTP_CLIENT_IP'])) 
      {
        $IP = $_SERVER['HTTP_CLIENT_IP'];
      } 
      elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) 
      {
        $IP = $_SERVER['HTTP_X_FORWARDED_FOR'];
      } 
      else 
      {
        $IP = $_SERVER['REMOTE_ADDR'];
      }
      $FQDN=$_GET["hostname"];
      $HOSTNAMEARRAY = array_reverse(explode(".", $FQDN));
      $DOMAIN = $HOSTNAMEARRAY[1].".".$HOSTNAMEARRAY[0];
      if (isset($HOSTNAMEARRAY[2])) $HOSTNAME = $HOSTNAMEARRAY[2];
        else $HOSTNAME=$DOMAIN.".";

      if (isset($_GET["debug"])) print("\\nFQDN=$FQDN HOSTNAME=$HOSTNAME DOMAIN=$DOMAIN OLDIP=".gethostbyname($FQDN)." NEWIP=$IP\\n");
        
      $ERROR=0;
      // Controleer of het IP
      if (($IP !== gethostbyname($FQDN)) || (isset($_GET["force"]))) {
     
        // Maak een instantie aan van het HTTPSocket object.
        $sock = new HTTPSocket;
     
        // Stel de hostnaam en de poort in van het DirectAdmin panel.
        $sock->connect("127.0.0.1",2222);
     
        // Stel de gebruikersnaam, het wachtwoord en kies voor de POST of GET methode.
        $sock->set_login($DIRECTADMINUSER,$DIRECTADMINPASSWORD);
        $sock->set_method('POST');
     
        // Set ttl to 60 seconds
        $sock->query("/CMD_API_DNS_CONTROL?domain=".$DOMAIN."&action=ttl&ttl_select=custom&ttl=60");
        if (!strstr($sock->fetch_body(),"error=0")) $ERROR=1;
        
        // Een update is niet mogelijk dus eerst het oude record verwijderen.
        $sock->query("/CMD_API_DNS_CONTROL?domain=".$DOMAIN."&action=select&arecs0=name=".$HOSTNAME."&value=".gethostbyname("$HOSTNAME"));
        if (!strstr($sock->fetch_body(),"error=0")) $ERROR=1;
     
        // Maak vervolgens een nieuw record aan in de DNS met het nieuwe IP.
        $sock->query("/CMD_API_DNS_CONTROL?domain=".$DOMAIN."&action=add&type=A&name=".$HOSTNAME."&value=".$IP);
        if (!strstr($sock->fetch_body(),"error=0")) $ERROR=1;

        if (ERROR == 0) print("good\\n"); else print ("dnserr\\n");
      }
      else print("nochg\\n");
    }
    else print("notfqdn\\n");

     

    Vond u dit antwoord nuttig?