Modifying the dyndns detection method



  • Hi All -

    So I'm working in a country where every ISP is mandated to have a web filtering system.  Most of the time, I could care less about this… that is until the upstream proxy is improperly configured!

    We have the situation where checkip.dyndns.org is being improperly cached and renders my ability to update my hostnames and OpenDNS account useless.  I finally tweaked around a bit in /etc/inc/dyndns.class and /usr/local/www/services_dyndns.php and added the line:

    curl_setopt($ip_ch, CURLOPT_PORT, 8245); 
    

    which forces the IP check to run over port 8245, thereby bypassing the proxy which swallows up anything going to a destination port 80.

    I run 5 pfSense boxes running at various offices and decided that I'd like this to be a little more friendly - by friendly, I mean that I'd like the ability to choose what port the detection will run on in each dynDNS section.  I got this working brilliantly at the Services/Dynamic DNS page.  I tweaked services_dyndns_edit.php and added a "checkport" section to the array and that updates in /conf/config.xml brilliantly.

    I noticed, though, that the cronjob /etc/rc.dyndns.update is what actually does my updating.  That's when i realized that i also needed to be looking at /etc/inc/dyndns.class.

    This, however, has proven more difficult.  I'm not sure exactly how to get that function to look at my port specification.

    Any hints here?  It's great that Dyndns.org offers checking for IP addys on multiple ports and I could see this coming in handy for other people too.

    Here is my modified /usr/local/www/services_dyndns_edit.php (changes highlighted):

    
    /* $Id$ */
    /*
    	Copyright (C) 2008 Ermal LuÁi
    	All rights reserved.
    
    	Redistribution and use in source and binary forms, with or without
    	modification, are permitted provided that the following conditions are met:
    
    	1\. Redistributions of source code must retain the above copyright notice,
    	   this list of conditions and the following disclaimer.
    
    	2\. Redistributions in binary form must reproduce the above copyright
    	   notice, this list of conditions and the following disclaimer in the
    	   documentation and/or other materials provided with the distribution.
    
    	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
    	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
    	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
    	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
    	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    	POSSIBILITY OF SUCH DAMAGE.
    */
    /*
    	pfSense_BUILDER_BINARIES:	/bin/rm
    	pfSense_MODULE:	dyndns
    */
    
    ##|+PRIV
    ##|*IDENT=page-services-dynamicdnsclient
    ##|*NAME=Services: Dynamic DNS client page
    ##|*DESCR=Allow access to the 'Services: Dynamic DNS client' page.
    ##|*MATCH=services_dyndns_edit.php*
    ##|-PRIV
    
    /* returns true if $uname is a valid DynDNS username */
    function is_dyndns_username($uname) {
            if (!is_string($uname))
                    return false;
    
            if (preg_match("/[^a-z0-9\-.@_:]/i", $uname))
                    return false;
            else
                    return true;
    }
    
    require("guiconfig.inc");
    
    if (!is_array($config['dyndnses']['dyndns'])) {
    	$config['dyndnses']['dyndns'] = array();
    }
    
    $a_dyndns = &$config['dyndnses']['dyndns'];
    
    $id = $_GET['id'];
    if (isset($_POST['id']))
    	$id = $_POST['id'];
    
    if (isset($id) && isset($a_dyndns[$id])) {
    	$pconfig['username'] = $a_dyndns[$id]['username'];
    	$pconfig['password'] = $a_dyndns[$id]['password'];
    	$pconfig['host'] = $a_dyndns[$id]['host'];
    	[color]$pconfig['checkport'] = $a_dyndns[$id]['checkport'];[/color]
    	$pconfig['mx'] = $a_dyndns[$id]['mx'];
    	$pconfig['type'] = $a_dyndns[$id]['type'];
    	$pconfig['enable'] = !isset($a_dyndns[$id]['enable']);
    	$pconfig['interface'] = $a_dyndns[$id]['interface'];
    	$pconfig['wildcard'] = isset($a_dyndns[$id]['wildcard']);
    	$pconfig['descr'] = $a_dyndns[$id]['descr'];
    }
    
    if ($_POST) {
    
    	unset($input_errors);
    	$pconfig = $_POST;
    
    	if(($pconfig['type'] == "freedns" || $pconfig['type'] == "namecheap") && $_POST['username'] == "")
    		$_POST['username'] = "none"; 
    
    	/* input validation */
    	$reqdfields = array();
    	$reqdfieldsn = array();
    	$reqdfields = array("host"[color], "checkport"[/color], "username", "password", "type");
    	$reqdfieldsn = array(gettext("Hostname"),gettext("Username"),gettext("Password"),gettext("Service type"));
    
    	do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
    
    	if (($_POST['mx'] && !is_domain($_POST['mx']))) 
    		$input_errors[] = gettext("The MX contains invalid characters.");
    	if (($_POST['username'] && !is_dyndns_username($_POST['username'])) || (($pconfig['type'] != "namecheap") && ($_POST['username'] == ""))) 
    		$input_errors[] = gettext("The username contains invalid characters.");
    
    	if (!$input_errors) {
    		$dyndns = array();
    		$dyndns['type'] = $_POST['type'];
    		$dyndns['username'] = $_POST['username'];
    		$dyndns['password'] = $_POST['password'];
    		$dyndns['host'] = $_POST['host'];
    		[color]$dyndns['checkport'] = $_POST['checkport'];[/color]
    		$dyndns['mx'] = $_POST['mx'];
    		$dyndns['wildcard'] = $_POST['wildcard'] ? true : false;
    		$dyndns['enable'] = $_POST['enable'] ? false : true;
    		$dyndns['interface'] = $_POST['interface'];
    		$dyndns['descr'] = $_POST['descr'];
    
    		if($dyndns['username'] == "none")
    			$dyndns['username'] = "";
    
    		if (isset($id) && $a_dyndns[$id])
    			$a_dyndns[$id] = $dyndns;
    		else
    			$a_dyndns[] = $dyndns;
    
    		write_config();
    
    		$retval = 0;
    
    		conf_mount_rw();
    
    		unlink("{$g['conf_path']}/dyndns_{$dyndns['interface']}{$dyndns['type']}{$dyndns['host']}.cache");
    
    		$retval = services_dyndns_configure_client($dyndns);
    
    		conf_mount_ro();
    
    		header("Location: services_dyndns.php");
    		exit;
    	}
    }
    
    $pgtitle = array(gettext("Services"),gettext("Dynamic DNS client"));
    include("head.inc");
    
    ?>
    
    <form action="services_dyndns_edit.php" method="post" name="iform" id="iform">
    
    [color]				
    
    [/color]
    
    | 
    
    |  |
    
    				   |
    |  | 
    				    " >
    				   |
    |  | 
    			<select name="type" class="formselect" id="type">$types = explode(",", "DNS-O-Matic, DynDNS (dynamic),DynDNS (static),DynDNS (custom),DHS,DyNS,easyDNS,No-IP,ODS.org,ZoneEdit,Loopia,freeDNS, DNSexit, OpenDNS, Namecheap, HE.net");						$vals = explode(" ", "dnsomatic dyndns dyndns-static dyndns-custom dhs dyns easydns noip ods zoneedit loopia freedns dnsexit opendns namecheap he-net");						$j = 0; for ($j = 0; $j < count($vals); $j++): ?>                      <option value="<?=$vals[$j];?>" <?php="" if="" ($vals[$j]="=" $pconfig['type'])="" echo="" "selected";?="">></option></select>  |								
    |  | 
    				   <select name="interface" class="formselect" id="interface">foreach ($iflist as $if => $ifdesc):?>							<option value="<?=$if;?>" <?php="" if="" ($pconfig['interface']="=" $if)="" echo="" "selected";?="">></option></select> 
    					 |										
    |  | 
    
    		           |				
    |  | 
                        value="">
    
    		           |				
    |  | 
    
                                           " all services support this.");?> |				
    |  | 
                        >
                         |				
    |  | 
    
                       |
    |  | 
    
                       |
    |  | 
    
                       |
    |   | 
                        " onClick="enable_change(true)">
    					[">](services_dyndns.php)
    
                       |
    |   |                     General setup%s or allow the DNS server list to be overridden
                        by DHCP/PPP on WAN for dynamic DNS updates to work."),'[','](system.php)');?> |
    
    </form>
    
    

    and /usr/local/www/services_dyndns.php:

    /* $Id$ */
    /*
    	Copyright (C) 2008 Ermal LuÁi
    	All rights reserved.
    
    	Redistribution and use in source and binary forms, with or without
    	modification, are permitted provided that the following conditions are met:
    
    	1\. Redistributions of source code must retain the above copyright notice,
    	   this list of conditions and the following disclaimer.
    
    	2\. Redistributions in binary form must reproduce the above copyright
    	   notice, this list of conditions and the following disclaimer in the
    	   documentation and/or other materials provided with the distribution.
    
    	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
    	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
    	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
    	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
    	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    	POSSIBILITY OF SUCH DAMAGE.
    */
    /*
    	pfSense_BUILDER_BINARIES:	/usr/bin/host	
    	pfSense_MODULE:	dyndns
    */
    
    ##|+PRIV
    ##|*IDENT=page-services-dynamicdnsclients
    ##|*NAME=Services: Dynamic DNS clients page
    ##|*DESCR=Allow access to the 'Services: Dynamic DNS clients' page.
    ##|*MATCH=services_dyndns.php*
    ##|-PRIV
    
    require("guiconfig.inc");
    
    if (!is_array($config['dyndnses']['dyndns']))
    	$config['dyndnses']['dyndns'] = array();
    
    $a_dyndns = &$config['dyndnses']['dyndns'];
    
    if ($_GET['act'] == "del") {
    		unset($a_dyndns[$_GET['id']]);
    
    		write_config();
    
    		header("Location: services_dyndns.php");
    		exit;
    }
    
    function dyndnsCheckIP($int, $checkport) {
    
    	$ip_address = get_interface_ip($int);
    	if (is_private_ip($ip_address)) {
    		$hosttocheck = "checkip.dyndns.org";
    		$checkip = gethostbyname($hosttocheck);
    		$ip_ch = curl_init("http://{$checkip}");
    		curl_setopt($ip_ch, CURLOPT_RETURNTRANSFER, 1);
    		curl_setopt($ip_ch, CURLOPT_PORT, $checkport);
    		curl_setopt($ip_ch, CURLOPT_SSL_VERIFYPEER, FALSE);
    		curl_setopt($ip_ch, CURLOPT_INTERFACE, $ip_address);
    		$ip_result_page = curl_exec($ip_ch);
    		curl_close($ip_ch);
    		$ip_result_decoded = urldecode($ip_result_page);
    		preg_match('=Current IP Address: (.*)=siU', $ip_result_decoded, $matches);
    		$ip_address = trim($matches[1]);
    	}
    
    	return $ip_address;
    }
    
    $pgtitle = array(gettext("Services"), gettext("Dynamic DNS clients"));
    include("head.inc");
    
    ?>
    
    <form action="services_dyndns.php" method="post" name="iform" id="iform">
    
    | 
    	$tab_array = array();
    	$tab_array[] = array(gettext("DynDns"), true, "services_dyndns.php");
    	$tab_array[] = array(gettext("RFC 2136"), false, "services_rfc2136.php");
    	display_top_tabs($tab_array);
    ?>
       |
    | 
    
    |  |  |  |  |  |  |		
    | 
    		  	  		foreach ($iflist as $if => $ifdesc):
    				if ($dyndns['interface'] == $if): ?>
    
    		   | 
    				  					$types = explode(",", "DNS-O-Matic, DynDNS (dynamic),DynDNS (static),DynDNS (custom),DHS,DyNS,easyDNS,No-IP,ODS.org,ZoneEdit,Loopia,freeDNS, DNSexit, OpenDNS, Namecheap, HE.net");
    					$vals = explode(" ", "dnsomatic dyndns dyndns-static dyndns-custom dhs dyns easydns noip ods zoneedit loopia freedns dnsexit opendns namecheap he-net");
    					$j = 0; for ($j = 0; $j < count($vals); $j++) 
                          			if ($vals[$j] == $dyndns['type']) { 
                          				echo htmlspecialchars($types[$j]);
    							break;
    					}
    				?>
                       | 
    
                       | 
    							$filename = "{$g['conf_path']}/dyndns_{$if}{$dyndns['type']}" . escapeshellarg($dyndns['host']) . ".cache";
    				$ipaddr = dyndnsCheckIP($if, $dyndns['checkport']);
    				if(file_exists($filename)) {
    					$cached_ip_s = split(":", file_get_contents($filename));
    					$cached_ip = $cached_ip_s[0];
    					if($ipaddr <> $cached_ip) 
    						echo "";
    					else 
    						echo "";
    						echo htmlspecialchars($cached_ip);
    						echo "";
    				} else {
    					echo "N/A";
    				}
    			?>  | 
    
                       |  [![](./themes/<?= $g['theme']; ?>/images/icons/icon_e.gif)](services_dyndns_edit.php?id=<?=$i;?>)
                          [')">![](./themes/<?= $g['theme']; ?>/images/icons/icon_x.gif)](services_dyndns.php?act=del&id=<?=$i;?>) |				
    |  |  [![](./themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif)](services_dyndns_edit.php) |								
    				  |				   |				
    
    	 |	
    
    </form>
    
    


  • forget the highlighting apparently. doesn't work in "code" sections!


Locked