diff options
Diffstat (limited to 'config/openvpn-client-export')
-rwxr-xr-x | config/openvpn-client-export/openvpn-client-export.inc | 233 |
1 files changed, 136 insertions, 97 deletions
diff --git a/config/openvpn-client-export/openvpn-client-export.inc b/config/openvpn-client-export/openvpn-client-export.inc index 9488119e..de0ef7e7 100755 --- a/config/openvpn-client-export/openvpn-client-export.inc +++ b/config/openvpn-client-export/openvpn-client-export.inc @@ -1,6 +1,7 @@ <?php /* openvpn-client-export.inc + part of pfSense (http://www.pfSense.com) Copyright (C) 2009 Scott Ullrich <sullrich@gmail.com> Copyright (C) 2008 Shrew Soft Inc Copyright (C) 2010 Ermal Luci @@ -39,7 +40,7 @@ require_once("util.inc"); require_once("pfsense-utils.inc"); global $current_openvpn_version, $current_openvpn_version_rev; -$current_openvpn_version = "2.3.6"; +$current_openvpn_version = "2.3.6"; $current_openvpn_version_rev = "03"; function openvpn_client_export_install() { @@ -52,9 +53,9 @@ function openvpn_client_export_install() { $ovpndir = "/usr/local/share/openvpn"; $workdir = "{$ovpndir}/client-export"; - if (!is_dir($workdir)) + if (!is_dir($workdir)) { mkdir($workdir, 0777, true); - + } exec("/usr/bin/tar zxf {$tarpath} -C {$ovpndir}"); conf_mount_ro(); } @@ -80,21 +81,22 @@ function openvpn_client_export_prefix($srvid, $usrid = null, $crtid = null) { // lookup server settings $settings = $config['openvpn']['openvpn-server'][$srvid]; - if (empty($settings)) + if (empty($settings)) { return false; - if ($settings['disable']) + } + if ($settings['disable']) { return false; - + } $host = empty($config['system']['hostname']) ? "openvpn" : $config['system']['hostname']; $prot = ($settings['protocol'] == 'UDP' ? 'udp' : $settings['protocol']); $port = $settings['local_port']; $filename_addition = ""; - if ($usrid && is_numeric($usrid)) + if ($usrid && is_numeric($usrid)) { $filename_addition = "-".$config['system']['user'][$usrid]['name']; - elseif ($crtid && is_numeric($crtid) && function_exists("cert_get_cn")) + } elseif ($crtid && is_numeric($crtid) && function_exists("cert_get_cn")) { $filename_addition = "-" . str_replace(' ', '_', cert_get_cn($config['cert'][$crtid]['crt'])); - + } return "{$host}-{$prot}-{$port}{$filename_addition}"; } @@ -106,13 +108,15 @@ function openvpn_client_pem_to_pk12($outpath, $outpass, $crtpath, $keypath, $cap if ($capath) { $ecapath = escapeshellarg($capath); exec("/usr/bin/openssl pkcs12 -export -in {$ecrtpath} -inkey {$ekeypath} -certfile {$ecapath} -out {$eoutpath} -passout pass:{$eoutpass}"); - } else + } else { exec("/usr/bin/openssl pkcs12 -export -in {$ecrtpath} -inkey {$ekeypath} -out {$eoutpath} -passout pass:{$eoutpass}"); + } unlink($crtpath); unlink($keypath); - if ($capath) + if ($capath) { unlink($capath); + } } function openvpn_client_export_validate_config($srvid, $usrid, $crtid) { @@ -131,8 +135,7 @@ function openvpn_client_export_validate_config($srvid, $usrid, $crtid) { // lookup server certificate info $server_cert = lookup_cert($settings['certref']); - if (!$server_cert) - { + if (!$server_cert) { $input_errors[] = "Could not locate server certificate."; } else { $server_ca = lookup_ca($server_cert['caref']); @@ -159,24 +162,26 @@ function openvpn_client_export_validate_config($srvid, $usrid, $crtid) { } else { $cert = $config['cert'][$crtid]; } - if (!$cert) - { + if (!$cert) { $input_errors[] = "Could not find client certificate."; } else { // If $cert is not an array, it's a certref not a cert. - if (!is_array($cert)) + if (!is_array($cert)) { $cert = lookup_cert($cert); + } } } elseif (($settings['mode'] == "server_tls") || (($settings['mode'] == "server_tls_user") && ($settings['authmode'] != "Local Database"))) { $cert = $config['cert'][$crtid]; - if (!$cert) + if (!$cert) { $input_errors[] = "Could not find client certificate."; - } else + } + } else { $nokeys = true; + } - if ($input_errors) + if ($input_errors) { return false; - + } return array($settings, $server_cert, $server_ca, $servercn, $user, $cert, $nokeys); } @@ -202,9 +207,10 @@ function openvpn_client_export_config($srvid, $usrid, $crtid, $useaddr, $verifys // add basic settings $devmode = empty($settings['dev_mode']) ? "tun" : $settings['dev_mode']; - if (($expformat != "inlinedroid") && ($expformat != "inlineios")) + if (($expformat != "inlinedroid") && ($expformat != "inlineios")) { $conf .= "dev {$devmode}{$nl}"; - if(!empty($settings['tunnel_networkv6']) && ($expformat != "inlinedroid") && ($expformat != "inlineios")) { + } + if (!empty($settings['tunnel_networkv6']) && ($expformat != "inlinedroid") && ($expformat != "inlineios")) { $conf .= "tun-ipv6{$nl}"; } $conf .= "persist-tun{$nl}"; @@ -216,14 +222,16 @@ function openvpn_client_export_config($srvid, $usrid, $crtid, $useaddr, $verifys $conf .= "auth {$digest}{$nl}"; $conf .= "tls-client{$nl}"; $conf .= "client{$nl}"; - if (($expformat != "inlinedroid") && ($expformat != "inlineios")) + if (($expformat != "inlinedroid") && ($expformat != "inlineios")) { $conf .= "resolv-retry infinite{$nl}"; + } $conf .= "$remotes{$nl}"; /* Use a random local port, otherwise two clients will conflict if they run at the same time. May not be supported on older clients (Released before May 2010) */ - if (($randomlocalport != 0) && (substr($expformat, 0, 7) != "yealink") && ($expformat != "snom")) + if (($randomlocalport != 0) && (substr($expformat, 0, 7) != "yealink") && ($expformat != "snom")) { $conf .= "lport 0{$nl}"; + } /* This line can cause problems with auth-only setups and also with Yealink/Snom phones since they are stuck on an older OpenVPN version that does not support this feature. */ @@ -246,19 +254,20 @@ function openvpn_client_export_config($srvid, $usrid, $crtid, $useaddr, $verifys if (!empty($proxy)) { if ($proxy['proxy_type'] == "http") { - if (strtoupper(substr($settings['protocol'], 0, 3)) == "UDP") { $input_errors[] = "This server uses UDP protocol and cannot communicate with HTTP proxy."; return; } $conf .= "http-proxy {$proxy['ip']} {$proxy['port']} "; } - if ($proxy['proxy_type'] == "socks") + if ($proxy['proxy_type'] == "socks") { $conf .= "socks-proxy {$proxy['ip']} {$proxy['port']} "; + } if ($proxy['proxy_authtype'] != "none") { - if (!isset($proxy['passwdfile'])) + if (!isset($proxy['passwdfile'])) { $proxy['passwdfile'] = openvpn_client_export_prefix($srvid, $usrid, $crtid) . "-proxy"; - $conf .= " {$proxy['passwdfile']} {$proxy['proxy_authtype']}"; + $conf .= " {$proxy['passwdfile']} {$proxy['proxy_authtype']}"; + } } $conf .= "{$nl}"; } @@ -274,7 +283,7 @@ function openvpn_client_export_config($srvid, $usrid, $crtid, $useaddr, $verifys // add key settings $prefix = openvpn_client_export_prefix($srvid, $usrid, $crtid); $cafile = "{$prefix}-ca.crt"; - if($nokeys == false) { + if ($nokeys == false) { if ($expformat == "yealink_t28") { $conf .= "ca /yealink/config/openvpn/keys/ca.crt{$nl}"; $conf .= "cert /yealink/config/openvpn/keys/client1.crt{$nl}"; @@ -297,22 +306,24 @@ function openvpn_client_export_config($srvid, $usrid, $crtid, $useaddr, $verifys } elseif (substr($expformat, 0, 6) != "inline") { $conf .= "pkcs12 {$prefix}.p12{$nl}"; } - } else if ($settings['mode'] == "server_user") { - if (substr($expformat, 0, 6) != "inline") + } elseif ($settings['mode'] == "server_user") { + if (substr($expformat, 0, 6) != "inline") { $conf .= "ca {$cafile}{$nl}"; + } } if ($settings['tls'] && !$skiptls) { - if ($expformat == "yealink_t28") + if ($expformat == "yealink_t28") { $conf .= "tls-auth /yealink/config/openvpn/keys/ta.key 1{$nl}"; - elseif ($expformat == "yealink_t38g") + } elseif ($expformat == "yealink_t38g") { $conf .= "tls-auth /phone/config/openvpn/keys/ta.key 1{$nl}"; - elseif ($expformat == "yealink_t38g2") + } elseif ($expformat == "yealink_t38g2") { $conf .= "tls-auth /config/openvpn/keys/ta.key 1{$nl}"; - elseif ($expformat == "snom") + } elseif ($expformat == "snom") { $conf .= "tls-auth /openvpn/ta.key 1{$nl}"; - elseif (substr($expformat, 0, 6) != "inline") + } elseif (substr($expformat, 0, 6) != "inline") { $conf .= "tls-auth {$prefix}-tls.key 1{$nl}"; + } } // Prevent MITM attacks by verifying the server certificate. @@ -323,24 +334,26 @@ function openvpn_client_export_config($srvid, $usrid, $crtid, $useaddr, $verifys if (function_exists("cert_get_purpose")) { if (is_array($server_cert) && ($server_cert['crt'])) { $purpose = cert_get_purpose($server_cert['crt'], true); - if ($purpose['server'] == 'Yes') + if ($purpose['server'] == 'Yes') { $conf .= "ns-cert-type server{$nl}"; + } } } // add optional settings if (!empty($settings['compression'])) { - if ($pfs_version > 2.1) + if ($pfs_version > 2.1) { $conf .= "comp-lzo {$settings['compression']}{$nl}"; - else + } else { $conf .= "comp-lzo{$nl}"; + } } - if ($settings['passtos']) + if ($settings['passtos']) { $conf .= "passtos{$nl}"; + } - if ($openvpnmanager) - { + if ($openvpnmanager) { if (!empty($settings['client_mgmt_port'])) { $client_mgmt_port = $settings['client_mgmt_port']; } else { @@ -393,10 +406,11 @@ function openvpn_client_export_config($srvid, $usrid, $crtid, $useaddr, $verifys // convert to pkcs12 format $p12file = "{$tempdir}/{$prefix}.p12"; - if ($usetoken) + if ($usetoken) { openvpn_client_pem_to_pk12($p12file, $outpass, $crtfile, $keyfile); - else + } else { openvpn_client_pem_to_pk12($p12file, $outpass, $crtfile, $keyfile, $cafile); + } } $command = "cd " . escapeshellarg("{$tempdir}/..") . " && /usr/local/bin/zip -r " @@ -432,7 +446,7 @@ function openvpn_client_export_config($srvid, $usrid, $crtid, $useaddr, $verifys case "yealink_t38g2": // create template directory $tempdir = "{$g['tmp_path']}/{$prefix}"; - $keydir = "{$tempdir}/keys"; + $keydir = "{$tempdir}/keys"; mkdir($tempdir, 0700, true); mkdir($keydir, 0700, true); @@ -511,8 +525,9 @@ function openvpn_client_export_installer($srvid, $usrid, $crtid, $useaddr, $veri $ovpndir = "/usr/local/share/openvpn"; $workdir = "{$ovpndir}/client-export"; - if (!file_exists($workdir . "/template/{$client_install_exe}")) + if (!file_exists($workdir . "/template/{$client_install_exe}")) { openvpn_client_export_install(); + } $validconfig = openvpn_client_export_validate_config($srvid, $usrid, $crtid); if ($validconfig) { @@ -527,15 +542,17 @@ function openvpn_client_export_installer($srvid, $usrid, $crtid, $useaddr, $veri // create config directory $confdir = "{$tempdir}/config"; - if (!is_dir($conf_dir)) + if (!is_dir($conf_dir)) { mkdir($confdir, 0700, true); + } // copy the template directory exec("cp -r {$workdir}/template/* {$tempdir}"); // and put the required installer exe in place exec("/bin/cp {$tempdir}/{$client_install_exe} {$tempdir}/openvpn-install.exe"); - if (stristr($openvpn_version, "x64")) + if (stristr($openvpn_version, "x64")) { rename("{$tempdir}/openvpn-postinstall64.exe", "{$tempdir}/openvpn-postinstall.exe"); + } // write configuration file $prefix = openvpn_client_export_prefix($srvid, $usrid, $crtid); @@ -546,7 +563,7 @@ function openvpn_client_export_installer($srvid, $usrid, $crtid, $useaddr, $veri $pwdfle .= "{$proxy['password']}\r\n"; file_put_contents("{$confdir}/{$proxy['passwdfile']}", $pwdfle); } - $conf = openvpn_client_export_config($srvid, $usrid, $crtid, $useaddr, $verifyservercn, $randomlocalport, $usetoken, $nokeys, $proxy, "", "baseconf", false, true, $openvpnmanager, $advancedoptions); + $conf = openvpn_client_export_config($srvid, $usrid, $crtid, $useaddr, $verifyservercn, $randomlocalport, $usetoken, $nokeys, $proxy, "", "baseconf", false, true, $openvpnmanager, $advancedoptions); if (!$conf) { $input_errors[] = "Could not create a config to export."; return false; @@ -569,37 +586,40 @@ function openvpn_client_export_installer($srvid, $usrid, $crtid, $useaddr, $veri file_put_contents($keyfile, base64_decode($cert['prv'])); // convert to pkcs12 format $p12file = "{$tempdir}/config/{$prefix}.p12"; - if ($usetoken) + if ($usetoken) { openvpn_client_pem_to_pk12($p12file, $outpass, $crtfile, $keyfile); - else + } else { openvpn_client_pem_to_pk12($p12file, $outpass, $crtfile, $keyfile, $cafile); + } } // 7zip the configuration data chdir($tempdir); - $files = "config "; - if ($openvpnmanager) + $files = "config "; + if ($openvpnmanager) { $files .= "openvpnmanager "; + } $files .= "openvpn-install.exe "; $files .= "openvpn-postinstall.exe "; - if ($usetoken) + if ($usetoken) { $procchain = ';!@Install@!UTF-8! RunProgram="openvpn-postinstall.exe /Import" ;!@InstallEnd@!' ; - else + } else { $procchain = ';!@Install@!UTF-8! RunProgram="openvpn-postinstall.exe" ;!@InstallEnd@!' ; + } file_put_contents("{$tempdir}/7zipConfig",$procchain); - if(file_exists("/usr/pbi/p7zip-{$uname_p}/bin/7z")) + if (file_exists("/usr/pbi/p7zip-{$uname_p}/bin/7z")) { exec("/usr/pbi/p7zip-{$uname_p}/bin/7z -y a archive.7z {$files}"); - else + } else { exec("/usr/local/libexec/p7zip/7z -y a archive.7z {$files}"); - + } // create the final installer $outfile = "{$tempdir}-install.exe"; chdir($g['tmp_path']); @@ -616,8 +636,9 @@ function viscosity_openvpn_client_config_exporter($srvid, $usrid, $crtid, $usead $uname_p = trim(exec("uname -p")); $ovpndir = "/usr/local/share/openvpn/"; - if (!file_exists($workdir . "/template/openvpn-install.exe")) + if (!file_exists($workdir . "/template/openvpn-install.exe")) { openvpn_client_export_install(); + } $uniq = uniqid(); $tempdir = $g['tmp_path'] . "/openvpn-export-" . $uniq; @@ -653,8 +674,9 @@ function viscosity_openvpn_client_config_exporter($srvid, $usrid, $crtid, $usead // We need to nuke the ca line from the above config if it exists. $conf = explode("\n", $conf); for ($i=0; $i < count($conf); $i++) { - if ((substr($conf[$i], 0, 3) == "ca ") || (substr($conf[$i], 0, 7) == "pkcs12 ")) + if ((substr($conf[$i], 0, 3) == "ca ") || (substr($conf[$i], 0, 7) == "pkcs12 ")) { unset($conf[$i]); + } } $conf = implode("\n", $conf); @@ -716,11 +738,11 @@ EOF; } // Zip Viscosity file - if(file_exists("/usr/pbi/zip-{$uname_p}/bin/zip")) + if (file_exists("/usr/pbi/zip-{$uname_p}/bin/zip")) { exec("cd {$tempdir}/.. && /usr/pbi/zip-{$uname_p}/bin/zip -r {$zipfile} Viscosity.visc"); - else + } else { exec("cd {$tempdir}/.. && /usr/local/bin/zip -r {$zipfile} Viscosity.visc"); - + } // Remove temporary directory exec("rm -rf {$tempdir}"); @@ -748,30 +770,34 @@ function openvpn_client_export_sharedkey_config($srvid, $useaddr, $proxy, $zipco if (!empty($settings['ipaddr']) && is_ipaddr($settings['ipaddr'])) { $server_host = $settings['ipaddr']; } else { - if (!$interface) + if (!$interface) { $interface = "wan"; - if (in_array(strtolower($settings['protocol']), array("udp6", "tcp6"))) + } + if (in_array(strtolower($settings['protocol']), array("udp6", "tcp6"))) { $server_host = get_interface_ipv6($interface); - else + } else { $server_host = get_interface_ip($interface); + } } - } else if ($useaddr == "serverhostname" || empty($useaddr)) { + } elseif ($useaddr == "serverhostname" || empty($useaddr)) { $server_host = empty($config['system']['hostname']) ? "" : "{$config['system']['hostname']}."; $server_host .= "{$config['system']['domain']}"; - } else + } else { $server_host = $useaddr; + } $server_port = $settings['local_port']; $proto = strtolower($settings['protocol']); - if (strtolower(substr($settings['protocol'], 0, 3)) == "tcp") + if (strtolower(substr($settings['protocol'], 0, 3)) == "tcp") { $proto .= "-client"; + } $cipher = $settings['crypto']; $digest = !empty($settings['digest']) ? $settings['digest'] : "SHA1"; // add basic settings - $conf = "dev tun\n"; + $conf = "dev tun\n"; if(! empty($settings['tunnel_networkv6'])) { $conf .= "tun-ipv6\n"; } @@ -807,14 +833,16 @@ function openvpn_client_export_sharedkey_config($srvid, $useaddr, $proxy, $zipco } $conf .= "http-proxy {$proxy['ip']} {$proxy['port']} "; } - if ($proxy['proxy_type'] == "socks") + if ($proxy['proxy_type'] == "socks") { $conf .= "socks-proxy {$proxy['ip']} {$proxy['port']} "; + } if ($proxy['proxy_authtype'] != "none") { - if (!isset($proxy['passwdfile'])) + if (!isset($proxy['passwdfile'])) { $proxy['passwdfile'] = openvpn_client_export_prefix($srvid) . "-proxy"; - $conf .= " {$proxy['passwdfile']} {$proxy['proxy_authtype']}"; + $conf .= " {$proxy['passwdfile']} {$proxy['proxy_authtype']}"; + } + $conf .= "\n"; } - $conf .= "\n"; } // add key settings @@ -846,8 +874,9 @@ function openvpn_client_export_sharedkey_config($srvid, $useaddr, $proxy, $zipco // Remove temporary directory exec("rm -rf {$tempdir}"); return "{$prefix}-config.zip"; - } else + } else { return $conf; + } } function openvpn_client_export_build_remote_lines($settings, $useaddr, $interface, $expformat, $nl) { @@ -858,25 +887,30 @@ function openvpn_client_export_build_remote_lines($settings, $useaddr, $interfac if (!empty($settings['ipaddr']) && is_ipaddr($settings['ipaddr'])) { $server_host = $settings['ipaddr']; } else { - if (!$interface || ($interface == "any")) + if (!$interface || ($interface == "any")) { $interface = "wan"; - if (in_array(strtolower($settings['protocol']), array("udp6", "tcp6"))) + } + if (in_array(strtolower($settings['protocol']), array("udp6", "tcp6"))) { $server_host = get_interface_ipv6($interface); - else + } else { $server_host = get_interface_ip($interface); + } } } else if ($useaddr == "serverhostname" || empty($useaddr)) { $server_host = empty($config['system']['hostname']) ? "" : "{$config['system']['hostname']}."; $server_host .= "{$config['system']['domain']}"; - } else + } else { $server_host = $useaddr; + } $proto = strtolower($settings['protocol']); - if (strtolower(substr($settings['protocol'], 0, 3)) == "tcp") + if (strtolower(substr($settings['protocol'], 0, 3)) == "tcp") { $proto .= "-client"; + } - if (($expformat == "inlineios") && ($proto == "tcp-client")) + if (($expformat == "inlineios") && ($proto == "tcp-client")) { $proto = "tcp"; + } if (($useaddr == "servermagic") || ($useaddr == "servermagichost")) { $destinations = openvpn_client_export_find_port_forwards($server_host, $settings['local_port'], $proto, true, ($useaddr == "servermagichost")); @@ -892,19 +926,18 @@ function openvpn_client_export_build_remote_lines($settings, $useaddr, $interfac function openvpn_client_export_find_port_forwards($targetip, $targetport, $targetproto, $skipprivate, $findhostname=false) { global $config, $FilterIflist; - if (empty($FilterIflist)) + if (empty($FilterIflist)) { filter_generate_optcfg_array(); + } $destinations = array(); - if (!is_array($config['nat']) || !is_array($config['nat']['rule'])) + if (!is_array($config['nat']) || !is_array($config['nat']['rule'])) { return $destinations; + } foreach ($config['nat']['rule'] as $natent) { $dest = array(); - if (!isset($natent['disabled']) - && ($natent['target'] == $targetip) - && ($natent['local-port'] == $targetport) - && ($natent['protocol'] == $targetproto)) { + if (!isset($natent['disabled']) && ($natent['target'] == $targetip) && ($natent['local-port'] == $targetport) && ($natent['protocol'] == $targetproto)) { $dest['proto'] = $natent['protocol']; // Could be multiple ports... But we can only use one. @@ -914,32 +947,36 @@ function openvpn_client_export_find_port_forwards($targetip, $targetport, $targe // Could be network or address ... $natif = (!$natent['interface']) ? "wan" : $natent['interface']; - if (!isset($FilterIflist[$natif])) + if (!isset($FilterIflist[$natif])) { continue; // Skip if there is no interface + } $dstaddr = trim(filter_generate_address($natent, 'destination', true)); - if(!$dstaddr) + if(!$dstaddr) { $dstaddr = $FilterIflist[$natif]['ip']; + } $dstaddr_port = explode(" ", $dstaddr); - if(empty($dstaddr_port[0]) || strtolower(trim($dstaddr_port[0])) == "port") + if (empty($dstaddr_port[0]) || strtolower(trim($dstaddr_port[0])) == "port") { continue; // Skip port forward if no destination address found + } - - if (!is_ipaddr($dstaddr_port[0])) + if (!is_ipaddr($dstaddr_port[0])) { continue; // We can only work with single IPs, not subnets! + } - - if ($skipprivate && is_private_ip($dstaddr_port[0])) + if ($skipprivate && is_private_ip($dstaddr_port[0])) { continue; // Skipping a private IP destination! + } $dest['host'] = $dstaddr_port[0]; if ($findhostname) { $hostname = openvpn_client_export_find_hostname($natif); - if (!empty($hostname)) + if (!empty($hostname)) { $dest['host'] = $hostname; + } } $destinations[] = $dest; @@ -954,14 +991,16 @@ function openvpn_client_export_find_hostname($interface) { $hostname = ""; if (is_array($config['dyndnses']['dyndns'])) { foreach ($config['dyndnses']['dyndns'] as $ddns) { - if (($ddns['interface'] == $interface) && isset($ddns['enable']) && !empty($ddns['host']) && !is_numeric($ddns['host']) && is_hostname($ddns['host'])) + if (($ddns['interface'] == $interface) && isset($ddns['enable']) && !empty($ddns['host']) && !is_numeric($ddns['host']) && is_hostname($ddns['host'])) { return $ddns['host']; + } } } if (is_array($config['dnsupdates']['dnsupdate'])) { foreach ($config['dnsupdates']['dnsupdate'] as $ddns) { - if (($ddns['interface'] == $interface) && isset($ddns['enable']) && !empty($ddns['host']) && !is_numeric($ddns['host']) && is_hostname($ddns['host'])) + if (($ddns['interface'] == $interface) && isset($ddns['enable']) && !empty($ddns['host']) && !is_numeric($ddns['host']) && is_hostname($ddns['host'])) { return $ddns['host']; + } } } |