diff options
74 files changed, 9990 insertions, 1356 deletions
diff --git a/config/apcupsd/apcupsd.inc b/config/apcupsd/apcupsd.inc index c123861c..9ebb263b 100644 --- a/config/apcupsd/apcupsd.inc +++ b/config/apcupsd/apcupsd.inc @@ -224,5 +224,45 @@ EOF; } +function check_nis_running_apcupsd(){ + global $config, $g; + + if (is_array($config['installedpackages']['apcupsd'])){ + $apcupsd_config = $config['installedpackages']['apcupsd']['config'][0]; + + if ($apcupsd_config['apcupsdenabled']=="on" && $apcupsd_config['netserver']=="on" ) + return(true); + } + + return(false); +} + + +function check_nis_ip_apcupsd(){ + global $config, $g; + + if (is_array($config['installedpackages']['apcupsd'])){ + $apcupsd_config = $config['installedpackages']['apcupsd']['config'][0]; + + if ($apcupsd_config['apcupsdenabled']=="on" && $apcupsd_config['netserver']=="on" ) + return($apcupsd_config['nisip']); + } + + return(false); +} + +function check_nis_port_apcupsd(){ + global $config, $g; + + if (is_array($config['installedpackages']['apcupsd'])){ + $apcupsd_config = $config['installedpackages']['apcupsd']['config'][0]; + + if ($apcupsd_config['apcupsdenabled']=="on" && $apcupsd_config['netserver']=="on" ) + return($apcupsd_config['nisport']); + } + + return(false); +} + ?> diff --git a/config/apcupsd/apcupsd.xml b/config/apcupsd/apcupsd.xml index 0b2a96e0..bef6c330 100644 --- a/config/apcupsd/apcupsd.xml +++ b/config/apcupsd/apcupsd.xml @@ -40,7 +40,7 @@ <name>Apcupsd</name> <title>Services: Apcupsd (General)</title> <category>Monitoring</category> - <version>0.3.3</version> + <version>0.3.4</version> <include_file>/usr/local/pkg/apcupsd.inc</include_file> <addedit_string>Apcupsd has been created/modified.</addedit_string> <delete_string>Apcupsd has been deleted.</delete_string> diff --git a/config/apcupsd/apcupsd_status.php b/config/apcupsd/apcupsd_status.php index 693ec290..a8d3776d 100755 --- a/config/apcupsd/apcupsd_status.php +++ b/config/apcupsd/apcupsd_status.php @@ -28,6 +28,7 @@ */ require("guiconfig.inc"); +require_once("apcupsd.inc"); $pf_version=substr(trim(file_get_contents("/etc/version")),0,3); if ($pf_version < 2.0) @@ -38,6 +39,9 @@ include("head.inc"); function puts( $arg ) { echo "$arg\n"; } +if (isset($_GET['strapcaccess'])) + $strapcaccess = trim($_GET['strapcaccess']); + ?> <style> @@ -98,14 +102,66 @@ pre { <div id="mainarea" style="padding-top: 0px; padding-bottom: 0px; "> <table class="tabcont" width="100%" border="0" cellspacing="0" cellpadding="6"> - <tr><td> + <form name="frm_apcupsd_status" method="GET"> + <tr> + <td width="14%" valign="top" class="vncellreq">Host:</td> + <td width="86%" class="vtable"> + <input name="strapcaccess" type="text" class="formfld unknown" id="strapcaccess" size="22" value="<? echo "{$strapcaccess}"; ?>"> + <br/> + <span class="vexpl"> + Default: <b>localhost</b><br/> + apcaccess uses apcupsd's inbuilt Network Information Server (NIS) to obtain the current status information <br/> + from the UPS on the local or remote computer. It is therefore necessary to have the following configuration directives: <br/> + NETSERVER on<br/> + NISPORT 3551<br/> + <br/> + <?php if ($pf_version < 2.2): ?> + <input type="Submit" value="Execute" class="formbtn" disabled/> + <?php else: ?> + <input type="Submit" value="Execute" class="formbtn"/> + <?php endif; ?> + </span> + </td> + </tr> + </form> + <tr><td colspan="2"> <?php - puts("<pre>"); - putenv("PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin"); - $ph = popen('apcaccess 2>&1', "r" ); - while ($line = fgets($ph)) echo htmlspecialchars($line); - pclose($ph); - puts("</pre>"); + $nis_server = check_nis_running_apcupsd(); + + if ($pf_version >= 2.2){ + if($strapcaccess) { + echo "Running: apcaccess -h {$strapcaccess} <br/>"; + puts("<pre>"); + putenv("PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin"); + $ph = popen("apcaccess -h {$strapcaccess} 2>&1", "r" ); + while ($line = fgets($ph)) echo htmlspecialchars($line); + pclose($ph); + puts("</pre>"); + }elseif($nis_server){ + $nisip=(check_nis_ip_apcupsd() != ''? check_nis_ip_apcupsd() : "0.0.0.0"); + $nisport=(check_nis_port_apcupsd() != ''? check_nis_port_apcupsd() : "3551"); + echo "Running: apcaccess -h {$nisip}:{$nisport} <br/>"; + puts("<pre>"); + putenv("PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin"); + $ph = popen("apcaccess -h localhost 2>&1", "r" ); + while ($line = fgets($ph)) echo htmlspecialchars($line); + pclose($ph); + puts("</pre>"); + }else + echo "Network Information Server (NIS) not running, in order to run apcaccess on localhost, you need to enable it on APCupsd General settings. <br/>"; + }else{ + echo "pfSense version prior to 2.2 runs APCupsd 3.14.10 and apcaccess doesn't accept host parameter. <br/>"; + if ($nis_server){ + puts("<pre>"); + putenv("PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin"); + $ph = popen("apcaccess 2>&1", "r" ); + while ($line = fgets($ph)) echo htmlspecialchars($line); + pclose($ph); + puts("</pre>"); + }else + echo "Network Information Server (NIS) not running, in order to run apcaccess on localhost, you need to enable it on APCupsd General settings. <br/>"; + } + ?> </td></tr> </table> diff --git a/config/bind/bind.inc b/config/bind/bind.inc index 54d536d0..66b16464 100644 --- a/config/bind/bind.inc +++ b/config/bind/bind.inc @@ -36,107 +36,127 @@ require_once('util.inc'); require_once('pfsense-utils.inc'); require_once('pkg-utils.inc'); require_once('service-utils.inc'); -if(!function_exists("filter_configure")) +if (!function_exists("filter_configure")) { require_once("filter.inc"); +} + +$pf_version = substr(trim(file_get_contents("/etc/version")), 0, 3); +if ($pf_version > 2.0) { + define('BIND_LOCALBASE', '/usr/pbi/bind-'.php_uname("m")); +} else { + define('BIND_LOCALBASE', '/usr/local'); +} -$pf_version=substr(trim(file_get_contents("/etc/version")),0,3); -if ($pf_version > 2.0) - define('BIND_LOCALBASE', '/usr/pbi/bind-' . php_uname("m")); -else - define('BIND_LOCALBASE','/usr/local'); +define('CHROOT_LOCALBASE', '/cf/named'); -define('CHROOT_LOCALBASE','/cf/named'); +function bind_zone_validate($post, &$input_errors) +{ + if (array_key_exists("mail", $_POST)) { + $_POST['mail'] = preg_replace("/@/", ".", $post['mail']); + } -function bind_zone_validate($post, &$input_errors){ - if (key_exists("mail",$_POST)) - $_POST['mail']=preg_replace("/@/",".",$post['mail']); - - switch ($_POST['type']){ + switch ($_POST['type']) { case 'slave': - if( $_POST['slaveip'] == "") + if ($_POST['slaveip'] == "") { $input_errors[] = 'The field \'Master Zone IP\' is required for slave zones.'; - break; + } + break; case 'forward': - if( $_POST['forwarders'] == "") - $input_errors[] = 'The field \'Forwarders\' is required for forward zones.'; - break; + if ($_POST['forwarders'] == "") { + $input_errors[] = 'The field \'Forwarders\' is required for forward zones.'; + } + break; case 'redirect': - $_POST['tll']=300; - $_POST['refresh']=0; - $_POST['serial']=0; - $_POST['retry']=0; - $_POST['expire']=0; - $_POST['minimum']=0; - if($_POST['mail']=='') + $_POST['tll'] = 300; + $_POST['refresh'] = 0; + $_POST['serial'] = 0; + $_POST['retry'] = 0; + $_POST['expire'] = 0; + $_POST['minimum'] = 0; + if ($_POST['mail'] == '') { $input_errors[] = "The field 'Mail Admin Zone' is required for {$_POST['type']} zones."; - + } default: - if($_POST['nameserver']=='') + if ($_POST['nameserver'] == '') { $input_errors[] = "The field 'Name server' is required for {$_POST['type']} zones."; - for ($i=0;$i < count($_POST);$i++){ - if (key_exists("hostname$i",$_POST)){ - if ($_POST['reverso']=="on"){ - $_POST["hostvalue$i"]=""; - if (!preg_match("/(PTR|NS)/",$_POST["hosttype$i"])) + } + for ($i = 0; $i < count($_POST); $i++) { + if (array_key_exists("hostname$i", $_POST)) { + if ($_POST['reverso'] == "on") { + $_POST["hostvalue$i"] = ""; + if (!preg_match("/(PTR|NS)/", $_POST["hosttype$i"])) { $input_errors[] = 'On reverse zones, valid record types are NS or PTR'; } - if (preg_match("/(MX|NS)/",$_POST["hosttype$i"])) - $_POST["hostname$i"]=""; - if (!preg_match("/(MX|NS)/",$_POST["hosttype$i"]) && $_POST["hostname$i"]=="") + } + if (preg_match("/(MX|NS)/", $_POST["hosttype$i"])) { + $_POST["hostname$i"] = ""; + } + if (!preg_match("/(MX|NS)/", $_POST["hosttype$i"]) && $_POST["hostname$i"] == "") { $input_errors[] = 'Record cannot be empty for '.$_POST["hosttype$i"].' type '; - if ($_POST["hosttype$i"]=="MX" && $_POST["hostvalue$i"]=="") - $_POST["hostvalue$i"]="10"; - if ($_POST["hosttype$i"]!="MX" && $_POST["hostvalue$i"]!="") - $_POST["hostvalue$i"]=""; - if ($_POST["hostdst$i"]=="") + } + if ($_POST["hosttype$i"] == "MX" && $_POST["hostvalue$i"] == "") { + $_POST["hostvalue$i"] = "10"; + } + if ($_POST["hosttype$i"] != "MX" && $_POST["hostvalue$i"] != "") { + $_POST["hostvalue$i"] = ""; + } + if ($_POST["hostdst$i"] == "") { $input_errors[] = 'Alias or IP address cannot be empty.'; + } } } - } + break; + } } -function bind_sync(){ +function bind_sync() +{ global $config; conf_mount_rw(); //create rndc - $rndc_confgen="/usr/local/sbin/rndc-confgen"; - if (!file_exists(BIND_LOCALBASE."/etc/rndc-confgen.pfsense") && file_exists($rndc_confgen)){ - exec("$rndc_confgen ",$rndc_conf); - foreach($rndc_conf as $line) - $confgen_file.="$line\n"; - file_put_contents(BIND_LOCALBASE."/etc/rndc-confgen.pfsense",$confgen_file); + $rndc_confgen = "/usr/local/sbin/rndc-confgen"; + if (!file_exists(BIND_LOCALBASE."/etc/rndc-confgen.pfsense") && file_exists($rndc_confgen)) { + exec("$rndc_confgen ", $rndc_conf); + $confgen_file = ""; + foreach ($rndc_conf as $line) { + $confgen_file .= "$line\n"; } - if (file_exists(BIND_LOCALBASE."/etc/rndc-confgen.pfsense")){ - $rndc_conf=file(BIND_LOCALBASE."/etc/rndc-confgen.pfsense"); - $confgen="rndc.conf"; - $rndc_bindconf=""; - foreach ($rndc_conf as $line){ - if ($confgen =="rndc.conf"){ - if (!preg_match ("/^#/",$line)) - $rndc_file.=$line; - } - else{ - if (!preg_match ("/named.conf/",$line)) - $rndc_bindconf.=preg_replace('/#/',"",$line); + file_put_contents(BIND_LOCALBASE."/etc/rndc-confgen.pfsense", $confgen_file); + } + $rndc_bindconf = ""; + $rndc_file = ""; + if (file_exists(BIND_LOCALBASE."/etc/rndc-confgen.pfsense")) { + $rndc_conf = file(BIND_LOCALBASE."/etc/rndc-confgen.pfsense"); + $confgen = "rndc.conf"; + $rndc_bindconf = ""; + foreach ($rndc_conf as $line) { + if ($confgen == "rndc.conf") { + if (!preg_match("/^#/", $line)) { + $rndc_file .= $line; } - if (preg_match("/named.conf/",$line)){ - $confgen="named.conf"; - file_put_contents(BIND_LOCALBASE."/etc/rndc.conf",$rndc_file); + } else { + if (!preg_match("/named.conf/", $line)) { + $rndc_bindconf .= preg_replace('/#/', "", $line); } + } + if (preg_match("/named.conf/", $line)) { + $confgen = "named.conf"; + file_put_contents(BIND_LOCALBASE."/etc/rndc.conf", $rndc_file); + } } } - - $bind = $config["installedpackages"]["bind"]["config"][0]; + + $bind = $config['installedpackages']['bind']['config'][0]; $bind_enable = $bind['enable_bind']; $bind_forwarder = $bind['bind_forwarder']; $forwarder_ips = $bind['bind_forwarder_ips']; - $ram_limit = ($bind['bind_ram_limit']?$bind['bind_ram_limit']:"256M"); + $ram_limit = ($bind['bind_ram_limit'] ? $bind['bind_ram_limit'] : "256M"); $hide_version = $bind['bind_hide_version']; $bind_notify = $bind['bind_notify']; $custom_options = base64_decode($bind['bind_custom_options']); $bind_logging = $bind['bind_logging']; - $bind_conf ="#Bind pfsense configuration\n"; - $bind_conf .="#Do not edit this file!!!\n\n"; + $bind_conf = "#Bind pfsense configuration\n"; + $bind_conf .= "#Do not edit this file!!!\n\n"; $bind_conf .= "$rndc_bindconf\n"; $bind_conf .= <<<EOD @@ -145,280 +165,296 @@ options { pid-file "/var/run/named/pid"; statistics-file "/var/log/named.stats"; max-cache-size {$ram_limit}; - + EOD; // check response rate limit option //https://kb.isc.org/article/AA-01000/0/A-Quick-Introduction-to-Response-Rate-Limiting.html //http://ss.vix.su/~vjs/rl-arm.html - if ($bind['rate_enabled']=="on"){ - $rate_limit=($bind['rate_limit']?$bind['rate_limit']:"15"); - $log_only=($bind['log_only']=="no"?"no":"yes"); + if ($bind['rate_enabled'] == "on") { + $rate_limit = ($bind['rate_limit'] ? $bind['rate_limit'] : "15"); + $log_only = ($bind['log_only'] == "no" ? "no" : "yes"); $bind_conf .= <<<EOD - rate-limit { - responses-per-second {$rate_limit}; - log-only {$log_only}; - }; - + rate-limit { + responses-per-second { $rate_limit }; + log-only { $log_only }; + }; + EOD; } //check ips to listen on - if (preg_match("/All/",$bind['listenon'])){ - $bind_listenonv6="any;"; - $bind_listenon="any;"; - } - else{ - $bind_listenonv6=""; - $bind_listenon =""; - foreach (explode(',',$bind['listenon']) as $listenon){ - if (is_ipaddrv6($listenon)) + if (preg_match("/All/", $bind['listenon'])) { + $bind_listenonv6 = "any;"; + $bind_listenon = "any;"; + } else { + $bind_listenonv6 = ""; + $bind_listenon = ""; + foreach (explode(',', $bind['listenon']) as $listenon) { + if (is_ipaddrv6($listenon)) { $bind_listenonv6 .= $listenon."; "; - elseif (is_ipaddr($listenon)) + } elseif (is_ipaddr($listenon)) { $bind_listenon .= $listenon."; "; - else{ - $listenon=(pfSense_get_interface_addresses(convert_friendly_interface_to_real_interface_name($listenon))); - if (is_ipaddr($listenon['ipaddr'])) + } else { + $listenon = (pfSense_get_interface_addresses(convert_friendly_interface_to_real_interface_name($listenon))); + if (is_ipaddr($listenon['ipaddr'])) { $bind_listenon .= $listenon['ipaddr']."; "; - if(is_ipaddrv6($listenon['ipaddr6'])) + } + if (is_ipaddrv6($listenon['ipaddr6'])) { $bind_listenonv6 .= $listenon['ipaddr6']."; "; - } + } + } } } - $bind_listenonv6=($bind_listenonv6==""?"none;":$bind_listenonv6); - $bind_listenon=($bind_listenon==""?"none;":$bind_listenon); - //print "<PRE>$bind_listenonv6 $bind_listenon"; - if (key_exists("ipv6allow",$config['system'])){ - $bind_conf .="\t\tlisten-on-v6 { $bind_listenonv6 };\n"; - } - $bind_conf .="\t\tlisten-on { $bind_listenon };\n"; + $bind_listenonv6 = ($bind_listenonv6 == "" ? "none;" : $bind_listenonv6); + $bind_listenon = ($bind_listenon == "" ? "none;" : $bind_listenon); + // print "<PRE>$bind_listenonv6 $bind_listenon"; + if (array_key_exists("ipv6allow", $config['system'])) { + $bind_conf .= "\t\tlisten-on-v6 { $bind_listenonv6 };\n"; + } + $bind_conf .= "\tlisten-on { $bind_listenon };\n"; - #forwarder config - if ($bind_forwarder == on) - $bind_conf .="\t\tforwarders { $forwarder_ips };\n"; - if ($bind_notify == on) - $bind_conf .="\t\tnotify yes;\n"; - if ($hide_version == on) - $bind_conf .="\t\tversion none;\n"; + // forwarder config + if ($bind_forwarder == 'on') { + $bind_conf .= "\t\tforwarders { $forwarder_ips };\n"; + } + if ($bind_notify == 'on') { + $bind_conf .= "\t\tnotify yes;\n"; + } + if ($hide_version == 'on') { + $bind_conf .= "\t\tversion none;\n"; + } - $bind_conf .= preg_replace("/^/m","\t\t",$custom_options); + $bind_conf .= preg_replace("/^/m", "\t", $custom_options); $bind_conf .= "\n\t};\n\n"; - - if ($bind_logging == on){ + + if ($bind_logging == 'on') { //check if bind is included on syslog - $syslog_files=array("/etc/inc/system.inc","/var/etc/syslog.conf"); - $restart_syslog=0; - foreach ($syslog_files as $syslog_file){ - $syslog_file_data=file_get_contents($syslog_file); - if ( !preg_match("/dnsmasq,named,filterdns/",$syslog_file_data) || !preg_match("/'dnsmasq','named','filterdns'/",$syslog_file_data) ) { - $syslog_file_data=preg_replace("/dnsmasq,filterdns/","dnsmasq,named,filterdns",$syslog_file_data); - $syslog_file_data=preg_replace("/'dnsmasq','filterdns'/","'dnsmasq','named','filterdns'",$syslog_file_data); - file_put_contents($syslog_file,$syslog_file_data); + $syslog_files = array("/etc/inc/system.inc", "/var/etc/syslog.conf"); + $restart_syslog = 0; + foreach ($syslog_files as $syslog_file) { + $syslog_file_data = file_get_contents($syslog_file); + if (!preg_match("/dnsmasq,named,filterdns/", $syslog_file_data) || !preg_match("/'dnsmasq','named','filterdns'/", $syslog_file_data)) { + $syslog_file_data = preg_replace("/dnsmasq,filterdns/", "dnsmasq,named,filterdns", $syslog_file_data); + $syslog_file_data = preg_replace("/'dnsmasq','filterdns'/", "'dnsmasq','named','filterdns'", $syslog_file_data); + file_put_contents($syslog_file, $syslog_file_data); $restart_syslog++; - } } - if ($restart_syslog > 0){ + } + if ($restart_syslog > 0) { system("/usr/bin/killall -HUP syslogd"); } - $log_categories=explode(",",$bind['log_options']); - $log_severity=($bind['log_severity']?$bind['log_severity']:'default'); - if (sizeof($log_categories) > 0 && $log_categories[0]!=""){ + $log_categories = explode(",", $bind['log_options']); + $log_severity = ($bind['log_severity'] ? $bind['log_severity'] : 'default'); + if (sizeof($log_categories) > 0 && $log_categories[0] != "") { $bind_conf .= <<<EOD - - logging { - channel custom { - syslog daemon; - print-time no; - print-severity yes; - print-category yes; - severity {$log_severity}; - }; + +logging { + channel custom { + syslog daemon; + print-time no; + print-severity yes; + print-category yes; + severity {$log_severity}; + }; EOD; - foreach ($log_categories as $category) - $bind_conf .="\t\t\tcategory $category\t{custom;};\n"; - $bind_conf .="\t\t};\n\n"; - } - } - else { - $bind_conf .="\t\tlogging { category default { null; }; };\n\n"; - } - - #Config Zone domain - if(!is_array($config["installedpackages"]["bindacls"]) || !is_array($config["installedpackages"]["bindacls"]["config"])){ - $config["installedpackages"]["bindacls"]["config"][] = - array("name"=>"none","description"=>"BIND Built-in ACL","row"=>array("value"=>"","description"=>"")); - $config["installedpackages"]["bindacls"]["config"][] = - array("name"=>"any","description"=>"BIND Built-in ACL","row"=>array("value"=>"","description"=>"")); - $config["installedpackages"]["bindacls"]["config"][] = - array("name"=>"localhost","description"=>"BIND Built-in ACL","row"=>array("value"=>"","description"=>"")); - $config["installedpackages"]["bindacls"]["config"][] = - array("name"=>"localnets","description"=>"BIND Built-in ACL","row"=>array("value"=>"","description"=>"")); - write_config("Create BIND Built-in ACLs"); + foreach ($log_categories as $category) { + $bind_conf .= "\t\t\tcategory $category\t{custom;};\n"; + } + $bind_conf .= "\t\t};\n\n"; } - $bindacls = $config["installedpackages"]["bindacls"]["config"]; - for ($i=0; $i<sizeof($bindacls); $i++) - { + } else { + $bind_conf .= "\t\tlogging { category default { null; }; };\n\n"; + } + + // Config Zone domain + + // Add ACLS + if (!is_array($config['installedpackages']['bindacls']) || !is_array($config['installedpackages']['bindacls']['config'])) { + $config['installedpackages']['bindacls']['config'][] = + array("name" => "none", "description" => "BIND Built-in ACL", "row" => array("value" => "", "description" => "")); + $config['installedpackages']['bindacls']['config'][] = + array("name" => "any", "description" => "BIND Built-in ACL", "row" => array("value" => "", "description" => "")); + $config['installedpackages']['bindacls']['config'][] = + array("name" => "localhost", "description" => "BIND Built-in ACL", "row" => array("value" => "", "description" => "")); + $config['installedpackages']['bindacls']['config'][] = + array("name" => "localnets", "description" => "BIND Built-in ACL", "row" => array("value" => "", "description" => "")); + write_config("Create BIND Built-in ACLs"); + } + $bindacls = $config['installedpackages']['bindacls']['config']; + for ($i = 0; $i < sizeof($bindacls); $i++) { $aclname = $bindacls[$i]['name']; $aclhost = $bindacls[$i]['row']; - if($aclname != "none" && $aclname != "any" && $aclname != "localhost" && $aclname != "localnets"){ - $bind_conf .= "acl \"$aclname\" {\n"; - for ($u=0; $u<sizeof($aclhost); $u++) - { + if ($aclname != "none" && $aclname != "any" && $aclname != "localhost" && $aclname != "localnets") { + $bind_conf .= "acl \"$aclname\" {\n"; + for ($u = 0; $u < sizeof($aclhost); $u++) { $aclhostvalue = $aclhost[$u]['value']; $bind_conf .= "\t$aclhostvalue;\n"; } $bind_conf .= "};\n\n"; - } - } - - if(is_array($config["installedpackages"]["bindviews"])) - $bindview = $config["installedpackages"]["bindviews"]["config"]; - else - $bindview =array(); - - for ($i=0; $i<sizeof($bindview); $i++) - { - $views = $config["installedpackages"]["bindviews"]["config"][$i]; + } + } + + // Add Views + if (is_array($config['installedpackages']['bindviews'])) { + $bindview = $config['installedpackages']['bindviews']['config']; + } else { + $bindview = array(); + } + + for ($i = 0; $i < sizeof($bindview); $i++) { + $views = $config['installedpackages']['bindviews']['config'][$i]; $viewname = $views['name']; - $viewrecursion = $views['recursion']; - if($views['match-clients'] == '') + $viewrecursion = $views['recursion']; + if ($views['match-clients'] == '') { $viewmatchclients = "none"; - else - $viewmatchclients = str_replace(',','; ',$views['match-clients']); - if($views['allow-recursion'] == '') + } else { + $viewmatchclients = str_replace(',', '; ', $views['match-clients']); + } + if ($views['allow-recursion'] == '') { $viewallowrecursion = "none"; - else - $viewallowrecursion = str_replace(',','; ',$views['allow-recursion']); + } else { + $viewallowrecursion = str_replace(',', '; ', $views['allow-recursion']); + } $viewcustomoptions = base64_decode($views['bind_custom_options']); - - $bind_conf .= "view \"$viewname\" { \n\n"; - $bind_conf .= "\trecursion $viewrecursion;\n"; - $bind_conf .= "\tmatch-clients { $viewmatchclients;};\n"; - $bind_conf .= "\tallow-recursion { $viewallowrecursion;};\n"; - $bind_conf .= "\t$viewcustomoptions\n\n"; - - if(is_array($config["installedpackages"]["bindzone"])) - $bindzone = $config["installedpackages"]["bindzone"]["config"]; - else - $bindzone =array(); - $write_config=0; - for ($x=0; $x<sizeof($bindzone); $x++) - { + $bind_conf .= "view \"$viewname\" { \n\n"; + $bind_conf .= "\trecursion $viewrecursion;\n"; + $bind_conf .= "\tmatch-clients { $viewmatchclients; };\n"; + $bind_conf .= "\tallow-recursion { $viewallowrecursion; };\n"; + $bind_conf .= "\t$viewcustomoptions\n\n"; + + if (is_array($config['installedpackages']['bindzone'])) { + $bindzone = $config['installedpackages']['bindzone']['config']; + } else { + $bindzone = array(); + } + + // Add Zones in View + $write_config = 0; + $custom_root_zone = false; + for ($x = 0; $x < sizeof($bindzone); $x++) { $zone = $bindzone[$x]; - if ($zone['disabled']=="on"){ + if ($zone['disabled'] == "on") { continue; - } + } $zonename = $zone['name']; - if ($zonename=="."){ - $custom_root_zone[$i]=true; + if ($zonename == ".") { + $custom_root_zone = true; } $zonetype = $zone['type']; $zoneview = $zone['view']; $zonecustom = base64_decode($zone['custom']); $zoneipslave = $zone['slaveip']; - $zoneforwarders=$zone['forwarders']; + $zoneforwarders = $zone['forwarders']; $zonereverso = $zone['reverso']; - - if (!(is_dir(CHROOT_LOCALBASE."/etc/namedb/$zonetype/$zoneview"))) - mkdir(CHROOT_LOCALBASE."/etc/namedb/$zonetype/$zoneview",0755,true); - - if($zone['allowupdate'] == '') + + // Ensure zone view folder exists + if (!(is_dir(CHROOT_LOCALBASE."/etc/namedb/$zonetype/$zoneview"))) { + mkdir(CHROOT_LOCALBASE."/etc/namedb/$zonetype/$zoneview", 0755, true); + } + + if ($zone['allowupdate'] == '') { $zoneallowupdate = "none"; - else - $zoneallowupdate = str_replace(',','; ',$zone['allowupdate']); - if($zone['allowquery'] == '') + } else { + $zoneallowupdate = str_replace(',', '; ', $zone['allowupdate']); + } + if ($zone['allowquery'] == '') { $zoneallowquery = "none"; - else - $zoneallowquery = str_replace(',','; ',$zone['allowquery']); - if($zone['allowtransfer'] == '') + } else { + $zoneallowquery = str_replace(',', '; ', $zone['allowquery']); + } + if ($zone['allowtransfer'] == '') { $zoneallowtransfer = "none"; - else - $zoneallowtransfer = str_replace(',','; ',$zone['allowtransfer']); - - if ($zoneview == $viewname){ - if($zonereverso == "on") - $bind_conf .= "\tzone \"$zonename.in-addr.arpa\" {\n"; - else - $bind_conf .= "\tzone \"$zonename\" {\n"; - - $bind_conf .= "\t\ttype $zonetype;\n"; - if ($zonetype != "forward") - $bind_conf .= "\t\tfile \"/etc/namedb/$zonetype/$zoneview/$zonename.DB\";\n"; - switch ($zonetype){ - case "slave": - $bind_conf .= "\t\tmasters { $zoneipslave; };\n"; - $bind_conf .= "\t\tallow-transfer { $zoneallowtransfer;};\n"; - $bind_conf .= "\t\tnotify no;\n"; - break; - case "forward": - $bind_conf .= "\t\tforward only;\n"; - $bind_conf .= "\t\tforwarders { $zoneforwarders; };\n"; - break; - case "redirect": - $bind_conf .= "\t\t# While using redirect zones,NXDOMAIN Redirection will not override DNSSEC\n"; - $bind_conf .= "\t\t# If the client has requested DNSSEC records (DO=1) and the NXDOMAIN response is signed then no substitution will occur\n"; - $bind_conf .= "\t\t# https://kb.isc.org/article/AA-00376/192/BIND-9.9-redirect-zones-for-NXDOMAIN-redirection.html\n"; - break; - default: - $bind_conf .= "\t\tallow-update { $zoneallowupdate;};\n"; - $bind_conf .= "\t\tallow-query { $zoneallowquery;};\n"; - $bind_conf .= "\t\tallow-transfer { $zoneallowtransfer;};\n"; - if ($zone['dnssec']=="on"){ - //https://kb.isc.org/article/AA-00626/ - $bind_conf .="\n\t\t# look for dnssec keys here:\n"; - $bind_conf .="\t\tkey-directory \"/etc/namedb/keys\";\n\n"; - $bind_conf .="\t\t# publish and activate dnssec keys:\n"; - $bind_conf .="\t\tauto-dnssec maintain;\n\n"; - $bind_conf .="\t\t# use inline signing:\n"; - $bind_conf .="\t\tinline-signing yes;\n\n"; - } - } - if ($zonecustom != '') - $bind_conf .= "\t\t$zonecustom\n"; - - $bind_conf .= "\t};\n\n"; - - switch($zonetype){ - case "redirect": - case "master": - //check/update slave dir permission - chown(CHROOT_LOCALBASE."/etc/namedb/$zonetype","bind"); - chown(CHROOT_LOCALBASE."/etc/namedb/$zonetype/$zoneview","bind"); - $zonetll = ($zone['tll']?$zone['tll']:"43200"); - $zonemail = ($zone['mail']?$zone['mail']:"zonemaster.{$zonename}"); - $zonemail = preg_replace("/@/",".",$zonemail); + } else { + $zoneallowtransfer = str_replace(',', '; ', $zone['allowtransfer']); + } + + if ($zoneview == $viewname) { + // Add zone name + if ($zonereverso == "on") { + $bind_conf .= "\tzone \"$zonename.in-addr.arpa\" {\n"; + } else { + $bind_conf .= "\tzone \"$zonename\" {\n"; + } + + // Add zone file (if not forwarder) + $bind_conf .= "\t\ttype $zonetype;\n"; + if ($zonetype != "forward") { + $bind_conf .= "\t\tfile \"/etc/namedb/$zonetype/$zoneview/$zonename.DB\";\n"; + } + + // Add zone statements + switch ($zonetype) { + case 'slave': + $bind_conf .= "\t\tmasters { $zoneipslave; };\n"; + $bind_conf .= "\t\tallow-transfer { $zoneallowtransfer; };\n"; + $bind_conf .= "\t\tnotify no;\n"; + break; + case 'forward': + $bind_conf .= "\t\tforward only;\n"; + $bind_conf .= "\t\tforwarders { $zoneforwarders; };\n"; + break; + case 'redirect': + $bind_conf .= "\t\t# While using redirect zones,NXDOMAIN Redirection will not override DNSSEC\n"; + $bind_conf .= "\t\t# If the client has requested DNSSEC records (DO=1) and the NXDOMAIN response is signed then no substitution will occur\n"; + $bind_conf .= "\t\t# https://kb.isc.org/article/AA-00376/192/BIND-9.9-redirect-zones-for-NXDOMAIN-redirection.html\n"; + break; + default: + $bind_conf .= "\t\tallow-update { $zoneallowupdate; };\n"; + $bind_conf .= "\t\tallow-query { $zoneallowquery; };\n"; + $bind_conf .= "\t\tallow-transfer { $zoneallowtransfer; };\n"; + if ($zone['dnssec'] == "on") { + //https://kb.isc.org/article/AA-00626/ + $bind_conf .= "\n\t\t# look for dnssec keys here:\n"; + $bind_conf .= "\t\tkey-directory \"/etc/namedb/keys\";\n\n"; + $bind_conf .= "\t\t# publish and activate dnssec keys:\n"; + $bind_conf .= "\t\tauto-dnssec maintain;\n\n"; + $bind_conf .= "\t\t# use inline signing:\n"; + $bind_conf .= "\t\tinline-signing yes;\n\n"; + } + break; + } + + // Add custom zone statements + if ($zonecustom != '') { + $bind_conf .= "\t\t$zonecustom\n"; + } + + $bind_conf .= "\t};\n\n"; + + // Create zone config DB file + switch ($zonetype) { + case 'master': + case 'redirect': + // check/update slave dir permission + chown(CHROOT_LOCALBASE."/etc/namedb/$zonetype", "bind"); + chown(CHROOT_LOCALBASE."/etc/namedb/$zonetype/$zoneview", "bind"); + $zonetll = ($zone['tll'] ? $zone['tll'] : "43200"); + $zonemail = ($zone['mail'] ? $zone['mail'] : "zonemaster.{$zonename}"); + $zonemail = preg_replace("/@/", ".", $zonemail); $zoneserial = $zone['serial']; - $zonerefresh = ($zone['refresh']?$zone['refresh']:"3600"); - $zoneretry = ($zone['retry']?$zone['retry']:"600"); - $zoneexpire = ($zone['expire']?$zone['expire']:"86400"); - $zoneminimum = ($zone['minimum']?$zone['minimum']:"3600"); + $zonerefresh = ($zone['refresh'] ? $zone['refresh'] : "3600"); + $zoneretry = ($zone['retry'] ? $zone['retry'] : "600"); + $zoneexpire = ($zone['expire'] ? $zone['expire'] : "86400"); + $zoneminimum = ($zone['minimum'] ? $zone['minimum'] : "3600"); $zonenameserver = $zone['nameserver']; $zoneipns = $zone['ipns']; $zonereverso = $zone['reverso']; - if($zone['allowupdate'] == '') - $zoneallowupdate = "none"; - else - $zoneallowupdate = str_replace(',','; ',$zone['allowupdate']); - if($zone['allowquery'] == '') - $zoneallowquery = "none"; - else - $zoneallowquery = str_replace(',','; ',$zone['allowquery']); - if($zone['allowtransfer'] == '') - $zoneallowtransfer = "none"; - else - $zoneallowtransfer = str_replace(',','; ',$zone['allowtransfer']); + $zone_conf = "\$TTL {$zonetll}\n;\n"; - if($zonereverso == "on") + if ($zonereverso == "on") { $zone_conf .= "\$ORIGIN {$zonename}.in-addr.arpa.\n\n"; - else + } else { $zone_conf .= "\$ORIGIN {$zonename}.\n\n"; + } $zone_conf .= ";\tDatabase file {$zonename}.DB for {$zonename} zone.\n"; $zone_conf .= ";\tDo not edit this file!!!\n"; $zone_conf .= ";\tZone version {$zoneserial}\n;\n"; - if($zonereverso == "on" || $zonetype =="redirect") + if ($zonereverso == "on" || $zonetype == "redirect") { $zone_conf .= "@\t IN SOA $zonenameserver. \t $zonemail. (\n"; - else + } else { $zone_conf .= "$zonename.\t IN SOA $zonenameserver. \t $zonemail. (\n"; + } $zone_conf .= "\t\t$zoneserial ; serial\n"; $zone_conf .= "\t\t$zonerefresh ; refresh\n"; @@ -427,30 +463,31 @@ EOD; $zone_conf .= "\t\t$zoneminimum ; default_ttl\n\t\t)\n\n"; $zone_conf .= ";\n; Zone Records\n;\n"; - if($zonereverso == "on") + if ($zonereverso == "on") { $zone_conf .= "\t IN NS \t$zonenameserver.\n"; - else{ + } else { $zone_conf .= "@ \t IN NS \t$zonenameserver.\n"; - if ($zoneipns !="") + if ($zoneipns != "") { $zone_conf .= "@ \t IN A \t$zoneipns\n"; + } } - for ($y=0; $y<sizeof($zone['row']); $y++) - { - $hostname = (preg_match("/(MX|NS)/",$zone['row'][$y]['hosttype'])?"@":$zone['row'][$y]['hostname']); + for ($y = 0; $y < sizeof($zone['row']); $y++) { + $hostname = (preg_match("/(MX|NS)/", $zone['row'][$y]['hosttype']) ? "@" : $zone['row'][$y]['hostname']); $hosttype = $zone['row'][$y]['hosttype']; $hostdst = $zone['row'][$y]['hostdst']; - if (preg_match("/[a-zA-Z]/",$hostdst) && !preg_match("/(TXT|SPF|AAAA)/",$hosttype)) + if (preg_match("/[a-zA-Z]/", $hostdst) && !preg_match("/(TXT|SPF|AAAA)/", $hosttype)) { $hostdst .= "."; + } $hostvalue = $zone['row'][$y]['hostvalue']; - + $zone_conf .= "$hostname \t IN $hosttype $hostvalue \t$hostdst\n"; } - # Register DHCP static mappings - if (($zone[regdhcpstatic] == 'on') && is_array($config['dhcpd'])) { - $zoneparts = array_reverse(explode('.',$zonename)); + // Register DHCP static mappings + if (($zone['regdhcpstatic'] == 'on') && is_array($config['dhcpd'])) { + $zoneparts = array_reverse(explode('.', $zonename)); foreach ($config['dhcpd'] as $dhcpif => $dhcpifconf) { - if (!isset($dhcpifconf['enable']) || !is_array($dhcpifconf['staticmap'])) { + if (!isset($dhcpifconf['enable']) || !is_array($dhcpifconf['staticmap'])) { continue; } foreach ($dhcpifconf['staticmap'] as $host) { @@ -463,20 +500,20 @@ EOD; } else { continue; } - if (!is_hostname($host['hostname']) || !is_ipaddr($host['ipaddr'])) { + if (!is_hostname($host['hostname']) || !is_ipaddr($host['ipaddr'])) { continue; } if ($zonereverso == "on") { - $parts = explode('.',$host['ipaddr']); - $intersect = array_intersect_assoc($parts,$zoneparts); + $parts = explode('.', $host['ipaddr']); + $intersect = array_intersect_assoc($parts, $zoneparts); if (count($zoneparts) == count($intersect)) { - $diff = array_diff_assoc($parts,$zoneparts); - $shortaddr = implode('.',array_reverse($diff)); + $diff = array_diff_assoc($parts, $zoneparts); + $shortaddr = implode('.', array_reverse($diff)); $zone_conf .= "{$shortaddr}\tIN PTR\t{$host['hostname']}.{$domain}.\n"; } } else { - $parts = array_reverse(explode('.',$domain)); - $diff = array_diff_assoc($parts,$zoneparts); + $parts = array_reverse(explode('.', $domain)); + $diff = array_diff_assoc($parts, $zoneparts); if (count($diff) == 0) { $zone_conf .= "{$host['hostname']}\tIN A\t{$host['ipaddr']}\n"; } @@ -485,173 +522,184 @@ EOD; } } - if ($zone['customzonerecords']!=""){ + // Add custom zone records + if ($zone['customzonerecords'] != "") { $zone_conf .= "\n\n;\n;custom zone records\n;\n".base64_decode($zone['customzonerecords'])."\n"; } + + // Save zone configuration DB file file_put_contents(CHROOT_LOCALBASE."/etc/namedb/$zonetype/$zoneview/$zonename.DB", $zone_conf); - $config["installedpackages"]["bindzone"]["config"][$x][resultconfig]=base64_encode($zone_conf); + + $config['installedpackages']['bindzone']['config'][$x]['resultconfig'] = base64_encode($zone_conf); $write_config++; //check dnssec keys creation for master zones - if($zone['dnssec']=="on"){ - $zone_found=0; - foreach (glob(CHROOT_LOCALBASE."/etc/namedb/keys/*{$zonename}*key",GLOB_NOSORT) as $filename){ + if ($zone['dnssec'] == "on") { + $zone_found = 0; + foreach (glob(CHROOT_LOCALBASE."/etc/namedb/keys/*{$zonename}*key", GLOB_NOSORT) as $filename) { $zone_found++; - } - if ($zone_found==0){ - $key_restored=0; - if(is_array($config['installedpackages']['dnsseckeys']) && is_array($config['installedpackages']['dnsseckeys']['config'])){ - foreach ($config['installedpackages']['dnsseckeys']['config']as $filer) - if (preg_match ("/K$zonename\.+/",$filer['fullfile'])){ - file_put_contents($filer['fullfile'],base64_decode($filer['filedata']),LOCK_EX); - chmod($filer['fullfile'],0700); - chown($filer['fullfile'],"bind"); + } + if ($zone_found == 0) { + $key_restored = 0; + if (is_array($config['installedpackages']['dnsseckeys']) && is_array($config['installedpackages']['dnsseckeys']['config'])) { + foreach ($config['installedpackages']['dnsseckeys']['config'] as $filer) { + if (preg_match("/K$zonename\.+/", $filer['fullfile'])) { + file_put_contents($filer['fullfile'], base64_decode($filer['filedata']), LOCK_EX); + chmod($filer['fullfile'], 0700); + chown($filer['fullfile'], "bind"); $key_restored++; - } } - if ($key_restored > 0){ + } + } + if ($key_restored > 0) { log_error("[bind] {$key_restored} DNSSEC keys restored from XML backup for {$zonename} zone."); + } + $dnssec_bin = "/usr/local/sbin/dnssec-keygen"; + if (file_exists($dnssec_bin) && $key_restored == 0) { + exec("{$dnssec_bin} -K ".CHROOT_LOCALBASE."/etc/namedb/keys {$zonename}", $kout); + exec("{$dnssec_bin} -K ".CHROOT_LOCALBASE."/etc/namedb/keys -fk {$zonename}", $kout); + foreach ($kout as $filename) { + chown(CHROOT_LOCALBASE."/etc/namedb/keys/{$filename}.key", "bind"); + chown(CHROOT_LOCALBASE."/etc/namedb/keys/{$filename}.private", "bind"); } - $dnssec_bin="/usr/local/sbin/dnssec-keygen"; - if (file_exists($dnssec_bin) && $key_restored==0){ - exec("{$dnssec_bin} -K ".CHROOT_LOCALBASE."/etc/namedb/keys {$zonename}",$kout); - exec("{$dnssec_bin} -K ".CHROOT_LOCALBASE."/etc/namedb/keys -fk {$zonename}",$kout); - foreach($kout as $filename){ - chown(CHROOT_LOCALBASE."/etc/namedb/keys/{$filename}.key","bind"); - chown(CHROOT_LOCALBASE."/etc/namedb/keys/{$filename}.private","bind"); - } log_error("[bind] DNSSEC keys for {$zonename} created."); - } - } - //get ds keys - $dsfromkey="/usr/local/sbin/dnssec-dsfromkey"; - foreach (glob(CHROOT_LOCALBASE."/etc/namedb/keys/*{$zonename}*key",GLOB_NOSORT) as $filename) { - $zone_key=file_get_contents($filename); - if (preg_match("/IN DNSKEY 257 /",$zone_key) && file_exists($dsfromkey)){ - exec("$dsfromkey $filename",$dsset); - $config["installedpackages"]["bindzone"]["config"][$x]['dsset']=base64_encode(array_pop($dsset)."\n".array_pop($dsset)); - $write_config++; - } } - //save dnssec keys to xml - - if($zone['backupkeys']=="on"){ - $dnssec_keys=0; - foreach (glob(CHROOT_LOCALBASE."/etc/namedb/keys/*{$zonename}*",GLOB_NOSORT) as $filename){ - $file_found=0; - if(is_array($config['installedpackages']['dnsseckeys']) && is_array($config['installedpackages']['dnsseckeys']['config'])){ - foreach ($config['installedpackages']['dnsseckeys']['config']as $filer){ - if ($filer['fullfile']==$filename) + } + // get ds keys + $dsfromkey = "/usr/local/sbin/dnssec-dsfromkey"; + foreach (glob(CHROOT_LOCALBASE."/etc/namedb/keys/*{$zonename}*key", GLOB_NOSORT) as $filename) { + $zone_key = file_get_contents($filename); + if (preg_match("/IN DNSKEY 257 /", $zone_key) && file_exists($dsfromkey)) { + exec("$dsfromkey $filename", $dsset); + $config['installedpackages']['bindzone']['config'][$x]['dsset'] = base64_encode(array_pop($dsset)."\n".array_pop($dsset)); + $write_config++; + } + } + + // save dnssec keys to xml + if ($zone['backupkeys'] == "on") { + $dnssec_keys = 0; + foreach (glob(CHROOT_LOCALBASE."/etc/namedb/keys/*{$zonename}*", GLOB_NOSORT) as $filename) { + $file_found = 0; + if (is_array($config['installedpackages']['dnsseckeys']) && is_array($config['installedpackages']['dnsseckeys']['config'])) { + foreach ($config['installedpackages']['dnsseckeys']['config'] as $filer) { + if ($filer['fullfile'] == $filename) { $file_found++; } } - if ($file_found==0){ - $config['installedpackages']['dnsseckeys']['config'][]=array('fullfile'=> $filename, - 'description'=> "bind {$zonename} DNSSEC backup file", - 'filedata'=> base64_encode(file_get_contents($filename))); + } + if ($file_found == 0) { + $config['installedpackages']['dnsseckeys']['config'][] = array('fullfile' => $filename, + 'description' => "bind {$zonename} DNSSEC backup file", + 'filedata' => base64_encode(file_get_contents($filename))); $write_config++; $dnssec_keys++; - } - } - if($dnssec_keys>0){ - log_error("[bind] {$dnssec_keys} DNSSEC keys for {$zonename} zone saved on XML config."); } } - } - break; - case "slave": - //check/update slave dir permission - chown(CHROOT_LOCALBASE."/etc/namedb/$zonetype","bind"); - chown(CHROOT_LOCALBASE."/etc/namedb/$zonetype/$zoneview","bind"); - //check if exists slave zone file - $rsconfig=""; - if ($zone['dnssec']=="on"){ - if (file_exists(CHROOT_LOCALBASE."/etc/namedb/$zonetype/$zoneview/$zonename.DB.signed")) - exec("/usr/local/sbin/named-checkzone -D -f raw -o - {$zonename} ".CHROOT_LOCALBASE."/etc/namedb/$zonetype/$zoneview/$zonename.DB.signed",$slave_file); + if ($dnssec_keys > 0) { + log_error("[bind] {$dnssec_keys} DNSSEC keys for {$zonename} zone saved on XML config."); + } + } } - else{ - if (file_exists(CHROOT_LOCALBASE."/etc/namedb/$zonetype/$zoneview/$zonename.DB")) - $slave_file=file(CHROOT_LOCALBASE."/etc/namedb/$zonetype/$zoneview/$zonename.DB"); + break; + case 'slave': + // check/update slave dir permission + chown(CHROOT_LOCALBASE."/etc/namedb/$zonetype", "bind"); + chown(CHROOT_LOCALBASE."/etc/namedb/$zonetype/$zoneview", "bind"); + // check if exists slave zone file + $rsconfig = ""; + if ($zone['dnssec'] == "on") { + if (file_exists(CHROOT_LOCALBASE."/etc/namedb/$zonetype/$zoneview/$zonename.DB.signed")) { + exec("/usr/local/sbin/named-checkzone -D -f raw -o - {$zonename} ".CHROOT_LOCALBASE."/etc/namedb/$zonetype/$zoneview/$zonename.DB.signed", $slave_file); + } + } else { + if (file_exists(CHROOT_LOCALBASE."/etc/namedb/$zonetype/$zoneview/$zonename.DB")) { + $slave_file = file(CHROOT_LOCALBASE."/etc/namedb/$zonetype/$zoneview/$zonename.DB"); + } } - if (is_array($slave_file)){ - foreach ($slave_file as $zfile) - $rsconfig.= $zfile; - $config["installedpackages"]["bindzone"]["config"][$x][resultconfig]=base64_encode($rsconfig); - $write_config++; - } - break; - } + // TODO is is_array() the best test to use? is it only checking for existence? + if (is_array($slave_file)) { + foreach ($slave_file as $zfile) { + $rsconfig .= $zfile; + } + } + $config['installedpackages']['bindzone']['config'][$x]['resultconfig'] = base64_encode($rsconfig); + $write_config++; + break; } + } } - if (!$custom_root_zone[$i]){ - $bind_conf .="\tzone \".\" {\n"; - $bind_conf .="\t\ttype hint;\n"; - $bind_conf .="\t\tfile \"/etc/namedb/named.root\";\n"; + if (!$custom_root_zone) { + $bind_conf .= "\tzone \".\" {\n"; + $bind_conf .= "\t\ttype hint;\n"; + $bind_conf .= "\t\tfile \"/etc/namedb/named.root\";\n"; $bind_conf .= "\t};\n\n"; - } - if($write_config > 0){ + } + if ($write_config > 0) { write_config("save result config file for zone on xml"); } $bind_conf .= "};\n"; } - $dirs=array("/etc/namedb/keys","/var/run/named","/var/dump","/var/log","/var/stats","/dev"); - foreach ($dirs as $dir){ - if (!is_dir(CHROOT_LOCALBASE .$dir)) - mkdir(CHROOT_LOCALBASE .$dir,0755,true); + $dirs = array("/etc/namedb/keys", "/var/run/named", "/var/dump", "/var/log", "/var/stats", "/dev"); + foreach ($dirs as $dir) { + if (!is_dir(CHROOT_LOCALBASE.$dir)) { + mkdir(CHROOT_LOCALBASE.$dir, 0755, true); + } + } + // dev dirs for chroot + $bind_dev_dir = CHROOT_LOCALBASE."/dev"; + if (!file_exists("$bind_dev_dir/random")) { + $dev_dirs = array("null", "zero", "random", "urandom"); + exec("/sbin/mount -t devfs devfs {$bind_dev_dir}", $dout); + exec("/sbin/devfs -m {$bind_dev_dir} ruleset 1", $dout); + exec("/sbin/devfs -m {$bind_dev_dir} rule add hide", $dout); + foreach ($dev_dirs as $dev_dir) { + exec("/sbin/devfs -m {$bind_dev_dir} rule add path $dev_dir unhide", $dout); } - //dev dirs for chroot - $bind_dev_dir=CHROOT_LOCALBASE."/dev"; - if (!file_exists("$bind_dev_dir/random")){ - $dev_dirs=array("null","zero","random","urandom"); - exec("/sbin/mount -t devfs devfs {$bind_dev_dir}",$dout); - exec("/sbin/devfs -m {$bind_dev_dir} ruleset 1",$dout); - exec("/sbin/devfs -m {$bind_dev_dir} rule add hide",$dout); - foreach ($dev_dirs as $dev_dir) - exec("/sbin/devfs -m {$bind_dev_dir} rule add path $dev_dir unhide",$dout); - exec("/sbin/devfs -m {$bind_dev_dir} rule applyset",$dout); - } - //http://www.unixwiz.net/techtips/bind9-chroot.html - file_put_contents(CHROOT_LOCALBASE.'/etc/namedb/named.conf', $bind_conf); - file_put_contents(CHROOT_LOCALBASE.'/etc/namedb/rndc.conf', $rndc_file); - - if (!file_exists(CHROOT_LOCALBASE."/etc/namedb/named.root")){ - //dig +tcp @a.root-servers.net > CHROOT_LOCALBASE."/etc/namedb/named.root" - $named_root=file_get_contents("http://www.internic.net/domain/named.root"); - file_put_contents(CHROOT_LOCALBASE."/etc/namedb/named.root",$named_root,LOCK_EX); - } - if (!file_exists(CHROOT_LOCALBASE."/etc/localtime")){ + exec("/sbin/devfs -m {$bind_dev_dir} rule applyset", $dout); + } + // http://www.unixwiz.net/techtips/bind9-chroot.html + file_put_contents(CHROOT_LOCALBASE.'/etc/namedb/named.conf', $bind_conf); + file_put_contents(CHROOT_LOCALBASE.'/etc/namedb/rndc.conf', $rndc_file); + + if (!file_exists(CHROOT_LOCALBASE."/etc/namedb/named.root")) { + // dig +tcp @a.root-servers.net > CHROOT_LOCALBASE."/etc/namedb/named.root" + $named_root = file_get_contents("http://www.internic.net/domain/named.root"); + file_put_contents(CHROOT_LOCALBASE."/etc/namedb/named.root", $named_root, LOCK_EX); + } + if (!file_exists(CHROOT_LOCALBASE."/etc/localtime")) { copy("/etc/localtime", CHROOT_LOCALBASE."/etc/localtime"); } - + bind_write_rcfile(); - chown(CHROOT_LOCALBASE."/etc/namedb/keys","bind"); - chown(CHROOT_LOCALBASE."/etc/namedb","bind"); - chown(CHROOT_LOCALBASE."/var/log","bind"); - chown(CHROOT_LOCALBASE."/var/run/named","bind"); - chgrp(CHROOT_LOCALBASE."/var/log","bind"); - $bind_sh="/usr/local/etc/rc.d/named.sh"; - if($bind_enable == "on"){ - chmod ($bind_sh,0755); - mwexec("{$bind_sh} restart"); - } - elseif (is_service_running('named')){ - mwexec("{$bind_sh} stop"); - chmod ($bind_sh,0644); - } - //sync to backup servers - bind_sync_on_changes(); - conf_mount_ro(); + chown(CHROOT_LOCALBASE."/etc/namedb/keys", "bind"); + chown(CHROOT_LOCALBASE."/etc/namedb", "bind"); + chown(CHROOT_LOCALBASE."/var/log", "bind"); + chown(CHROOT_LOCALBASE."/var/run/named", "bind"); + chgrp(CHROOT_LOCALBASE."/var/log", "bind"); + $bind_sh = "/usr/local/etc/rc.d/named.sh"; + if ($bind_enable == "on") { + chmod($bind_sh, 0755); + mwexec("{$bind_sh} restart"); + } elseif (is_service_running('named')) { + mwexec("{$bind_sh} stop"); + chmod($bind_sh, 0644); + } + // sync to backup servers + bind_sync_on_changes(); + conf_mount_ro(); } -function bind_print_javascript_type_zone(){ -?> - <script language="JavaScript"> - <!-- - function on_type_zone_changed() { - - var field = document.iform.type; - var tipo = field.options[field.selectedIndex].value; - switch (tipo){ - case 'master': +function bind_print_javascript_type_zone() +{ + ?> + <script language="JavaScript"> + <!-- + function on_type_zone_changed() { + + var field = document.iform.type; + var tipo = field.options[field.selectedIndex].value; + switch (tipo) { + case 'master': document.iform.slaveip.disabled = 1; document.iform.tll.disabled = 0; document.iform.nameserver.disabled = 0; @@ -667,8 +715,8 @@ function bind_print_javascript_type_zone(){ document.iform.retry.disabled = 0; document.iform.expire.disabled = 0; document.iform.minimum.disabled = 0; - break; - case 'slave': + break; + case 'slave': document.iform.slaveip.disabled = 0; document.iform.tll.disabled = 1; document.iform.nameserver.disabled = 1; @@ -685,7 +733,7 @@ function bind_print_javascript_type_zone(){ document.iform.expire.disabled = 1; document.iform.minimum.disabled = 1; break; - case 'forward': + case 'forward': document.iform.slaveip.disabled = 1; document.iform.tll.disabled = 1; document.iform.nameserver.disabled = 1; @@ -701,8 +749,8 @@ function bind_print_javascript_type_zone(){ document.iform.retry.disabled = 1; document.iform.expire.disabled = 1; document.iform.minimum.disabled = 1; - break; - case 'redirect': + break; + case 'redirect': document.iform.slaveip.disabled = 1; document.iform.tll.disabled = 1; document.iform.nameserver.disabled = 0; @@ -718,127 +766,137 @@ function bind_print_javascript_type_zone(){ document.iform.retry.disabled = 0; document.iform.expire.disabled = 0; document.iform.minimum.disabled = 0; - break; - } - } - --> - </script> -<?php + break; + default: + break; + } + } + --> + </script> + <?php } -function bind_print_javascript_type_zone2(){ - print("<script language=\"JavaScript\">on_type_zone_changed();document.iform.resultconfig.disabled = 1;document.iform.dsset.disabled = 1;</script>\n"); +function bind_print_javascript_type_zone2() +{ + print("<script language=\"JavaScript\">on_type_zone_changed();document.iform.resultconfig.disabled = 1;document.iform.dsset.disabled = 1;</script>\n"); } -function bind_write_rcfile() { - $rc = array(); - $BIND_LOCALBASE = "/usr/local"; - $rc['file'] = 'named.sh'; - $rc['start'] = <<<EOD -if [ -z "`ps auxw | grep "[n]amed -c /etc/namedb/named.conf"|awk '{print $2}'`" ];then - {$BIND_LOCALBASE}/sbin/named -c /etc/namedb/named.conf -u bind -t /cf/named/ -fi - -EOD; - $rc['stop'] = <<<EOD -killall -9 named 2>/dev/null -sleep 2 +function bind_write_rcfile() +{ + $rc = array(); + $BIND_LOCALBASE = "/usr/local"; + $rc['file'] = 'named.sh'; + $rc['start'] = <<<EOD + if [ -z "`ps auxw | grep "[n]amed -c /etc/namedb/named.conf"|awk '{print $2}'`" ];then + {$BIND_LOCALBASE}/sbin/named -c /etc/namedb/named.conf -u bind -t /cf/named/ + fi EOD; - $rc['restart'] = <<<EOD -if [ -z "`ps auxw | grep "[n]amed -c /etc/namedb/named.conf"|awk '{print $2}'`" ];then - {$BIND_LOCALBASE}/sbin/named -c /etc/namedb/named.conf -u bind -t /cf/named/ - else + $rc['stop'] = <<<EOD killall -9 named 2>/dev/null - sleep 3 - {$BIND_LOCALBASE}/sbin/named -c /etc/namedb/named.conf -u bind -t /cf/named/ - fi - + sleep 2 EOD; - conf_mount_rw(); - write_rcfile($rc); - conf_mount_ro(); + $rc['restart'] = <<<EOD + if [ -z "`ps auxw | grep "[n]amed -c /etc/namedb/named.conf"|awk '{print $2}'`" ];then + {$BIND_LOCALBASE}/sbin/named -c /etc/namedb/named.conf -u bind -t /cf/named/ + else + killall -9 named 2>/dev/null + sleep 3 + {$BIND_LOCALBASE}/sbin/named -c /etc/namedb/named.conf -u bind -t /cf/named/ + fi +EOD; + conf_mount_rw(); + write_rcfile($rc); + conf_mount_ro(); } /* Uses XMLRPC to synchronize the changes to a remote node */ -function bind_sync_on_changes() { +function bind_sync_on_changes() +{ global $config, $g; - if (is_array($config['installedpackages']['bindsync']['config'])){ - $bind_sync=$config['installedpackages']['bindsync']['config'][0]; + if (is_array($config['installedpackages']['bindsync']['config'])) { + $bind_sync = $config['installedpackages']['bindsync']['config'][0]; $synconchanges = $bind_sync['synconchanges']; $synctimeout = $bind_sync['synctimeout']; - $master_zone_ip=$bind_sync['masterip']; - switch ($synconchanges){ - case "manual": - if (is_array($bind_sync[row])){ - $rs=$bind_sync[row]; - } - else{ + $master_zone_ip = $bind_sync['masterip']; + switch ($synconchanges) { + case 'manual': + if (is_array($bind_sync['row'])) { + $rs = $bind_sync['row']; + } else { log_error("[bind] xmlrpc sync is enabled but there is no hosts to push on bind config."); return; - } + } + break; + case 'auto': + if (is_array($config['hasync'])) { + $hasync = $config['hasync'][0]; + $rs[0]['ipaddress'] = $hasync['synchronizetoip']; + $rs[0]['username'] = $hasync['username']; + $rs[0]['password'] = $hasync['password']; + } else { + log_error("[bind] xmlrpc sync is enabled but there is no system backup hosts to push bind config."); + return; + } break; - case "auto": - if (is_array($config['hasync'])){ - $hasync=$config['hasync'][0]; - $rs[0]['ipaddress']=$hasync['synchronizetoip']; - $rs[0]['username']=$hasync['username']; - $rs[0]['password']=$hasync['password']; - } - else{ - log_error("[bind] xmlrpc sync is enabled but there is no system backup hosts to push bind config."); - return; - } - break; default: return; - break; + break; } - if (is_array($rs)){ + if (is_array($rs)) { log_error("[bind] xmlrpc sync is starting."); - foreach($rs as $sh){ + foreach ($rs as $sh) { $sync_to_ip = $sh['ipaddress']; $password = $sh['password']; - if($sh['username']) + if ($sh['username']) { $username = $sh['username']; - else + } else { $username = 'admin'; - if($password && $sync_to_ip) - bind_do_xmlrpc_sync($sync_to_ip, $username, $password,$synctimeout,$master_zone_ip); } - log_error("[bind] xmlrpc sync is ending."); + if ($password && $sync_to_ip) { + bind_do_xmlrpc_sync($sync_to_ip, $username, $password, $synctimeout, $master_zone_ip); + } } - } + log_error("[bind] xmlrpc sync is ending."); + } + } } + /* Do the actual XMLRPC sync */ -function bind_do_xmlrpc_sync($sync_to_ip, $username, $password, $synctimeout,$master_zone_ip) { +function bind_do_xmlrpc_sync($sync_to_ip, $username, $password, $synctimeout, $master_zone_ip) +{ global $config, $g; - if(!$username) + if (!$username) { return; - - if(!$password) + } + + if (!$password) { return; + } - if(!$sync_to_ip) + if (!$sync_to_ip) { return; + } + + if (!$synctimeout) { + $synctimeout = 25; + } + - if(!$synctimeout) - $synctimeout=25; - - $xmlrpc_sync_neighbor = $sync_to_ip; - if($config['system']['webgui']['protocol'] != "") { + if ($config['system']['webgui']['protocol'] != "") { $synchronizetoip = $config['system']['webgui']['protocol']; $synchronizetoip .= "://"; - } - $port = $config['system']['webgui']['port']; - /* if port is empty lets rely on the protocol selection */ - if($port == "") { - if($config['system']['webgui']['protocol'] == "http") + } + $port = $config['system']['webgui']['port']; + /* if port is empty lets rely on the protocol selection */ + if ($port == "") { + if ($config['system']['webgui']['protocol'] == "http") { $port = "80"; - else + } else { $port = "443"; - } + } + } $synchronizetoip .= $sync_to_ip; /* xml will hold the sections to sync */ @@ -847,17 +905,19 @@ function bind_do_xmlrpc_sync($sync_to_ip, $username, $password, $synctimeout,$ma $xml['bindacls'] = $config['installedpackages']['bindacls']; $xml['bindviews'] = $config['installedpackages']['bindviews']; $xml['bindzone'] = $config['installedpackages']['bindzone']; - if (is_array($config['installedpackages']['dnsseckeys'])) - $xml['dnsseckeys']=$config['installedpackages']['dnsseckeys']; + if (is_array($config['installedpackages']['dnsseckeys'])) { + $xml['dnsseckeys'] = $config['installedpackages']['dnsseckeys']; + } //change master zone to slave on backup servers - if(is_array($xml['bindzone']["config"])) - for ($x=0; $x<sizeof($xml['bindzone']["config"]); $x++){ - if ($xml['bindzone']["config"][$x]['type']=="master"){ - $xml['bindzone']["config"][$x]['type']="slave"; - $xml['bindzone']["config"][$x]['slaveip']=$master_zone_ip; + if (is_array($xml['bindzone']["config"])) { + for ($x = 0; $x < sizeof($xml['bindzone']["config"]); $x++) { + if ($xml['bindzone']["config"][$x]['type'] == "master") { + $xml['bindzone']["config"][$x]['type'] = "slave"; + $xml['bindzone']["config"][$x]['slaveip'] = $master_zone_ip; } - + } + } /* assemble xmlrpc payload */ $params = array( XML_RPC_encode($password), @@ -871,52 +931,53 @@ function bind_do_xmlrpc_sync($sync_to_ip, $username, $password, $synctimeout,$ma $msg = new XML_RPC_Message($method, $params); $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port); $cli->setCredentials($username, $password); - if($g['debug']) + if ($g['debug']) { $cli->setDebug(1); + } /* send our XMLRPC message and timeout after defined sync timeout value*/ $resp = $cli->send($msg, $synctimeout); - if(!$resp) { + if (!$resp) { $error = "A communications error occurred while attempting BIND XMLRPC sync with {$url}:{$port}."; log_error($error); file_notice("sync_settings", $error, "bind Settings Sync", ""); - } elseif($resp->faultCode()) { + } elseif ($resp->faultCode()) { $cli->setDebug(1); $resp = $cli->send($msg, $synctimeout); - $error = "An error code was received while attempting BIND XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); + $error = "An error code was received while attempting BIND XMLRPC sync with {$url}:{$port} - Code ".$resp->faultCode().": ".$resp->faultString(); log_error($error); file_notice("sync_settings", $error, "bind Settings Sync", ""); } else { log_error("[bind] XMLRPC sync successfully completed with {$url}:{$port}."); } - + /* tell bind to reload our settings on the destination sync host. */ $method = 'pfsense.exec_php'; - $execcmd = "require_once('/usr/local/pkg/bind.inc');\n"; + $execcmd = "require_once('/usr/local/pkg/bind.inc');\n"; $execcmd .= "bind_sync('yes');"; /* assemble xmlrpc payload */ $params = array( XML_RPC_encode($password), XML_RPC_encode($execcmd) ); - + log_error("[bind] XMLRPC reload data {$url}:{$port}."); $msg = new XML_RPC_Message($method, $params); $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port); $cli->setCredentials($username, $password); $resp = $cli->send($msg, $synctimeout); - if(!$resp) { + if (!$resp) { $error = "A communications error occurred while attempting BIND XMLRPC sync with {$url}:{$port} (pfsense.exec_php)."; log_error($error); file_notice("sync_settings", $error, "Bind Settings Sync", ""); - } elseif($resp->faultCode()) { + } elseif ($resp->faultCode()) { $cli->setDebug(1); $resp = $cli->send($msg, $synctimeout); - $error = "[Bind] An error code was received while attempting BIND XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); + $error = "[Bind] An error code was received while attempting BIND XMLRPC sync with {$url}:{$port} - Code ".$resp->faultCode().": ".$resp->faultString(); log_error($error); file_notice("sync_settings", $error, "bind Settings Sync", ""); } else { log_error("BIND XMLRPC reload data success with {$url}:{$port} (pfsense.exec_php)."); } - } + ?> diff --git a/config/bind/bind.widget.php b/config/bind/bind.widget.php index dc6b3bf0..1e8c0cc8 100644 --- a/config/bind/bind.widget.php +++ b/config/bind/bind.widget.php @@ -1,4 +1,4 @@ -<?php +<?php /* Copyright 2013 Marcello Coutinho Part of bind package for pfSense(www.pfsense.org) @@ -28,59 +28,65 @@ @require_once("pfsense-utils.inc"); @require_once("functions.inc"); -$uname=posix_uname(); -if ($uname['machine']=='amd64') - ini_set('memory_limit', '250M'); - -function open_table(){ +$uname = posix_uname(); +if ($uname['machine'] == 'amd64') { + ini_set('memory_limit', '250M'); +} + +function open_table() +{ echo "<table style=\"padding-top:0px; padding-bottom:0px; padding-left:0px; padding-right:0px\" width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\">"; - echo" <tr>"; + echo " <tr>"; } -function close_table(){ - echo" </tr>"; - echo"</table>"; - + +function close_table() +{ + echo " </tr>"; + echo "</table>"; + } -$pfb_table=array(); -$img['Sick']="<img src ='/themes/{$g['theme']}/images/icons/icon_interface_down.gif'>"; -$img['Healthy']="<img src ='/themes/{$g['theme']}/images/icons/icon_interface_up.gif'>"; +$pfb_table = array(); +$img['Sick'] = "<img src ='/themes/{$g['theme']}/images/icons/icon_interface_down.gif'>"; +$img['Healthy'] = "<img src ='/themes/{$g['theme']}/images/icons/icon_interface_up.gif'>"; #var_dump($pfb_table); #exit; -?><div id='bind'><?php -global $config; -$rndc_bin="/usr/local/sbin/rndc"; +?> +<div id='bind'><?php + global $config; + $rndc_bin = "/usr/local/sbin/rndc"; -if (file_exists($rndc_bin)) - exec("$rndc_bin status",$status); + if (file_exists($rndc_bin)) { + exec("$rndc_bin status", $status); + } -open_table(); -foreach($status as $line){ - $fields=explode(":",$line); - print "<tr><td class=\"vncellt\"width=50%><strong>".ucfirst($fields[0])."</strong></td>\n"; - print "<td class=\"listlr\">{$fields[1]}</td>\n</tr>"; + open_table(); + foreach ($status as $line) { + $fields = explode(":", $line); + print "<tr><td class=\"vncellt\"width=50%><strong>" . ucfirst($fields[0]) . "</strong></td>\n"; + print "<td class=\"listlr\">{$fields[1]}</td>\n</tr>"; } -close_table(); -echo"</div>"; + close_table(); + echo "</div>"; -?> -<script type="text/javascript"> - function getstatus_bind() { - var url = "/widgets/widgets/bind.widget.php"; - var pars = 'getupdatestatus=yes'; - var myAjax = new Ajax.Request( - url, - { - method: 'get', - parameters: pars, - onComplete: activitycallback_bind - }); + ?> + <script type="text/javascript"> + function getstatus_bind() { + var url = "/widgets/widgets/bind.widget.php"; + var pars = 'getupdatestatus=yes'; + var myAjax = new Ajax.Request( + url, + { + method: 'get', + parameters: pars, + onComplete: activitycallback_bind + }); } - function activitycallback_bind(transport) { - $('bind').innerHTML = transport.responseText; - setTimeout('getstatus_postfix()', 5000); - } - getstatus_bind(); -</script> + function activitycallback_bind(transport) { + $('bind').innerHTML = transport.responseText; + setTimeout('getstatus_postfix()', 5000); + } + getstatus_bind(); + </script> diff --git a/config/bind/bind.xml b/config/bind/bind.xml index 37c13017..b64ba256 100644 --- a/config/bind/bind.xml +++ b/config/bind/bind.xml @@ -2,8 +2,8 @@ <!DOCTYPE packagegui SYSTEM "../schema/packages.dtd"> <?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?> <packagegui> - <copyright> - <![CDATA[ + <copyright> + <![CDATA[ /* $Id$ */ /* ========================================================================== */ /* @@ -43,273 +43,277 @@ /* ========================================================================== */ ]]> - </copyright> - <description>Describe your package here</description> - <requirements>Describe your package requirements here</requirements> - <faq>Currently there are no FAQ items provided.</faq> - <name>bind</name> - <version>1.0</version> - <title>Bind: Domain Named Settings</title> - <include_file>/usr/local/pkg/bind.inc</include_file> - <menu> - <name>BIND Server</name> - <tooltiptext>Modify BIND settings</tooltiptext> - <section>Services</section> - <url>/pkg_edit.php?xml=bind.xml</url> - </menu> - <service> - <name>named</name> - <rcfile>named.sh</rcfile> - <executable>named</executable> - <description>Domain Name Service</description> - </service> - <tabs> - <tab> - <text>Settings</text> - <url>/pkg_edit.php?xml=bind.xml</url> - <active/> - </tab> - <tab> - <text>ACLs</text> - <url>/pkg.php?xml=bind_acls.xml</url> - </tab> - <tab> - <text>Views</text> - <url>/pkg.php?xml=bind_views.xml</url> - </tab> - <tab> - <text>Zones</text> - <url>/pkg.php?xml=bind_zones.xml</url> - </tab> - <tab> - <text>Sync</text> - <url>/pkg_edit.php?xml=bind_sync.xml</url> - </tab> + </copyright> + <description>Describe your package here</description> + <requirements>Describe your package requirements here</requirements> + <faq>Currently there are no FAQ items provided.</faq> + <name>bind</name> + <version>1.0</version> + <title>Bind: Domain Named Settings</title> + <include_file>/usr/local/pkg/bind.inc</include_file> + <menu> + <name>BIND Server</name> + <tooltiptext>Modify BIND settings</tooltiptext> + <section>Services</section> + <url>/pkg_edit.php?xml=bind.xml</url> + </menu> + <service> + <name>named</name> + <rcfile>named.sh</rcfile> + <executable>named</executable> + <description>Domain Name Service</description> + </service> + <tabs> + <tab> + <text>Settings</text> + <url>/pkg_edit.php?xml=bind.xml</url> + <active/> + </tab> + <tab> + <text>ACLs</text> + <url>/pkg.php?xml=bind_acls.xml</url> + </tab> + <tab> + <text>Views</text> + <url>/pkg.php?xml=bind_views.xml</url> + </tab> + <tab> + <text>Zones</text> + <url>/pkg.php?xml=bind_zones.xml</url> + </tab> + <tab> + <text>Sync</text> + <url>/pkg_edit.php?xml=bind_sync.xml</url> + </tab> - </tabs> - <!-- Installation --> - <additional_files_needed> - <prefix>/usr/local/pkg/</prefix> - <chmod>0755</chmod> - <item>https://packages.pfsense.org/packages/config/bind/bind.xml</item> - </additional_files_needed> - <additional_files_needed> - <prefix>/usr/local/pkg/</prefix> - <chmod>0755</chmod> - <item>https://packages.pfsense.org/packages/config/bind/bind_views.xml</item> - </additional_files_needed> - <additional_files_needed> - <prefix>/usr/local/pkg/</prefix> - <chmod>0755</chmod> - <item>https://packages.pfsense.org/packages/config/bind/bind_zones.xml</item> - </additional_files_needed> - <additional_files_needed> - <prefix>/usr/local/pkg/</prefix> - <chmod>0755</chmod> - <item>https://packages.pfsense.org/packages/config/bind/bind_acls.xml</item> - </additional_files_needed> - <additional_files_needed> - <prefix>/usr/local/pkg/</prefix> - <chmod>0755</chmod> - <item>https://packages.pfsense.org/packages/config/bind/bind.inc</item> - </additional_files_needed> - <additional_files_needed> - <prefix>/usr/local/pkg/</prefix> - <chmod>0755</chmod> - <item>https://packages.pfsense.org/packages/config/bind/bind_sync.xml</item> - </additional_files_needed> - <additional_files_needed> - <prefix>/usr/local/www/shortcuts/</prefix> - <chmod>0755</chmod> - <item>https://packages.pfsense.org/packages/config/bind/pkg_bind.inc</item> - </additional_files_needed> - <additional_files_needed> - <prefix>/usr/local/www/widgets/widgets/</prefix> - <chmod>0755</chmod> - <item>https://packages.pfsense.org/packages/config/bind/bind.widget.php</item> - </additional_files_needed> - <fields> - <field> - <type>listtopic</type> - <name>Daemon Settings</name> - <fieldname>temp01</fieldname> - </field> - <field> - <fielddescr>Enable BIND</fielddescr> - <fieldname>enable_bind</fieldname> - <description><![CDATA[Enable BIND DNS server<br> + </tabs> + <!-- Installation --> + <additional_files_needed> + <prefix>/usr/local/pkg/</prefix> + <chmod>0755</chmod> + <item>https://packages.pfsense.org/packages/config/bind/bind.xml</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/pkg/</prefix> + <chmod>0755</chmod> + <item>https://packages.pfsense.org/packages/config/bind/bind_views.xml</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/pkg/</prefix> + <chmod>0755</chmod> + <item>https://packages.pfsense.org/packages/config/bind/bind_zones.xml</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/pkg/</prefix> + <chmod>0755</chmod> + <item>https://packages.pfsense.org/packages/config/bind/bind_acls.xml</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/pkg/</prefix> + <chmod>0755</chmod> + <item>https://packages.pfsense.org/packages/config/bind/bind.inc</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/pkg/</prefix> + <chmod>0755</chmod> + <item>https://packages.pfsense.org/packages/config/bind/bind_sync.xml</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/www/shortcuts/</prefix> + <chmod>0755</chmod> + <item>https://packages.pfsense.org/packages/config/bind/pkg_bind.inc</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/www/widgets/widgets/</prefix> + <chmod>0755</chmod> + <item>https://packages.pfsense.org/packages/config/bind/bind.widget.php</item> + </additional_files_needed> + <fields> + <field> + <type>listtopic</type> + <name>Daemon Settings</name> + <fieldname>temp01</fieldname> + </field> + <field> + <fielddescr>Enable BIND</fielddescr> + <fieldname>enable_bind</fieldname> + <description><![CDATA[Enable BIND DNS server<br> Disable DNS Forwarder and Resolver services on selected interfaces before enabling BIND.]]></description> - <type>checkbox</type> - <required/> - </field> - <field> - <fielddescr>Listen on</fielddescr> - <fieldname>listenon</fieldname> - <description><![CDATA[Choose the interfaces on which to enable BIND.]]></description> - <type>interfaces_selection</type> - <showlistenall/> - <showvirtualips/> - <multiple/> - </field> - <field> - <fielddescr>Enable Notify</fielddescr> - <fieldname>bind_notify</fieldname> - <description>Notify slave server after any update on master.</description> - <type>checkbox</type> - </field> - <field> - <fielddescr>Hide Version</fielddescr> - <fieldname>bind_hide_version</fieldname> - <description>Hide the version of BIND (ignore queries for version.bind).</description> - <type>checkbox</type> - </field> - <field> - <fielddescr>Limit Memory use</fielddescr> - <fieldname>bind_ram_limit</fieldname> - <description>Limits RAM use for DNS server, recommend 256M</description> - <type>input</type> - <size>10</size> - <default_value>256M</default_value> - </field> - <field> - <type>listtopic</type> - <name>Logging options</name> - <fieldname>temp01</fieldname> - </field> - <field> - <fielddescr>Enable logging</fielddescr> - <fieldname>bind_logging</fieldname> - <description><![CDATA[Enable BIND logs under Status > System logs, Resolver tab.]]></description> - <type>checkbox</type> - </field> - <field> - <fielddescr>Logging serverity</fielddescr> - <fieldname>log_severity</fieldname> - <description><![CDATA[Choose logging level for selected categories.<BR> - The value 'dynamic' means assume the global level defined by either the command line parameter -d or by running rndc trace.]]></description> - <type>select</type> - <options> - <option><name>Critital</name><value>critical</value></option> - <option><name>Error</name><value>error</value></option> - <option><name>Warning</name><value>warning</value></option> - <option><name>Notice</name><value>Notice</value></option> - <option><name>info</name><value>info</value></option> - <option><name>Debug level 1</name><value>debug 1</value></option> - <option><name>Debug level 3</name><value>debug 3</value></option> - <option><name>Debug level 5</name><value>debug 5</value></option> - <option><name>Dynamic</name><value>dynamic</value></option> - </options> - </field> - <field> - <fielddescr>Logging options</fielddescr> - <fieldname>log_options</fieldname> - <description><![CDATA[Select categories to log.<BR> - use CTRL+click to select/unselect.]]></description> - <type>select</type> - <options> - <option><name>Default-if this is the only category selected, it will log all categories except queries</name><value>default</value></option> - <option><name>General-Anything that is not classified as any other item in this list defaults to this category</name><value>general</value></option> - <option><name>Database-The value 'dynamic' means assume the global level defined by either the command line parameter -d or by running rndc trace</name><value>database</value></option> - <option><name>Security-Approval and denial of requests</name><value>security</value></option> - <option><name>Config-Configuration file parsing and processing</name><value>config</value></option> - <option><name>Resolver-Name resolution including recursive lookups</name><value>resolver</value></option> - <option><name>Xfer-in-Details of zone transfers the server is receiving.</name><value>xfer-in</value></option> - <option><name>Xfer-out-Details of zone transfers the server is sending.</name><value>xfer-out</value></option> - <option><name>Notify-Logs all NOTIFY operations.</name><value>notify</value></option> - <option><name>Client-Processing of client requests</name><value>client</value></option> - <option><name>Unmatched-No matching view clause or unrecognized class value.</name><value>unmatched</value></option> - <option><name>Queries-Logs all query transactions</name><value>queries</value></option> - <option><name>Network-Logs all network operations</name><value>network</value></option> - <option><name>Update-Logging of all dynamic update (DDNS) transactions</name><value>update</value></option> - <option><name>Dispatch-Dispatching of incoming packets to the server modules</name><value>dispatch</value></option> - <option><name>DNSSEC-DNSSEC and TSIG protocol processing</name><value>dnssec</value></option> - <option><name>lame-servers-Mis-configuration in the delegation of domains discovered by BIND</name><value>lame-servers</value></option> - </options> - <multiple/> - <size>18</size> - </field> - <field> - <type>listtopic</type> - <name>Response Rate Limit</name> - <fieldname>temp01</fieldname> - </field> - <field> - <fielddescr>Rate limit</fielddescr> - <fieldname>rate_enabled</fieldname> - <description><![CDATA[<a target=_new href='https://kb.isc.org/article/AA-01000/189/A-Quick-Introduction-to-Response-Rate-Limiting.html?utm_source=isc&utm_medium=website&utm_term=rrl-kb&utm_content=kbarticle&utm_campaign=bind994_release_091913'> - Limit/rate response queries</a> to prevent DOS attack.]]></description> - <type>checkbox</type> - <enablefields>rate_limit,log_only</enablefields> - </field> - <field> - <fielddescr>Limit Action</fielddescr> - <fieldname>log_only</fieldname> - <description>Select what to do when a query reaches a limit.</description> - <type>select</type> - <options> - <option><name>Deny query</name><value>no</value></option> - <option><name>Log only</name><value>yes</value></option> - </options> - </field> - <field> - <fielddescr>limit</fielddescr> - <fieldname>rate_limit</fieldname> - <description>Set rate limit. Default to 15.</description> - <type>input</type> - <size>10</size> - </field> - - <field> - <type>listtopic</type> - <name>Forwarder Config</name> - <fieldname>temp01</fieldname> - </field> - <field> - <fielddescr>Enable Forwarding</fielddescr> - <fieldname>bind_forwarder</fieldname> - <description>Enable forwarding queries to other DNS servers listed below rather than this server performing its own recursion.</description> - <type>checkbox</type> - <enablefields>bind_forwarder_ips</enablefields> - </field> - <field> - <fielddescr>Forwarder IPs</fielddescr> - <fieldname>bind_forwarder_ips</fieldname> - <description>Enter IPs of DNS servers to use for recursion. Separate by semi-colons (;). Applies only if Enable Forwarding is chosen.</description> - <type>input</type> - <size>80</size> - </field> - <field> - <type>listtopic</type> - <name>custom Options</name> - <fieldname>temp01</fieldname> - </field> - <field> - <fielddescr>Custom Options</fielddescr> - <fieldname>bind_custom_options</fieldname> - <description><![CDATA[You can put your own custom options here, one per line.<br> - They'll be added to the configuration. They need to be named.conf native options.]]> - </description> - <type>textarea</type> - <cols>65</cols> - <rows>5</rows> - <encoding>base64</encoding> - </field> - </fields> - <custom_php_after_head_command> - </custom_php_after_head_command> - <custom_php_command_before_form> - </custom_php_command_before_form> - <custom_add_php_command> - </custom_add_php_command> - <custom_php_validation_command> - </custom_php_validation_command> - <custom_php_resync_config_command> - bind_sync(); - </custom_php_resync_config_command> - <custom_php_install_command> - bind_write_rcfile(); + <type>checkbox</type> + <required/> + </field> + <field> + <fielddescr>Listen on</fielddescr> + <fieldname>listenon</fieldname> + <description><![CDATA[Choose the interfaces on which to enable BIND.]]></description> + <type>interfaces_selection</type> + <showlistenall/> + <showvirtualips/> + <multiple/> + </field> + <field> + <fielddescr>Enable Notify</fielddescr> + <fieldname>bind_notify</fieldname> + <description>Notify slave server after any update on master.</description> + <type>checkbox</type> + </field> + <field> + <fielddescr>Hide Version</fielddescr> + <fieldname>bind_hide_version</fieldname> + <description>Hide the version of BIND (ignore queries for version.bind).</description> + <type>checkbox</type> + </field> + <field> + <fielddescr>Limit Memory Use</fielddescr> + <fieldname>bind_ram_limit</fieldname> + <description>Limits RAM use for DNS server, recommend 256M</description> + <type>input</type> + <size>10</size> + <default_value>256M</default_value> + </field> + <field> + <type>listtopic</type> + <name>Logging options</name> + <fieldname>temp01</fieldname> + </field> + <field> + <fielddescr>Enable Logging</fielddescr> + <fieldname>bind_logging</fieldname> + <description><![CDATA[Enable BIND logs under Status > System logs, Resolver tab.]]></description> + <type>checkbox</type> + </field> + <field> + <fielddescr>Logging Serverity</fielddescr> + <fieldname>log_severity</fieldname> + <description><![CDATA[Choose logging level for selected categories.<BR> + The value 'dynamic' means assume the global level defined by either the command line parameter -d or by running rndc trace.]]></description> + <type>select</type> + <options> + <option><name>Critital</name><value>critical</value></option> + <option><name>Error</name><value>error</value></option> + <option><name>Warning</name><value>warning</value></option> + <option><name>Notice</name><value>Notice</value></option> + <option><name>info</name><value>info</value></option> + <option><name>Debug level 1</name><value>debug 1</value></option> + <option><name>Debug level 3</name><value>debug 3</value></option> + <option><name>Debug level 5</name><value>debug 5</value></option> + <option><name>Dynamic</name><value>dynamic</value></option> + </options> + </field> + <field> + <fielddescr>Logging Options</fielddescr> + <fieldname>log_options</fieldname> + <description><![CDATA[Select categories to log.<BR> + use CTRL+click to select/unselect.]]></description> + <type>select</type> + <options> + <option><name>Default-if this is the only category selected, it will log all categories except queries</name><value>default</value></option> + <option><name>General-Anything that is not classified as any other item in this list defaults to this category</name><value>general</value></option> + <option><name>Database-The value 'dynamic' means assume the global level defined by either the command line parameter -d or by running rndc trace</name><value>database</value></option> + <option><name>Security-Approval and denial of requests</name><value>security</value></option> + <option><name>Config-Configuration file parsing and processing</name><value>config</value></option> + <option><name>Resolver-Name resolution including recursive lookups</name><value>resolver</value></option> + <option><name>Xfer-in-Details of zone transfers the server is receiving.</name><value>xfer-in</value></option> + <option><name>Xfer-out-Details of zone transfers the server is sending.</name><value>xfer-out</value></option> + <option><name>Notify-Logs all NOTIFY operations.</name><value>notify</value></option> + <option><name>Client-Processing of client requests</name><value>client</value></option> + <option><name>Unmatched-No matching view clause or unrecognized class value.</name><value>unmatched</value></option> + <option><name>Queries-Logs all query transactions</name><value>queries</value></option> + <option><name>Network-Logs all network operations</name><value>network</value></option> + <option><name>Update-Logging of all dynamic update (DDNS) transactions</name><value>update</value></option> + <option><name>Dispatch-Dispatching of incoming packets to the server modules</name><value>dispatch</value></option> + <option><name>DNSSEC-DNSSEC and TSIG protocol processing</name><value>dnssec</value></option> + <option><name>lame-servers-Mis-configuration in the delegation of domains discovered by BIND</name><value>lame-servers</value></option> + </options> + <multiple/> + <size>18</size> + </field> + <field> + <type>listtopic</type> + <name>Response Rate Limit</name> + <fieldname>temp01</fieldname> + </field> + <field> + <fielddescr>Rate Limit</fielddescr> + <fieldname>rate_enabled</fieldname> + <description><![CDATA[<a target=_new href='https://kb.isc.org/article/AA-01000/189/A-Quick-Introduction-to-Response-Rate-Limiting.html?utm_source=isc&utm_medium=website&utm_term=rrl-kb&utm_content=kbarticle&utm_campaign=bind994_release_091913'> + Limit/rate response queries</a> to prevent DOS attack.]]></description> + <type>checkbox</type> + <enablefields>rate_limit,log_only</enablefields> + </field> + <field> + <fielddescr>Limit Action</fielddescr> + <fieldname>log_only</fieldname> + <description>Select what to do when a query reaches a limit.</description> + <type>select</type> + <options> + <option><name>Deny query</name><value>no</value></option> + <option><name>Log only</name><value>yes</value></option> + </options> + </field> + <field> + <fielddescr>Limit</fielddescr> + <fieldname>rate_limit</fieldname> + <description>Set rate limit. Default to 15.</description> + <type>input</type> + <size>10</size> + </field> + <field> + <type>listtopic</type> + <name>Forwarder Config</name> + <fieldname>temp01</fieldname> + </field> + <field> + <fielddescr>Enable Forwarding</fielddescr> + <fieldname>bind_forwarder</fieldname> + <description>Enable forwarding queries to other DNS servers listed below rather than this server + performing its own recursion. + </description> + <type>checkbox</type> + <enablefields>bind_forwarder_ips</enablefields> + </field> + <field> + <fielddescr>Forwarder IPs</fielddescr> + <fieldname>bind_forwarder_ips</fieldname> + <description>Enter IPs of DNS servers to use for recursion. Separate by semi-colons (;). Applies + only if Enable Forwarding is chosen. + </description> + <type>input</type> + <size>80</size> + </field> + <field> + <type>listtopic</type> + <name>Custom Options</name> + <fieldname>temp01</fieldname> + </field> + <field> + <fielddescr>Custom Options</fielddescr> + <fieldname>bind_custom_options</fieldname> + <description> + <![CDATA[You can put your own custom options here, one per line.<br> + They'll be added to the configuration. They need to be named.conf native options.]]> + </description> + <type>textarea</type> + <cols>65</cols> + <rows>5</rows> + <encoding>base64</encoding> + </field> + </fields> + <custom_php_after_head_command> + </custom_php_after_head_command> + <custom_php_command_before_form> + </custom_php_command_before_form> + <custom_add_php_command> + </custom_add_php_command> + <custom_php_validation_command> + </custom_php_validation_command> + <custom_php_resync_config_command> + bind_sync(); + </custom_php_resync_config_command> + <custom_php_install_command> + bind_write_rcfile(); </custom_php_install_command> - <custom_php_deinstall_command> - </custom_php_deinstall_command> - <filter_rules_needed></filter_rules_needed> + <custom_php_deinstall_command> + </custom_php_deinstall_command> + <filter_rules_needed></filter_rules_needed> </packagegui> diff --git a/config/bind/bind_acls.xml b/config/bind/bind_acls.xml index c9b49f47..49794a69 100644 --- a/config/bind/bind_acls.xml +++ b/config/bind/bind_acls.xml @@ -2,8 +2,8 @@ <!DOCTYPE packagegui SYSTEM "./schema/packages.dtd"> <?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?> <packagegui> - <copyright> - <![CDATA[ + <copyright> + <![CDATA[ /* $Id$ */ /* ========================================================================== */ /* @@ -42,10 +42,10 @@ */ /* ========================================================================== */ ]]> - </copyright> - <description>Describe your package here</description> - <requirements>Describe your package requirements here</requirements> - <faq>Currently there are no FAQ items provided.</faq> + </copyright> + <description>Describe your package here</description> + <requirements>Describe your package requirements here</requirements> + <faq>Currently there are no FAQ items provided.</faq> <name>bindacls</name> <version>0.1.0</version> <title>BIND: ACLs Settings</title> @@ -56,29 +56,29 @@ <section>Services</section> <configfile>bind.xml</configfile> </menu> - <tabs> - <tab> - <text>Settings</text> - <url>/pkg_edit.php?xml=bind.xml</url> - </tab> - <tab> - <text>ACLs</text> - <url>/pkg.php?xml=bind_acls.xml</url> - <active/> - </tab> - <tab> - <text>Views</text> - <url>/pkg.php?xml=bind_views.xml</url> - </tab> - <tab> - <text>Zones</text> - <url>/pkg.php?xml=bind_zones.xml</url> - </tab> - <tab> - <text>Sync</text> - <url>/pkg_edit.php?xml=bind_sync.xml</url> - </tab> - </tabs> + <tabs> + <tab> + <text>Settings</text> + <url>/pkg_edit.php?xml=bind.xml</url> + </tab> + <tab> + <text>ACLs</text> + <url>/pkg.php?xml=bind_acls.xml</url> + <active/> + </tab> + <tab> + <text>Views</text> + <url>/pkg.php?xml=bind_views.xml</url> + </tab> + <tab> + <text>Zones</text> + <url>/pkg.php?xml=bind_zones.xml</url> + </tab> + <tab> + <text>Sync</text> + <url>/pkg_edit.php?xml=bind_sync.xml</url> + </tab> + </tabs> <configpath>['installedpackages']['bindacls']['config']</configpath> <adddeleteeditpagefields> <columnitem> @@ -92,7 +92,7 @@ <movable>on</movable> </adddeleteeditpagefields> <!-- fields gets invoked when the user adds or edits a item. the following items - will be parsed and rendered for the user as a gui with input, and selectboxes. --> + will be parsed and rendered for the user as a gui with input, and selectboxes. --> <fields> <field> <fielddescr>ACL Name</fielddescr> @@ -107,32 +107,32 @@ <description>Enter the description for this ACL.</description> <type>input</type> </field> - <field> - <fielddescr>Enter IP or range block network.</fielddescr> - <description>Leave blank to allow All</description> - <fieldname>none</fieldname> - <type>rowhelper</type> - <rowhelper> - <rowhelperfield> - <fielddescr>Value</fielddescr> - <fieldname>value</fieldname> - <type>input</type> - <size>20</size> - </rowhelperfield> - <rowhelperfield> - <fielddescr>Description</fielddescr> - <fieldname>description</fieldname> - <type>input</type> - <size>20</size> - </rowhelperfield> - </rowhelper> - </field> + <field> + <fielddescr>Enter IP or range block network.</fielddescr> + <description>Leave blank to allow All</description> + <fieldname>none</fieldname> + <type>rowhelper</type> + <rowhelper> + <rowhelperfield> + <fielddescr>Value</fielddescr> + <fieldname>value</fieldname> + <type>input</type> + <size>20</size> + </rowhelperfield> + <rowhelperfield> + <fielddescr>Description</fielddescr> + <fieldname>description</fieldname> + <type>input</type> + <size>20</size> + </rowhelperfield> + </rowhelper> + </field> </fields> - <custom_php_command_before_form> - </custom_php_command_before_form> + <custom_php_command_before_form> + </custom_php_command_before_form> <custom_delete_php_command> - </custom_delete_php_command> - <custom_php_resync_config_command> - bind_sync(); - </custom_php_resync_config_command> + </custom_delete_php_command> + <custom_php_resync_config_command> + bind_sync(); + </custom_php_resync_config_command> </packagegui> diff --git a/config/bind/bind_sync.xml b/config/bind/bind_sync.xml index d2f9c95b..97fdad81 100644 --- a/config/bind/bind_sync.xml +++ b/config/bind/bind_sync.xml @@ -3,7 +3,7 @@ <?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?> <packagegui> <copyright> - <![CDATA[ + <![CDATA[ /* $Id$ */ /* ========================================================================== */ /* @@ -105,7 +105,7 @@ <fielddescr>Zone Master IP</fielddescr> <fieldname>masterip</fieldname> <description><![CDATA[Set master zone ip you want to use to sync backup server zones with master.<br> - <b>All master zones will be configured as backup on slave servers.<b>]]></description> + <b>All master zones will be configured as backup on slave servers.<b>]]></description> <type>input</type> <size>20</size> <required/> @@ -115,24 +115,24 @@ <fieldname>none</fieldname> <type>rowhelper</type> <description><![CDATA[<b>Do not forget to:</b><br> - Create firewall rules to allow zone transfer between master and slave servers.<br> - Create a acls with these slave servers.<br> - Include created acl on allow-transfer option on zone config.]]></description> + Create firewall rules to allow zone transfer between master and slave servers.<br> + Create a acls with these slave servers.<br> + Include created acl on allow-transfer option on zone config.]]></description> <rowhelper> - <rowhelperfield> - <fielddescr>IP Address</fielddescr> - <fieldname>ipaddress</fieldname> - <description>IP Address of remote server</description> - <type>input</type> - <size>20</size> - </rowhelperfield> - <rowhelperfield> - <fielddescr>Password</fielddescr> - <fieldname>password</fieldname> - <description>Password for remote server.</description> - <type>password</type> - <size>20</size> - </rowhelperfield> + <rowhelperfield> + <fielddescr>IP Address</fielddescr> + <fieldname>ipaddress</fieldname> + <description>IP Address of remote server</description> + <type>input</type> + <size>20</size> + </rowhelperfield> + <rowhelperfield> + <fielddescr>Password</fielddescr> + <fieldname>password</fieldname> + <description>Password for remote server.</description> + <type>password</type> + <size>20</size> + </rowhelperfield> </rowhelper> </field> </fields> diff --git a/config/bind/bind_views.xml b/config/bind/bind_views.xml index 505f2b0d..7d38f481 100644 --- a/config/bind/bind_views.xml +++ b/config/bind/bind_views.xml @@ -2,8 +2,8 @@ <!DOCTYPE packagegui SYSTEM "./schema/packages.dtd"> <?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?> <packagegui> - <copyright> - <![CDATA[ + <copyright> + <![CDATA[ /* $Id$ */ /* ========================================================================== */ /* @@ -42,10 +42,10 @@ */ /* ========================================================================== */ ]]> - </copyright> - <description>Describe your package here</description> - <requirements>Describe your package requirements here</requirements> - <faq>Currently there are no FAQ items provided.</faq> + </copyright> + <description>Describe your package here</description> + <requirements>Describe your package requirements here</requirements> + <faq>Currently there are no FAQ items provided.</faq> <name>bindviews</name> <version>0.1.0</version> <title>Bind: Views Settings</title> @@ -56,29 +56,29 @@ <section>Services</section> <configfile>bind.xml</configfile> </menu> - <tabs> - <tab> - <text>Settings</text> - <url>/pkg_edit.php?xml=bind.xml</url> - </tab> - <tab> - <text>ACLs</text> - <url>/pkg.php?xml=bind_acls.xml</url> - </tab> - <tab> - <text>Views</text> - <url>/pkg.php?xml=bind_views.xml</url> - <active/> - </tab> - <tab> - <text>Zones</text> - <url>/pkg.php?xml=bind_zones.xml</url> - </tab> - <tab> - <text>Sync</text> - <url>/pkg_edit.php?xml=bind_sync.xml</url> - </tab> - </tabs> + <tabs> + <tab> + <text>Settings</text> + <url>/pkg_edit.php?xml=bind.xml</url> + </tab> + <tab> + <text>ACLs</text> + <url>/pkg.php?xml=bind_acls.xml</url> + </tab> + <tab> + <text>Views</text> + <url>/pkg.php?xml=bind_views.xml</url> + <active/> + </tab> + <tab> + <text>Zones</text> + <url>/pkg.php?xml=bind_zones.xml</url> + </tab> + <tab> + <text>Sync</text> + <url>/pkg_edit.php?xml=bind_sync.xml</url> + </tab> + </tabs> <configpath>['installedpackages']['bindviews']['config']</configpath> <adddeleteeditpagefields> <columnitem> @@ -106,19 +106,26 @@ <type>input</type> </field> <field> - <fielddescr>Recursion</fielddescr> - <fieldname>recursion</fieldname> - <description>A recursive query occurs when your DNS server is queried for a domain that it currently knows nothing about, in which case it will try to resolve the given host by performing further queries (eg by starting at the root servers and working out, or by simply passing the request to yet another DNS server).</description> - <type>select</type> - <options> - <option><name>No</name><value>no</value></option> - <option><name>Yes</name><value>yes</value></option> - </options> + <fielddescr>Recursion</fielddescr> + <fieldname>recursion</fieldname> + <description>A recursive query occurs when your DNS server is queried for a domain that it + currently knows nothing about, in which case it will try to resolve the given host by + performing further queries (eg by starting at the root servers and working out, or by + simply passing the request to yet another DNS server). + </description> + <type>select</type> + <options> + <option><name>No</name><value>no</value></option> + <option><name>Yes</name><value>yes</value></option> + </options> </field> <field> <fielddescr>Match-clients</fielddescr> <fieldname>match-clients</fieldname> - <description>If either or both of match-clients are missing they default to any (all hosts match). The match-clients statement defines the address_match_list for the source IP address of the incoming messages.</description> + <description>If either or both of match-clients are missing they default to any (all hosts + match). The match-clients statement defines the address_match_list for the source IP + address of the incoming messages. + </description> <type>select_source</type> <source><![CDATA[$config['installedpackages']['bindacls']['config']]]></source> <source_name>name</source_name> @@ -129,8 +136,10 @@ <field> <fielddescr>Allow-recursion</fielddescr> <fieldname>allow-recursion</fieldname> - <description>For example, if you have one DNS server serving your local network, you may want all of your local computers to use your DNS server.</description> - <type>select_source</type> + <description>For example, if you have one DNS server serving your local network, you may want + all of your local computers to use your DNS server. + </description> + <type>select_source</type> <source><![CDATA[$config['installedpackages']['bindacls']['config']]]></source> <source_name>name</source_name> <source_value>name</source_value> @@ -138,25 +147,26 @@ <size>03</size> </field> <field> - <type>listtopic</type> - <name>Custom Views </name> - <fieldname>temp</fieldname> - </field> - <field> - <fielddescr>Custom Options</fielddescr> - <fieldname>bind_custom_options</fieldname> - <description>You can put your own custom options here, separated by semi-colons (;).</description> - <type>textarea</type> - <cols>65</cols> - <rows>8</rows> - <encoding>base64</encoding> - </field> + <type>listtopic</type> + <name>Custom Views</name> + <fieldname>temp</fieldname> + </field> + <field> + <fielddescr>Custom Options</fielddescr> + <fieldname>bind_custom_options</fieldname> + <description>You can put your own custom options here, separated by semi-colons (;). + </description> + <type>textarea</type> + <cols>65</cols> + <rows>8</rows> + <encoding>base64</encoding> + </field> </fields> - <custom_php_command_before_form> - </custom_php_command_before_form> + <custom_php_command_before_form> + </custom_php_command_before_form> <custom_delete_php_command> - </custom_delete_php_command> - <custom_php_resync_config_command> - bind_sync(); - </custom_php_resync_config_command> + </custom_delete_php_command> + <custom_php_resync_config_command> + bind_sync(); + </custom_php_resync_config_command> </packagegui> diff --git a/config/bind/bind_zones.xml b/config/bind/bind_zones.xml index 1576cd79..a62c1aaf 100644 --- a/config/bind/bind_zones.xml +++ b/config/bind/bind_zones.xml @@ -2,8 +2,8 @@ <!DOCTYPE packagegui SYSTEM "./schema/packages.dtd"> <?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?> <packagegui> - <copyright> - <![CDATA[ + <copyright> + <![CDATA[ /* $Id$ */ /* ========================================================================== */ /* @@ -42,10 +42,10 @@ */ /* ========================================================================== */ ]]> - </copyright> - <description>Describe your package here</description> - <requirements>Describe your package requirements here</requirements> - <faq>Currently there are no FAQ items provided.</faq> + </copyright> + <description>Describe your package here</description> + <requirements>Describe your package requirements here</requirements> + <faq>Currently there are no FAQ items provided.</faq> <name>bindzone</name> <version>none</version> <title>BIND: Zones Settings</title> @@ -56,47 +56,47 @@ <section>Services</section> <configfile>bind.xml</configfile> </menu> - <tabs> - <tab> - <text>Settings</text> - <url>/pkg_edit.php?xml=bind.xml</url> - </tab> - <tab> - <text>ACLs</text> - <url>/pkg.php?xml=bind_acls.xml</url> - </tab> - <tab> - <text>Views</text> - <url>/pkg.php?xml=bind_views.xml</url> - </tab> - <tab> - <text>Zones</text> - <url>/pkg.php?xml=bind_zones.xml&id=0</url> - <active/> - </tab> - <tab> - <text>Sync</text> - <url>/pkg_edit.php?xml=bind_sync.xml</url> - </tab> - </tabs> + <tabs> + <tab> + <text>Settings</text> + <url>/pkg_edit.php?xml=bind.xml</url> + </tab> + <tab> + <text>ACLs</text> + <url>/pkg.php?xml=bind_acls.xml</url> + </tab> + <tab> + <text>Views</text> + <url>/pkg.php?xml=bind_views.xml</url> + </tab> + <tab> + <text>Zones</text> + <url>/pkg.php?xml=bind_zones.xml&id=0</url> + <active/> + </tab> + <tab> + <text>Sync</text> + <url>/pkg_edit.php?xml=bind_sync.xml</url> + </tab> + </tabs> <configpath>['installedpackages']['bindzone']['config']</configpath> <adddeleteeditpagefields> <columnitem> - <fielddescr>status</fielddescr> + <fielddescr>Status</fielddescr> <fieldname>disabled</fieldname> <listmodeon>Disabled</listmodeon> <listmodeoff>Enabled</listmodeoff> </columnitem> <columnitem> - <fielddescr>Zone Name</fielddescr> + <fielddescr>Name</fielddescr> <fieldname>name</fieldname> </columnitem> <columnitem> - <fielddescr>Zone Type</fielddescr> + <fielddescr>Type</fielddescr> <fieldname>type</fieldname> </columnitem> <columnitem> - <fielddescr>View Name</fielddescr> + <fielddescr>View(s)</fielddescr> <fieldname>view</fieldname> </columnitem> <columnitem> @@ -111,9 +111,9 @@ </adddeleteeditpagefields> <fields> <field> - <type>listtopic</type> - <name>Domain Zone Configuration</name> - <fieldname>temp01</fieldname> + <type>listtopic</type> + <name>Domain Zone Configuration</name> + <fieldname>temp01</fieldname> </field> <field> <fielddescr>Disable this zone</fielddescr> @@ -141,21 +141,21 @@ <fielddescr>Zone Type</fielddescr> <fieldname>type</fieldname> <description><![CDATA[Select zone type.]]></description> - <type>select</type> - <options> - <option><name>Master</name><value>master</value><enablefields>description</enablefields></option> - <option><name>Slave</name><value>slave</value><enablefields>ttl</enablefields></option> - <option><name>Forward</name><value>forward</value><enablefields>forward</enablefields></option> - <option><name>Redirect</name><value>redirect</value><enablefields>redirect</enablefields></option> - </options> - <onchange>on_type_zone_changed()</onchange> + <type>select</type> + <options> + <option><name>Master</name><value>master</value><enablefields>description</enablefields></option> + <option><name>Slave</name><value>slave</value><enablefields>ttl</enablefields></option> + <option><name>Forward</name><value>forward</value><enablefields>forward</enablefields></option> + <option><name>Redirect</name><value>redirect</value><enablefields>redirect</enablefields></option> + </options> + <onchange>on_type_zone_changed()</onchange> <required/> </field> <field> <fielddescr>View</fielddescr> <fieldname>view</fieldname> - <description><![CDATA[Select the View that this area will belong.]]></description> - <type>select_source</type> + <description><![CDATA[Select the View that this zone will belong.]]></description> + <type>select_source</type> <source><![CDATA[$config['installedpackages']['bindviews']['config']]]></source> <source_name>name</source_name> <source_value>name</source_value> @@ -204,20 +204,21 @@ <encoding>base64</encoding> </field> <field> - <type>listtopic</type> - <name>Slave Zone Configuration </name> - <fieldname>temp04</fieldname> + <type>listtopic</type> + <name>Slave Zone Configuration</name> + <fieldname>temp04</fieldname> </field> <field> <fielddescr>Master Zone IP</fielddescr> <fieldname>slaveip</fieldname> - <description>If this is a slave zone, enter the IP address of the master DNS server.</description> + <description>If this is a slave zone, enter the IP address of the master DNS server. + </description> <type>input</type> </field> <field> - <type>listtopic</type> - <name>Forward Zone Configuration </name> - <fieldname>temp04</fieldname> + <type>listtopic</type> + <name>Forward Zone Configuration</name> + <fieldname>temp04</fieldname> </field> <field> <fielddescr>Forwarders</fielddescr> @@ -228,14 +229,15 @@ </field> <field> - <type>listtopic</type> - <name>Master Zone Configuration </name> - <fieldname>temp03</fieldname> + <type>listtopic</type> + <name>Master Zone Configuration</name> + <fieldname>temp03</fieldname> </field> <field> <fielddescr>TLL</fielddescr> <fieldname>tll</fieldname> - <description>Default expiration time of all resource records without their own TTL value</description> + <description>Default expiration time of all resource records without their own TTL value + </description> <type>input</type> </field> <field> @@ -267,35 +269,35 @@ <fieldname>refresh</fieldname> <description>Slave refresh (1 day)</description> <type>input</type> - <default_value>1d</default_value> + <default_value>1d</default_value> </field> <field> <fielddescr>Retry</fielddescr> <fieldname>retry</fieldname> <description>Slave retry time in case of a problem (2 hours)</description> <type>input</type> - <default_value>2h</default_value> + <default_value>2h</default_value> </field> <field> <fielddescr>Expire</fielddescr> <fieldname>expire</fieldname> <description>Slave expiration time (4 weeks)</description> <type>input</type> - <default_value>4w</default_value> + <default_value>4w</default_value> </field> <field> <fielddescr>Minimum</fielddescr> <fieldname>minimum</fieldname> <description>Maximum caching time in case of failed lookups (1 hour)</description> <type>input</type> - <default_value>1h</default_value> + <default_value>1h</default_value> </field> <field> <fielddescr>Allow-update</fielddescr> <fieldname>allowupdate</fieldname> <description><![CDATA[Select(CTRL+click) who are allowed to send updates to this zone.<br> - Allow-update defines a match list eg IP address(es) that are allowed to submit dynamic updates for 'master' zones ie it enables Dynamic DNS (DDNS).]]></description> - <type>select_source</type> + Allow-update defines a match list eg IP address(es) that are allowed to submit dynamic updates for 'master' zones, ie it enables Dynamic DNS (DDNS).]]></description> + <type>select_source</type> <source><![CDATA[$config['installedpackages']['bindacls']['config']]]></source> <source_name>name</source_name> <source_value>name</source_value> @@ -306,7 +308,7 @@ <fielddescr>Allow-query</fielddescr> <fieldname>allowquery</fieldname> <description><![CDATA[Select(CTRL+click) who are allowed to query this zone.<br> - Allow-query defines an match list of IP address(es) which are allowed to issue queries to the server.]]></description> + Allow-query defines an match list of IP address(es) which are allowed to issue queries to the server.]]></description> <type>select_source</type> <source><![CDATA[$config['installedpackages']['bindacls']['config']]]></source> <source_name>name</source_name> @@ -319,7 +321,7 @@ <fieldname>allowtransfer</fieldname> <description><![CDATA[Select(CTRL+click) who are allowed to copy this zone.<br> Allow-transfer defines a match list eg IP address(es) that are allowed to transfer (copy) the zone information from the server (master or slave for the zone). While on its face this may seem an excessively friendly default, DNS data is essentially public (that's why its there) and the bad guys can get all of it anyway. However if the thought of anyone being able to transfer your precious zone file is repugnant, or (and this is far more significant) you are concerned about possible DoS attack initiated by XFER requests, then use the following policy.]]></description> - <type>select_source</type> + <type>select_source</type> <source><![CDATA[$config['installedpackages']['bindacls']['config']]]></source> <source_name>name</source_name> <source_value>name</source_value> @@ -327,69 +329,72 @@ <size>03</size> </field> <field> - <type>listtopic</type> - <name>Zone Domain records</name> - <fieldname>temp02</fieldname> - </field> - <field> - <fielddescr>Enter Domain records.</fielddescr> - <description><![CDATA[<b>"Record"</b> is the name or last octet of IP. Example: www or pop<br> - <b>"Type"</b> is the type of the record Sample: A CNAME MX NS<br> - <b>"Priority"</b> in used only in mx records to define its priority<br> - <b>"Alias or IP address"</b> is the destination host or ip address.<br><br> - You can order elements on this list with drag and drop between columns.]]></description> - <fieldname>none</fieldname> - <type>rowhelper</type> - <rowhelper> - <rowhelperfield> - <fielddescr>Record</fielddescr> - <fieldname>hostname</fieldname> - <description>Enter the Host Name (ex: www)</description> - <type>input</type> - <size>10</size> - </rowhelperfield> - <rowhelperfield> - <fielddescr>Type</fielddescr> - <fieldname>hosttype</fieldname> - <description>Select Type Host</description> - <type>select</type> - <options> - <option><name>A</name><value>A</value></option> - <option><name>AAAA</name><value>AAAA</value></option> - <option><name>DNAME</name><value>DNAME</value></option> - <option><name>MX</name><value>MX</value></option> - <option><name>CNAME</name><value>CNAME</value></option> - <option><name>NS</name><value>NS</value></option> - <option><name>LOC</name><value>LOC</value></option> - <option><name>SRV</name><value>SRV</value></option> - <option><name>PTR</name><value>PTR</value></option> - <option><name>TXT</name><value>TXT</value></option> - <option><name>SPF</name><value>SPF</value></option> - </options> - </rowhelperfield> - <rowhelperfield> - <fielddescr>Priority</fielddescr> - <fieldname>hostvalue</fieldname> - <description>MX 10 or 20</description> - <type>input</type> - <size>3</size> - </rowhelperfield> - <rowhelperfield> - <fielddescr>Alias or IP address</fielddescr> - <fieldname>hostdst</fieldname> - <description>Enter the IP address or FQDN destination for domain MX (ex: 10.31.11.1 or mail.example.com)</description> - <type>input</type> - <size>35</size> - </rowhelperfield> - <movable>on</movable> - </rowhelper> - </field> + <type>listtopic</type> + <name>Zone Domain records</name> + <fieldname>temp02</fieldname> + </field> + <field> + <fielddescr>Enter Domain records.</fielddescr> + <description><![CDATA[<b>"Record"</b> is the name or last octet of IP. Example: www or pop<br> + <b>"Type"</b> is the type of the record Sample: A CNAME MX NS<br> + <b>"Priority"</b> in used only in mx records to define its priority<br> + <b>"Alias or IP address"</b> is the destination host or ip address.<br><br> + You can order elements on this list with drag and drop between columns.]]></description> + <fieldname>none</fieldname> + <type>rowhelper</type> + <rowhelper> + <rowhelperfield> + <fielddescr>Record</fielddescr> + <fieldname>hostname</fieldname> + <description>Enter the Host Name (ex: www)</description> + <type>input</type> + <size>10</size> + </rowhelperfield> + <rowhelperfield> + <fielddescr>Type</fielddescr> + <fieldname>hosttype</fieldname> + <description>Select Type Host</description> + <type>select</type> + <options> + <option><name>A</name><value>A</value></option> + <option><name>AAAA</name><value>AAAA</value></option> + <option><name>DNAME</name><value>DNAME</value></option> + <option><name>MX</name><value>MX</value></option> + <option><name>CNAME</name><value>CNAME</value></option> + <option><name>NS</name><value>NS</value></option> + <option><name>LOC</name><value>LOC</value></option> + <option><name>SRV</name><value>SRV</value></option> + <option><name>PTR</name><value>PTR</value></option> + <option><name>TXT</name><value>TXT</value></option> + <option><name>SPF</name><value>SPF</value></option> + </options> + </rowhelperfield> + <rowhelperfield> + <fielddescr>Priority</fielddescr> + <fieldname>hostvalue</fieldname> + <description>MX 10 or 20</description> + <type>input</type> + <size>3</size> + </rowhelperfield> + <rowhelperfield> + <fielddescr>Alias or IP address</fielddescr> + <fieldname>hostdst</fieldname> + <description>Enter the IP address or FQDN destination for domain MX (ex: 10.31.11.1 or mail.example.com) + </description> + <type>input</type> + <size>35</size> + </rowhelperfield> + <movable>on</movable> + </rowhelper> + </field> <field> <fieldname>regdhcpstatic</fieldname> <fielddescr>Register DHCP static mappings</fielddescr> - <description>If this option is set, then DHCP static mappings will be registered in DNS, so that their name can be resolved.</description> + <description>If this option is set, then DHCP static mappings will be registered in DNS, so that + their name can be resolved. + </description> <type>checkbox</type> - </field> + </field> <field> <type>listtopic</type> <name>Custom Zone Domain records</name> @@ -399,13 +404,13 @@ <fielddescr></fielddescr> <fieldname>customzonerecords</fieldname> <description><![CDATA[Paste any custom zone records to include in this zone.<br> - This can be used for a fast migration setup.]]></description> - <type>textarea</type> - <cols>84</cols> - <rows>10</rows> - <encoding>base64</encoding> - <dontdisplayname/> - <usecolspan2/> + This can be used for a fast migration setup.]]></description> + <type>textarea</type> + <cols>84</cols> + <rows>10</rows> + <encoding>base64</encoding> + <dontdisplayname/> + <usecolspan2/> </field> <field> <type>listtopic</type> @@ -415,31 +420,32 @@ <fielddescr></fielddescr> <fieldname>resultconfig</fieldname> <description>Resulting BIND config file for this zone.</description> - <type>textarea</type> - <cols>84</cols> - <rows>15</rows> - <encoding>base64</encoding> - <dontdisplayname/> - <usecolspan2/> + <type>textarea</type> + <cols>84</cols> + <rows>15</rows> + <encoding>base64</encoding> + <dontdisplayname/> + <usecolspan2/> </field> </fields> - <custom_php_after_form_command> - bind_print_javascript_type_zone2(); - </custom_php_after_form_command> - <custom_php_after_head_command> - bind_print_javascript_type_zone(); - </custom_php_after_head_command> - <custom_php_command_before_form> - </custom_php_command_before_form> + <custom_php_after_form_command> + bind_print_javascript_type_zone2(); + </custom_php_after_form_command> + <custom_php_after_head_command> + bind_print_javascript_type_zone(); + </custom_php_after_head_command> + <custom_php_command_before_form> + </custom_php_command_before_form> <custom_php_validation_command> - if ($_POST['type']=="master" and $_POST['serial']=="") + if ($_POST['type']=="master" and $_POST['serial']=="") { $_POST['serial']=(date("U")+ 1000000000); + } bind_zone_validate($_POST, $input_errors); </custom_php_validation_command> <custom_delete_php_command> - bind_sync(); - </custom_delete_php_command> - <custom_php_resync_config_command> - bind_sync(); - </custom_php_resync_config_command> + bind_sync(); + </custom_delete_php_command> + <custom_php_resync_config_command> + bind_sync(); + </custom_php_resync_config_command> </packagegui> diff --git a/config/freeradius2/freeradius.inc b/config/freeradius2/freeradius.inc index df231821..00076816 100644 --- a/config/freeradius2/freeradius.inc +++ b/config/freeradius2/freeradius.inc @@ -134,7 +134,42 @@ function freeradius_install_command() { $rcfile = array(); $rcfile['file'] = 'radiusd.sh'; - $rcfile['start'] = FREERADIUS_ETC . '/rc.d/radiusd onestart'; + $freeradius_etc_dir = FREERADIUS_ETC; + $rcfile['start'] = <<<EOD +SERVICENAME="radiusd" + LOCKFILE="/tmp/\${SERVICENAME}_start.lock" + PIDFILE="/var/run/\${SERVICENAME}.pid" + + # prevent this part of script from running in parallel + if ( set -o noclobber; echo "\$\$" > "\$LOCKFILE") 2> /dev/null; then + # make sure lock file is removed even if script is terminated + trap 'rm -f "\$LOCKFILE"; exit \$?' INT TERM EXIT + + {$freeradius_etc_dir}/rc.d/radiusd onestart + + # try to wait until the service starts + if [ ! -f "\$PIDFILE" ]; then + echo "\$SERVICENAME.sh: PID file was not found" + + for i in 1 2 3 4 5; do + if [ -f "\$PIDFILE" ]; then + echo "\$SERVICENAME.sh: Service started PID: `cat \$PIDFILE`" + break + else + echo "\$SERVICENAME.sh: Waiting 0.5 seconds" + sleep 0.5 + fi + done + else + echo "\$SERVICENAME.sh: Service running PID: `cat \$PIDFILE`" + fi + + rm -f "\$LOCKFILE" + trap - INT TERM EXIT + else + echo "\$SERVICENAME.sh: Cannot continue at this moment, this script is already trying to start service PID: \$(cat \$LOCKFILE)" + fi +EOD; $rcfile['stop'] = FREERADIUS_ETC . '/rc.d/radiusd onestop'; write_rcfile($rcfile); conf_mount_ro(); diff --git a/config/freeradius2/freeradiussettings.xml b/config/freeradius2/freeradiussettings.xml index 78c65372..8982d93e 100644 --- a/config/freeradius2/freeradiussettings.xml +++ b/config/freeradius2/freeradiussettings.xml @@ -183,9 +183,9 @@ </options> </field> <field> - <fielddescr>Log Bad Authentication Attempts</fielddescr> + <fielddescr>Log Password on Authentication Failure</fielddescr> <fieldname>varsettingsauthbadpass</fieldname> - <description><![CDATA[If an authentication fails then it will log the username and <b>wrong</b> password visible in syslog. Logging must be enabled. (Default: no)]]></description> + <description><![CDATA[Log the <b>password</b> of failed authentication attempts to syslog. Not recommended for security reasons. Logging must be enabled. (Default: no)]]></description> <type>select</type> <default_value>no</default_value> <options> @@ -204,9 +204,9 @@ <size>80</size> </field> <field> - <fielddescr>Log good authentication attempts?</fielddescr> + <fielddescr>Log Password on Authentication Success</fielddescr> <fieldname>varsettingsauthgoodpass</fieldname> - <description><![CDATA[If an authentication succeeds then it will log the username and <b>correct</b> password visible in syslog. Logging must be enabled. (Default: no)]]></description> + <description><![CDATA[Log the <b>password</b> of successful authentication attempts to syslog. Not recommended for security reasons. Logging must be enabled. (Default: no)]]></description> <type>select</type> <default_value>no</default_value> <options> diff --git a/config/ftpproxy/ftpproxy.inc b/config/ftpproxy/ftpproxy.inc new file mode 100644 index 00000000..7fc54775 --- /dev/null +++ b/config/ftpproxy/ftpproxy.inc @@ -0,0 +1,147 @@ +<?php +function sync_package_ftpproxy() { + conf_mount_rw(); + config_lock(); + global $config; + $cf = $config['installedpackages']['ftpclientproxy']['config'][0]; + + /* Proxy is not enabled, kill the daemon and issue a filter reload. */ + if ($cf["proxy_enable"] != "on") { + mwexec("/usr/bin/killall -9 ftp-proxy"); + filter_configure(); + return; + } + $interface_list = explode(",", $cf['localints']); + /* Bail if there is nothing to do */ + if (empty($interface_list)) { + log_error("FTP Proxy cannot sync: No interfaces selected."); + return; + } + + $start = "/usr/bin/killall -9 ftp-proxy\n"; + $start .= "\t/usr/sbin/ftp-proxy "; + + if ($cf["anononly"] == "on") { + $start .= " -A "; + } + if (is_ipaddr($cf["sourceaddr"])) { + $start .= " -a " . escapeshellarg($cf["sourceaddr"]); + } + if (is_port($cf["bindport"])) { + $start .= " -p " . escapeshellarg($cf["bindport"]); + } + if (is_numeric($cf["maxessions"]) && ($cf["maxessions"] >= 1) && ($cf["maxessions"] <= 500)) { + $start .= " -m " . escapeshellarg($cf["maxessions"]); + } + if (!empty($cf["tsq"])) { + $start .= " -q " . escapeshellarg($cf["tsq"]); + } + if ($cf["src20"] == "on") { + $start .= " -r "; + } + if (is_numeric($cf["idletimeout"]) && ($cf["idletimeout"] > 0) && ($cf["idletimeout"] <= 86400)) { + $start .= " -t " . escapeshellarg($cf["idletimeout"]); + } + if ($cf["log"] == "on") { + $start .= " -v "; + } + $start .= "\n"; + + write_rcfile(array( + "file" => "ftp-proxy.sh", + "start" => $start, + "stop" => "/usr/bin/killall -9 ftp-proxy" + ) + ); + restart_service("ftp-proxy"); + conf_mount_ro(); + config_unlock(); + filter_configure(); +} + +function validate_form_ftpproxy($post, &$input_errors) { + if (empty($post["localints"])) { + $input_errors[] = 'One or more Local Interfaces must be selected'; + } + if (!empty($post["sourceaddr"]) && !is_ipaddr($post["sourceaddr"])) { + $input_errors[] = 'You must specify a valid ip address in the \'Source Address\' field'; + } + if (!empty($post["bindport"]) && !is_port($post["bindport"])) { + $input_errors[] = 'You must specify a valid port number in the \'Bind Port\' field'; + } + if (!empty($post["maxessions"]) && (!is_numeric($post["maxessions"]) || ($post["maxessions"] < 1) || ($post["maxessions"] > 500))) { + $input_errors[] = 'You must specify a valid number in the \'Max Sessions\' field (Between 1 and 500)'; + } + if (!empty($post["idletimeout"]) && (is_numeric($post["idletimeout"]) || ($post["idletimeout"] <= 0) || ($post["idletimeout"] > 86400))) { + $input_errors[] = 'You must specify a valid number in the \'Idle Timeout\' field (Between 1 and 86400)'; + } + if (!empty($post["bypasssrc"]) && !(is_alias($post["bypasssrc"]) || is_subnetv4($post["bypasssrc"]) || is_ipaddr($post["bypasssrc"]))) { + $input_errors[] = 'You must specify a valid IP address or alias for Proxy Bypass: Source'; + } + if (!empty($post["bypassdst"]) && !(is_alias($post["bypassdst"]) || is_subnetv4($post["bypassdst"]) || is_ipaddr($post["bypassdst"]))) { + $input_errors[] = 'You must specify a valid IP address or alias for Proxy Bypass: Destination'; + } +} + +function ftpproxy_get_port() { + global $config; + $cf = $config['installedpackages']['ftpclientproxy']['config'][0]; + if (!empty($cf["bindport"]) && is_port($cf["bindport"])) { + return $cf["bindport"]; + } else { + return 8021; + } +} + +function ftpproxy_generate_rules($type) { + global $config; + $cf = $config['installedpackages']['ftpclientproxy']['config'][0]; + $interface_list = explode(",", $cf['localints']); + + /* Proxy is not enabled, therefore, no rules/anchors. */ + if ($cf["proxy_enable"] != "on") { + return; + } + + /* Bail if there is nothing to do */ + if (empty($interface_list)) { + log_error("FTP Proxy cannot sync: No interfaces selected."); + return; + } + + $rules = ""; + switch ($type) { + case "nat": + $rules .= "nat-anchor \"ftp-proxy/*\"\n"; + $rules .= "rdr-anchor \"ftp-proxy/*\"\n"; + + foreach ($interface_list as $interface_friendly) { + if (empty($interface_friendly)) { + continue; + } + $interface = get_real_interface($interface_friendly); + if (empty($interface)) { + continue; + } + if (is_subnetv4($cf["bypasssrc"]) || is_ipaddr($cf["bypasssrc"])) { + $rules .= "no rdr on {$interface} inet proto tcp from {$cf['bypasssrc']} to any port 21\n"; + } elseif (is_alias($cf["bypasssrc"])) { + $rules .= "no rdr on {$interface} inet proto tcp from \${$cf['bypasssrc']} to any port 21\n"; + } + if (is_subnetv4($cf["bypassdst"]) || is_ipaddr($cf["bypassdst"])) { + $rules .= "no rdr on {$interface} inet proto tcp from any to {$cf['bypassdst']} port 21\n"; + } elseif (is_alias($cf["bypassdst"])) { + $rules .= "no rdr on {$interface} inet proto tcp from any to \${$cf['bypassdst']} port 21\n"; + } + $rules .= "rdr pass on {$interface} inet proto tcp from any to any port 21 -> 127.0.0.1 port " . ftpproxy_get_port() . "\n"; + } + break; + case "filter": + $rules .= "anchor \"ftp-proxy/*\"\n"; + // $rules = "pass out proto tcp from any to any port 21\n"; + break; + + } + return $rules; +} +?>
\ No newline at end of file diff --git a/config/ftpproxy/ftpproxy.xml b/config/ftpproxy/ftpproxy.xml new file mode 100644 index 00000000..5bd123dc --- /dev/null +++ b/config/ftpproxy/ftpproxy.xml @@ -0,0 +1,116 @@ +<packagegui> + <name>FTP Client Proxy</name> + <version>0.2</version> + <title>FTP Client Proxy</title> + <aftersaveredirect>pkg_edit.php?xml=ftpproxy.xml</aftersaveredirect> + <include_file>/usr/local/pkg/ftpproxy.inc</include_file> + <additional_files_needed> + <prefix>/usr/local/pkg/</prefix> + <chmod>077</chmod> + <item>https://packages.pfsense.org/packages/config/ftpproxy/ftpproxy.inc</item> + </additional_files_needed> + <menu> + <name>FTP Client Proxy</name> + <tooltiptext>Modify FTP Client Proxy settings.</tooltiptext> + <section>Services</section> + <configfile>ftpproxy.xml</configfile> + <url>/pkg_edit.php?xml=ftpproxy.xml</url> + </menu> + <service> + <name>ftp-proxy</name> + <rcfile>ftp-proxy.sh</rcfile> + <executable>ftp-proxy</executable> + <description>Client FTP Proxy Daemon</description> + </service> + <fields> + <field> + <name>General Settings</name> + <type>listtopic</type> + </field> + <field> + <fielddescr>Proxy Enabled</fielddescr> + <fieldname>proxy_enable</fieldname> + <description>Enable the FTP Proxy.</description> + <type>checkbox</type> + <default_value>off</default_value> + </field> + <field> + <fielddescr>Local Interface</fielddescr> + <fieldname>localints</fieldname> + <type>interfaces_selection</type> + <description>Select the local (LAN type) interfaces which contain FTP clients.</description> + <required/> + <multiple/> + </field> + <field> + <fielddescr>Anonymous Only</fielddescr> + <fieldname>anononly</fieldname> + <description>Only permit anonymous FTP connections using the "ftp" or "anonymous" users.</description> + <type>checkbox</type> + <default_value>off</default_value> + </field> + <field> + <fielddescr>Source Address</fielddescr> + <fieldname>sourceaddr</fieldname> + <description>Enter a VIP to be the source of outgoing control traffic. Leave blank to use the default WAN IP address.</description> + <type>input</type> + </field> + <field> + <fielddescr>Proxy Bypass: Source</fielddescr> + <fieldname>bypasssrc</fieldname> + <description>Enter an IP address or alias for source client host(s) which should bypass the proxy.</description> + <type>input</type> + </field> + <field> + <fielddescr>Proxy Bypass: Destination</fielddescr> + <fieldname>bypassdst</fieldname> + <description>Enter an IP address or alias for destination server host(s) which should bypass the proxy.</description> + <type>input</type> + </field> + <field> + <fielddescr>Bind Port (Default: 8021)</fielddescr> + <fieldname>bindport</fieldname> + <description>Port where the proxy will listen for redirected connections. Do not set this to 21.</description> + <type>input</type> + </field> + <field> + <fielddescr>Maximum Sessions (Default: 100)</fielddescr> + <fieldname>maxessions</fieldname> + <description>Maximum number of concurrent FTP sessions. When the proxy reaches this limit, new connections are denied. Must be between 1 and 500.</description> + <type>input</type> + </field> + <field> + <fielddescr>Traffic Shaping Queue</fielddescr> + <fieldname>tsq</fieldname> + <description>Create rules with the specified queue appended so that data connections can be queued.</description> + <type>input</type> + </field> + <field> + <fielddescr>Rewrite Source to Port 20</fielddescr> + <fieldname>src20</fieldname> + <description>Rewrite source port to 20 in active mode to suit ancient clients that insist on this behavior.</description> + <type>checkbox</type> + <default_value>off</default_value> + </field> + <field> + <fielddescr>Idle Timeout (Default: 86400)</fielddescr> + <fieldname>idletimeout</fieldname> + <description>(Seconds) Number of seconds that the control connection can be idle, before the proxy will disconnect. The maximum is 86400 seconds. Do not set this too low, because the control connection is usually idle when large data transfers are taking place.</description> + <type>input</type> + </field> + <field> + <fielddescr>Log Connections</fielddescr> + <fieldname>log</fieldname> + <description>Set the 'log' flag on pf rules committed by ftp-proxy.</description> + <type>checkbox</type> + <default_value>off</default_value> + </field> + + </fields> + <custom_php_resync_config_command> + sync_package_ftpproxy(); + </custom_php_resync_config_command> + <custom_php_validation_command> + validate_form_ftpproxy($_POST, $input_errors); + </custom_php_validation_command> +</packagegui> diff --git a/config/haproxy-devel/pkg/haproxy.inc b/config/haproxy-devel/pkg/haproxy.inc index 15fbcd17..135f2d4f 100644 --- a/config/haproxy-devel/pkg/haproxy.inc +++ b/config/haproxy-devel/pkg/haproxy.inc @@ -1087,16 +1087,6 @@ function haproxy_writeconf($configpath) { fwrite ($fd, "\tbind /tmp/haproxy_chroot/{$bind['name']}.socket name unixsocket accept-proxy {$ssl_info} {$advanced_bind}\n"); } - // Advanced pass thru - if($bind['advanced']) { - $advanced = explode("\n", base64_decode($bind['advanced'])); - foreach($advanced as $adv_line) { - if ($adv_line != "") { - fwrite($fd, "\t" . str_replace("\r", "", $adv_line) . "\n"); - } - } - } - // https is an alias for tcp for clarity purposes if($bind['type'] == "https") { $backend_type = "tcp"; @@ -1142,6 +1132,16 @@ function haproxy_writeconf($configpath) { fwrite ($fd, "\ttimeout client\t\t" . $bind['client_timeout'] . "\n"); + + // Advanced pass thru + if($bind['advanced']) { + $advanced = explode("\n", base64_decode($bind['advanced'])); + foreach($advanced as $adv_line) { + if ($adv_line != "") { + fwrite($fd, "\t" . str_replace("\r", "", $adv_line) . "\n"); + } + } + } // Combine the rest of the frontend configs $default_backend = ""; @@ -1302,7 +1302,7 @@ function haproxy_writeconf($configpath) { } if ($inspectdelay > 0) - fwrite ($fd, "\ttcp-request inspect-delay\t" . $inspectdelay . "\n"); + fwrite ($fd, "\ttcp-request inspect-delay\t" . $inspectdelay . "s\n"); // Write acl's first, so they may be used by advanced text options written by user. fwrite ($fd, $config_acls); @@ -1897,9 +1897,9 @@ function get_frontend_acls($frontend) { // Filter out acls for different modes if ($acl['mode'] != '' && $acl['mode'] != strtolower($mainfrontend['type'])) continue; - $not = $entry['not'] == "yes" ? "not " : ""; + $not = $entry['not'] == "yes" ? "not: " : ""; $acl_item = array(); - $acl_item['descr'] = $acl['name'] . " " . (isset($acl['novalue']) ? "" : $entry['value']); + $acl_item['descr'] = $acl['name'] . " " . (isset($acl['novalue']) ? "" : $not . $entry['value']); $acl_item['ref'] = $entry; $result[] = $acl_item; diff --git a/config/haproxy-devel/pkg/haproxy_utils.inc b/config/haproxy-devel/pkg/haproxy_utils.inc index 4b945c06..d8c4faf4 100644 --- a/config/haproxy-devel/pkg/haproxy_utils.inc +++ b/config/haproxy-devel/pkg/haproxy_utils.inc @@ -354,7 +354,7 @@ function haproxy_get_certificates($type = 'server,user', $get_includeWebCert=fal $ok |= stristr($type,',user,') && $purpose['server'] != 'Yes'; if (!$ok) continue; - if ($get_includeWebCert == false && is_webgui_cert($cert['refid'])) + if ($get_includeWebCert == false && $cert['descr'] == "webConfigurator default") continue; $certificates[$cert['refid']]['name'] = haproxy_get_certificate_descriptivename($cert); } diff --git a/config/haproxy1_5/haproxy.xml b/config/haproxy1_5/haproxy.xml new file mode 100644 index 00000000..7468b211 --- /dev/null +++ b/config/haproxy1_5/haproxy.xml @@ -0,0 +1,180 @@ +<?xml version="1.0" encoding="utf-8" ?> +<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd"> +<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?> +<packagegui> + <copyright> + <![CDATA[ +/* $Id$ */ +/* ========================================================================== */ +/* + haproxy.xml + part of pfSense (http://www.pfSense.com) + Copyright (C) 2009 Scott Ullrich + 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. + */ +/* ========================================================================== */ + ]]> + </copyright> + <description>Describe your package here</description> + <requirements>Describe your package requirements here</requirements> + <faq>Currently there are no FAQ items provided.</faq> + <name>haproxy</name> + <version>1.0</version> + <title>HAProxy</title> + <aftersaveredirect>/pkg_edit.php?xml=haproxy_pools.php</aftersaveredirect> + <include_file>/usr/local/pkg/haproxy.inc</include_file> + <menu> + <name>HAProxy</name> + <tooltiptext></tooltiptext> + <section>Services</section> + <url>/haproxy_listeners.php</url> + </menu> + <menu> + <name>HAProxy Stats</name> + <tooltiptext>Stats of HAProxy</tooltiptext> + <section>Status</section> + <url>/haproxy_stats.php?haproxystats=1</url> + </menu> + <service> + <name>HAProxy</name> + <rcfile>haproxy.sh</rcfile> + <executable>haproxy</executable> + <description>The Reliable, High Performance TCP/HTTP Load Balancer</description> + </service> + <plugins> + <item> + <type>plugin_carp</type> + </item> + <item> + <type>plugin_certificates</type> + </item> + </plugins> + <configpath>installedpackages->haproxy->config</configpath> + <additional_files_needed> + <prefix>/usr/local/pkg/</prefix> + <chmod>077</chmod> + <item>https://packages.pfsense.org/packages/config/haproxy1_5/pkg/haproxy.inc</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/www/</prefix> + <chmod>077</chmod> + <item>https://packages.pfsense.org/packages/config/haproxy1_5/www/haproxy_listeners.php</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/www/</prefix> + <chmod>077</chmod> + <item>https://packages.pfsense.org/packages/config/haproxy1_5/www/haproxy_listeners_edit.php</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/www/</prefix> + <chmod>077</chmod> + <item>https://packages.pfsense.org/packages/config/haproxy1_5/www/haproxy_global.php</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/www/</prefix> + <chmod>077</chmod> + <item>https://packages.pfsense.org/packages/config/haproxy1_5/www/haproxy_files.php</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/www/</prefix> + <chmod>077</chmod> + <item>https://packages.pfsense.org/packages/config/haproxy1_5/www/haproxy_pools.php</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/www/</prefix> + <chmod>077</chmod> + <item>https://packages.pfsense.org/packages/config/haproxy1_5/www/haproxy_pool_edit.php</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/www/</prefix> + <chmod>077</chmod> + <item>https://packages.pfsense.org/packages/config/haproxy1_5/www/haproxy_stats.php</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/www/</prefix> + <chmod>077</chmod> + <item>https://packages.pfsense.org/packages/config/haproxy1_5/www/haproxy_templates.php</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/pkg/</prefix> + <chmod>077</chmod> + <item>https://packages.pfsense.org/packages/config/haproxy1_5/pkg/haproxy_socketinfo.inc</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/pkg/</prefix> + <chmod>077</chmod> + <item>https://packages.pfsense.org/packages/config/haproxy1_5/pkg/haproxy_xmlrpcsyncclient.inc</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/pkg/</prefix> + <chmod>077</chmod> + <item>https://packages.pfsense.org/packages/config/haproxy1_5/pkg/haproxy_htmllist.inc</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/pkg/</prefix> + <chmod>077</chmod> + <item>https://packages.pfsense.org/packages/config/haproxy1_5/pkg/haproxy_utils.inc</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/www/widgets/widgets/</prefix> + <chmod>077</chmod> + <item>https://packages.pfsense.org/packages/config/haproxy1_5/www/widgets/widgets/haproxy.widget.php</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/www/shortcuts/</prefix> + <chmod>0755</chmod> + <item>https://packages.pfsense.org/packages/config/haproxy1_5/www/shortcuts/pkg_haproxy.inc</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/pkg/</prefix> + <chmod>077</chmod> + <item>https://packages.pfsense.org/packages/config/haproxy1_5/pkg/pkg_haproxy_tabs.inc</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/pkg/</prefix> + <chmod>077</chmod> + <item>https://packages.pfsense.org/packages/config/haproxy1_5/pkg/haproxy_upgrade_config.inc</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/www/javascript/</prefix> + <chmod>077</chmod> + <item>https://packages.pfsense.org/packages/config/haproxy1_5/www/javascript/haproxy_geturl.js</item> + </additional_files_needed> + <custom_delete_php_command> + </custom_delete_php_command> + <custom_add_php_command> + </custom_add_php_command> + <custom_php_resync_config_command> + </custom_php_resync_config_command> + <custom_php_install_command> + haproxy_custom_php_install_command(); + </custom_php_install_command> + <custom_php_deinstall_command> + haproxy_custom_php_deinstall_command(); + </custom_php_deinstall_command> + <custom_php_command_before_form> + </custom_php_command_before_form> +</packagegui> diff --git a/config/haproxy1_5/pkg/haproxy.inc b/config/haproxy1_5/pkg/haproxy.inc new file mode 100644 index 00000000..135f2d4f --- /dev/null +++ b/config/haproxy1_5/pkg/haproxy.inc @@ -0,0 +1,2006 @@ +<?php +/* + haproxy.inc + Copyright (C) 2013-2015 PiBa-NL + Copyright (C) 2009 Scott Ullrich <sullrich@pfsense.com> + Copyright (C) 2008 Remco Hoef + 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. +*/ + +/* include all configuration functions */ +require_once("functions.inc"); +require_once("pkg-utils.inc"); +require_once("notices.inc"); +require_once("filter.inc"); +require_once("haproxy_utils.inc"); +require_once("haproxy_xmlrpcsyncclient.inc"); + +$d_haproxyconfdirty_path = $g['varrun_path'] . "/haproxy.conf.dirty"; + +global $a_frontendmode; +$a_frontendmode = array(); +$a_frontendmode['http'] = array('name' => "http / https(offloading)", 'shortname' => "http/https"); +$a_frontendmode['https'] = array('name' => "ssl / https(TCP mode)", 'shortname' => "ssl/https"); +$a_frontendmode['tcp'] = array('name' => "tcp", 'shortname' => "tcp"); +$a_frontendmode['health'] = array('name' => "health", 'shortname' => "health"); + +global $a_acltypes; +$a_acltypes = array(); +$a_acltypes["host_starts_with"] = array('name' => 'Host starts with:', + 'mode' => 'http', 'syntax' => 'hdr_beg(host) -i %1$s'); +$a_acltypes["host_ends_with"] = array('name' => 'Host ends with:', + 'mode' =>'http', 'syntax' => 'hdr_end(host) -i %1$s'); +$a_acltypes["host_matches"] = array('name' => 'Host matches:', + 'mode' =>'http', 'syntax' => 'hdr(host) -i %1$s'); +$a_acltypes["host_regex"] = array('name' => 'Host regex:', + 'mode' =>'http', 'syntax' => 'hdr_reg(host) -i %1$s'); +$a_acltypes["host_contains"] = array('name' => 'Host contains:', + 'mode' => 'http', 'syntax' => 'hdr_dir(host) -i %1$s'); +$a_acltypes["path_starts_with"] = array('name' => 'Path starts with:', + 'mode' => 'http', 'syntax' => 'path_beg -i %1$s'); +$a_acltypes["path_ends_with"] = array('name' => 'Path ends with:', + 'mode' => 'http', 'syntax' => 'path_end -i %1$s'); +$a_acltypes["path_matches"] = array('name' => 'Path matches:', + 'mode' => 'http', 'syntax' => 'path -i %1$s'); +$a_acltypes["path_regex"] = array('name' => 'Path regex:', + 'mode' => 'http', 'syntax' => 'path_reg -i %1$s'); +$a_acltypes["path_contains"] = array('name' => 'Path contains:', + 'mode' => 'http', 'syntax' => 'path_dir -i %1$s'); +$a_acltypes["ssl_c_verify_code"] = array('name' => 'SSL Client certificate verify error result:', + 'mode' => 'http', 'syntax' => 'ssl_c_verify %1$s', 'require_client_cert' => '1'); + // ssl_c_verify result codes: https://www.openssl.org/docs/apps/verify.html#DIAGNOSTICS +$a_acltypes["ssl_c_verify"] = array('name' => 'SSL Client certificate valid.', + 'mode' => 'http', 'syntax' => 'ssl_c_verify 0', 'novalue' => '1', 'require_client_cert' => '1'); +$a_acltypes["ssl_c_ca_commonname"] = array('name' => 'SSL Client issued by CA common-name:', + 'mode' => 'http', 'syntax' => 'ssl_c_i_dn(CN) %1$s', 'require_client_cert' => '1'); +$a_acltypes["source_ip"] = array('name' => 'Source IP matches IP or Alias:', + 'mode' => '', 'syntax' => 'src %1$s'); +$a_acltypes["backendservercount"] = array('name' => 'Minimum count usable servers:', + 'mode' => '', 'syntax' => 'nbsrv(%2$s) ge %1$d', 'parameters' => 'value,backendname'); +$a_acltypes["traffic_is_http"] = array('name' => 'Traffic is http (no value needed):', 'inspect-delay' => '5', + 'mode' => 'tcp', 'syntax' => 'req.proto_http', 'advancedoptions' => "tcp-request content accept if { req.proto_http }"); +$a_acltypes["traffic_is_ssl"] = array('name' => 'Traffic is ssl (no value needed):', 'inspect-delay' => '5', + 'mode' => 'tcp', 'syntax' => 'req.ssl_ver gt 0', 'advancedoptions' => "tcp-request content accept if { req.ssl_ver gt 0 }"); +// 'ssl_sni_matches' was added in HAProxy1.5dev17 +$a_acltypes["ssl_sni_matches"] = array('name' => 'Server Name Indication TLS extension matches:', 'inspect-delay' => '5', + 'mode' => 'https', 'syntax' => 'req.ssl_sni -i %1$s', 'advancedoptions' => "tcp-request content accept if { req.ssl_hello_type 1 }"); +$a_acltypes["ssl_sni_contains"] = array('name' => 'Server Name Indication TLS extension contains:', 'inspect-delay' => '5', + 'mode' => 'https', 'syntax' => 'req.ssl_sni -m sub -i %1$s', 'advancedoptions' => "tcp-request content accept if { req.ssl_hello_type 1 }"); +$a_acltypes["ssl_sni_starts_with"] = array('name' => 'Server Name Indication TLS extension starts with:', 'inspect-delay' => '5', + 'mode' => 'https', 'syntax' => 'req.ssl_sni -m beg -i %1$s', 'advancedoptions' => "tcp-request content accept if { req.ssl_hello_type 1 }"); +$a_acltypes["ssl_sni_ends_with"] = array('name' => 'Server Name Indication TLS extension ends with:', 'inspect-delay' => '5', + 'mode' => 'https', 'syntax' => 'req.ssl_sni -m end -i %1$s', 'advancedoptions' => "tcp-request content accept if { req.ssl_hello_type 1 }"); +$a_acltypes["ssl_sni_regex"] = array('name' => 'Server Name Indication TLS extension regex:', 'inspect-delay' => '5', + 'mode' => 'https', 'syntax' => 'req.ssl_sni -m reg -i %1$s', 'advancedoptions' => "tcp-request content accept if { req.ssl_hello_type 1 }"); +$a_acltypes["custom"] = array('name' => 'Custom acl:', + 'mode' => '', 'syntax' => '%1$s'); + +global $a_checktypes; +$a_checktypes = array(); +$a_checktypes['none'] = array('name' => 'none', 'syntax' => '', + 'descr' => 'No health checks will be performed.'); +$a_checktypes['Basic'] = array('name' => 'Basic', 'syntax' => '', + 'descr' => 'Basic socket connection check'); +$a_checktypes['HTTP'] = array('name' => 'HTTP', 'syntax' => 'httpchk', + 'descr' => 'HTTP protocol to check on the servers health, can also be used for HTTPS servers(requirs checking the SSL box for the servers).', 'parameters' => "uri,method,version"); +// 'Agent' was added in HAProxy1.5dev18, and removed in 1.5dev20, in favor of the seperate agent-check option. +$a_checktypes['Agent'] = array('name' => 'Agent', 'syntax' => 'lb-agent-chk', 'usedifferenport' => 'yes', + 'descr' => 'Use a TCP connection to read an ASCII string of the form 100%,75%,drain,down (others in haproxy manual)', + 'deprecated' => true); +$a_checktypes['LDAP'] = array('name' => 'LDAP', 'syntax' => 'ldap-check', + 'descr' => 'Use LDAPv3 health checks for server testing'); +$a_checktypes['MySQL'] = array('name' => 'MySQL', 'syntax' => 'mysql-check', + 'descr' => 'Use MySQL health checks for server testing', 'parameters' => 'username'); +$a_checktypes['PostgreSQL'] = array('name' => 'PostgreSQL', 'syntax' => 'pgsql-check', + 'descr' => 'Use PostgreSQL health checks for server testing', 'parameters' => 'username'); +$a_checktypes['Redis'] = array('name' => 'Redis', 'syntax' => 'redis-check', + 'descr' => 'Test that the server correctly talks REDIS protocol.'); +$a_checktypes['SMTP'] = array('name' => 'SMTP', 'syntax' => 'smtpchk HELO', + 'descr' => 'Use SMTP HELO health checks for server testing', 'parameters' => 'domain'); +$a_checktypes['ESMTP'] = array('name' => 'ESMTP', 'syntax' => 'smtpchk EHLO', + 'descr' => 'Use ESMTP EHLO health checks for server testing', 'parameters' => 'domain'); +$a_checktypes['SSL'] = array('name' => 'SSL', 'syntax' => 'ssl-hello-chk', + 'descr' => 'Use SSLv3 client hello health checks for server testing.'); + +global $a_httpcheck_method; +$a_httpcheck_method = array(); +$a_httpcheck_method['OPTIONS'] = array('name' => 'OPTIONS', 'syntax' => 'OPTIONS'); +$a_httpcheck_method['HEAD'] = array('name' => 'HEAD', 'syntax' => 'HEAD'); +$a_httpcheck_method['GET'] = array('name' => 'GET', 'syntax' => 'GET'); +$a_httpcheck_method['POST'] = array('name' => 'POST', 'syntax' => 'POST'); +$a_httpcheck_method['PUT'] = array('name' => 'PUT', 'syntax' => 'PUT'); +$a_httpcheck_method['DELETE'] = array('name' => 'DELETE', 'syntax' => 'DELETE'); +$a_httpcheck_method['TRACE'] = array('name' => 'TRACE', 'syntax' => 'TRACE'); + +global $a_closetypes; +$a_closetypes = array(); +//$a_closetypes['none'] = array('name' => 'none', 'syntax' => '', +// 'descr' => 'No close headers will be changed.'); +$a_closetypes['http-keep-alive'] = array('name' => 'http-keep-alive (default)', 'syntax' => 'http-keep-alive', + 'descr' => 'By default HAProxy operates in keep-alive mode with regards to persistent connections: for each connection it processes each request and response, and leaves the connection idle on both sides between the end of a response and the start of a new request.'); +$a_closetypes['http-tunnel'] = array('name' => 'http-tunnel', 'syntax' => 'http-tunnel', + 'descr' => 'Option "http-tunnel" disables any HTTP processing past the first request and the first response. This is the mode which was used by default in versions 1.0 to 1.5-dev21. It is the mode with the lowest processing overhead, which is normally not needed anymore unless in very specific cases such as when using an in-house protocol that looks like HTTP but is not compatible, or just to log one request per client in order to reduce log size. Note that everything which works at the HTTP level, including header parsing/addition, cookie processing or content switching will only work for the first request and will be ignored after the first response.'); +$a_closetypes['httpclose'] = array('name' => 'httpclose', 'syntax' => 'httpclose', + 'descr' => 'The "httpclose" option removes any "Connection" header both ways, and adds a "Connection: close" header in each direction. This makes it easier to disable HTTP keep-alive than the previous 4-rules block.'); +$a_closetypes['http-server-close'] = array('name' => 'http-server-close', 'syntax' => 'http-server-close', + 'descr' => 'By default, when a client communicates with a server, HAProxy will only analyze, log, and process the first request of each connection. Setting "option http-server-close" enables HTTP connection-close mode on the server side while keeping the ability to support HTTP keep-alive and pipelining on the client side. This provides the lowest latency on the client side (slow network) and the fastest session reuse on the server side to save server resources.'); +$a_closetypes['forceclose'] = array('name' => 'forceclose', 'syntax' => 'forceclose', + 'descr' => 'Some HTTP servers do not necessarily close the connections when they receive the "Connection: close" set by "option httpclose", and if the client does not close either, then the connection remains open till the timeout expires. This causes high number of simultaneous connections on the servers and shows high global session times in the logs. Note that this option also enables the parsing of the full request and response, which means we can close the connection to the server very quickly, releasing some resources earlier than with httpclose.'); + +global $a_servermodes; +$a_servermodes = array(); +$a_servermodes["active"]['name'] = "active"; +$a_servermodes["active"]['sign'] = ""; +$a_servermodes["backup"]['name'] = "backup"; +$a_servermodes["backup"]['sign'] = "*"; +$a_servermodes["disabled"]['name'] = "disabled"; +$a_servermodes["disabled"]['sign'] = "?"; +$a_servermodes["inactive"]['name'] = "inactive"; +$a_servermodes["inactive"]['sign'] = "-"; + +// http://www.exceliance.fr/sites/default/files/biblio/aloha_load_balancer_haproxy_cookie_persistence_methods_memo.pdf +global $a_cookiemode; +$a_cookiemode = array(); +$a_cookiemode['passive'] = array('name' => 'Passive', 'syntax' => 'cookie <cookie name>', + 'descr' => 'Cookie is analysed on incoming request to choose server. HAProxy does not perform any insertion update or deletion on the Cookie or Set-Cookie. If the Cookie is not set, then the load-balancing algorithm is applied.'); +$a_cookiemode['passive-silent'] = array('name' => 'Passive-silent', 'syntax' => 'cookie <cookie name> indirect', + 'descr' => 'Cookie is analysed on incoming request to choose server. HAProxy does not perform any insertion, update or deletion on the Cookie. Set-Cookie is removed from response if not required. If the Cookie is not set, then HAProxy applies the load-balancing algorithm.'); +$a_cookiemode['reset'] = array('name' => 'Reset', 'syntax' => 'cookie <cookie name> rewrite', + 'descr' => 'Cookie is analysed on incoming request to choose server and Set-Cookie value is overwritten in response if present. If the Set-Cookie isn\'t sent by the server, then HAProxy won\'t set it.'); +$a_cookiemode['set'] = array('name' => 'Insert', 'syntax' => 'cookie <cookie name> insert', + 'descr' => 'Cookie is analyzed on incoming request to choose server and Set-Cookie value is overwritten if present and set to an unknown value or inserted in response if not present.'); +$a_cookiemode['set-silent'] = array('name' => 'Insert-silent', 'syntax' => 'cookie <cookie name> insert indirect', + 'descr' => 'Cookie is analyzed on incoming request to choose server and Set-Cookie value is overwritten if present, inserted in response if needed and removed if a valid Cookie was provided.'); +$a_cookiemode['insert-only'] = array('name' => 'Insert-preserve', 'syntax' => 'cookie <cookie name> preserve insert', + 'descr' => 'Cookie is analyzed on incoming request to choose server. Set-Cookie value is set only if the server does not provide one or if the client came without the Cookie.'); +$a_cookiemode['insert-only-silent'] = array('name' => 'Insert-preserve-silent', 'syntax' => 'cookie <cookie name> preserve insert indirect', + 'descr' => 'Cookie is analyzed on incoming request to choose server and Set-Cookie value is left untouched if present, inserted in response if needed or removed if not needed.'); +$a_cookiemode['session-prefix'] = array('name' => 'Session-prefix', 'syntax' => 'cookie <cookie name> prefix', + 'descr' => 'Cookie is analyzed on incoming request to choose server whose Cookie Name prefix matches. Set Cookie value is prefixed using server line Cookie ID in response. Cookie is modified only between HAProxy and the client only'); +$a_cookiemode['passive-session-prefix'] = array('name' => 'Passive-session-prefix', 'syntax' => 'cookie <cookie name> preserve prefix indirect', + 'descr' => 'Cookie is analysed on incoming request to choose server whose Cookie ID prefix matches.'); +foreach($a_cookiemode as &$cookiemode) + $cookiemode['descr'] = $cookiemode['descr'] . "\n\n" . $cookiemode['syntax'] . ""; + +global $a_sticky_type; +$a_sticky_type = array(); +$a_sticky_type['none'] = array('name' => 'none', + 'descr' => "No stick-table will be used"); +$a_sticky_type['stick_sslsessionid'] = array('name' => 'Stick on SSL-Session-ID', + 'descr' => "Only used on https frontends. Uses the SSL-Session-ID to persist clients to a server."); +$a_sticky_type['stick_sourceipv4'] = array('name' => 'Stick on SourceIP IPv4', + 'descr' => "Stick on the client ip, drawback is that multiple clients behind a natted public ip will be balanced to the same server."); +$a_sticky_type['stick_sourceipv6'] = array('name' => 'Stick on SourceIP IPv6', + 'descr' => "Stick on the client ip, drawback is that multiple clients behind a natted public ip will be balanced to the same server."); +$a_sticky_type['stick_cookie_value'] = array('name' => 'Stick on existing Cookie value', + 'descr' => "Stick on the value of a session cookie", + 'cookiedescr' => "Enables SSL-session-id based persistence. (only use on 'https' and 'tcp' frontends that use SSL)<br/>EXAMPLE: JSESSIONID PHPSESSIONID ASP.NET_SessionId"); +$a_sticky_type['stick_rdp_cookie'] = array('name' => 'Stick on RDP-cookie', + 'descr' => "Uses a RDP-Cookie send by the mstsc client, note that not all clients send this.", + 'cookiedescr' => 'EXAMPLE: msts or mstshash'); + + +global $a_error; +$a_error = array(); +$a_error['200'] = array('descr' => "stats or monitoring requests"); +$a_error['400'] = array('descr' => "request invalid or too large"); +$a_error['401'] = array('descr' => "authentication is required to perform the action"); +$a_error['403'] = array('descr' => "request is forbidden"); +$a_error['408'] = array('descr' => "timeout before the request is complete"); +$a_error['500'] = array('descr' => "internal error"); +$a_error['502'] = array('descr' => "server response invalid or blocked"); +$a_error['503'] = array('descr' => "no server was available to handle the request"); +$a_error['504'] = array('descr' => "timeout before the server responds"); + +if(!function_exists('group_ports')){ +// function group_ports() is present in pfSense 2.2 in util.inc +/* create ranges of sequential port numbers (200:215) and remove duplicates */ +function group_ports($ports) { + if (!is_array($ports) || empty($ports)) + return; + + $uniq = array(); + foreach ($ports as $port) { + if (is_portrange($port)) { + list($begin, $end) = explode(":", $port); + if ($begin > $end) { + $aux = $begin; + $begin = $end; + $end = $aux; + } + for ($i = $begin; $i <= $end; $i++) + if (!in_array($i, $uniq)) + $uniq[] = $i; + } else if (is_port($port)) { + if (!in_array($port, $uniq)) + $uniq[] = $port; + } + } + sort($uniq, SORT_NUMERIC); + + $result = array(); + foreach ($uniq as $idx => $port) { + if ($idx == 0) { + $result[] = $port; + continue; + } + + $last = end($result); + if (is_portrange($last)) + list($begin, $end) = explode(":", $last); + else + $begin = $end = $last; + + if ($port == ($end+1)) { + $end++; + $result[count($result)-1] = "{$begin}:{$end}"; + } else { + $result[] = $port; + } + } + + return $result; +} +} + +function haproxy_portoralias_to_list($port_or_alias) { + // input: a port or aliasname: 80 https MyPortAlias + // returns: a array of ports and portranges 80 443 8000:8010 + + global $aliastable; + $portresult = array(); + if (alias_get_type($port_or_alias) == "port") { + $aliasports = $aliastable[$port_or_alias]; + $ports = explode(' ',$aliasports); + foreach($ports as $port) { + $portresults = haproxy_portoralias_to_list($port); + $portresult = array_merge($portresult, $portresults); + } + return $portresult; + } else if (is_portrange($port_or_alias)) { + return (array)$port_or_alias; + } else { + $ports = explode(",", $port_or_alias); + foreach($ports as $port){ + if (is_port($port)) { + if (getservbyname($port, "tcp")) + $port = getservbyname($port, "tcp"); + if (getservbyname($port, "udp")) + $port = getservbyname($port, "udp"); + $portresult[] = $port; + } + } + return $portresult; + } +} +function haproxy_addressoralias_to_list($address_or_alias) { + global $aliastable; + $result = array(); + $alias_type = alias_get_type($address_or_alias); + if (!empty($alias_type)) { + $alias = $aliastable[$address_or_alias]; + if ($alias_type == "url") { + $result = explode(' ',$alias); + } else + if ($alias_type == "network") { + //$result = explode(' ',$alias); + } else + if ($alias_type == "host") { + $result = explode(' ',$alias); + } + } else { + $result[] = $address_or_alias; + } + return $result; +} + +function haproxy_hostoralias_to_list($host_or_alias) { + if (is_alias($host_or_alias)){ + $result = filter_expand_alias_array($host_or_alias); + } else { + $result = array(); + $result[] = $host_or_alias; + } + return $result; +} + +function haproxy_get_fileslist() { + // returns the files array with 'keys'. + $result = array(); + global $config; + // create a copy to not modify the original 'keyless' array + $a_files = $config['installedpackages']['haproxy']['files']['item']; + if (!is_array($a_files)) $a_files = array(); + foreach($a_files as $file) { + $key = $file['name']; + $result[$key] = $file; + } + return $result; +} + +function haproxy_custom_php_deinstall_command() { + global $static_output; + $static_output .= "HAProxy, running haproxy_custom_php_deinstall_command()\n"; + update_output_window($static_output); + $static_output .= "HAProxy, deleting haproxy webgui\n"; + update_output_window($static_output); + exec("rm /usr/local/etc/rc.d/haproxy.sh"); + $static_output .= "HAProxy, installing cron job if needed\n"; + update_output_window($static_output); + haproxy_install_cron(false); + $static_output .= "HAProxy, running haproxy_custom_php_deinstall_command() DONE\n"; + update_output_window($static_output); +} + +function haproxy_custom_php_install_command() { + global $g, $config, $static_output; + $static_output .= "HAProxy, running haproxy_custom_php_install_command()\n"; + update_output_window($static_output); + + $static_output .= "HAProxy, conf_mount_rw\n"; + update_output_window($static_output); + conf_mount_rw(); + + $static_output .= "HAProxy, create '/usr/local/etc/rc.d/haproxy.sh'\n"; + update_output_window($static_output); + $haproxy = <<<EOD +#!/bin/sh + +# PROVIDE: haproxy +# REQUIRE: LOGIN +# KEYWORD: FreeBSD + +. /etc/rc.subr + +name="haproxy" +rcvar="\${name}_enable" +command="/usr/pbi/haproxy-devel-`uname -m`/sbin/haproxy" +haproxy_enable=\${haproxy-"YES"} + +start_cmd="haproxy_start" +stop_postcmd="haproxy_stop" +check_cmd="haproxy_check" +extra_commands="check" + +load_rc_config \$name + +haproxy_start () { + echo "Starting haproxy." + /usr/bin/env \ + PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \ + /usr/local/bin/php -q -d auto_prepend_file=config.inc <<ENDOFF + <?php + require_once("globals.inc"); + require_once("functions.inc"); + require_once("haproxy.inc"); + haproxy_configure(); + ?> +ENDOFF +} + +haproxy_check () { + echo "Checking haproxy." + /usr/bin/env \ + PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \ + /usr/local/bin/php -q -d auto_prepend_file=config.inc <<ENDOFF + <?php + require_once("globals.inc"); + require_once("functions.inc"); + require_once("haproxy.inc"); + haproxy_check_run(0); + ?> +ENDOFF +} + +haproxy_stop () { + echo "Stopping haproxy." + killall haproxy +} + +run_rc_command "\$1" + +EOD; + + $fd = fopen("/usr/local/etc/rc.d/haproxy.sh", "w"); + fwrite($fd, $haproxy); + fclose($fd); + exec("chmod a+rx /usr/local/etc/rc.d/haproxy.sh"); + + $static_output .= "HAProxy, update configuration\n"; + update_output_window($static_output); + + // call from external file, so it is surely from the newly downloaded version + // this avoids a problem with php cache that loaded haproxy.inc during uninstalling the old version + require_once('haproxy_upgrade_config.inc'); + haproxy_upgrade_config(); + + $static_output .= "HAProxy, conf_mount_ro\n"; + update_output_window($static_output); + conf_mount_ro(); + + $static_output .= "HAProxy, starting haproxy (if previously enabled)\n"; + update_output_window($static_output); + haproxy_check_run(1); + + $static_output .= "HAProxy, running haproxy_custom_php_install_command() DONE\n"; + update_output_window($static_output); +} + +function haproxy_install_cron($should_install) { + global $config, $g; + if($g['booting']==true) + return; + $is_installed = false; + if(!$config['cron']['item']) + return; + $x=0; + foreach($config['cron']['item'] as $item) { + if(strstr($item['command'], "/usr/local/etc/rc.d/haproxy.sh")) { + $is_installed = true; + break; + } + $x++; + } + switch($should_install) { + case true: + if(!$is_installed) { + $cron_item = array(); + $cron_item['minute'] = "*/2"; + $cron_item['hour'] = "*"; + $cron_item['mday'] = "*"; + $cron_item['month'] = "*"; + $cron_item['wday'] = "*"; + $cron_item['who'] = "root"; + $cron_item['command'] = "/usr/local/etc/rc.d/haproxy.sh onecheck"; + $config['cron']['item'][] = $cron_item; + parse_config(true); + write_config("haproxy, install cron CARP job"); + configure_cron(); + } + break; + case false: + if($is_installed == true) { + if($x > 0) { + unset($config['cron']['item'][$x]); + parse_config(true); + write_config("haproxy, remove cron CARP job"); + } + configure_cron(); + } + break; + } +} + +function haproxy_find_backend($backendname) { + global $config; + $a_backends = &$config['installedpackages']['haproxy']['ha_pools']['item']; + foreach ($a_backends as &$backend) { + if ($backend['name'] == $backendname) { + return $backend; + } + } + return null; +} + +function haproxy_find_acl($name) { + global $a_acltypes; + if($a_acltypes) { + foreach ($a_acltypes as $key => $acl) { + if ($key == $name) + return $acl; + } + } +} + +function write_backend($configpath, $fd, $name, $pool, $backendsettings) { + $frontend = $backendsettings['frontend']; + $ipversion = $backendsettings['ipversion']; + + if(!is_array($pool['ha_servers']['item']) && !$pool['stats_enabled']=='yes') + return; + global $a_checktypes, $a_cookiemode, $a_files_cache, $a_error; + + $a_servers = &$pool['ha_servers']['item']; + $frontendtype = $frontend['type']; + + fwrite ($fd, "backend " . $name . "\n"); + // https is an alias for tcp for clarity purposes + if($frontendtype == "https") { + $backend_mode = "tcp"; + } else { + $backend_mode = $frontendtype; + } + fwrite ($fd, "\tmode\t\t\t" . $backend_mode . "\n"); + if ($pool['log-health-checks'] == 'yes') + fwrite ($fd, "\toption\t\t\tlog-health-checks\n"); + + if ($frontendtype == "http") { + // actions that read/write http headers only work when 'mode http' is used + if ($pool["persist_cookie_enabled"] == "yes") { + $cookie_mode = $pool["persist_cookie_mode"]; + $cookie_cachable = $pool["persist_cookie_cachable"]; + $cookiesyntax = $a_cookiemode[$cookie_mode]["syntax"]; + $cookie = str_replace("<cookie name>", $pool["persist_cookie_name"], $cookiesyntax); + $cookie .= $cookie_cachable == "yes" ? "" : " nocache"; + fwrite ($fd, "\t" . $cookie . "\n"); + } + + if ($pool["strict_transport_security"] && is_numeric($pool["strict_transport_security"])){ + fwrite ($fd, "\trspadd Strict-Transport-Security:\\ max-age={$pool["strict_transport_security"]};\n"); + } + + if ($pool["cookie_attribute_secure"] == 'yes'){ + fwrite ($fd, "\trspirep ^(Set-Cookie:((?!;\\ secure).)*)$ \\1;\ secure if { ssl_fc }\n"); + } + + if($pool['stats_enabled']=='yes') { + fwrite ($fd, "\tstats\t\t\tenable\n"); + if($pool['stats_uri']) + fwrite ($fd, "\tstats\t\t\turi ".$pool['stats_uri']."\n"); + if($pool['stats_realm']) + fwrite ($fd, "\tstats\t\t\trealm " . haproxy_escapestring($pool['stats_realm']) . "\n"); + else + fwrite ($fd, "\tstats\t\t\trealm .\n"); + + if ($pool['stats_username'] && $pool['stats_password']) + fwrite ($fd, "\tstats\t\t\tauth " . haproxy_escapestring($pool['stats_username']).":". haproxy_escapestring($pool['stats_password'])."\n"); + + if($pool['stats_admin']=='yes') + fwrite ($fd, "\tstats\t\t\tadmin if TRUE" . "\n"); + + if($pool['stats_node']) + fwrite ($fd, "\tstats\t\t\tshow-node " . $pool['stats_node'] . "\n"); + if($pool['stats_desc']) + fwrite ($fd, "\tstats\t\t\tshow-desc " . haproxy_escapestring($pool['stats_desc']) . "\n"); + if($pool['stats_refresh']) + fwrite ($fd, "\tstats\t\t\trefresh " . $pool['stats_refresh'] . "\n"); + + if ($pool['stats_scope']) { + $scope_items = explode(",", $pool['stats_scope']); + foreach($scope_items as $scope_item) + fwrite ($fd, "\tstats\t\t\tscope " . $scope_item . "\n"); + } + } + + if (is_arrayset($pool,'errorfiles','item')) { + foreach($pool['errorfiles']['item'] as $errorfile) { + if (!is_array($a_files_cache))// load only once + $a_files_cache = haproxy_get_fileslist(); + $file = $errorfile['errorfile']; + $errorcodes = explode(",",$errorfile['errorcode']); + foreach($errorcodes as $errorcode) { + $filename = "$configpath/errorfile_{$name}_{$errorcode}_{$file}"; + $content = base64_decode($a_files_cache[$file]['content']); + $content = str_replace('{errormsg}', $a_error[$errorcode]['descr'], $content); + $content = str_replace('{errorcode}', $errorcode, $content); + file_put_contents($filename, $content); + fwrite ($fd, "\terrorfile\t\t\t" . $errorcode ." " . $filename . "\n"); + } + } + } + } + + switch($pool["persist_sticky_type"]) { + case 'stick_sslsessionid': + if ($frontendtype == "https") { + fwrite ($fd, "\ttcp-request inspect-delay 5s\n"); + fwrite ($fd, "\tstick-table type binary len 32 size ".$pool["persist_stick_tablesize"]." expire ".$pool["persist_stick_expire"]."\n"); + fwrite ($fd, "\tacl clienthello req.ssl_hello_type 1\n"); + fwrite ($fd, "\tacl serverhello res.ssl_hello_type 2\n"); + fwrite ($fd, "\ttcp-request content accept if clienthello\n"); + fwrite ($fd, "\ttcp-response content accept if serverhello\n"); + fwrite ($fd, "\tstick on payload_lv(43,1) if clienthello\n"); + fwrite ($fd, "\tstick store-response payload_lv(43,1) if serverhello\n"); + } + break; + case 'stick_rdp_cookie': + //tcp-request content accept if RDP_COOKIE + //fwrite ($fd, "\tstick on req.rdp_cookie(msts)\n"); + fwrite ($fd, "\tstick-table type binary len 32 size ".$pool["persist_stick_tablesize"]." expire ".$pool["persist_stick_expire"]."\n"); + fwrite ($fd, "\tstick on req.rdp_cookie(mstshash)\n"); + break; + case 'stick_sourceipv4': + fwrite ($fd, "\tstick-table type ip size ".$pool["persist_stick_tablesize"]." expire ".$pool["persist_stick_expire"]."\n"); + fwrite ($fd, "\tstick on src\n"); + break; + case 'stick_sourceipv6': + fwrite ($fd, "\tstick-table type ip size ".$pool["persist_stick_tablesize"]." expire ".$pool["persist_stick_expire"]."\n"); + fwrite ($fd, "\tstick on src\n"); + break; + case 'stick_cookie_value': + if ($frontendtype == "http") { + fwrite ($fd, "\tstick-table type string len {$pool["persist_stick_length"]} size ".$pool["persist_stick_tablesize"]." expire ".$pool["persist_stick_expire"]."\n"); + fwrite ($fd, "\tstick store-response res.cook({$pool["persist_stick_cookiename"]})\n"); + fwrite ($fd, "\tstick on req.cook({$pool["persist_stick_cookiename"]})\n"); + } + break; + } + + unset($checkport); + $check_type = $pool['check_type']; + if ($check_type != 'none') { + $optioncheck = $a_checktypes[$check_type]['syntax']; + if ($check_type == "MySQL" || $check_type == "PostgreSQL") + $optioncheck .= " user " . $pool['monitor_username']; + if ($check_type == "SMTP" || $check_type == "ESMTP") + $optioncheck .= " " . $pool['monitor_domain']; + if ($check_type == "HTTP") { + $uri = $pool['monitor_uri']; + if (!$uri) + $uri = "/"; + $optioncheck .= " {$pool['httpcheck_method']} {$uri} {$pool['monitor_httpversion']}"; + } + if ($check_type == "Agent") { + $checkport = " port " . $pool['monitor_agentport']; + } + } else { + $optioncheck = "httpchk"; + } + + if($pool['balance']) + fwrite ($fd, "\tbalance\t\t\t" . $pool['balance'] . "\n"); + + if(!$pool['connection_timeout']) + $pool['connection_timeout'] = 30000; + fwrite ($fd, "\ttimeout connect\t\t" . $pool['connection_timeout'] . "\n"); + + if(!$pool['server_timeout']) + $pool['server_timeout'] = 30000; + fwrite ($fd, "\ttimeout server\t\t" . $pool['server_timeout'] . "\n"); + + if(!$pool['retries']) + $pool['retries'] = 3; + fwrite ($fd, "\tretries\t\t\t" . $pool['retries'] . "\n"); + + $addrprefix = ""; + $dnsquerytype = "A,AAAA"; + if ($pool['transparent_clientip'] == 'yes') { + if ($ipversion == "ipv6") { + $addrprefix = "ipv6@"; + $dnsquerytype = "AAAA"; + } + if ($ipversion == "ipv4") { + $addrprefix = "ipv4@"; + $dnsquerytype = "A"; + } + fwrite ($fd, "\tsource $addrprefix usesrc clientip\n"); + } + + $uri = $pool['monitor_uri']; + if ($pool['monitor_uri']) + $uri = $pool['monitor_uri']; + else + $uri = "/"; + + if ($optioncheck) + fwrite ($fd, "\toption\t\t\t{$optioncheck}\n"); + + if ($pool['advanced_backend']) { + $adv_be = explode("\n", base64_decode($pool['advanced_backend'])); + foreach($adv_be as $adv_line) { + if ($adv_line != "") { + fwrite($fd, "\t" . str_replace("\r", "", $adv_line) . "\n"); + } + } + } + + if($pool['advanced']) { + $advanced = base64_decode($pool['advanced']); + $advanced_txt = " " . $advanced; + } else { + $advanced_txt = ""; + } + + if ($check_type != 'none') { + if($pool['checkinter']) + $checkinter = " check inter {$pool['checkinter']}"; + else + $checkinter = " check inter 1000"; + } + + //agent-check requires at least haproxy v1.5dev20 + if ($pool['agent_check']) + $agentcheck = " agent-check agent-inter {$pool['agent_inter']} agent-port {$pool['agent_port']}"; + + if (is_array($a_servers)) { + foreach($a_servers as $be) { + if ($be['status'] == "inactive") + continue; + if($be['cookie'] && $frontendtype == "http") + $cookie = " cookie {$be['cookie']}"; + else + $cookie = ""; + + if (!$be['name']) + $be['name'] = $be['address']; + if(!$be['status'] || $be['status'] != 'active') { + $isbackup = $be['status']; + } else { + $isbackup = ""; + } + $ssl = ""; + $cafile = ""; + $crlfile = ""; + $crtfile = ""; + $verifynone = ""; + $verifyhost = ""; + if ($be['ssl'] == 'yes') + { + $ssl = $frontendtype == "http" ? ' ssl' : ' check-ssl'; + + if ($be['sslserververify'] != 'yes') { + $verifynone = " verify none"; + } else { + $verifyhost = isset($be['verifyhost']) && $be['verifyhost'] != "" ? " verifyhost {$be['verifyhost']}" : ""; + + $ca = $be['ssl-server-ca']; + $filename = "$configpath/ca_$ca.pem"; + haproxy_write_certificate_crt($filename, $ca); + $cafile = " ca-file $filename"; + + $crl = $be['ssl-server-crl']; + if ($crl && $crl != "") { + $filename = "$configpath/crl_$crl.pem"; + haproxy_write_certificate_crl($filename, $crl); + $crlfile = " crl-file $filename"; + } + } + + $server_clientcert = $be['ssl-server-clientcert']; + if ($server_clientcert && $server_clientcert != "") { + $filename = "$configpath/server_clientcert_$server_clientcert.pem"; + haproxy_write_certificate_crt($filename, $server_clientcert, true); + $crtfile = " crt $filename"; + } + + } + $weight = ""; + if (is_numeric($be['weight'])){ + $weight = " weight " . $be['weight']; + } + $maxconn = ""; + if (is_numeric($be['maxconn'])){ + $maxconn = " maxconn " . $be['maxconn']; + } + + $servers = array(); + if ($be['forwardto'] && $be['forwardto'] != "") { + $servers[] = "/{$be['forwardto']}.socket send-proxy-v2-ssl-cn"; + } else { + if (is_ipaddr($be['address'])) { + $servers[] = $be['address']; + } else if (is_hostname($be['address'])) { + $dnsresult_servers = haproxy_utils::query_dns($be['address'], $dnsquerytype); + foreach($dnsresult_servers as $dnsresult_server){ + $servers[] = $dnsresult_server['data']; + } + } + } + $counter = 0; + foreach($servers as $server) { + if (is_ipaddr($server)) { + // skip ipv4 servers when using transparent client ip with ipv6 backend servers, and vice versa + if ($ipversion == "ipv4" && !is_ipaddrv4($server)) + continue; + if ($ipversion == "ipv6" && !is_ipaddrv6($server)) + continue; + if (isset($be['port'])) + $server = $server . ":" . $be['port']; + } + $servername = $be['name']; + if (count($servers) > 1) { + $servername .= "_" . $counter; + } + fwrite ($fd, "\tserver\t\t\t" . $servername . " " . $server . "$ssl$cookie$checkinter$checkport$agentcheck $isbackup$weight$maxconn$cafile$crlfile$verifynone$verifyhost$crtfile{$advanced_txt} {$be['advanced']}\n"); + $counter++; + } + } + } + fwrite ($fd, "\n"); +} + +function haproxy_configure() { + global $g; + // reload haproxy + return haproxy_check_run(1); +} + +function haproxy_check_and_run(&$messages, $reload) { + global $g; + $testpath = "{$g['varetc_path']}/haproxy_test"; + haproxy_writeconf($testpath); + $retval = exec("haproxy -c -V -f $testpath/haproxy.cfg 2>&1", $output, $err); + $messages = ""; + if ($err > 1) + $messages = "<h2><strong>FATAL ERROR CODE: $err while starting haproxy</strong></h2>"; + elseif ($err == 1) + $messages = "Errors found while starting haproxy"; + + if ((count($output) > 1) && $output[0] != "Configuration file is valid") + { + foreach($output as $line) + $messages .= "<br/>" . htmlspecialchars($line) . "\n"; + } + $ok = strstr($retval, "Configuration file is valid"); + if ($ok && $reload) { + global $haproxy_run_message; + rmdir_recursive($testpath); + $ok = haproxy_check_run(1) == 0; + $messages = $haproxy_run_message; + } + return $ok; +} + +function haproxy_lookup_cert($certid) { + $res = lookup_ca($certid); + if (!$res) + $res = lookup_cert($certid); + return $res; +} + +function haproxy_write_certificate_crt($filename, $certid, $include_psk = false, $append = false) { + $cert = haproxy_lookup_cert($certid); + $certcontent = base64_decode($cert['crt']); + if ($include_psk && isset($cert['prv'])) + $certcontent .= "\r\n".base64_decode($cert['prv']); + $flags = $append ? FILE_APPEND : 0; + file_put_contents($filename, $certcontent, $flags); + unset($certcontent); + unset($cert); +} + +function haproxy_write_certificate_crl($filename, $crlid, $append = false) { + $crl = lookup_crl($crlid); + $content = base64_decode($crl['text']); + $flags = $append ? FILE_APPEND : 0; + file_put_contents($filename, $content, $flags); + unset($content); + unset($crl); +} + +function haproxy_write_certificate_fullchain($filename, $certid, $append = false) { + $cert = haproxy_lookup_cert($certid); + + $certcontent = base64_decode($cert['crt']); + if (isset($cert['prv'])) + $certcontent .= "\r\n".base64_decode($cert['prv']); + + $certchaincontent = ca_chain($cert); + if ($certchaincontent != "") { + $certcontent .= "\r\n" . $certchaincontent; + } + unset($certchaincontent); + $flags = $append ? FILE_APPEND : 0; + file_put_contents($filename, $certcontent, $flags); + unset($certcontent); + unset($cert); +} + +function haproxy_writeconf($configpath) { + global $config; + global $aliastable; + if (!isset($aliastable)) + alias_make_table($config); + $chroot_dir = "/tmp/haproxy_chroot"; // can contain socket to forward connection from backend to frontend. "/var/empty" + make_dirs($chroot_dir); + + $configfile = $configpath . "/haproxy.cfg"; + + rmdir_recursive($configpath); + make_dirs($configpath); + + $a_global = &$config['installedpackages']['haproxy']; + $a_frontends = &$config['installedpackages']['haproxy']['ha_backends']['item']; + $a_backends = &$config['installedpackages']['haproxy']['ha_pools']['item']; + + $fd = fopen($configfile, "w"); + if(is_array($a_global)) { + fwrite ($fd, "global\n"); + if ($a_global['maxconn']) + fwrite ($fd, "\tmaxconn\t\t\t".$a_global['maxconn']."\n"); + if($a_global['remotesyslog']) + fwrite ($fd, "\tlog\t\t\t{$a_global['remotesyslog']}\t{$a_global['logfacility']}\t{$a_global['loglevel']}\n"); + fwrite ($fd, "\tstats socket /tmp/haproxy.socket level admin\n"); + + if(!use_transparent_clientip_proxying()) + fwrite ($fd, "\tuid\t\t\t80\n"); + + fwrite ($fd, "\tgid\t\t\t80\n"); + // Set numprocs if defined or use system default (#cores) + if($a_global['nbproc']) + $numprocs = $a_global['nbproc']; + else + $numprocs ="1"; + fwrite ($fd, "\tnbproc\t\t\t$numprocs\n"); + fwrite ($fd, "\tchroot\t\t\t$chroot_dir\n"); + fwrite ($fd, "\tdaemon\n"); + //fwrite ($fd, "\tssl-server-verify none\n"); + + if($a_global['ssldefaultdhparam']) + fwrite ($fd, "\ttune.ssl.default-dh-param\t{$a_global['ssldefaultdhparam']}\n"); + if($a_global['log-send-hostname']) + fwrite ($fd, "\tlog-send-hostname\t\t{$a_global['log-send-hostname']}\n"); + + // Keep the advanced options on the bottom of the global settings, to allow additional sections to be easely added + if($a_global['advanced']) { + $adv = explode("\n", base64_decode($a_global['advanced'])); + foreach($adv as $adv_line) { + fwrite($fd, "\t" . str_replace("\r", "", $adv_line) . "\n"); + + } + } + fwrite ($fd, "\n"); + + $localstatsport = $a_global['localstatsport']; + if ($localstatsport){ + fwrite ($fd, "listen HAProxyLocalStats\n"); + fwrite ($fd, "\tbind 127.0.0.1:$localstatsport name localstats\n"); + fwrite ($fd, "\tmode http\n"); + fwrite ($fd, "\tstats enable\n"); + if (is_numeric($a_global['localstats_refreshtime'])) + fwrite ($fd, "\tstats refresh {$a_global['localstats_refreshtime']}\n"); + fwrite ($fd, "\tstats admin if TRUE\n"); + fwrite ($fd, "\tstats uri /haproxy_stats.php?haproxystats=1\n"); + fwrite ($fd, "\ttimeout client 5000\n"); + fwrite ($fd, "\ttimeout connect 5000\n"); + fwrite ($fd, "\ttimeout server 5000\n"); + fwrite ($fd, "\n"); + } + } + + // Try and get a unique array for address:port as frontends can duplicate + $a_bind = array(); + if(is_array($a_frontends)) { + foreach ($a_frontends as $frontend) { + if($frontend['status'] != 'active') + continue; + if(!$frontend['backend_serverpool']) + continue; + $primaryfrontend = get_primaryfrontend($frontend); + + $bname = $primaryfrontend['name']; + if (!is_array($a_bind[$bname])) { + $a_bind[$bname] = array(); + $a_bind[$bname] = $primaryfrontend; + $a_bind[$bname]['config'] = array(); + } + + //check ssl info + $ssl = get_frontend_uses_ssl($frontend); + + if ($ssl) { + //ssl crt ./server.pem ca-file ./ca.crt verify optional crt-ignore-err all crl-file ./ca_crl.pem + $filename = "$configpath/{$frontend['name']}.pem"; + $ssl_crt = " crt $filename"; + haproxy_write_certificate_fullchain($filename, $frontend['ssloffloadcert']); + $subfolder = "$configpath/{$frontend['name']}"; + $certs = $frontend['ha_certificates']['item']; + if (is_array($certs)){ + if (count($certs) > 0){ + make_dirs($subfolder); + foreach($certs as $cert){ + haproxy_write_certificate_fullchain("$subfolder/{$cert['ssl_certificate']}.pem", $cert['ssl_certificate']); + } + $ssl_crt .= " crt $subfolder"; + } + } + }else{ + $ssl_crt=""; + unlink_if_exists("var/etc/{$frontend['name']}.{$frontend['port']}.crt");//cleanup for possible old haproxy package version + } + + $b = &$a_bind[$bname]; + + if (($frontend['secondary'] != 'yes') && ($frontend['name'] != $b['name'])) { + // only 1 frontend can be the primary for a set of frontends that share 1 address:port. + $input_errors[] = "Multiple primary frontends for $bname use the 'Shared Frontend' option instead"; + } + + if ($ssl_crt != "") { + if ($b['ssl_info'] == "") + $b['ssl_info'] = "ssl {$frontend['dcertadv']}"; + $b['ssl_info'] .= $ssl_crt; + } + + // pointer to each frontend + $b['config'][] = $frontend; + } + } + + $a_pendingpl = array(); + + // Construct and write out configuration for each "frontend" + if(is_array($a_bind)) { + foreach ($a_bind as $bind) { + if (count($bind['config']) > 1) + $frontendinfo = "frontend {$bind['name']}-merged\n"; + else + $frontendinfo = "frontend {$bind['name']}\n"; + + fwrite ($fd, "{$frontendinfo}"); + + $advancedextra = array(); + $ca_file = ""; + $first = true; + if (is_array($bind['clientcert_ca']['item'])){ + $filename = "$configpath/clientca_{$bind['name']}.pem"; + foreach($bind['clientcert_ca']['item'] as $ca){ + if (!empty($ca['cert_ca'])){ + haproxy_write_certificate_crt($filename, $ca['cert_ca'], false, !$first); + $first = false; + } + } + $verify = $bind['sslclientcert-none'] == 'yes' ? "verify optional" : "verify required"; + $ca_file = " ca-file $filename $verify"; + } + $crl_file = ""; + $first = true; + if (is_array($bind['clientcert_crl']['item'])){ + $filename = "$configpath/clientcrl_{$bind['name']}.pem"; + foreach($bind['clientcert_crl']['item'] as $ca){ + haproxy_write_certificate_crl($filename, $ca['cert_crl'], !$first); + $first = false; + } + $crl_file = " crl-file $filename"; + } + $advanced_bind = $bind['advanced_bind']; + $ssl_info = $bind['ssl_info']; + $ssl_info .= $ca_file . $crl_file; + if ($bind['sslclientcert-invalid']) + $ssl_info .= " crt-ignore-err all"; + + $useipv4 = false; + $useipv6 = false; + // Process and add bind directives for ports + $bindips = get_frontend_bindips($bind); + $listenip = ""; + foreach($bindips as $bindip) { + $ssl = $bindip['extaddr_ssl'] == 'yes' ? $ssl_info : ""; + $listenip .= "\tbind\t\t\t{$bindip['addr']}:{$bindip['port']} name {$bindip['addr']}:{$bindip['port']} {$ssl} {$advanced_bind} {$bindip['extaddr_advanced']}\n"; + $useipv4 |= is_ipaddrv4($bindip['addr']); + $useipv6 |= is_ipaddrv6($bindip['addr']); + } + fwrite ($fd, "{$listenip}"); + + if (use_frontend_as_unixsocket($bind['name'])){ + fwrite ($fd, "\tbind /tmp/haproxy_chroot/{$bind['name']}.socket name unixsocket accept-proxy {$ssl_info} {$advanced_bind}\n"); + } + + // https is an alias for tcp for clarity purposes + if($bind['type'] == "https") { + $backend_type = "tcp"; + } else { + $backend_type = $bind['type']; + } + + fwrite ($fd, "\tmode\t\t\t" . $backend_type . "\n"); + fwrite ($fd, "\tlog\t\t\tglobal\n"); + + if ($bind['socket-stats'] == 'yes') + fwrite ($fd, "\toption\t\t\tsocket-stats\n"); + if ($bind['dontlognull'] == 'yes') + fwrite ($fd, "\toption\t\t\tdontlognull\n"); + if ($bind['dontlog-normal'] == 'yes') + fwrite ($fd, "\toption\t\t\tdontlog-normal\n"); + if ($bind['log-separate-errors'] == 'yes') + fwrite ($fd, "\toption\t\t\tlog-separate-errors\n"); + if ($bind['log-detailed'] == 'yes'){ + if ($backend_type == 'http') + fwrite ($fd, "\toption\t\t\thttplog\n"); + else + fwrite ($fd, "\toption\t\t\ttcplog\n"); + } + + if ($backend_type == 'http') { + if($bind['httpclose'] && $bind['httpclose'] != "none" ) + fwrite ($fd, "\toption\t\t\t{$bind['httpclose']}\n"); + + if($bind['forwardfor']) { + fwrite ($fd, "\toption\t\t\tforwardfor\n"); + fwrite ($fd, "\tacl https ssl_fc\n"); + fwrite ($fd, "\treqadd X-Forwarded-Proto:\ http if !https\n"); + fwrite ($fd, "\treqadd X-Forwarded-Proto:\ https if https\n"); + } + } + + if($bind['max_connections']) + fwrite ($fd, "\tmaxconn\t\t\t" . $bind['max_connections'] . "\n"); + + if(!$bind['client_timeout']) + $bind['client_timeout'] = 30000; + + fwrite ($fd, "\ttimeout client\t\t" . $bind['client_timeout'] . "\n"); + + + // Advanced pass thru + if($bind['advanced']) { + $advanced = explode("\n", base64_decode($bind['advanced'])); + foreach($advanced as $adv_line) { + if ($adv_line != "") { + fwrite($fd, "\t" . str_replace("\r", "", $adv_line) . "\n"); + } + } + } + + // Combine the rest of the frontend configs + $default_backend = ""; + $config_acls = ""; + $config_usebackends = ""; + $config_usedefaultbackends = ""; + + $transparent_clientip = false; + foreach ($bind['config'] as $frontend) { + $backend = haproxy_find_backend($frontend['backend_serverpool']); + if ($backend["transparent_clientip"] == 'yes') { + $transparent_clientip = true; + break; + } + } + if ($transparent_clientip && $useipv4 && $useipv6) { + // set the src_is_ipv4 acl if needed. + $config_acls .= "\tacl\t\t\tsrc_is_ipv4\tsrc 0.0.0.0/0\n"; + } + + $inspectdelay = 0; + $i = 0; + $acllist = array(); + $acl_newid = 0; + foreach ($bind['config'] as $frontend) { + $a_acl = get_frontend_acls($frontend); + + $backend = haproxy_find_backend($frontend['backend_serverpool']); + $transparent_clientip = $backend["transparent_clientip"] == 'yes'; + + $allowfordefaultbackend = true; + $ipv = array(); + if ($transparent_clientip) { + if ($useipv4 && $useipv6) { + $ipv["ipv4"]['acl'] = " src_is_ipv4 "; + $ipv["ipv6"]['acl'] = " !src_is_ipv4 "; + $allowfordefaultbackend = false; // transparent backend must always match client-ip which is ipv4 v.s. ipv6 specific so there cannot be a default. + } else if ($useipv6) + $ipv["ipv6"]['acl'] = " "; + else + $ipv["ipv4"]['acl'] = " "; + } else + $ipv["ipvANY"]['acl'] = " "; + + // combine acl's with same name to allow for 'combined checks' to check for example hostname and fileextension together.. + $a_acl_combine = array(); + foreach ($a_acl as $entry) { + $name = $entry['ref']['name']; + + $acl = array(); + $acl['ref'] = $entry['ref']; + $acltype = haproxy_find_acl($entry['ref']['expression']); + $acl['acltype'] = $acltype; + if (!isset($acltype)) + continue; + $a_acl_combine[$name][] = $acl; + + if (isset($acltype['require_client_cert'])){ + $acl = array(); + $acl['ref']['expression'] = "ssl_c_used"; + $acl['acltype']['syntax'] = "ssl_c_used"; + $acl['acltype']['novalue'] = 1; + $a_acl_combine[$name][] = $acl; + } + } + + $certacl = ""; + $y = 0; + foreach($ipv as $ipversion => $ipversionoptions) { + $useracls = array(); + $poolname = $frontend['backend_serverpool'] . "_" . strtolower($bind['type'])."_".$ipversion; + if (!isset($a_pendingpl[$poolname])) { + $a_pendingpl[$poolname] = array(); + $a_pendingpl[$poolname]['name'] = $poolname; + $a_pendingpl[$poolname]['backend'] = $frontend['backend_serverpool']; + $a_pendingpl[$poolname]['frontend'] = $bind; + $a_pendingpl[$poolname]['ipversion'] = $ipversion; + } + $canbedefaultbackend = false; + // Write this out once, and must be before any backend config text + if (($default_backend == "" || $frontend['secondary'] != 'yes') && count($a_acl) == 0 ) { + $canbedefaultbackend = true; + if ($allowfordefaultbackend) + $default_backend = $poolname; + } + + foreach ($a_acl_combine as $a_usebackend) { + $aclnames = ""; + foreach ($a_usebackend as $entry2) { + $entry = $entry2['ref']; + $acl = $entry2['acltype']; + + // Filter out acls for different modes + if ($acl['mode'] != '' && $acl['mode'] != strtolower($bind['type'])) + continue; + if (($entry['expression'] == "source_ip") && is_alias($entry['value'])) { + $filename = "$configpath/ipalias_{$entry['value']}.lst"; + $listitems = haproxy_hostoralias_to_list($entry['value']); + $fd_alias = fopen("$filename", "w"); + foreach($listitems as $item) + fwrite($fd_alias, $item."\r\n"); + fclose($fd_alias); + $expr = "src -f $filename"; + } else + $expr = sprintf($acl['syntax'],$entry['value'],$poolname); + + $not = $entry['not'] == "yes" ? "!" : ""; + + unset($aclkey); + foreach($acllist as $aclid => $aclitem) { + if ($aclitem['expr'] == $expr) { + $aclkey = $aclid; + } + } + if (isset($aclkey)) { + $aclname = $acllist[$aclkey]['aclname']; + } else { + $aclkey = $acl_newid++; + if ($entry['certacl']) { + $aclname = "aclcrt_".$frontend['name']; + $certacl = $aclname; + } else { + $aclname = "aclusr_{$entry['expression']}"; + if (!isset($acl['novalue'])) + $aclname .= "_{$entry['value']}"; + $aclname = haproxy_escape_acl_name($aclname); + $i++; + } + $acllist[$aclkey]['aclname'] = $aclname; + $acllist[$aclkey]['expr'] = $expr; + $config_acls .= "\tacl\t\t\t" . $aclname . "\t" . $expr . "\n"; + } + if (!isset($entry['certacl'])) + $useracls[$y] .= $not . $aclname . " "; + + if ($acl['inspect-delay'] != '') + $inspectdelay = $acl['inspect-delay']; + + if ($acl['advancedoptions'] != '') + $advancedextra[$acl['syntax']] = $acl['advancedoptions']."\n"; + } + $y++; + } + + $systemacl = trim("{$certacl}{$ipversionoptions['acl']}"); + if (!empty($systemacl) && count($useracls) == 0) $useracls[] = ""; // add empty item to enter foreach loop at least once when a system acl is pressent. + foreach($useracls as $useracl) { + $backendacl = ""; + $backendacl .= "|| {$useracl}{$systemacl}"; + $backendacl = substr($backendacl, 3); + if ($canbedefaultbackend) { + // makes sure these come last even though systemacl's might have been added. + $config_usedefaultbackends .= "\tuse_backend\t\t" . $poolname . " if " . $backendacl . "\n"; + } else + $config_usebackends .= "\tuse_backend\t\t" . $poolname . " if " . $backendacl . "\n"; + } + } + } + + if ($inspectdelay > 0) + fwrite ($fd, "\ttcp-request inspect-delay\t" . $inspectdelay . "s\n"); + + // Write acl's first, so they may be used by advanced text options written by user. + fwrite ($fd, $config_acls); + + foreach($advancedextra as $extra) + fwrite ($fd, "\t".$extra."\n"); + + // Write backends after advanced options so custom use_backend rules can be applied first. + fwrite ($fd, $config_usebackends); + fwrite ($fd, $config_usedefaultbackends); + if ($default_backend) + fwrite ($fd, "\tdefault_backend\t\t" . $default_backend . "\n"); + + fwrite ($fd, "\n"); + } + } + // Construct and write out configuration for each "backend" + if (is_array($a_pendingpl) && is_array($a_backends)) { + foreach ($a_pendingpl as $pending) { + foreach ($a_backends as $pool) { + if ($pending['backend'] == $pool['name']) { + write_backend($configpath, $fd, $pending['name'], $pool, $pending); + } + } + } + } + fwrite ($fd, "\n"); + + // close config file + fclose($fd); + + if ($input_errors) + { + require_once("guiconfig.inc"); + print_input_errors($input_errors); + } else { + // Only sync to xmlrpc backup machine if no errors are found in config + if(isset($config['installedpackages']['haproxy']['enablesync'])) { + haproxy_do_xmlrpc_sync(); + } + } + + if (isset($a_global['carpdev'])) + haproxy_install_cron(true); + else + haproxy_install_cron(false); +} + +function haproxy_is_running() { + $running = (shell_exec("/bin/pgrep -x haproxy") != ''); + return $running; +} + +function haproxy_load_modules() { + // On FreeBSD 8 ipfw is needed to allow 'transparent' proxying (getting reply's to a non-local ip to pass back to the client-socket). + // On FreeBSD 9 and 10 it should have been possible to do the same with the pf(4) option "divert-reply" however that is not implemented. + // FreeBSD 10 patch proposal: http://lists.freebsd.org/pipermail/freebsd-bugs/2014-April/055823.html + + mute_kernel_msgs(); + if (!is_module_loaded("ipfw.ko")) { + mwexec("/sbin/kldload ipfw"); + /* make sure ipfw is not on pfil hooks */ + mwexec("/sbin/sysctl net.inet.ip.pfil.inbound=\"pf\" net.inet6.ip6.pfil.inbound=\"pf\"" . + " net.inet.ip.pfil.outbound=\"pf\" net.inet6.ip6.pfil.outbound=\"pf\""); + } + + /* Activate layer2 filtering */ + mwexec("/sbin/sysctl net.link.ether.ipfw=1 net.inet.ip.fw.one_pass=1"); + + unmute_kernel_msgs(); +} + +function use_transparent_clientip_proxying() { + global $config; + $a_backends = &$config['installedpackages']['haproxy']['ha_pools']['item']; + if (is_array($a_backends)) { + foreach ($a_backends as $backend) { + if ($backend["transparent_clientip"] == 'yes') { + return true; + break; + } + } + } + return false; +} + +function haproxy_get_transparent_backends(){ + global $config; + $a_backends = &$config['installedpackages']['haproxy']['ha_pools']['item']; + $transparent_backends = array(); + foreach ($a_backends as $backend) { + if ($backend["transparent_clientip"] != 'yes') + continue; + $real_if = get_real_interface($backend["transparent_interface"]); + $a_servers = &$backend['ha_servers']['item']; + if (is_array($a_servers)) { + foreach($a_servers as $be) { + if (!$be['status'] == "inactive") + continue; + if (!is_ipaddr($be['address'])) + continue; + $item = array(); + $item['name'] = $be['name']; + $item['interface'] = $real_if; + $item['forwardto'] = $be['forwardto']; + $item['address'] = $be['address']; + $item['port'] = $be['port']; + $transparent_backends[] = $item; + } + } + } + return $transparent_backends; +} + +function haproxy_generate_rules($type) { + // called by filter.inc when pfSense rules generation happens + global $g, $config; + $rules = ""; + switch($type) { + case 'filter': + // Sloppy pf rules are needed because of ipfw is used to 'catch' return traffic, and pf would otherwise terminate the connection after a few packets.. + $transparent_backends = haproxy_get_transparent_backends(); + if (count($transparent_backends) > 0) { + $rules .= "# allow HAProxy transparent traffic\n"; + foreach($transparent_backends as $tb){ + if (is_ipaddrv4($tb['address'])) + $rules .= "pass out quick on {$tb['interface']} inet proto tcp from any to {$tb['address']} port {$tb['port']} flags S/SA keep state ( sloppy ) label \"HAPROXY_transparent_rule_{$tb['name']}\"\n"; + if (is_ipaddrv6($tb['address'])) { + list ($addr, $scope) = explode("%", $tb['address']); + $rules .= "pass out quick on {$tb['interface']} inet6 proto tcp from any to {$addr} port {$tb['port']} flags S/SA keep state ( sloppy ) label \"HAPROXY_transparent_rule_{$tb['name']}\"\n"; + } + } + } + break; + } + return $rules; +} + +function load_ipfw_rules() { + // On FreeBSD 8 pf does not support "divert-reply" so ipfw is needed. + global $g, $config; + if (haproxy_utils::$pf_version < 2.2) { + $ipfw_zone_haproxy = "haproxy"; + } else { + $ipfw_zone_haproxy = "4000"; // seems that 4000 is a safe zone number to avoid conflicts with captive portal.. and 4095 is the max? + } + + $a_backends = &$config['installedpackages']['haproxy']['ha_pools']['item']; + + haproxy_load_modules(); + + $transparent_backends = haproxy_get_transparent_backends(); + + $transparent_interfaces = array(); + foreach($transparent_backends as $transparent_backend){ + $interface = $transparent_backend['interface']; + $transparent_interfaces[$interface] = 1; + } + + if (haproxy_utils::$pf_version < 2.2) { + // pfSense 2.1 FreeBSD 8.3 + mwexec("/usr/local/sbin/ipfw_context -a $ipfw_zone_haproxy", true); + + foreach($transparent_interfaces as $transparent_if => $value) { + mwexec("/usr/local/sbin/ipfw_context -a $ipfw_zone_haproxy -n $transparent_if", true); + } + } else { + // pfSense 2.2 FreeBSD 10 + mwexec("/sbin/ipfw zone $ipfw_zone_haproxy create", true); + foreach($transparent_interfaces as $transparent_if => $value) { + mwexec("/sbin/ipfw zone $ipfw_zone_haproxy madd $transparent_if", true); + } + } + + $rulenum = 64000; // why that high? captiveportal.inc also does it... + $rules = "flush\n"; + foreach($transparent_backends as $transparent_be) { + if (is_ipaddrv4($transparent_be["address"])) + $rules .= "add $rulenum fwd localhost tcp from {$transparent_be["address"]} {$transparent_be["port"]} to any in recv {$transparent_be["interface"]}\n"; + else if (is_ipaddrv6($transparent_be["address"])) { + list ($addr, $scope) = explode("%", $transparent_be['address']); + $rules .= "add $rulenum fwd ::1 tcp from {$addr} {$transparent_be["port"]} to any in recv {$transparent_be["interface"]}\n"; + } + + $rulenum++; + } + + + file_put_contents("{$g['tmp_path']}/ipfw_{$ipfw_zone_haproxy}.haproxy.rules", $rules); + if (haproxy_utils::$pf_version < 2.2) + mwexec("/usr/local/sbin/ipfw_context -s $ipfw_zone_haproxy", true); + mwexec("/sbin/ipfw -x $ipfw_zone_haproxy -q {$g['tmp_path']}/ipfw_{$ipfw_zone_haproxy}.haproxy.rules", true); +} + +function haproxy_plugin_carp($pluginparams) { + // called by pfSense when a CARP interface changes its state (called multiple times when multiple interfaces change state) + // $pluginparams['type'] always 'carp' + // $pluginparams['event'] either 'rc.carpmaster' or 'rc.carpbackup' + // $pluginparams['interface'] contains the affected interface + $type = $pluginparams['type']; + $event = $pluginparams['event']; + $interface = $pluginparams['interface']; + haproxy_check_run(0); +} + +function haproxy_plugin_certificates($pluginparams) { + global $config; + $result = array(); + if ($pluginparams['type'] == 'certificates' && $pluginparams['event'] == 'used_certificates') { + $result['pkgname'] = "HAProxy"; + $result['certificatelist'] = array(); + // return a array of used certificates. + foreach($config['installedpackages']['haproxy']['ha_backends']['item'] as &$frontend) { + if (get_frontend_uses_ssl($frontend)) { + if ($frontend['ssloffloadacl']){ + $item = array(); + $cert = $frontend['ssloffloadcert']; + $item['usedby'] = $frontend['name']; + $result['certificatelist'][$cert][] = $item; + } + if ($frontend['ssloffloadacladditional']){ + foreach($frontend['ha_certificates']['item'] as $certref){ + $item = array(); + $cert = $certref['ssl_certificate']; + $item['usedby'] = $frontend['name']; + $result['certificatelist'][$cert][] = $item; + } + } + } + } + } + return $result; +} + +function haproxy_carpipismaster($ip) { + global $config; + foreach($config['virtualip']['vip'] as $carp) { + if ($carp['mode'] != "carp") + continue; + $ipaddress = $carp['subnet']; + if ($ipaddress != $ip) + continue; + + $carp_int = "{$carp['interface']}_vip{$carp['vhid']}"; + $status = get_carp_interface_status($carp_int); + return ($status == "MASTER"); + } + return null; +} + +function haproxy_check_run($reload) { + global $config, $g, $haproxy_run_message; + + $haproxylock = lock("haproxy", LOCK_EX); + $a_global = &$config['installedpackages']['haproxy']; + $configpath = "{$g['varetc_path']}/haproxy"; + + if ($reload) + haproxy_writeconf($configpath); + + if(isset($a_global['enable'])) { + if (isset($a_global['carpdev'])) { + $status = haproxy_carpipismaster($a_global['carpdev']); + if (!$status) { + if (haproxy_is_running()) { + log_error("Stopping haproxy on CARP backup."); + //exec("/bin/pkill -F /var/run/haproxy.pid haproxy");//doesnt work for multiple pid's in a pidfile + haproxy_kill(); + } + unlock($haproxylock); + return (0); + } else if (haproxy_is_running() && $reload == 0) { + unlock($haproxylock); + return (0); + } + log_error("Starting haproxy on CARP master."); + /* fallthrough */ + } else if ($reload == 0){ + unlock($haproxylock); + return (0); + } + + if(use_transparent_clientip_proxying()) { + filter_configure(); + load_ipfw_rules(); + } else { + if (haproxy_utils::$pf_version < 2.2) { + mwexec("/usr/local/sbin/ipfw_context -d haproxy", true); + } else { + $ipfw_zone_haproxy = 4000; + mwexec("/sbin/ipfw zone $ipfw_zone_haproxy destroy", true); + } + } + + if (file_exists('/var/run/haproxy.pid')){ + $old_pid = file_get_contents('/var/run/haproxy.pid'); + } else + $old_pid = 'none'; + + if (haproxy_is_running()) { + if (isset($a_global['terminate_on_reload'])) + $sf_st = "-st";//terminate old process as soon as the new process is listening + else + $sf_st = "-sf";//finish serving existing connections exit when done, and the new process is listening + + syslog(LOG_NOTICE, "haproxy: reload old pid:$old_pid"); + exec("/usr/local/sbin/haproxy -f {$configpath}/haproxy.cfg -p /var/run/haproxy.pid $sf_st `cat /var/run/haproxy.pid` 2>&1", $output, $errcode); + } else { + syslog(LOG_NOTICE, "haproxy: starting old pid:$old_pid"); + exec("/usr/local/sbin/haproxy -f {$configpath}/haproxy.cfg -p /var/run/haproxy.pid -D 2>&1", $output, $errcode); + } + if (file_exists('/var/run/haproxy.pid')){ + $new_pid = file_get_contents('/var/run/haproxy.pid'); + } else + $new_pid = 'none'; + syslog(LOG_NOTICE, "haproxy: started new pid:$new_pid"); + + foreach($output as $line) + $haproxy_run_message .= "<br/>" . htmlspecialchars($line) . "\n"; + } else { + if ($reload && haproxy_is_running()) { + //exec("/bin/pkill -F /var/run/haproxy.pid haproxy");//doesnt work for multiple pid's in a pidfile + haproxy_kill(); + } + $errcode = 0; + } + unlock($haproxylock); + return ($errcode); +} + +function haproxy_kill($killimmediately = true) { + if ($killimmediately) + $signal = "KILL"; // stop now + else + $signal = "USR1"; // stop when all connections are closed + killprocesses("haproxy", "/var/run/haproxy.pid", $signal); +} + +function killprocesses($processname, $pidfile, $signal = "KILL") { + exec("kill -$signal `pgrep -x $processname | grep -w -f $pidfile`"); +} + +function haproxy_sync_xmlrpc_settings() { + global $config; + // preserve 'old' sync settings, that should not be overwritten by xmlrpc-sync. + $old_config = $config['installedpackages']['haproxy']; + $enable = isset($config['installedpackages']['haproxy']['enablesync']); + + $config['installedpackages']['haproxy'] = $config['installedpackages']['haproxysyncpkg']; + unset($config['installedpackages']['haproxysyncpkg']); + $new_config = &$config['installedpackages']['haproxy']; + + // restore 'old' settings. + $config['installedpackages']['haproxy']['enablesync'] = $enable ? true : false; + $new_config['log-send-hostname'] = $old_config['log-send-hostname']; + + write_config("haproxy, xmlrpc config synced"); // Write new 'merged' configuration +} + +function haproxy_do_xmlrpc_sync() { + $syncinfo = array(); + $syncinfo['sync_logname'] = "HAProxy"; + $syncinfo['data'] = haproxy_xmlrpc_sync_prepare_config(); + $syncinfo['sync_include'] = "/usr/local/pkg/haproxy.inc"; + $syncinfo['sync_done_execute'] = "haproxy_xmlrpc_sync_configure"; + xmlrpc_sync_execute($syncinfo); +} + +function haproxy_xmlrpc_sync_prepare_config() { + /* xml will hold the sections to sync */ + global $config; + $xml = array(); + $xml['haproxysyncpkg'] = $config['installedpackages']['haproxy']; + return $xml; +} + +function haproxy_xmlrpc_sync_configure() { + // this function is called by xmlrpc after config has been synced. + + haproxy_sync_xmlrpc_settings(); + haproxy_configure(); // Configure HAProxy config files to use the new configuration. + + // sync 2nd and further nodes in the chain if applicable. + if(isset($config['installedpackages']['haproxy']['enablesync'])) { + haproxy_do_xmlrpc_sync(); + } +} + +function get_frontend_id($name) { + global $config; + $a_frontend = &$config['installedpackages']['haproxy']['ha_backends']['item']; + $i = 0; + foreach($a_frontend as $frontend) + { + if ($frontend['name'] == $name) + return $i; + $i++; + } + return null; +} + +function haproxy_is_frontendname($name) { + if ($name[0] == '!') + $name = substr($name, 1); + return get_frontend_id($name) != null; +} + +function get_primaryfrontend($frontend) { + global $config; + $a_frontend = &$config['installedpackages']['haproxy']['ha_backends']['item']; + if ($frontend['secondary'] == 'yes') + $mainfrontend = $a_frontend[get_frontend_id($frontend['primary_frontend'])]; + else + $mainfrontend = $frontend; + return $mainfrontend; +} + +function get_frontend_ipport($frontend, $userfriendly=false) { + $mainfrontend = get_primaryfrontend($frontend); + $result = array(); + if (!is_arrayset($mainfrontend,"a_extaddr","item")) + return $result; + foreach($mainfrontend['a_extaddr']['item'] as $extaddr) { + if ($extaddr['extaddr'] == 'custom'){ + $addr = $extaddr['extaddr_custom']; + } else { + $addr = haproxy_interface_ip($extaddr['extaddr'], $userfriendly); + } + if ($userfriendly and is_ipaddrv6($addr)) + $addr = "[{$addr}]"; + + $port = $extaddr['extaddr_port']; + $newitem = array(); + $newitem['addr'] = $addr; + $newitem['port'] = $port; + $newitem['ssl'] = $extaddr['extaddr_ssl']; + $result[$addr.$port] = $newitem; + } + ksort($result); + return $result; +} + +function get_frontend_bindips($frontend) { + $mainfrontend = get_primaryfrontend($frontend); + $result = array(); + if (!is_arrayset($mainfrontend,"a_extaddr","item")) + return $result; + foreach($mainfrontend['a_extaddr']['item'] as $extaddr) { + $a_ip = array(); + if (isset($extaddr['extaddr']) && $extaddr['extaddr'] != "custom") { + $a_ip[] = haproxy_interface_ip($extaddr['extaddr']); + } else { + $iporalias = $extaddr['extaddr_custom']; + $a_ip = haproxy_addressoralias_to_list($iporalias); + } + if ($extaddr['extaddr_ssl'] == 'yes') + $ssl = $ssl_info; + else + $ssl = ""; + + foreach($a_ip as $ip) { + $portsnumeric = group_ports(haproxy_portoralias_to_list($extaddr['extaddr_port'])); + if (is_array($portsnumeric)) { + foreach($portsnumeric as $portnumeric) { + $portnumeric = str_replace(":","-",$portnumeric); + $newitem = array(); + $newitem['addr'] = $ip; + $newitem['port'] = $portnumeric; + $newitem['extaddr_ssl'] = $extaddr['extaddr_ssl']; + $newitem['extaddr_advanced'] = $extaddr['extaddr_advanced']; + $result[] = $newitem; + } + } + } + } + return $result; +} + +function haproxy_check_config() { + global $config; + $a_backends = &$config['installedpackages']['haproxy']['ha_backends']['item']; + $result = false; + $activefrontends = array(); + $issues = array(); + + foreach($a_backends as $frontend) { + if (($frontend['status'] != 'active') || ($frontend['secondary'] == 'yes')) + continue; + $ipports = get_frontend_ipport($frontend); + foreach($ipports as $ipport) { + $id = "{$ipport['addr']}:{$ipport['port']}"; + if (isset($activefrontends[$id])) + $issues['P_'.$id] = "Multiple primary frontends with IP:Port \"$id\", use Shared-Frontends instead."; + else + $activefrontends[$id] = true; + } + } + foreach($a_backends as $frontend) { + if (($frontend['status'] != 'active') || ($frontend['secondary'] != 'yes')) + continue; + $mainfrontend = get_primaryfrontend($frontend); + if (!isset($mainfrontend)) + $issues['S_'.$frontend['name']] = "Secondary frontend \"{$frontend['name']}\" without active primary frontend."; + } + foreach ($issues as $item) + $result .= ($result == false ? "" : "<br/>") . $item; + return $result; +} + +function get_haproxy_frontends($excludeitem="") { + global $config; + $a_frontend = &$config['installedpackages']['haproxy']['ha_backends']['item']; + $result = array(); + if(!is_array($a_frontend)) + return $result; + foreach($a_frontend as &$frontend) + { + if ($frontend['secondary']) + continue; + if ($frontend['name'] == $excludeitem) + continue; + + $serveraddress = get_frontend_ipport($frontend, true); + $serveradresstext = null; + foreach($serveraddress as $addr) { + $serveradresstext .=($serveradresstext == null ? "" : ", ") . "{$addr['addr']}:{$addr['port']}"; + } + $result[$frontend['name']]['name'] = "{$frontend['name']} - {$frontend['type']} ({$serveradresstext})"; + $result[$frontend['name']]['ref'] = &$frontend; + } + uasort($result, haproxy_compareByName); + return $result; +} + +function get_frontend_uses_ssl($frontend) { + $mainfrontend = get_primaryfrontend($frontend); + $ssl = false; + if (is_arrayset($mainfrontend,'a_extaddr','item')) { + foreach($mainfrontend['a_extaddr']['item'] as $extaddr) { + if ($extaddr['extaddr_ssl'] == 'yes') { + $ssl = true; + break; + } + } + } + if ($mainfrontend['name'] != $frontend['name']) + $ssl = $ssl && $frontend['ssloffload'] == 'yes'; + return $ssl; +} + +function get_frontend_uses_ssl_only($frontend) { + $mainfrontend = get_primaryfrontend($frontend); + if (is_arrayset($mainfrontend,'a_extaddr','item')) { + foreach($mainfrontend['a_extaddr']['item'] as $extaddr) { + if ($extaddr['extaddr_ssl'] != 'yes') + return false; + } + } + return true; +} + +function haproxy_get_cert_acl($cert) { + $acl_item = array(); + + $cert_cn = cert_get_cn($cert['crt']); + $descr = haproxy_escape_acl_name($cert['descr']); + unset($cert); + $is_wildcard = substr($cert_cn, 0, 2) == "*."; + $cert_cn_regex = str_replace(".", "\.", $cert_cn); // escape '.' in regex. + $wild_regex = ""; + if ($is_wildcard) { + $cert_cn_regex = "([^\.]*)" . substr($cert_cn_regex, 1);// match only subdomains directly under the wildcard + } + $cert_cn_regex = "^{$cert_cn_regex}(:([0-9]){1,5})?$";// match both with and without port. + + $acl_item['descr'] = "Certificate ACL matches: {$cert_cn}"; + $acl_item['ref'] = array('name' => "{$aclname}_{$descr}",'expression' => 'host_regex', 'value' => $cert_cn_regex, 'certacl' => true); + return $acl_item; +} + +function get_frontend_acls($frontend) { + $mainfrontend = get_primaryfrontend($frontend); + $result = array(); + $a_acl = &$frontend['ha_acls']['item']; + if (is_array($a_acl)) + { + foreach ($a_acl as $entry) { + $acl = haproxy_find_acl($entry['expression']); + if (!$acl) + continue; + + // Filter out acls for different modes + if ($acl['mode'] != '' && $acl['mode'] != strtolower($mainfrontend['type'])) + continue; + $not = $entry['not'] == "yes" ? "not: " : ""; + $acl_item = array(); + $acl_item['descr'] = $acl['name'] . " " . (isset($acl['novalue']) ? "" : $not . $entry['value']); + $acl_item['ref'] = $entry; + + $result[] = $acl_item; + } + } + + if (get_frontend_uses_ssl($frontend)) { + $a_acl = &$frontend['ha_acls']['item']; + if(!is_array($a_acl)) + $a_acl=array(); + + $poolname = $frontend['backend_serverpool'] . "_" . strtolower($frontend['type']); + $aclname = "SNI_" . $poolname; + + if (ifset($frontend['ssloffloadacl']) == 'yes' || ifset($frontend['ssloffloadaclnondefault']) == 'yes') { + $cert = lookup_cert($frontend['ssloffloadcert']); + $result[] = haproxy_get_cert_acl($cert); + } + if (ifset($frontend['ssloffloadacladditional']) == 'yes') { + $certs = $frontend['ha_certificates']['item']; + if (is_array($certs)){ + foreach($certs as $certref){ + $cert = lookup_cert($certref['ssl_certificate']); + $result[] = haproxy_get_cert_acl($cert); + } + } + } + } + return $result; +} + +function get_backend_id($name) { + global $config; + $a_backend = &$config['installedpackages']['haproxy']['ha_pools']['item']; + $i = 0; + if(is_array($a_backend)) + foreach($a_backend as $key => $backend) { + if ($backend['name'] == $name) + return $i; + $i++; + } + return null; +} + +function get_backend($name) { + global $config; + $a_backend = &$config['installedpackages']['haproxy']['ha_pools']['item']; + $id = get_backend_id($name); + if (is_numeric($id)) + return $a_backend[$id]; + return null; +} + +function use_frontend_as_unixsocket($name) { + global $config; + $a_backends = &$config['installedpackages']['haproxy']['ha_pools']['item']; + foreach ($a_backends as $backend) { + $a_servers = &$backend['ha_servers']['item']; + if (is_array($a_servers)) { + foreach($a_servers as $server) { + if ($server['forwardto'] && $server['forwardto'] == $name) + return true; + } + } + } + return false; +} + +function haproxy_escapestring($configurationsting) { + $result = str_replace('\\', '\\\\', $configurationsting); + $result = str_replace(' ', '\\ ', $result); + return str_replace('#', '\\#', $result); +} + +function haproxy_escape_acl_name($aclname) { + return preg_replace_callback('([^A-Za-z0-9\._\-\:])', function($match){return "_".dechex(ord($match[0]));}, $aclname); +} + +function haproxy_find_create_certificate($certificatename) { + global $g; + $cert = lookup_cert_by_name($certificatename); + if (is_array($cert)) + return $cert; + global $config; + $a_cert =& $config['cert']; + $cert = array(); + $cert['refid'] = uniqid(); + $cert['descr'] = gettext($certificatename); + + $new_cert = array(); + $dn = array( + "organizationName" => "haproxy-pfsense", + "commonName" => "haproxy-pfsense" + ); + $new_cert = array(); + ca_create($new_cert, 1024, 2000, $dn); + $crt = base64_decode($new_cert['crt']); + $prv = base64_decode($new_cert['prv']); + cert_import($cert, $crt, $prv); + $a_cert[] = $cert; + return $cert; +} + +?> diff --git a/config/haproxy1_5/pkg/haproxy_htmllist.inc b/config/haproxy1_5/pkg/haproxy_htmllist.inc new file mode 100644 index 00000000..f873028e --- /dev/null +++ b/config/haproxy1_5/pkg/haproxy_htmllist.inc @@ -0,0 +1,455 @@ +<?php +/* + haproxy_htmllist.php + part of pfSense (https://www.pfsense.org/) + Copyright (C) 2013 PiBa-NL + 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, 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. +*/ +/* + This file contains functions which are NOT specific to HAProxy and may/could/should + be moved to the general pfSense php library for possible easy use by other parts of pfSense +*/ + +require_once("config.inc"); +require_once("haproxy_utils.inc"); + +class HaproxyHtmlList +{ + /* + javascript 'events': + <tableId>_row_added(tableId, rowNr) + <tableId>_field_changed(tableId, rowNr, fieldId, field) + */ + + private $tablename = ""; + private $fields = array(); + public $editmode = false; + public $fields_details = null; + public $keyfield = ""; + + public function HaproxyHtmlList($tablename, $fields){ + $this->tablename = $tablename; + $this->fields = $fields; + } + + public function Draw($data){ + $this->haproxy_htmllist($data, $this->fields, $this->editmode, $this->fields_details); + } + + function haproxy_htmllist_get_values(){ + $values = array(); + for($x=0; $x<99; $x++) { + $value = array(); + $add_item = false; + foreach($this->fields as $item){ + $itemname = $item['name']; + $value[$itemname] = $_POST[$itemname.$x]; + if ($item['type'] == 'textarea') + $value[$itemname] = base64_encode($value[$itemname]); + $add_item |= isset($_POST[$itemname.$x]); + } + if ($add_item) { + if ($this->keyfield != "") { + if (isset($_POST[$this->tablename."_key".$x])) + $key = $_POST[$this->tablename."_key".$x]; + else + $key = $_POST[$this->keyfield.$x]; + + } else + $key = ""; + + if (isset($values[$key])) + $values[] = $value; + else + $values[$key] = $value; + } + } + return $values; + } + + private function haproxy_htmllist_drawcell($item, $itemvalue, $editable, $itemname, $counter) { + $itemnamenr = $itemname . $counter; + $itemtype = $item['type']; + if ($editable) { + $itemtype = $item['type']; + if ($itemtype == "select"){ + echo_html_select($itemnamenr, $item['items'], $itemvalue,"","html_listitem_change(\"{$this->tablename}\",\"{$itemname}\",\"{$counter}\",this);", "width:{$item['size']}"); + } else + if ($itemtype == "checkbox"){ + $checked = $itemvalue=='yes' ? " checked" : ""; + echo "<input onclick='html_listitem_change(\"{$this->tablename}\",\"{$itemname}\",\"{$counter}\",this);' name='$itemnamenr' id='$itemnamenr' type='checkbox'$checked value='yes' size='{$item['size']}' />"; + } else + if ($itemtype == "textarea"){ + echo "<textarea name='$itemnamenr' id='$itemnamenr' type='text' cols='{$item['size']}' rows='10'>"; + echo htmlspecialchars(base64_decode($itemvalue)); + echo "</textarea>"; + } else + echo "<input name='$itemnamenr' id='$itemnamenr' type='text' value='{$itemvalue}' size='{$item['size']}' />"; + } else { + if ($itemtype == "select"){ + echo $item['items'][$itemvalue]['name']; + } else + if ($itemtype == "checkbox"){ + echo $itemvalue=='yes' ? gettext('yes') : gettext('no'); + } else + if ($itemtype == "textarea"){ + echo htmlspecialchars(base64_decode($itemvalue)); + } else + echo htmlspecialchars($itemvalue); + } + } + + function haproxy_htmllist($rowvalues,$items,$editstate=false,$itemdetails=null){ + $tablename = $this->tablename; + global $g, $counter; + echo "<table class='' width='100%' cellpadding='0' cellspacing='0' id='$tablename'> + <tr>"; + foreach($items as $item){ + echo "<td width='{$item['colwidth']}' class='listhdrr'>{$item['columnheader']}</td>"; + } + echo "<td width='5%' class=''></td> + </tr>"; + if (is_array($rowvalues)){ + foreach($rowvalues as $keyid => $value){ + if ($this->keyfield != "") { + if (preg_match("/[^0-9]/", $keyid)) + $itemvalue = $keyid; + else + $itemvalue = $value[$this->keyfield]; + $key = "<input name='{$tablename}_key{$counter}' id='{$tablename}_key{$counter}' type='hidden' value='{$itemvalue}'>"; + } else + $key = ""; + + if (!$editstate) { + echo "<tr id='tr_view_$counter' ondblclick='editRow($counter); return false;' >"; + $leftitem = true; + foreach($items as $item) { + $tdclass = $leftitem ? "vtable listlr" : "vtable listr"; + echo "<td class='$tdclass'>"; + $itemname = $item['name']; + $itemvalue = $value[$itemname]; + if (isset($item['customdrawcell'])) { + $item['customdrawcell']($item, $itemvalue, false); + } else + $this->haproxy_htmllist_drawcell($item, $itemvalue, false, $itemname, $counter); + echo "</td>"; + $leftitem = false; + + } + echo " + <td class='list'> + <table border='0' cellspacing='0' cellpadding='1'><tr> + <td valign='middle'> + <img src='/themes/{$g['theme']}/images/icons/icon_e.gif' title='edit entry' width='17' height='17' border='0' onclick='editRow($counter); return false;' /> + </td> + <td valign='middle'> + <img src='/themes/{$g['theme']}/images/icons/icon_x.gif' title='delete entry' width='17' height='17' border='0' onclick='deleteRow($counter, \"$tablename\"); return false;' /> + </td> + <td valign='middle'> + <img src='/themes/{$g['theme']}/images/icons/icon_plus.gif' title='duplicate entry' width='17' height='17' border='0' onclick='dupRow($counter, \"$tablename\"); return false;' /> + </td></tr></table> + </td>"; + echo "</tr>"; + } + $displaystyle = $editstate ? "" : "display: none;"; + echo "<tr id='tr_edit_$counter' style='$displaystyle'>"; + foreach($items as $item){ + $itemname = $item['name']; + $itemvalue = $value[$itemname]; + echo "<td class='vtable'>".$key; + if (isset($item['customdrawcell'])) { + $item['customdrawcell']($item, $itemvalue, true, $item['name'].$counter); + } else + $this->haproxy_htmllist_drawcell($item, $itemvalue, true, $itemname, $counter); + echo "</td>"; + $key = ""; + } + echo " + <td class='list'> + <table border='0' cellspacing='0' cellpadding='1'><tr> + <td valign='middle'> + <img src='/themes/{$g['theme']}/images/icons/icon_x.gif' title='delete entry' width='17' height='17' border='0' onclick='removeRow(this); return false;' /> + </td> + <td valign='middle'> + <img src='/themes/{$g['theme']}/images/icons/icon_plus.gif' title='duplicate entry' width='17' height='17' border='0' onclick='dupRow($counter, \"$tablename\"); return false;' /> + </td></tr></table> + </td>"; + echo "</tr>"; + if (isset($itemdetails)) { + $colspan = count($items)-1; + echo "<tr id='tr_viewdetail_$counter'>"; + ?> + <td class='vtable listlr' style='border-bottom-width: medium;vertical-align:top;'> + <div style="position:relative;float:right;width:11px;height:11px;"> + <a onclick="htmltable_toggle_details('<?="htmltable_{$tablename}_{$counter}_details"?>')"> + <img id="htmltable_<?="{$tablename}_{$counter}"?>_details_off" alt="Expand advanced server settings" + src="tree/plus.gif" style="clip:rect(19px 13px 30px 2px); top:-19px;position:absolute;"/> + </a> + </div> + </td> + <? + echo "<td class='vtable listr' colspan='$colspan' style='border-bottom-width: medium;'>"; + $itemnr = 0; + echo "<div id='htmltable_{$tablename}_{$counter}_details_view'>"; + $itemcount = count($itemdetails); + foreach($itemdetails as $item) { + echo "<div style='float: left;padding-right: 2px;'>"; + $tdclass = "";//$leftitem ? "vtable listlr" : "vtable listr"; + echo $item['columnheader'] . ": "; + $itemname = $item['name']; + $itemvalue = $value[$itemname]; + if (isset($item['customdrawcell'])) { + $item['customdrawcell']($item, $itemvalue, false); + } else + $this->haproxy_htmllist_drawcell($item, $itemvalue, false, $itemname, $counter); + $leftitem = false; + $itemnr++; + if ($itemcount != $itemnr) + echo ", "; + echo "</div>"; + } + echo "</div>"; + echo "<div id='htmltable_{$tablename}_{$counter}_details_edit' style='display:none;'>"; + echo "<table class='tabcont' style='border-collapse:collapse' border='1' cellspacing='0' >"; + $leftitem = true; + foreach($itemdetails as $item) { + echo "<tr id='tr_edititemdetails_$counter' ondblclick='editRow($counter); return false;'>"; + $tdclass = "";//$leftitem ? "vtable listlr" : "vtable listr"; + echo "<td style='border-right:0' class='$tdclass'>"; + echo "{$item['columnheader']}: "; + echo "</td>"; + echo "<td style='border-left:0' class='$tdclass'>"; + $itemname = $item['name']; + $itemvalue = $value[$itemname]; + echo "{$item['description']}<br/>"; + if (isset($item['customdrawcell'])) { + $item['customdrawcell']($item, $itemvalue, true, $itemname . $counter); + } else + $this->haproxy_htmllist_drawcell($item, $itemvalue, true, $itemname, $counter); + echo "</td>"; + $leftitem = false; + echo "</tr>"; + } + echo "</table>"; + echo "</div>"; + echo "</td>"; + echo "</tr>"; + } + if (isset($itemdetails)) { + $colspan = count($items)-1; + echo "<tr id='htmltable_{$tablename}_{$counter}_details' style='$displaystyle' >"; + echo "<td class='vtable listlr' style='border-bottom-width: medium;'> </td>"; + echo "<td class='vtable listr' colspan='$colspan' style='border-bottom-width: medium;'>"; + echo "</td>"; + echo "</tr>"; + } + + $counter++; + } + } + echo "</table> + <a onclick='javascript:addRowTo(\"$tablename\"); return false;' href='#'> + <img border='0' src='/themes/{$g['theme']}/images/icons/icon_plus.gif' alt='' title='add another entry' /> + </a>"; + } +} + +function haproxy_htmllist($tablename,$rowvalues,$items,$editstate=false,$itemdetails=null){ + $list = new HaproxyHtmlList($tablename, $items); + $list->haproxy_htmllist($rowvalues, $items, $editstate, $itemdetails); +} + +function haproxy_htmllist_get_values($html_list){ + $list = new HaproxyHtmlList("-", $html_list); + return $list->haproxy_htmllist_get_values(); +} + +function haproxy_htmllist_js(){ +?><script type="text/javascript"> + function html_listitem_change(tableId, fieldId, rowNr, field) { + javascript_event = tableId + "_listitem_change"; + var fn = window[javascript_event]; + if (typeof fn === 'function'){ + fn(tableId, fieldId, rowNr, field); + } + } + + function htmllist_get_select_items(prefix,tableId) { + var items; + var i = tableId.lastIndexOf('_'); + var items_name = prefix+"_"+tableId.substr(i+1); + items = eval("typeof "+items_name+" !== 'undefined' ? "+items_name+" : {}"); + return items; + } + + var addRowTo = (function() { + return (function (tableId) { + var d, tbody, tr, td, bgc, i, ii, j, type, seltext, items; + var btable, btbody, btr, btd; + d = document; + + items = htmllist_get_select_items('fields',tableId); + + tbody = d.getElementById(tableId).getElementsByTagName("tbody").item(0); + tr = d.createElement("tr"); + totalrows++; + tr.setAttribute("id","aclrow" + totalrows); + + for (var i in items) { + td = d.createElement("td"); + if(items[i]['type'] == 'textbox') { + td.innerHTML="<input size='" + items[i]['size'] + "' name='" + items[i]['name'] + totalrows + + "' id='" + items[i]['name'] + totalrows + + "'><\/input> "; + } else if(items[i]['type'] == 'textarea') { + td.innerHTML="<textarea cols='" + items[i]['size'] + "' rows='30' name='" + items[i]['name'] + totalrows + + "' id='" + items[i]['name'] + totalrows + + "'><\/textarea> "; + } else if(items[i]['type'] == 'select') { + seltext = htmllist_get_select_options(tableId, items[i]['name']); + td.innerHTML="<select style='width:" + items[i]['size'] + "' name='" + items[i]['name'] + totalrows + + "' id='" + items[i]['name'] + totalrows + "' "+ + "onchange='html_listitem_change(\""+tableId+"\",\""+items[i]['name']+"\",\""+totalrows+"\",this);' " + + ">" + seltext + "<\/select> "; + } else { + td.innerHTML="<input type='checkbox' name='" + items[i]['name'] + totalrows +"'"+ + "id='" + items[i]['name'] + totalrows + "' "+ + "onclick='html_listitem_change(\""+tableId+"\",\""+items[i]['name']+"\",\""+totalrows+"\",this);' " + + "value='yes'><\/input> "; + } + tr.appendChild(td); + } + td = d.createElement("td"); + td.rowSpan = "1"; + td.setAttribute("class","list"); + + items = htmllist_get_select_items('fields_details',tableId); + for (var i in items) { + td.innerHTML=td.innerHTML+"<input type='hidden' name='" + items[i]['name'] + totalrows + + "' id='" + items[i]['name'] + totalrows + + "'><\/input> "; + } + + // Recreate the button table. + btable = document.createElement("table"); + btable.setAttribute("border", "0"); + btable.setAttribute("cellspacing", "0"); + btable.setAttribute("cellpadding", "1"); + btbody = document.createElement("tbody"); + btr = document.createElement("tr"); + btd = document.createElement("td"); + btd.setAttribute("valign", "middle"); + btd.innerHTML = '<img src="/themes/' + theme + '/images/icons/icon_x.gif" title="delete entry" width="17" height="17" border="0" onclick="removeRow(this); return false;" />'; + btr.appendChild(btd); + btd = document.createElement("td"); + btd.setAttribute("valign", "middle"); + btd.innerHTML = '<img src="/themes/' + theme + "/images/icons/icon_plus.gif\" title=\"duplicate entry\" width=\"17\" height=\"17\" border=\"0\" onclick=\"dupRow(" + totalrows + ", '" + tableId + "'); return false;\" />"; + btr.appendChild(btd); + btbody.appendChild(btr); + btable.appendChild(btbody); + td.appendChild(btable); + tr.appendChild(td); + tbody.appendChild(tr); + + javascript_row_added = tableId + "_row_added"; + var fn = window[javascript_row_added]; + if (typeof fn === 'function'){ + fn(tableId, totalrows); + } + }); + })(); + function dupRow(rowId, tableId) { + var dupEl; + var newEl; + addRowTo(tableId); + items = htmllist_get_select_items('fields',tableId); + for (var i in items) { + dupEl = document.getElementById(items[i]['name'] + rowId); + newEl = document.getElementById(items[i]['name'] + totalrows); + if (dupEl && newEl) + if(items[i]['type'] == 'checkbox') + newEl.checked = dupEl.checked; + else + newEl.value = dupEl.value; + } + items = htmllist_get_select_items('fields_details',tableId); + for (var i in items) { + dupEl = document.getElementById(items[i]['name'] + rowId); + newEl = document.getElementById(items[i]['name'] + totalrows); + if (dupEl && newEl) + if(items[i]['type'] == 'checkbox') + newEl.value = dupEl.checked ? 'yes' : ''; + else + newEl.value = dupEl.value; + } + javascript_row_added = tableId + "_row_added"; + var fn = window[javascript_row_added]; + if (typeof fn === 'function'){ + fn(tableId, totalrows); + } + } + function editRow(num) { + var trview = document.getElementById('tr_view_' + num); + var tredit = document.getElementById('tr_edit_' + num); + trview.style.display='none'; + tredit.style.display=''; + } + function deleteRow(rowId, tableId) { + var view = document.getElementById("tr_view_" + rowId); + var viewdetail = document.getElementById("tr_viewdetail_" + rowId); + var edit = document.getElementById("tr_edit_" + rowId); + if (view) + view.parentNode.removeChild(view); + if (viewdetail) + viewdetail.parentNode.removeChild(viewdetail); + if (edit) + edit.parentNode.removeChild(edit); + } + function removeRow(el) { + var cel; + // Break out of one table first + while (el && el.nodeName.toLowerCase() != "table") + el = el.parentNode; + while (el && el.nodeName.toLowerCase() != "tr") + el = el.parentNode; + + if (el && el.parentNode) { + cel = el.getElementsByTagName("td").item(0); + el.parentNode.removeChild(el); + } + } + + function htmltable_toggle_details(table_row_detail_id) { + tredit = document.getElementById(table_row_detail_id+'_off'); + trviewdetail = document.getElementById(table_row_detail_id+'_edit'); + treditdetail = document.getElementById(table_row_detail_id+'_view'); + current_on = tredit.style.display == 'none'; + tredit.style.display=current_on ? '' : 'none'; + trviewdetail.style.display=current_on ? 'none' : ''; + treditdetail.style.display=current_on ? '' : 'none'; + } +</script><? +} + +?> diff --git a/config/haproxy1_5/pkg/haproxy_socketinfo.inc b/config/haproxy1_5/pkg/haproxy_socketinfo.inc new file mode 100644 index 00000000..cbfb131b --- /dev/null +++ b/config/haproxy1_5/pkg/haproxy_socketinfo.inc @@ -0,0 +1,165 @@ +<?php +/* + Copyright (C) 2013 PiBa-NL + Copyright 2011 Thomas Schaefer - Tomschaefer.org + Copyright 2011 Marcello Coutinho + Part of pfSense widgets (www.pfsense.org) + + 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. +*/ +/* + Some mods made from pfBlocker widget to make this for HAProxy on Pfsense + Copyleft 2012 by jvorhees +*/ + +//set variables +$refresh_rate = 5000; //miliseconds +$show_frontends = "YES"; +$show_clients = "YES"; +$show_clients_traffic = "YES"; + +function haproxy_socket_command($command){ + $result = array(); + if (file_exists("/tmp/haproxy.socket")) { + $socket = stream_socket_client('unix:///tmp/haproxy.socket', $errno, $errstr); + if ($socket) { + fwrite($socket, "$command\n"); + while (!feof($socket)) { + $result[] = fgets($socket); + } + fclose($socket); + } + } + return $result; +} + +function haproxy_set_server_enabled($backend, $server, $enable) {//"enable be/server ?"/"disable be/server ?" + $enablecommand = $enable ? "enable" : "disable"; + return haproxy_socket_command("$enablecommand server $backend/$server"); +} + +function haproxy_get_tables(){// "show table" + $result = array(); + $cmdresult = haproxy_socket_command("show table"); + foreach($cmdresult as $line) { + if (trim($line) == "") + continue; + list($table,$type,$size,$used) = explode(",", $line); + $table = explode(":", $table); + $type = explode(":", $type); + $size = explode(":", $size); + $used = explode(":", $used); + $newtable = array(); + $tablename = trim($table[1]); + $newtable['type'] = trim($type[1]); + $newtable['size'] = $size[1]; + $newtable['used'] = $used[1]; + $result[$tablename] = $newtable; + } + return $result; +} + +function haproxy_get_statistics(){// "show stat" + $result = array(); + $frontends=array(); + $backends=array(); + $servers=array(); + + $cmdresult = haproxy_socket_command("show stat"); + + foreach($cmdresult as $line) { + list($pxname,$svname,$qcur,$qmax,$scur,$smax,$slim,$stot,$bin,$bout,$dreq,$dresp,$ereq,$econ,$eresp,$wretr,$wredis,$status,$weight,$act,$bck,$chkfail,$chkdown,$lastchg,$downtime,$qlimit,$pid,$iid,$sid,$throttle,$lbtot,$tracked,$type,$rate,$rate_lim,$rate_max,$check_status,$check_code,$check_duration,$hrsp_1xx,$hrsp_2xx,$hrsp_3xx,$hrsp_4xx,$hrsp_5xx,$hrsp_other,$hanafail,$req_rate,$req_rate_max,$req_tot,$cli_abrt,$srv_abrt,$comp_in,$comp_out,$comp_byp,$comp_rsp) = explode(",", $line); + #Retrieve data + switch ($svname) { + case "FRONTEND": + $frontends[] = array( + "pxname" => $pxname, + "scur" => $scur, + "slim" => $slim, + "status" => $status); + break; + case "BACKEND": + $backends[] = array( + "pxname" => $pxname, + "scur" => $scur, + "slim" => $slim, + "status" => $status); + break; + default: + $servers[] = array( + "pxname" => $pxname, + "svname" => $svname, + "scur" => $scur, + "status" => $status); + } + } + $result['frontends'] = $frontends; + $result['backends'] = $backends; + $result['servers'] = $servers; + return $result; +} + +function haproxy_get_clients($show_traffic = false){// "show sess" + $clients=array(); + $sessions = haproxy_socket_command("show sess"); + foreach($sessions as $line) { + if (trim($line) == "") + continue; + list($sessid,$proto,$src,$fe,$be,$srv,$ts,$age,$calls,$rq,$rp,$s0,$s1,$exp) = explode(" ", $line); + #Retrieve data + $sessid = explode(":", $sessid); + $src = explode("=", $src); + $srcip = explode(":", $src[1]); + $srcport = explode(":", $src[1]); + $be = explode("=", $be); + $srv = explode("=", $srv); + $age = explode("=", $age); + $calls = explode("=", $calls); + $exp = explode("=", $exp); + $clients[] = array( + "sessid" => $sessid[0], + "src" => $src[1], + "srcip" => $srcip[0], + "srcport" => $srcport[1], + "be" => $be[1], + "srv" => $srv[1], + "age" => $age[1], + "calls" => $calls[1], + "exp" => $exp[1]); + } + if ($show_traffic) { + foreach($clients as &$client) { + $session_data = haproxy_socket_command("show sess {$client['sessid']}"); + $client['session_data'] = $session_data; + + $req = explode(" ",$session_data[12]); + $x = explode("=",$req[7]); + $client['session_datareq'] = $x[1]; + $res = explode(" ",$session_data[15]); + $x = explode("=",$res[7]); + $client['session_datares'] = $x[1]; + } + } + return $clients; +} + +?> diff --git a/config/haproxy1_5/pkg/haproxy_upgrade_config.inc b/config/haproxy1_5/pkg/haproxy_upgrade_config.inc new file mode 100644 index 00000000..c1c951df --- /dev/null +++ b/config/haproxy1_5/pkg/haproxy_upgrade_config.inc @@ -0,0 +1,204 @@ +<?php +/* + haproxy.inc + Copyright (C) 2015 PiBa-NL + 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. +*/ + +require_once("pkg-utils.inc"); + +function haproxy_upgrade_config() { + global $config, $static_output; + // for future config upgrades. + // make sure the version stays 'comparable' + if (is_arrayset($config,'installedpackages','haproxy') && isset($config['installedpackages']['haproxy']['configversion'])) + $configversion = $config['installedpackages']['haproxy']['configversion']; + else + $configversion = "00.12"; + + $static_output .= "HAProxy, from version $configversion\n"; + update_output_window($static_output); + + $writeconfigupdate = false; + if ($configversion < "00.13") { + /* Do XML upgrade from haproxy 0.31 to haproxy-dev */ + if (is_array($config['installedpackages']['haproxy']['ha_servers'])) { + $static_output .= "HAProxy, Do XML upgrade from haproxy 0.31 to haproxy-dev\n"; + update_output_window($static_output); + + /* We have an old config */ + $config['installedpackages']['haproxy']['ha_pools']['item'] = array(); + $a_global = &$config['installedpackages']['haproxy']; + $a_backends = &$config['installedpackages']['haproxy']['ha_backends']['item']; + $a_oldservers = &$config['installedpackages']['haproxy']['ha_servers']['item']; + $a_pools = &$config['installedpackages']['haproxy']['ha_pools']['item']; + + foreach ($a_backends as $id => $be) { + $a_backends[$id]['status'] = 'active'; + } + $id = 0; + foreach ($a_oldservers as $oldserver) { + $pool=$oldserver; + /* make server sub array */ + $server=array(); + $server['name'] = $oldserver['name']; + $server['address'] = $oldserver['address']; + $server['port'] = $oldserver['port']; + $server['weight'] = $oldserver['weight']; + $a_servers=array(); + $a_servers[]=$server; + /* set new pool */ + $pool['name'] = "pool$id"; + $id++; + $pool['ha_servers']['item']=$a_servers; + /* link to frontend */ + foreach ($a_backends as $id => $be) { + if ($a_backends[$id]['name'] == $oldserver['backend']) { + $a_backends[$id]['backend_serverpool'] = $pool['name']; + $pool['monitor_uri'] = $be['monitor_uri']; + unset($a_backends[$id]['monitor_uri']); + break; + } + } + unset($pool['backend']); + unset($pool['address']); + unset($pool['port']); + unset($pool['weight']); + $a_pools[] = $pool; + } + unset($config['installedpackages']['haproxy']['ha_servers']); + $writeconfigupdate = true; + } + + /* XML update to: pkg v1.3 and 'pool' changed to 'backend_serverpool' because 'pool' was added to listtags() in xmlparse.inc */ + if (is_arrayset($config,'installedpackages','haproxy','ha_backends','item',0,'pool')) { + $static_output .= "HAProxy, Do XML upgrade, change to backend_serverpool from pool array\n"; + update_output_window($static_output); + + foreach($config['installedpackages']['haproxy']['ha_backends']['item'] as &$frontend) + { + $backend_serverpool = $frontend['pool'][0]; + $frontend['backend_serverpool'] = $backend_serverpool; + unset($frontend['pool']); + } + $writeconfigupdate = true; + } + //also move setting for existing 2.0 installations as only the new variable is used + if (is_arrayset($config,'installedpackages','haproxy','ha_backends','item',0) && + isset($config['installedpackages']['haproxy']['ha_backends']['item'][0]['pool'])) { + $static_output .= "HAProxy, Do XML upgrade, change to backend_serverpool from pool\n"; + update_output_window($static_output); + foreach($config['installedpackages']['haproxy']['ha_backends']['item'] as &$frontend) + { + $backend_serverpool = $frontend['pool']; + $frontend['backend_serverpool'] = $backend_serverpool; + unset($frontend['pool']); + } + $writeconfigupdate = true; + } + // update config to "haproxy-devel 1.5-dev19 pkg v0.5" + if(is_arrayset($config,'installedpackages','haproxy','ha_backends','item')) { + $static_output .= "HAProxy, Do XML upgrade, update frontend options\n"; + update_output_window($static_output); + foreach ($config['installedpackages']['haproxy']['ha_backends']['item'] as &$bind) { + if($bind['httpclose'] && $bind['httpclose'] == "yes" ) { + $bind['httpclose'] = "httpclose"; + $writeconfigupdate = true; + } + if (!$bind['extaddr']){ + $bind['extaddr'] = "wan_ipv4"; + $writeconfigupdate = true; + } + if ($bind['extaddr'] == "localhost"){ + $bind['extaddr'] = "localhost_ipv4"; + $writeconfigupdate = true; + } + if ($bind['extaddr'] == "any"){ + $bind['extaddr'] = "any_ipv4"; + $writeconfigupdate = true; + } + } + } + } + if ($configversion < "00.13") { + // update config to "haproxy-devel 1.5-dev19 pkg v0.13" + foreach ($config['installedpackages']['haproxy']['ha_backends']['item'] as &$bind) { + if (isset($bind['extaddr'])) { + $new['extaddr'] = $bind['extaddr']; + $new['extaddr_port'] = $bind['port']; + $new['extaddr_ssl'] = $bind['ssloffload']; + $bind['a_extaddr']['item'][] = $new; + } + unset($bind['extaddr']); + unset($bind['port']); + //unset($bind['ssloffload']); + } + $configversion = "00.13"; + } + if ($configversion < "00.16") { + $static_output .= "HAProxy, 00.16\n"; + $static_output .= "HAProxy, NOTICE: Changes to certificate acl's might need adjusting current config accordingly.\n"; + $static_output .= "HAProxy, NOTICE: Certificate acls are now combined with user acls.\n"; + update_output_window($static_output); + $configversion = "00.16"; + } + if ($configversion < "00.17") { + $static_output .= "HAProxy, 00.17\n"; + update_output_window($static_output); + // remove 'none' ca-cert, and set checkbox to allow for no certificate instead. + foreach ($config['installedpackages']['haproxy']['ha_backends']['item'] as &$bind) { + $list = array(); + foreach ($bind['clientcert_ca']['item'] as $ca){ + if (empty($ca['cert_ca'])) + $bind['sslclientcert-none'] = 'yes'; + else + $list[] = $ca; + } + $bind['clientcert_ca']['item'] = $list; + } + $configversion = "00.17"; + } + if ($configversion < "00.19") { + update_output_window($static_output); + $carpint = $config['installedpackages']['haproxy']['carpdev']; + if (is_arrayset($config, 'virtualip', 'vip') && is_arrayset($config, 'installedpackages', 'haproxy')) { + foreach($config['virtualip']['vip'] as $carp) { + $carp_int = "{$carp['interface']}_vip{$carp['vhid']}"; + if ($carp_int == $carpint) { + $config['installedpackages']['haproxy']['carpdev'] = $carp['subnet']; + break; + } + } + } + $configversion = "00.19"; + } + + $writeconfigupdate = $config['installedpackages']['haproxy']['configversion'] <> $configversion; + if ($writeconfigupdate) { + $config['installedpackages']['haproxy']['configversion'] = $configversion; + $static_output .= "HAProxy, write updated config to version: $configversion\n"; + update_output_window($static_output); + write_config("HAProxy, update xml config version"); + } +} diff --git a/config/haproxy1_5/pkg/haproxy_utils.inc b/config/haproxy1_5/pkg/haproxy_utils.inc new file mode 100644 index 00000000..d8c4faf4 --- /dev/null +++ b/config/haproxy1_5/pkg/haproxy_utils.inc @@ -0,0 +1,459 @@ +<?php +/* + haproxy_utils.php + part of pfSense (https://www.pfsense.org/) + Copyright (C) 2013-2015 PiBa-NL + 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, 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. +*/ +/* + This file contains functions which are NOT specific to HAProxy and may/could/should + be moved to the general pfSense php library for possible easy use by other parts of pfSense +*/ + +require_once("config.inc"); + +class haproxy_utils { + public static $pf_version; + + public function query_dns($host, $querytype="A,AAAA", $dnsserver = "127.0.0.1") { + $result = array(); + $host = trim($host, " \t\n\r\0\x0B[];\"'"); + $host_esc = escapeshellarg($host); + $types = explode(',',$querytype); + foreach($types as $type){ + $resolved = gethostbyname($host); + if($resolved) { + $resolved = array(); + if (haproxy_utils::$pf_version < '2.2') + exec("/usr/bin/dig {$host_esc} $type @$dnsserver | /usr/bin/grep {$host_esc} | /usr/bin/grep -v ';' | /usr/bin/awk '{ print $5 }'", $resolved); + else + exec("/usr/bin/drill {$host_esc} $type @$dnsserver | /usr/bin/grep {$host_esc} | /usr/bin/grep -v ';' | /usr/bin/awk '{ print $5 }'", $resolved); + foreach($resolved as $item) { + $newitem = array(); + $newitem["typeid"] = $type; + $newitem["data"] = $item; + $result[] = $newitem; + } + } + } + return $result; + } +} +haproxy_utils::$pf_version = substr(trim(file_get_contents("/etc/version")),0,3); + +if(!function_exists('ifset')){ + function ifset(&$var, $default = ''){ + return isset($var) ? $var : $default; + }; +} + +if(!function_exists('is_arrayset')){ + function is_arrayset(&$array, $items){ + if (!isset($array)) + return false; + $item = $array; + $arg = func_get_args(); + for($i = 1; $i < count($arg); $i++) { + + $itemindex = $arg[$i]; + if (!isset($item[$itemindex]) || !is_array($item[$itemindex])) + return false; + $item = $item[$itemindex]; + + } + return true; + } +} + +function haproxy_compareByName($a, $b) { + return strcasecmp($a['name'], $b['name']); +} + +function haproxy_interface_ip($interfacebindname,$userfriendly=false){ + $list = haproxy_get_bindable_interfaces(); + $item = $list[$interfacebindname]; + $result = $item['ip']; + if ($userfriendly && !$result) + $result = $item['name']; + return $result; +} + +function haproxy_get_bindable_interfaces($ipv="ipv4,ipv6", $interfacetype="any,localhost,real,carp,ipalias"){ + // returns a list of ALL interface/IPs that can be used to bind a service to. + // filtered by the conditions given in the two filter parameters. + // result array includes: + // $bindable[key] can be stored and compared with previous setings + // $bindable[key]['ip'] the current IP (possibly changes for dhcp enabled interfaces..) + // $bindable[key]['description'] can be shown to user in a selection box + + global $config; + $ipverions = split(',',$ipv); + $interfacetypes= split(',',$interfacetype); + + $bindable = array(); + if (in_array("ipv4",$ipverions)){ + if (in_array('any',$interfacetypes)){ + $item = array(); + $item[ip] = '0.0.0.0'; + $item[name] = 'any (IPv4)'; + $bindable['any_ipv4'] = $item; + } + if (in_array('localhost',$interfacetypes)){ + $item = array(); + $item[ip] = '127.0.0.1'; + $item[name] = 'localhost (IPv4)'; + $bindable['localhost_ipv4'] = $item; + } + if (in_array('real',$interfacetypes)){ + foreach($config['interfaces'] as $if => $ifdetail) { + if (!isset($ifdetail['enable'])) + continue; + if (!isset($ifdetail['ipaddr'])) + continue; + $descr = $ifdetail['descr']; + if (!$descr){ + if ($if == "wan" && !$ifdetail['descr']) + $descr = "WAN"; + else if ($if == "lan" && !$ifdetail['descr']) + $descr = "LAN"; + else + $descr = $if; + } + $item = array(); + $item['ip'] = get_interface_ip($if); + $item['name'] = "$descr address (IPv4)"; + $bindable[$if.'_ipv4'] = $item; + } + } + if (in_array('carp',$interfacetypes)){ + $carplist = get_configured_carp_interface_list(); + foreach ($carplist as $carpif => $carpip){ + if (is_ipaddrv4($carpip)){ + $item = array(); + $item['ip'] = $carpip; + $item['name'] = $carpip." (".get_vip_descr($carpip).")"; + $bindable[$carpip] = $item; + } + } + + } + if (in_array('ipalias',$interfacetypes)){ + $aliaslist = get_configured_ip_aliases_list(); + foreach ($aliaslist as $aliasip => $aliasif){ + if (is_ipaddrv4($aliasip)){ + $item = array(); + $item['ip'] = $aliasip; + $item['name'] = $aliasip." (".get_vip_descr($aliasip).")"; + $bindable[$aliasip.'_ipv4'] = $item; + } + } + } + } + if (!isset($config['system']['ipv6allow'])) + return $bindable;// skip adding the IPv6 addresses if those are not 'allowed' + + if (in_array("ipv6",$ipverions)){ + if (in_array('any',$interfacetypes)){ + $item = array(); + $item[ip] = '::'; + $item[name] = 'any (IPv6)'; + $bindable['any_ipv6'] = $item; + } + if (in_array('localhost',$interfacetypes)){ + $item = array(); + $item[ip] = '::1'; + $item[name] = 'localhost (IPv6)'; + $bindable['localhost_ipv6'] = $item; + } + if (in_array('real',$interfacetypes)){ + foreach($config['interfaces'] as $if => $ifdetail) { + if (!isset($ifdetail['enable'])) + continue; + if (!isset($ifdetail['ipaddrv6'])) + continue; + $descr = $ifdetail['descr']; + if (!$descr){ + if ($if == "wan" && !$ifdetail['descr']) + $descr = "WAN"; + else if ($if == "lan" && !$ifdetail['descr']) + $descr = "LAN"; + else + $descr = $if; + } + $item = array(); + $item['ip'] = get_interface_ipv6($if); + $item['name'] = "$descr address (IPv6)"; + $bindable[$if.'_ipv6'] = $item; + } + } + if (in_array('carp',$interfacetypes)){ + $carplist = get_configured_carp_interface_list(); + foreach ($carplist as $carpif => $carpip){ + if (is_ipaddrv6($carpip)){ + $item = array(); + $item['ip'] = $carpip; + $item['name'] = $carpip." (".get_vip_descr($carpip).")"; + $bindable[$carpip] = $item; + } + } + + } + if (in_array('ipalias',$interfacetypes)){ + $aliaslist = get_configured_ip_aliases_list(); + foreach ($aliaslist as $aliasip => $aliasif){ + if (is_ipaddrv6($aliasip)){ + $item = array(); + $item['ip'] = $aliasip; + $item['name'] = $aliasip." (".get_vip_descr($aliasip).")"; + $bindable[$aliasip] = $item; + } + } + } + } + return $bindable; +} + +function haproxy_get_cert_extensions($crt){ + $cert = openssl_x509_parse(base64_decode($crt['crt'])); + return $cert['extensions']; +} + +function haproxy_get_cert_authoritykeyidentifier($cert) +{ + $certextension = haproxy_get_cert_extensions($cert); + $lines = preg_split('/[\n]+/',$certextension['authorityKeyIdentifier']); + return substr($lines[0],6);// cut off the starting string 'keyid:' +} +function haproxy_get_cert_subjectKeyIdentifier($cert) +{ + $certextension = haproxy_get_cert_extensions($cert); + $lines = preg_split('/[\n]+/',$certextension['subjectKeyIdentifier']); + return $lines[0]; +} + +function haproxy_cert_signed_by($cert, $signedbycert) { + // checks if $cert was signed by $signedbycert + // this does NOT validate a proper signature but only checks if the extension properties match. + $authoritykeyid = haproxy_get_cert_authoritykeyidentifier($cert); + $subjectid = haproxy_get_cert_subjectKeyIdentifier($signedbycert); + return $authoritykeyid == $subjectid; +} + +function haproxy_recalculate_certifcate_chain(){ + // and set "selfsigned" for certificates that where used to sign themselves + // recalculate the "caref" for all certificates where it is currently unkown. + + $allcertificates = haproxy_get_certificates('ca,server,user',true); + $items_recalculated = 0; + foreach($allcertificates as &$cert){ + $recalculate=false; + if (!isset($cert['selfsigned'])){ + if (!isset($cert['caref'])) + $recalculate=true; + else { + $ca = lookup_ca($cert['caref']); + if (!$ca) + $recalculate=true; + } + } + if ($recalculate){ + foreach($allcertificates as &$signedbycert){ + if(haproxy_cert_signed_by($cert, $signedbycert)){ + if ($cert['refid'] == $signedbycert['refid']){ + $cert['selfsigned'] = true; + } else { + $cert['caref'] = $signedbycert['refid']; + } + $items_recalculated++; + } + } + } + } + if ($items_recalculated > 0) + write_config("Services: HAProxy: Recalculated $items_recalculated certificate chains."); + return $items_recalculated; +} + +function get_certificat_usage($refid) { + $usage = array(); + $cert = lookup_cert($refid); + if (is_cert_revoked($cert)) + $usage[] = "*Revoked"; + if (is_webgui_cert($refid)) + $usage[] = "webConfigurator"; + if (is_user_cert($refid)) + $usage[] = "User Cert"; + if (is_openvpn_server_cert($refid)) + $usage[] = "OpenVPN Server"; + if (is_openvpn_client_cert($refid)) + $usage[] = "OpenVPN Client"; + if (is_ipsec_cert($refid)) + $usage[] = "IPsec Tunnel"; + if (function_exists("is_captiveportal_cert")) + if (is_captiveportal_cert($refid)) + $usage[] = "Captive Portal"; + return $usage; +} + +function haproxy_get_certificate_descriptivename($cert) { + $usage = get_certificat_usage($cert['crt']); + foreach($usage as $use){ + $usagestr .= " " . $use; + } + if ($usagestr != "") + $usagestr = " (".trim($usagestr).")"; + + $purpose = cert_get_purpose($cert['crt']); + $certserverpurpose = $purpose['server'] == 'Yes' ? " [Server cert]" : ""; + + $caname = ""; + $ca = lookup_ca($cert['caref']); + if ($ca) + $caname = " (CA: {$ca['descr']})"; + + return $cert['descr'] . $caname . $certserverpurpose . $usagestr; +} + +function haproxy_get_certificates($type = 'server,user', $get_includeWebCert=false) { + // $type one or multiple of these separated by a comma: ca,server,user + // $get_includeWebCert if the webgui certificate may be included. + + // This function (is intended to) provide a uniform way to retrieve a list of server certificates + global $config; + $type = ",$type,"; + $certificates = array(); + if (strpos($type,',server,') !== false || strpos($type,',user,') !== false ) { + if (is_array($config['cert'])) { + $a_cert = &$config['cert']; + foreach ($a_cert as $cert) { + $purpose = cert_get_purpose($cert['crt']); + + $ok = false; + $ok |= stristr($type,',server,') && $purpose['server'] == 'Yes'; + $ok |= stristr($type,',user,') && $purpose['server'] != 'Yes'; + if (!$ok) + continue; + if ($get_includeWebCert == false && $cert['descr'] == "webConfigurator default") + continue; + $certificates[$cert['refid']]['name'] = haproxy_get_certificate_descriptivename($cert); + } + } + } + if (strpos($type,',ca,') !== false) { + if (is_array($config['ca'])) { + $a_cert = &$config['ca']; + foreach ($a_cert as $cert) { + $certificates[$cert['refid']]['name'] = haproxy_get_certificate_descriptivename($cert); + } + } + } + uasort($certificates, haproxy_compareByName); + return $certificates; +} + +function haproxy_get_crls() { + global $config; + $certificates=array(); + if (is_array($config['crl'])) { + foreach ($config['crl'] as $crl) { + $caname = ""; + $ca = lookup_ca($crl['caref']); + if ($ca) + $caname = " (CA: {$ca['descr']})"; + + $certificates[$crl['refid']]['name'] = $crl['descr'] . $caname; + } + } + uasort($certificates, haproxy_compareByName); + return $certificates; +} + +function phparray_to_javascriptarray_recursive($nestID, $path, $items, $nodeName, $includeitems) { + $offset = str_repeat(' ',$nestID); + $itemName = "item$nestID"; + echo "{$offset}$nodeName = {};\n"; + if (is_array($items)) + foreach ($items as $key => $item) + { + if (in_array($path.'/'.$key, $includeitems)) + $subpath = $path.'/'.$key; + else + $subpath = $path.'/*'; + if (in_array($subpath, $includeitems) || in_array($path.'/*', $includeitems)) { + if (is_array($item)) { + $subNodeName = "item$nestID"; + phparray_to_javascriptarray_recursive($nestID+1, $subpath, $items[$key], $subNodeName, $includeitems); + echo "{$offset}{$nodeName}['{$key}'] = $itemName;\n"; + } else { + $item = json_encode($item); + echo "{$offset}{$nodeName}['$key'] = $item;\n"; + } + } + } +} +function phparray_to_javascriptarray($items, $javaMapName, $includeitems) { + phparray_to_javascriptarray_recursive(1,'',$items, $javaMapName, $includeitems); +} + +function haproxy_html_select_options($keyvaluelist, $selected="") { + $result = ""; + foreach($keyvaluelist as $key => $desc){ + $selectedhtml = $key == $selected ? "selected" : ""; + if ($desc['deprecated'] && $key != $selected){ + continue; + } + $name = htmlspecialchars($desc['name']); + $result .= "<option value='{$key}' {$selectedhtml}>{$name}</option>"; + } + return $result; +} + +function haproxy_js_select_options($keyvaluelist, $selected="") { + $result = ""; + foreach($keyvaluelist as $key => $desc){ + $selectedhtml = $key == $selected ? "selected" : ""; + if ($desc['deprecated'] && $key != $selected){ + continue; + } + $name = htmlspecialchars($desc['name']); + $result .= "<option value='{$key}' {$selectedhtml}>{$name}<\/option>"; + } + return $result; +} + +function echo_html_select($name, $keyvaluelist, $selected, $listEmptyMessage="", $onchangeEvent="", $style="") { + if (count($keyvaluelist)>0){ + if ($onchangeEvent != "") + $onchangeEvent = " onchange='$onchangeEvent'"; + if ($style != "") + $style = " style='$style'"; + echo "<select name=\"$name\" id=\"$name\" class=\"formselect\"$onchangeEvent$style>"; + echo haproxy_html_select_options($keyvaluelist, $selected); + echo "</select>"; + } else { + echo $listEmptyMessage; + } +} + +?>
\ No newline at end of file diff --git a/config/haproxy1_5/pkg/haproxy_utils.inc.bak b/config/haproxy1_5/pkg/haproxy_utils.inc.bak new file mode 100644 index 00000000..26c77b45 --- /dev/null +++ b/config/haproxy1_5/pkg/haproxy_utils.inc.bak @@ -0,0 +1,460 @@ +<?php +/* + haproxy_utils.php + part of pfSense (https://www.pfsense.org/) + Copyright (C) 2013-2015 PiBa-NL + 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, 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. +*/ +/* + This file contains functions which are NOT specific to HAProxy and may/could/should + be moved to the general pfSense php library for possible easy use by other parts of pfSense +*/ + +require_once("config.inc"); + +class haproxy_utils { + public static $pf_version; + + public function query_dns($host, $querytype="A,AAAA", $dnsserver = "127.0.0.1") { + $result = array(); + $host = trim($host, " \t\n\r\0\x0B[];\"'"); + $host_esc = escapeshellarg($host); + $types = explode(',',$querytype); + foreach($types as $type){ + $resolved = gethostbyname($host); + if($resolved) { + $resolved = array(); + if (haproxy_utils::$pf_version < '2.2') + exec("/usr/bin/dig {$host_esc} $type @$dnsserver | /usr/bin/grep {$host_esc} | /usr/bin/grep -v ';' | /usr/bin/awk '{ print $5 }'", $resolved); + else + exec("/usr/bin/drill {$host_esc} $type @$dnsserver | /usr/bin/grep {$host_esc} | /usr/bin/grep -v ';' | /usr/bin/awk '{ print $5 }'", $resolved); + foreach($resolved as $item) { + $newitem = array(); + $newitem["typeid"] = $type; + $newitem["data"] = $item; + $result[] = $newitem; + } + } + } + return $result; + } +} +haproxy_utils::$pf_version = substr(trim(file_get_contents("/etc/version")),0,3); + +if(!function_exists('ifset')){ + function ifset(&$var, $default = ''){ + return isset($var) ? $var : $default; + }; +} + +if(!function_exists('is_arrayset')){ + function is_arrayset(&$array, $items){ + if (!isset($array)) + return false; + $item = $array; + $arg = func_get_args(); + for($i = 1; $i < count($arg); $i++) { + + $itemindex = $arg[$i]; + if (!isset($item[$itemindex]) || !is_array($item[$itemindex])) + return false; + $item = $item[$itemindex]; + + } + return true; + } +} + +function haproxy_compareByName($a, $b) { + return strcasecmp($a['name'], $b['name']); +} + +function haproxy_interface_ip($interfacebindname,$userfriendly=false){ + $list = haproxy_get_bindable_interfaces(); + $item = $list[$interfacebindname]; + $result = $item['ip']; + if ($userfriendly && !$result) + $result = $item['name']; + return $result; +} + +function haproxy_get_bindable_interfaces($ipv="ipv4,ipv6", $interfacetype="any,localhost,real,carp,ipalias"){ + // returns a list of ALL interface/IPs that can be used to bind a service to. + // filtered by the conditions given in the two filter parameters. + // result array includes: + // $bindable[key] can be stored and compared with previous setings + // $bindable[key]['ip'] the current IP (possibly changes for dhcp enabled interfaces..) + // $bindable[key]['description'] can be shown to user in a selection box + + global $config; + $ipverions = split(',',$ipv); + $interfacetypes= split(',',$interfacetype); + + $bindable = array(); + if (in_array("ipv4",$ipverions)){ + if (in_array('any',$interfacetypes)){ + $item = array(); + $item[ip] = '0.0.0.0'; + $item[name] = 'any (IPv4)'; + $bindable['any_ipv4'] = $item; + } + if (in_array('localhost',$interfacetypes)){ + $item = array(); + $item[ip] = '127.0.0.1'; + $item[name] = 'localhost (IPv4)'; + $bindable['localhost_ipv4'] = $item; + } + if (in_array('real',$interfacetypes)){ + foreach($config['interfaces'] as $if => $ifdetail) { + if (!isset($ifdetail['enable'])) + continue; + if (!isset($ifdetail['ipaddr'])) + continue; + $descr = $ifdetail['descr']; + if (!$descr){ + if ($if == "wan" && !$ifdetail['descr']) + $descr = "WAN"; + else if ($if == "lan" && !$ifdetail['descr']) + $descr = "LAN"; + else + $descr = $if; + } + $item = array(); + $item['ip'] = get_interface_ip($if); + $item['name'] = "$descr address (IPv4)"; + $bindable[$if.'_ipv4'] = $item; + } + } + if (in_array('carp',$interfacetypes)){ + $carplist = get_configured_carp_interface_list(); + foreach ($carplist as $carpif => $carpip){ + if (is_ipaddrv4($carpip)){ + $item = array(); + $item['ip'] = $carpip; + $item['name'] = $carpip." (".get_vip_descr($carpip).")"; + $bindable[$carpip] = $item; + } + } + + } + if (in_array('ipalias',$interfacetypes)){ + $aliaslist = get_configured_ip_aliases_list(); + foreach ($aliaslist as $aliasip => $aliasif){ + if (is_ipaddrv4($aliasip)){ + $item = array(); + $item['ip'] = $aliasip; + $item['name'] = $aliasip." (".get_vip_descr($aliasip).")"; + $bindable[$aliasip.'_ipv4'] = $item; + } + } + } + } + if (!isset($config['system']['ipv6allow'])) + return $bindable;// skip adding the IPv6 addresses if those are not 'allowed' + + if (in_array("ipv6",$ipverions)){ + if (in_array('any',$interfacetypes)){ + $item = array(); + $item[ip] = '::'; + $item[name] = 'any (IPv6)'; + $bindable['any_ipv6'] = $item; + } + if (in_array('localhost',$interfacetypes)){ + $item = array(); + $item[ip] = '::1'; + $item[name] = 'localhost (IPv6)'; + $bindable['localhost_ipv6'] = $item; + } + if (in_array('real',$interfacetypes)){ + foreach($config['interfaces'] as $if => $ifdetail) { + if (!isset($ifdetail['enable'])) + continue; + if (!isset($ifdetail['ipaddrv6'])) + continue; + $descr = $ifdetail['descr']; + if (!$descr){ + if ($if == "wan" && !$ifdetail['descr']) + $descr = "WAN"; + else if ($if == "lan" && !$ifdetail['descr']) + $descr = "LAN"; + else + $descr = $if; + } + $item = array(); + $item['ip'] = get_interface_ipv6($if); + $item['name'] = "$descr address (IPv6)"; + $bindable[$if.'_ipv6'] = $item; + } + } + if (in_array('carp',$interfacetypes)){ + $carplist = get_configured_carp_interface_list(); + foreach ($carplist as $carpif => $carpip){ + if (is_ipaddrv6($carpip)){ + $item = array(); + $item['ip'] = $carpip; + $item['name'] = $carpip." (".get_vip_descr($carpip).")"; + $bindable[$carpip] = $item; + } + } + + } + if (in_array('ipalias',$interfacetypes)){ + $aliaslist = get_configured_ip_aliases_list(); + foreach ($aliaslist as $aliasip => $aliasif){ + if (is_ipaddrv6($aliasip)){ + $item = array(); + $item['ip'] = $aliasip; + $item['name'] = $aliasip." (".get_vip_descr($aliasip).")"; + $bindable[$aliasip] = $item; + } + } + } + } + return $bindable; +} + +function haproxy_get_cert_extensions($crt){ + $cert = openssl_x509_parse(base64_decode($crt['crt'])); + return $cert['extensions']; +} + +function haproxy_get_cert_authoritykeyidentifier($cert) +{ + $certextension = haproxy_get_cert_extensions($cert); + $lines = preg_split('/[\n]+/',$certextension['authorityKeyIdentifier']); + return substr($lines[0],6);// cut off the starting string 'keyid:' +} +function haproxy_get_cert_subjectKeyIdentifier($cert) +{ + $certextension = haproxy_get_cert_extensions($cert); + $lines = preg_split('/[\n]+/',$certextension['subjectKeyIdentifier']); + return $lines[0]; +} + +function haproxy_cert_signed_by($cert, $signedbycert) { + // checks if $cert was signed by $signedbycert + // this does NOT validate a proper signature but only checks if the extension properties match. + $authoritykeyid = haproxy_get_cert_authoritykeyidentifier($cert); + $subjectid = haproxy_get_cert_subjectKeyIdentifier($signedbycert); + return $authoritykeyid == $subjectid; +} + +function haproxy_recalculate_certifcate_chain(){ + // and set "selfsigned" for certificates that where used to sign themselves + // recalculate the "caref" for all certificates where it is currently unkown. + + $allcertificates = haproxy_get_certificates('ca,server,user',true); + $items_recalculated = 0; + foreach($allcertificates as &$cert){ + $recalculate=false; + if (!isset($cert['selfsigned'])){ + if (!isset($cert['caref'])) + $recalculate=true; + else { + $ca = lookup_ca($cert['caref']); + if (!$ca) + $recalculate=true; + } + } + if ($recalculate){ + foreach($allcertificates as &$signedbycert){ + if(haproxy_cert_signed_by($cert, $signedbycert)){ + if ($cert['refid'] == $signedbycert['refid']){ + $cert['selfsigned'] = true; + } else { + $cert['caref'] = $signedbycert['refid']; + } + $items_recalculated++; + } + } + } + } + if ($items_recalculated > 0) + write_config("Services: HAProxy: Recalculated $items_recalculated certificate chains."); + return $items_recalculated; +} + +function get_certificat_usage($refid) { + $usage = array(); + $cert = lookup_cert($refid); + if (is_cert_revoked($cert)) + $usage[] = "*Revoked"; + if (is_webgui_cert($refid)) + $usage[] = "webConfigurator"; + if (is_user_cert($refid)) + $usage[] = "User Cert"; + if (is_openvpn_server_cert($refid)) + $usage[] = "OpenVPN Server"; + if (is_openvpn_client_cert($refid)) + $usage[] = "OpenVPN Client"; + if (is_ipsec_cert($refid)) + $usage[] = "IPsec Tunnel"; + if (function_exists("is_captiveportal_cert")) + if (is_captiveportal_cert($refid)) + $usage[] = "Captive Portal"; + return $usage; +} + +function haproxy_get_certificate_descriptivename($cert) { + $usage = get_certificat_usage($cert['crt']); + foreach($usage as $use){ + $usagestr .= " " . $use; + } + if ($usagestr != "") + $usagestr = " (".trim($usagestr).")"; + + $purpose = cert_get_purpose($cert['crt']); + $certserverpurpose = $purpose['server'] == 'Yes' ? " [Server cert]" : ""; + + $caname = ""; + $ca = lookup_ca($cert['caref']); + if ($ca) + $caname = " (CA: {$ca['descr']})"; + + return $cert['descr'] . $caname . $certserverpurpose . $usagestr; +} + +function haproxy_get_certificates($type = 'server,user', $get_includeWebCert=false) { + // $type one or multiple of these separated by a comma: ca,server,user + // $get_includeWebCert if the webgui certificate may be included. + + // This function (is intended to) provide a uniform way to retrieve a list of server certificates + global $config; + $type = ",$type,"; + $certificates = array(); + if (strpos($type,',server,') !== false || strpos($type,',user,') !== false ) { + if (is_array($config['cert'])) { + $a_cert = &$config['cert']; + foreach ($a_cert as $cert) { + $purpose = cert_get_purpose($cert['crt']); + + $ok = false; + $ok |= stristr($type,',server,') && $purpose['server'] == 'Yes'; + $ok |= stristr($type,',user,') && $purpose['server'] != 'Yes'; + if (!$ok) + continue; + //if ($get_includeWebCert == false && is_webgui_cert($cert['refid'])) + if ($get_includeWebCert == false && $cert['descr'] == "def web cert") + continue; + $certificates[$cert['refid']]['name'] = haproxy_get_certificate_descriptivename($cert); + } + } + } + if (strpos($type,',ca,') !== false) { + if (is_array($config['ca'])) { + $a_cert = &$config['ca']; + foreach ($a_cert as $cert) { + $certificates[$cert['refid']]['name'] = haproxy_get_certificate_descriptivename($cert); + } + } + } + uasort($certificates, haproxy_compareByName); + return $certificates; +} + +function haproxy_get_crls() { + global $config; + $certificates=array(); + if (is_array($config['crl'])) { + foreach ($config['crl'] as $crl) { + $caname = ""; + $ca = lookup_ca($crl['caref']); + if ($ca) + $caname = " (CA: {$ca['descr']})"; + + $certificates[$crl['refid']]['name'] = $crl['descr'] . $caname; + } + } + uasort($certificates, haproxy_compareByName); + return $certificates; +} + +function phparray_to_javascriptarray_recursive($nestID, $path, $items, $nodeName, $includeitems) { + $offset = str_repeat(' ',$nestID); + $itemName = "item$nestID"; + echo "{$offset}$nodeName = {};\n"; + if (is_array($items)) + foreach ($items as $key => $item) + { + if (in_array($path.'/'.$key, $includeitems)) + $subpath = $path.'/'.$key; + else + $subpath = $path.'/*'; + if (in_array($subpath, $includeitems) || in_array($path.'/*', $includeitems)) { + if (is_array($item)) { + $subNodeName = "item$nestID"; + phparray_to_javascriptarray_recursive($nestID+1, $subpath, $items[$key], $subNodeName, $includeitems); + echo "{$offset}{$nodeName}['{$key}'] = $itemName;\n"; + } else { + $item = json_encode($item); + echo "{$offset}{$nodeName}['$key'] = $item;\n"; + } + } + } +} +function phparray_to_javascriptarray($items, $javaMapName, $includeitems) { + phparray_to_javascriptarray_recursive(1,'',$items, $javaMapName, $includeitems); +} + +function haproxy_html_select_options($keyvaluelist, $selected="") { + $result = ""; + foreach($keyvaluelist as $key => $desc){ + $selectedhtml = $key == $selected ? "selected" : ""; + if ($desc['deprecated'] && $key != $selected){ + continue; + } + $name = htmlspecialchars($desc['name']); + $result .= "<option value='{$key}' {$selectedhtml}>{$name}</option>"; + } + return $result; +} + +function haproxy_js_select_options($keyvaluelist, $selected="") { + $result = ""; + foreach($keyvaluelist as $key => $desc){ + $selectedhtml = $key == $selected ? "selected" : ""; + if ($desc['deprecated'] && $key != $selected){ + continue; + } + $name = htmlspecialchars($desc['name']); + $result .= "<option value='{$key}' {$selectedhtml}>{$name}<\/option>"; + } + return $result; +} + +function echo_html_select($name, $keyvaluelist, $selected, $listEmptyMessage="", $onchangeEvent="", $style="") { + if (count($keyvaluelist)>0){ + if ($onchangeEvent != "") + $onchangeEvent = " onchange='$onchangeEvent'"; + if ($style != "") + $style = " style='$style'"; + echo "<select name=\"$name\" id=\"$name\" class=\"formselect\"$onchangeEvent$style>"; + echo haproxy_html_select_options($keyvaluelist, $selected); + echo "</select>"; + } else { + echo $listEmptyMessage; + } +} + +?>
\ No newline at end of file diff --git a/config/haproxy1_5/pkg/haproxy_xmlrpcsyncclient.inc b/config/haproxy1_5/pkg/haproxy_xmlrpcsyncclient.inc new file mode 100644 index 00000000..699dffd1 --- /dev/null +++ b/config/haproxy1_5/pkg/haproxy_xmlrpcsyncclient.inc @@ -0,0 +1,149 @@ +<?php +/* + haproxy_xmlrpcsyncclient.inc + Copyright (C) 2013 PiBa-NL + Copyright (C) 2009 Scott Ullrich <sullrich@pfsense.com> + Copyright (C) 2008 Remco Hoef + 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. +*/ + +/* include all configuration functions */ +require_once("functions.inc"); +require_once("pkg-utils.inc"); +require_once("notices.inc"); + +function xmlrpc_sync_execute($syncinfo) { + // name that is logged if something fails during syncing + $sync_logname = $syncinfo['sync_logname']; + // configuration data to sync + $xml = $syncinfo['data']; + // include file in which the "function sync_done_execute(){xxx}" must be pressent + $sync_include = $syncinfo['sync_include']; + // executes to apply the changed configuration on the target system + $sync_function = $syncinfo['sync_done_execute']; + + global $config, $g; + //if(!$password) + $password = $config['hasync']['password']; + if(!$password) + return; + + //if(!$sync_to_ip) + $sync_to_ip = $config['hasync']['synchronizetoip']; + if(!$sync_to_ip) + return; + + // Do not allow syncing to self. + $donotsync = false; + $localips = get_configured_ip_addresses(); + if (in_array($sync_to_ip, $localips , true)) + $donotsync = true; + + if($donotsync) { + log_error("Disallowing sync loop for {$sync_logname} sync."); + return; + } + + $xmlrpc_sync_neighbor = $sync_to_ip; + if($config['system']['webgui']['protocol'] != "") { + $synchronizetoip = $config['system']['webgui']['protocol']; + $synchronizetoip .= "://"; + } + $port = $config['system']['webgui']['port']; + /* if port is empty lets rely on the protocol selection */ + if($port == "") { + if($config['system']['webgui']['protocol'] == "http") + $port = "80"; + else + $port = "443"; + } + $synchronizetoip .= $sync_to_ip; + + /* xml will hold the sections to sync */ + //$xml = prepare_xmlrpc_sync_config(); + + + /* assemble xmlrpc payload */ + $params = array( + XML_RPC_encode($password), + XML_RPC_encode($xml) + ); + + /* set a few variables needed for sync code borrowed from filter.inc */ + $url = $synchronizetoip; + log_error("Beginning {$sync_logname} XMLRPC sync to {$url}:{$port}."); + $method = 'pfsense.merge_installedpackages_section_xmlrpc'; + $msg = new XML_RPC_Message($method, $params); + $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port); + $cli->setCredentials('admin', $password); + if($g['debug']) + $cli->setDebug(1); + /* send our XMLRPC message and timeout after 250 seconds */ + $resp = $cli->send($msg, "250"); + if(!$resp) { + $error = "A communications error occurred while attempting {$sync_logname} XMLRPC sync with {$url}:{$port}."; + log_error($error); + file_notice("sync_settings", $error, "{$sync_logname} Settings Sync", ""); + } elseif($resp->faultCode()) { + $cli->setDebug(1); + $resp = $cli->send($msg, "250"); + $error = "An error code was received while attempting {$sync_logname} XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); + log_error($error); + file_notice("sync_settings", $error, "{$sync_logname} Settings Sync", ""); + } else { + log_error("{$sync_logname} XMLRPC sync successfully completed with {$url}:{$port}."); + } + + /* tell package to reload our settings on the destination sync host. */ + $method = 'pfsense.exec_php'; + $execcmd = "require_once('{$sync_include}');\n"; + $execcmd .= "{$sync_function}();\n"; + + /* assemble xmlrpc payload */ + $params = array( + XML_RPC_encode($password), + XML_RPC_encode($execcmd) + ); + + log_error("{$sync_logname} XMLRPC reload data {$url}:{$port}."); + $msg = new XML_RPC_Message($method, $params); + $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port); + $cli->setCredentials('admin', $password); + $resp = $cli->send($msg, "250"); + if(!$resp) { + $error = "A communications error occurred while attempting {$sync_logname} XMLRPC sync with {$url}:{$port} (exec_php)."; + log_error($error); + file_notice("sync_settings", $error, "{$sync_logname} Settings Reload", ""); + } elseif($resp->faultCode()) { + $cli->setDebug(1); + $resp = $cli->send($msg, "250"); + $error = "An error code was received while attempting {$sync_logname} XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); + log_error($error); + file_notice("sync_settings", $error, "{$sync_logname} Settings Sync", ""); + } else { + log_error("{$sync_logname} XMLRPC reload data success with {$url}:{$port} (exec_php)."); + } +} + +?> diff --git a/config/haproxy1_5/pkg/pkg_haproxy_tabs.inc b/config/haproxy1_5/pkg/pkg_haproxy_tabs.inc new file mode 100644 index 00000000..a74ee20a --- /dev/null +++ b/config/haproxy1_5/pkg/pkg_haproxy_tabs.inc @@ -0,0 +1,28 @@ +<?php + +//require_once("guiconfig.inc"); DO NOT REQUIRE THIS! + +// DO NOT REQUIRE guiconfig.inc HERE! though it contains the function display_top_tabs needed below. +// however if included it will hang filter rule generation, and might cause pf to not load any rules. +// This happens when /usr/local/pkg/*.inc files are dynamically loaded during package generation from filter.inc with function discover_pkg_rules(x). + +global $haproxy_tab_array; + +$haproxy_tab_array['haproxy'] = array(); +$haproxy_tab_array['haproxy']['settings'] = Array(name => "Settings", url => "haproxy_global.php"); +$haproxy_tab_array['haproxy']['frontend'] = Array(name => "Frontend", url => "haproxy_listeners.php"); +$haproxy_tab_array['haproxy']['backend'] = Array(name => "Backend", url => "haproxy_pools.php"); +$haproxy_tab_array['haproxy']['files'] = Array(name => "Files", url => "haproxy_files.php"); +$haproxy_tab_array['haproxy']['stats'] = Array(name => "Stats", url => "haproxy_stats.php"); +$haproxy_tab_array['haproxy']['statsfs'] = Array(name => "Stats FS", url => "haproxy_stats.php?haproxystats=1"); +$haproxy_tab_array['haproxy']['templates'] = Array(name => "Templates", url => "haproxy_templates.php"); + +function haproxy_display_top_tabs_active($top_tabs, $activetab) { + $tab_array = array(); + foreach($top_tabs as $key => $tab_item){ + $tab_array[] = array($tab_item['name'], $key == $activetab, $tab_item['url']); + } + display_top_tabs($tab_array); +} + +?> diff --git a/config/haproxy1_5/www/haproxy_files.php b/config/haproxy1_5/www/haproxy_files.php new file mode 100644 index 00000000..4946a7be --- /dev/null +++ b/config/haproxy1_5/www/haproxy_files.php @@ -0,0 +1,176 @@ +<?php +/* $Id: load_balancer_virtual_server.php,v 1.6.2.1 2006/01/02 23:46:24 sullrich Exp $ */ +/* + haproxy_pools.php + part of pfSense (https://www.pfsense.org/) + Copyright (C) 2014 PiBa-NL + 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. +*/ +$shortcut_section = "haproxy"; +require_once("guiconfig.inc"); +require_once("haproxy.inc"); +require_once("pkg_haproxy_tabs.inc"); +require_once("haproxy_htmllist.inc"); + +$a_files = &$config['installedpackages']['haproxy']['files']['item']; +if (!is_array($a_files)) $a_files = array(); +$a_pools = &$config['installedpackages']['haproxy']['ha_pools']['item']; +if (!is_array($a_pools)) $a_pools = array(); + + +$fields_files = array(); +$fields_files[0]['name']="name"; +$fields_files[0]['columnheader']="Name"; +$fields_files[0]['colwidth']="30%"; +$fields_files[0]['type']="textbox"; +$fields_files[0]['size']="20"; + +$fields_files[1]['name']="content"; +$fields_files[1]['columnheader']="content"; +$fields_files[1]['colwidth']="70%"; +$fields_files[1]['type']="textarea"; +$fields_files[1]['size']="70"; + +$fileslist = new HaproxyHtmlList("table_files", $fields_files); +$fileslist->keyfield = "name"; + +if ($_POST) { + $pconfig = $_POST; + + if ($_POST['apply']) { + $result = haproxy_check_and_run($savemsg, true); + if ($result) + unlink_if_exists($d_haproxyconfdirty_path); + } else { + $a_files = $fileslist->haproxy_htmllist_get_values($fields_files); + $filedupcheck = array(); + + foreach($a_files as $key => $file) { + $name = $file['name']; + if (!preg_match("/^[a-zA-Z][a-zA-Z0-9\.\-_]*$/", $file['name'])) + $input_errors[] = "The field 'Name' (".htmlspecialchars($file['name']).") contains invalid characters. Use only: a-zA-Z0-9.-_ and start with a letter"; + if (isset($filedupcheck[$name])) + $input_errors[] = "Duplicate names are not allowed: " . htmlspecialchars($name); + $filedupcheck[$name] = true; + } + + // replace references in backends to renamed 'files' + foreach($a_pools as &$backend) { + if (is_arrayset($backend,'errorfiles','item')) + foreach($backend['errorfiles']['item'] as &$errorfile) { + $found = false; + foreach($a_files as $key => $file) { + if ($errorfile['errorfile'] == $key) { + $errorfile['errorfile'] = $file['name']; + $found = true; + } + } + if (!$found) + $input_errors[] = "Errorfile marked for deletion: " . $errorfile['errorfile'] . " which is used in backend " . $backend['name']; + } + } + if (!$input_errors) { + // save config when no errors found + touch($d_haproxyconfdirty_path); + write_config($changedesc); + header("Location: haproxy_files.php"); + exit; + } + } +} + +$pf_version=substr(trim(file_get_contents("/etc/version")),0,3); + +$pgtitle = "Services: HAProxy: Files"; +include("head.inc"); + +?> +<body link="#0000CC" vlink="#0000CC" alink="#0000CC"> +<?php include("fbegin.inc"); ?> +<form action="haproxy_files.php" method="post"> +<?php if ($input_errors) print_input_errors($input_errors); ?> +<?php if ($savemsg) print_info_box($savemsg); ?> +<?php if (file_exists($d_haproxyconfdirty_path)): ?> +<?php print_info_box_np("The haproxy configuration has been changed.<br/>You must apply the changes in order for them to take effect.");?><br/> +<?php endif; ?> +<table width="100%" border="0" cellpadding="0" cellspacing="0"> + <tr><td class="tabnavtbl"> + <?php + haproxy_display_top_tabs_active($haproxy_tab_array['haproxy'], "files"); + ?> + </td></tr> + <tr> + <td> + <div id="mainarea"> + <table class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td> + Files can be used for errorfiles, that can return custom error pages in + case haproxy reports a error (like no available backend). The content needs + to be less than the buffer size which is typically 8kb. + There are 2 possible variables to use inside the template: + Put these variables in the content of the errorfile templates and they will be replaced by the actual errorcode / message. (include the curly braces around the text)<br/> + <b>{errorcode}</b> this represents the errorcode<br/> + <b>{errormsg}</b> this represents the human readable error<br/> + </td> + </tr> + <tr> + <td> + + </td> + </tr> + <tr> + <td> + <? + $counter=0; + $fileslist->Draw($a_files); + ?> + </td> + </tr> + <tr> + <td> + + </td> + </tr> + <tr> + <td width="78%"> + <input name="Submit" type="submit" class="formbtn" value="Save" onClick="enable_change(true)" /> + </td> + </tr> + </table> + </div> + </table> + </form> +<script type="text/javascript"> + totalrows = <?php echo $counter; ?>; +<? + phparray_to_javascriptarray($fields_files,"fields_files",Array('/*','/*/name','/*/type','/*/size','/*/items','/*/items/*','/*/items/*/*','/*/items/*/*/name')); +?> +</script> + +<?php +haproxy_htmllist_js(); +include("fend.inc"); ?> +</body> +</html> diff --git a/config/haproxy1_5/www/haproxy_global.php b/config/haproxy1_5/www/haproxy_global.php new file mode 100644 index 00000000..978d778d --- /dev/null +++ b/config/haproxy1_5/www/haproxy_global.php @@ -0,0 +1,500 @@ +<?php +/* $Id: load_balancer_pool.php,v 1.5.2.6 2007/03/02 23:48:32 smos Exp $ */ +/* + haproxy_global.php + part of pfSense (https://www.pfsense.org/) + Copyright (C) 2013 PiBa-NL + Copyright (C) 2009 Scott Ullrich <sullrich@pfsense.com> + Copyright (C) 2008 Remco Hoef <remcoverhoef@pfsense.com> + 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. +*/ +$shortcut_section = "haproxy"; +require_once("guiconfig.inc"); +require_once("haproxy.inc"); +require_once("haproxy_utils.inc"); +require_once("globals.inc"); +require_once("pkg_haproxy_tabs.inc"); + +$simplefields = array('localstats_refreshtime','localstats_sticktable_refreshtime','log-send-hostname','ssldefaultdhparam'); + +if (!is_array($config['installedpackages']['haproxy'])) + $config['installedpackages']['haproxy'] = array(); + + +if ($_POST) { + unset($input_errors); + $pconfig = $_POST; + + if ($_POST['calculate_certificate_chain']) { + $changed = haproxy_recalculate_certifcate_chain(); + if ($changed > 0) + touch($d_haproxyconfdirty_path); + } else + if ($_POST['apply']) { + $result = haproxy_check_and_run($savemsg, true); + if ($result) + unlink_if_exists($d_haproxyconfdirty_path); + } else { + //if ($_POST['enable']) { + // $reqdfields = explode(" ", "maxconn"); + // $reqdfieldsn = explode(",", "Maximum connections"); + //} + + if ($_POST['carpdev'] == "disabled") + unset($_POST['carpdev']); + + //do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors); + + if ($_POST['maxconn'] && (!is_numeric($_POST['maxconn']))) + $input_errors[] = "The maximum number of connections should be numeric."; + + if ($_POST['localstatsport'] && (!is_numeric($_POST['localstatsport']))) + $input_errors[] = "The local stats port should be numeric or empty."; + + if ($_POST['localstats_refreshtime'] && (!is_numeric($_POST['localstats_refreshtime']))) + $input_errors[] = "The local stats refresh time should be numeric or empty."; + + if ($_POST['localstats_sticktable_refreshtime'] && (!is_numeric($_POST['localstats_sticktable_refreshtime']))) + $input_errors[] = "The local stats sticktable refresh time should be numeric or empty."; + + /*if($_POST['synchost1'] && !is_ipaddr($_POST['synchost1'])) + $input_errors[] = "Synchost1 needs to be an IPAddress."; + if($_POST['synchost2'] && !is_ipaddr($_POST['synchost2'])) + $input_errors[] = "Synchost2 needs to be an IPAddress."; + if($_POST['synchost3'] && !is_ipaddr($_POST['synchost3'])) + $input_errors[] = "Synchost3 needs to be an IPAddress.";*/ + + if (!$input_errors) { + $config['installedpackages']['haproxy']['enable'] = $_POST['enable'] ? true : false; + $config['installedpackages']['haproxy']['terminate_on_reload'] = $_POST['terminate_on_reload'] ? true : false; + $config['installedpackages']['haproxy']['maxconn'] = $_POST['maxconn'] ? $_POST['maxconn'] : false; + $config['installedpackages']['haproxy']['enablesync'] = $_POST['enablesync'] ? true : false; + //$config['installedpackages']['haproxy']['synchost1'] = $_POST['synchost1'] ? $_POST['synchost1'] : false; + //$config['installedpackages']['haproxy']['synchost2'] = $_POST['synchost2'] ? $_POST['synchost2'] : false; + //$config['installedpackages']['haproxy']['synchost2'] = $_POST['synchost3'] ? $_POST['synchost3'] : false; + $config['installedpackages']['haproxy']['remotesyslog'] = $_POST['remotesyslog'] ? $_POST['remotesyslog'] : false; + $config['installedpackages']['haproxy']['logfacility'] = $_POST['logfacility'] ? $_POST['logfacility'] : false; + $config['installedpackages']['haproxy']['loglevel'] = $_POST['loglevel'] ? $_POST['loglevel'] : false; + $config['installedpackages']['haproxy']['carpdev'] = $_POST['carpdev'] ? $_POST['carpdev'] : false; + //$config['installedpackages']['haproxy']['syncpassword'] = $_POST['syncpassword'] ? $_POST['syncpassword'] : false; + $config['installedpackages']['haproxy']['localstatsport'] = $_POST['localstatsport'] ? $_POST['localstatsport'] : false; + $config['installedpackages']['haproxy']['advanced'] = $_POST['advanced'] ? base64_encode($_POST['advanced']) : false; + $config['installedpackages']['haproxy']['nbproc'] = $_POST['nbproc'] ? $_POST['nbproc'] : false; + foreach($simplefields as $stat) + $config['installedpackages']['haproxy'][$stat] = $_POST[$stat]; + touch($d_haproxyconfdirty_path); + write_config(); + } + } +} + +$pconfig['enable'] = isset($config['installedpackages']['haproxy']['enable']); +$pconfig['terminate_on_reload'] = isset($config['installedpackages']['haproxy']['terminate_on_reload']); +$pconfig['maxconn'] = $config['installedpackages']['haproxy']['maxconn']; +$pconfig['enablesync'] = isset($config['installedpackages']['haproxy']['enablesync']); +//$pconfig['syncpassword'] = $config['installedpackages']['haproxy']['syncpassword']; +//$pconfig['synchost1'] = $config['installedpackages']['haproxy']['synchost1']; +//$pconfig['synchost2'] = $config['installedpackages']['haproxy']['synchost2']; +//$pconfig['synchost3'] = $config['installedpackages']['haproxy']['synchost3']; +$pconfig['remotesyslog'] = $config['installedpackages']['haproxy']['remotesyslog']; +$pconfig['logfacility'] = $config['installedpackages']['haproxy']['logfacility']; +$pconfig['loglevel'] = $config['installedpackages']['haproxy']['loglevel']; +$pconfig['carpdev'] = $config['installedpackages']['haproxy']['carpdev']; +$pconfig['localstatsport'] = $config['installedpackages']['haproxy']['localstatsport']; +$pconfig['advanced'] = base64_decode($config['installedpackages']['haproxy']['advanced']); +$pconfig['nbproc'] = $config['installedpackages']['haproxy']['nbproc']; +foreach($simplefields as $stat) + $pconfig[$stat] = $config['installedpackages']['haproxy'][$stat]; + +// defaults +if (!$pconfig['logfacility']) + $pconfig['logfacility'] = 'local0'; +if (!$pconfig['loglevel']) + $pconfig['loglevel'] = 'info'; + +$pf_version=substr(trim(file_get_contents("/etc/version")),0,3); +if ($pf_version < 2.0) + $one_two = true; + +$pgtitle = "Services: HAProxy: Settings"; +include("head.inc"); + +?> +<body link="#0000CC" vlink="#0000CC" alink="#0000CC"> +<script type="text/javascript" src="javascript/scriptaculous/prototype.js"></script> +<script type="text/javascript" src="javascript/scriptaculous/scriptaculous.js"></script> +<?php include("fbegin.inc"); ?> +<script type="text/javascript"> +<!-- +function enable_change(enable_change) { + var endis; + endis = !(document.iform.enable.checked || enable_change); + document.iform.maxconn.disabled = endis; +} +//--> +</script> +<?php if($one_two): ?> +<p class="pgtitle"><?=$pgtitle?></p> +<?php endif; ?> +<form action="haproxy_global.php" method="post" name="iform"> +<?php if ($input_errors) print_input_errors($input_errors); ?> +<?php if ($savemsg) print_info_box($savemsg); ?> +<?php if (file_exists($d_haproxyconfdirty_path)): ?> +<?php print_info_box_np("The haproxy configuration has been changed.<br/>You must apply the changes in order for them to take effect.");?><br/> +<?php endif; ?> +<table width="100%" border="0" cellpadding="0" cellspacing="0"> + <tr><td class="tabnavtbl"> + <?php + haproxy_display_top_tabs_active($haproxy_tab_array['haproxy'], "settings"); + ?> + </td></tr> + <tr> + <td> + <div id="mainarea"> + <table class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0"> + <tr> + <td colspan="2" valign="top" class="listtopic">General settings</td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell"> </td> + <td width="78%" class="vtable"> + <input name="enable" type="checkbox" value="yes" <?php if ($pconfig['enable']) echo "checked"; ?> onClick="enable_change(false)" /> + <strong>Enable HAProxy</strong></td> + </tr> + <tr> + <td valign="top" class="vncell"> + Maximum connections + </td> + <td class="vtable"> + <table><tr><td> + <table cellpadding="0" cellspacing="0"> + <tr> + <td> + <input name="maxconn" type="text" class="formfld" id="maxconn" size="5" <?if ($pconfig['enable']!='yes') echo "enabled=\"false\"";?> value="<?=htmlspecialchars($pconfig['maxconn']);?>" /> per process. + </td> + </tr> + </table> + Sets the maximum per-process number of concurrent connections to X.<br/> + <strong>NOTE:</strong> setting this value too high will result in HAProxy not being able to allocate enough memory.<br/> + <p> + <?php + $memusage = trim(`ps auxw | grep haproxy | grep -v grep | awk '{ print $5 }'`); + if($memusage) + echo "Current memory usage: <b>{$memusage} kB.</b><br/>"; + ?> + Current <a href='/system_advanced_sysctl.php'>'System Tunables'</a> settings.<br/> + 'kern.maxfiles': <b><?=`sysctl kern.maxfiles | awk '{ print $2 }'`?></b><br/> + 'kern.maxfilesperproc': <b><?=`sysctl kern.maxfilesperproc | awk '{ print $2 }'`?></b><br/> + </p> + Full memory usage will only show after all connections have actually been used. + </td><td> + <table style="border: 1px solid #000;"> + <tr> + <td><font size=-1>Connections</font></td> + <td><font size=-1>Memory usage</font></td> + </tr> + <tr> + <td colspan="2"> + <hr noshade style="border: 1px solid #000;"></hr> + </td> + </tr> + <tr> + <td align="right"><font size=-1>1</font></td> + <td><font size=-1>50 kB</font></td> + </tr> + <tr> + <td align="right"><font size=-1>1.000</font></td> + <td><font size=-1>48 MB</font></td> + </tr> + <tr> + <td align="right"><font size=-1>10.000</font></td> + <td><font size=-1>488 MB</font></td> + </tr> + <tr> + <td align="right"><font size=-1>100.000</font></td> + <td><font size=-1>4,8 GB</font></td> + </tr> + <tr> + <td colspan="2" style="white-space: nowrap"><font size=-2>Calculated for plain HTTP connections,<br/>using ssl offloading will increase this.</font></td> + </tr> + </table> + </td></tr></table> + When setting a high amount of allowed simultaneous connections you will need to add and or increase the following two <b><a href='/system_advanced_sysctl.php'>'System Tunables'</a></b> kern.maxfiles and kern.maxfilesperproc. + For HAProxy alone set these to at least the number of allowed connections * 2 + 31. So for 100.000 connections these need to be 200.031 or more to avoid trouble, take into account that handles are also used by other processes when setting kern.maxfiles. + <br/> + </td> + </tr> + <tr> + <td valign="top" class="vncell"> + Number of processes to start + </td> + <td class="vtable"> + <input name="nbproc" type="text" class="formfld" id="nbproc" size="18" value="<?=htmlspecialchars($pconfig['nbproc']);?>" /> + <br/> + Defaults to 1 if left blank (<?php echo trim(`/sbin/sysctl kern.smp.cpus | cut -d" " -f2`); ?> CPU core(s) detected).<br/> + Note : Consider leaving this value empty or 1 because in multi-process mode (nbproc > 1) memory is not shared between the processes, which could result in random behaviours for several options like ACL's, sticky connections, stats pages, admin maintenance options and some others.<br/> + For more information about the <b>"nbproc"</b> option please see <b><a href='http://cbonte.github.io/haproxy-dconv/configuration-1.5.html#nbproc' target='_blank'>HAProxy Documentation</a> </b> + </td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell">Reload behaviour</td> + <td width="78%" class="vtable"> + <input name="terminate_on_reload" type="checkbox" value="yes" <?php if ($pconfig['terminate_on_reload']) echo "checked"; ?> /> + Force immediate stop of old process on reload. (closes existing connections)<br/><br/>Note: when this option is selected connections will be closed when haproxy is restarted. + Otherwise the existing connections will be served by the old haproxy process untill they are closed. + Checking this option will interupt existing connections on a restart. (which happens when the configuration is applied, + but possibly also when pfSense detects an interface comming up or changing its ip-address)</td> + </tr> + <tr> + <td valign="top" class="vncell"> + Carp monitor + </td> + <td class="vtable"> + <?php + $vipinterfaces = array(); + $vipinterfaces[] = array('ip' => '', 'name' => 'Disabled'); + $vipinterfaces += haproxy_get_bindable_interfaces($ipv="ipv4,ipv6", $interfacetype="carp"); + echo_html_select('carpdev',$vipinterfaces, $pconfig['carpdev'],"No carp interfaces pressent"); + ?> + <br/> + Monitor carp interface and only run haproxy on the firewall which is MASTER. + </td> + </tr> + <tr> + <td> + + </td> + </tr> + <tr> + <td colspan="2" valign="top" class="listtopic">Stats tab, 'internal' stats port</td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell">Internal stats port</td> + <td class="vtable"> + <input name="localstatsport" type="text" <?if(isset($pconfig['localstatsport'])) echo "value=\"{$pconfig['localstatsport']}\"";?> size="10" maxlength="5" /> EXAMPLE: 2200<br/> + Sets the internal port to be used for the stats tab. + This is bound to 127.0.0.1 so will not be directly exposed on any LAN/WAN/other interface. It is used to internally pass through the stats page. + Leave this setting empty to remove the "HAProxyLocalStats" item from the stats page and save a little on recources. + </td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell">Internal stats refresh rate</td> + <td class="vtable"> + <input name="localstats_refreshtime" type="text" <?if(isset($pconfig['localstats_refreshtime'])) echo "value=\"{$pconfig['localstats_refreshtime']}\"";?> size="10" maxlength="5" /> Seconds, Leave this setting empty to not refresh the page automatically. EXAMPLE: 10 + </td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell">Sticktable page refresh rate</td> + <td class="vtable"> + <input name="localstats_sticktable_refreshtime" type="text" <?if(isset($pconfig['localstats_sticktable_refreshtime'])) echo "value=\"{$pconfig['localstats_sticktable_refreshtime']}\"";?> size="10" maxlength="5" /> Seconds, Leave this setting empty to not refresh the page automatically. EXAMPLE: 10 + </td> + </tr> + <tr> + <td colspan="2" valign="top" class="listtopic">Logging</td> + </tr> + <tr> + <td valign="top" class="vncell"> + Remote syslog host + </td> + <td class="vtable"> + <input name="remotesyslog" type="text" class="formfld" id="remotesyslog" size="18" value="<?=htmlspecialchars($pconfig['remotesyslog']);?>" /><br/> + To log to the local pfSense systemlog fill the host with the value <b>/var/run/log</b>, however if a lot of messages are generated logging is likely to be incomplete. (Also currently no informational logging gets shown in the systemlog.) + </td> + </tr> + <tr> + <td valign="top" class="vncell"> + Syslog facility + </td> + <td class="vtable"> + <select name="logfacility" class="formfld"> + <?php + $facilities = array("kern", "user", "mail", "daemon", "auth", "syslog", "lpr", + "news", "uucp", "cron", "auth2", "ftp", "ntp", "audit", "alert", "cron2", + "local0", "local1", "local2", "local3", "local4", "local5", "local6", "local7"); + foreach ($facilities as $f): + ?> + <option value="<?=$f;?>" <?php if ($f == $pconfig['logfacility']) echo "selected"; ?>> + <?=$f;?> + </option> + <?php + endforeach; + ?> + </select> + </td> + </tr> + <tr> + <td valign="top" class="vncell"> + Syslog level + </td> + <td class="vtable"> + <select name="loglevel" class="formfld"> + <?php + $levels = array("emerg", "alert", "crit", "err", "warning", "notice", "info", "debug"); + foreach ($levels as $l): + ?> + <option value="<?=$l;?>" <?php if ($l == $pconfig['loglevel']) echo "selected"; ?>> + <?=$l;?> + </option> + <?php + endforeach; + ?> + </select> + </td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell">Log hostname</td> + <td width="78%" class="vtable"> + <input name="log-send-hostname" type="text" <?if(isset($pconfig['log-send-hostname'])) echo "value=\"{$pconfig['log-send-hostname']}\"";?> size="18" maxlength="50" /> EXAMPLE: HaproxyMasterNode<br/>Sets the hostname field in the syslog header. If empty defaults to the system hostname. + </td> + </tr> + <tr> + <td colspan="2" valign="top" class="listtopic">Tuning</td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell">Max SSL Diffie-Hellman size</td> + <td width="78%" class="vtable"> + <input name="ssldefaultdhparam" type="text" <?if(isset($pconfig['ssldefaultdhparam'])) echo "value=\"{$pconfig['ssldefaultdhparam']}\"";?> size="10" maxlength="5" /> EXAMPLE: 2048<br/>Sets the maximum size of the Diffie-Hellman parameters used for generating +the ephemeral/temporary Diffie-Hellman key in case of DHE key exchange. +Minimum and default value is: 1024, bigger values might increase CPU usage.<br/> + For more information about the <b>"tune.ssl.default-dh-param"</b> option please see <b><a href='http://cbonte.github.io/haproxy-dconv/configuration-1.5.html#3.2-tune.ssl.default-dh-param' target='_blank'>HAProxy Documentation</a></b><br/> + NOTE: HAProxy will emit a warning when starting when this setting is used but not configured. + </td> + </tr> + <tr> + <td colspan="2" valign="top" class="listtopic">Global Advanced pass thru</td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell"> </td> + <td width="78%" class="vtable"> + <? $textrowcount = max(substr_count($pconfig['advanced'],"\n"), 2) + 2; ?> + <textarea name='advanced' rows="<?=$textrowcount;?>" cols="70" id='advanced'><?php echo $pconfig['advanced']; ?></textarea> + <br/> + NOTE: paste text into this box that you would like to pass thru in the global settings area. + </td> + </tr> + <tr> + <td> + + </td> + </tr> + <tr> + <td colspan="2" valign="top" class="listtopic">Recalculate certificate chain.</td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell"> </td> + <td width="78%" class="vtable"> + <input type="hidden" name="calculate_certificate_chain" id="calculate_certificate_chain" /> + <input type="button" class="formbtn" value="Recalculate certificate chains" onclick="$('calculate_certificate_chain').value='true';document.iform.submit();" />(Other changes on this page will be lost) + <br/> + This can be required after certificates have been created or imported. As pfSense 2.1.0 currently does not + always keep track of these dependencies which might be required to create a proper certificate chain when using SSLoffloading. + </td> + </tr> + <tr> + <td colspan="2" valign="top" class="listtopic">Configuration synchronization</td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell">HAProxy Sync</td> + <td width="78%" class="vtable"> + <input name="enablesync" type="checkbox" value="yes" <?php if ($pconfig['enablesync']) echo "checked"; ?> /> + <strong>Sync HAProxy configuration to backup CARP members via XMLRPC.</strong><br/> + Note: remember to also turn on HAProxy Sync on the backup nodes.<br/> + The synchronisation host and password are those configured in pfSense main <a href="/system_hasync.php">"System: High Availability Sync"</a> settings. + </td> + </tr> +<!-- + <tr> + <td width="22%" valign="top" class="vncell">Synchronization password</td> + <td width="78%" class="vtable"> + <input name="syncpassword" type="password" autocomplete="off" value="<?=$pconfig['syncpassword'];?>"> + <br/> + <strong>Enter the password that will be used during configuration synchronization. This is generally the remote webConfigurator password.</strong> + </td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell">Sync host #1</td> + <td width="78%" class="vtable"> + <input name="synchost1" value="<?=$pconfig['synchost1'];?>"> + <br/> + <strong>Synchronize settings to this hosts IP address.</strong> + </td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell">Sync host #2</td> + <td width="78%" class="vtable"> + <input name="synchost2" value="<?=$pconfig['synchost2'];?>"> + <br/> + <strong>Synchronize settings to this hosts IP address.</strong> + </td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell">Sync host #3</td> + <td width="78%" class="vtable"> + <input name="synchost3" value="<?=$pconfig['synchost3'];?>"> + <br/> + <strong>Synchronize settings to this hosts IP address.</strong> + </td> + </tr> +--> + <tr> + <td> + + </td> + </tr> + <tr> + <td width="22%" valign="top"> </td> + <td width="78%"> + <input name="Submit" type="submit" class="formbtn" value="Save" onClick="enable_change(true)" /> + </td> + </tr> + </table> + </div> +</table> + +<?php if(file_exists("/var/etc/haproxy/haproxy.cfg")): ?> + <div id="configuration" style="display:none; border-style:dashed; padding: 8px;"> + <b><i>/var/etc/haproxy.cfg file contents:</i></b> + <?php + if(file_exists("/var/etc/haproxy/haproxy.cfg")) { + echo "<pre>" . trim(file_get_contents("/var/etc/haproxy/haproxy.cfg")) . "</pre>"; + } + ?> + </div> + <div id="showconfiguration"> + <a onClick="new Effect.Fade('showconfiguration'); new Effect.Appear('configuration'); setTimeout('scroll_after_fade();', 250); return false;" href="#">Show</a> automatically generated configuration. + </div> +<?php endif; ?> + +</form> +<script type="text/javascript"> + function scroll_after_fade() { + scrollTo(0,99999999999); + } +<!-- +enable_change(false); +//--> +</script> +<?php include("fend.inc"); ?> +</body> +</html> diff --git a/config/haproxy1_5/www/haproxy_listeners.php b/config/haproxy1_5/www/haproxy_listeners.php new file mode 100644 index 00000000..db1f3ff2 --- /dev/null +++ b/config/haproxy1_5/www/haproxy_listeners.php @@ -0,0 +1,338 @@ +<?php +/* $Id: load_balancer_virtual_server.php,v 1.6.2.1 2006/01/02 23:46:24 sullrich Exp $ */ +/* + haproxy_listeners.php + part of pfSense (https://www.pfsense.org/) + Copyright (C) 2013-2015 PiBa-NL + Copyright (C) 2009 Scott Ullrich <sullrich@pfsense.com> + Copyright (C) 2008 Remco Hoef <remcoverhoef@pfsense.com> + 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. +*/ +$shortcut_section = "haproxy"; +require_once("guiconfig.inc"); +require_once("haproxy.inc"); +require_once("certs.inc"); +require_once("haproxy_utils.inc"); +require_once("pkg_haproxy_tabs.inc"); + +$changedesc = "Services: HAProxy: Frontends"; + +if (!is_array($config['installedpackages']['haproxy']['ha_backends']['item'])) { + $config['installedpackages']['haproxy']['ha_backends']['item'] = array(); +} +$a_frontend = &$config['installedpackages']['haproxy']['ha_backends']['item']; + +if($_GET['action'] == "toggle") { + $id = $_GET['id']; + echo "$id|"; + if (isset($a_frontend[get_frontend_id($id)])) { + $frontent = &$a_frontend[get_frontend_id($id)]; + if ($frontent['status'] != "disabled"){ + $frontent['status'] = 'disabled'; + echo "0|"; + }else{ + $frontent['status'] = 'active'; + echo "1|"; + } + $changedesc .= " set frontend '$id' status to: {$frontent['status']}"; + + touch($d_haproxyconfdirty_path); + write_config($changedesc); + } + echo "ok|"; + exit; +} + +if ($_POST) { + $pconfig = $_POST; + + if ($_POST['apply']) { + $result = haproxy_check_and_run($savemsg, true); + if ($result) + unlink_if_exists($d_haproxyconfdirty_path); + } +} else { + $result = haproxy_check_config($retval); + if ($result) + $savemsg = gettext($result); +} + +$id = $_GET['id']; +$id = get_frontend_id($id); + +if ($_GET['act'] == "del") { + if (isset($a_frontend[$id])) { + if (!$input_errors) { + unset($a_frontend[$id]); + write_config(); + touch($d_haproxyconfdirty_path); + } + header("Location: haproxy_listeners.php"); + exit; + } +} + +$pgtitle = "Services: HAProxy: Frontends"; +include("head.inc"); + +?> +<body link="#0000CC" vlink="#0000CC" alink="#0000CC"> +<?php include("fbegin.inc"); ?> +<form action="haproxy_listeners.php" method="post"> +<?php if ($input_errors) print_input_errors($input_errors); ?> +<?php if ($savemsg) print_info_box($savemsg); ?> +<?php +$display_apply = file_exists($d_haproxyconfdirty_path) ? "" : "none"; +echo "<div id='showapplysettings' style='display: {$display_apply};'>"; +print_info_box_np("The haproxy configuration has been changed.<br/>You must apply the changes in order for them to take effect."); +echo "<br/></div>"; +?> +<script type="text/javascript" language="javascript" src="/javascript/haproxy_geturl.js"></script> +<script language="javascript"> +function toggle_on(button, image) { + var item = document.getElementById(button); + item.src = image; +} + +function js_callback(req) { + showapplysettings.style.display = 'block'; + if(req.content != '') { + var itemsplit = req.content.split("|"); + buttonid = itemsplit[0]; + enabled = itemsplit[1]; + if (enabled == 1){ + img = 'pass'; + } else { + img = 'reject'; + } + toggle_on('btn_'+buttonid, './themes/<?=$g['theme'];?>/images/icons/icon_'+img+'.gif'); + } +} +</script> + +<table width="100%" border="0" cellpadding="0" cellspacing="0"> + <tr><td class="tabnavtbl"> + <?php + haproxy_display_top_tabs_active($haproxy_tab_array['haproxy'], "frontend"); + ?> + </td></tr> + <tr> + <td> + <div id="mainarea"> + <table class="tabcont sortable" width="100%" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td width="5%" class="listhdrr">On</td> + <td width="5%" class="listhdrr">Primary</td> + <td width="20%" class="listhdrr">Advanced</td> + <td width="20%" class="listhdrr">Name</td> + <td width="30%" class="listhdrr">Description</td> + <td width="20%" class="listhdrr">Address</td> + <td width="5%" class="listhdrr">Type</td> + <td width="10%" class="listhdrr">Backend</td> + <!--td width="20%" class="listhdrr">Parent</td--> + <td width="5%" class="list"></td> + </tr> +<?php + + function sort_sharedfrontends(&$a, &$b) { + // make sure the 'primary frontend' is the first in the array, after that sort by name. + if ($a['secondary'] != $b['secondary']) + return $a['secondary'] > $b['secondary'] ? 1 : -1; + if ($a['name'] != $b['name']) + return $a['name'] > $b['name'] ? 1 : -1; + return 0; + } + + $a_frontend_grouped = array(); + foreach($a_frontend as &$frontend2) { + $mainfrontend = get_primaryfrontend($frontend2); + $mainname = $mainfrontend['name']; + $ipport = get_frontend_ipport($frontend2, true); + $frontend2['ipport'] = $ipport; + $frontend2['type'] = $mainfrontend['type']; + $a_frontend_grouped[$mainname][] = $frontend2; + } + ksort($a_frontend_grouped); + + $img_cert = "/themes/{$g['theme']}/images/icons/icon_frmfld_cert.png"; + $img_adv = "/themes/{$g['theme']}/images/icons/icon_advanced.gif"; + $img_acl = "/themes/{$g['theme']}/images/icons/icon_ts_rule.gif"; + $textgray = ""; + $first = true; + $last_frontend_shared = false; + foreach ($a_frontend_grouped as $a_frontend) { + usort($a_frontend,'sort_sharedfrontends'); + if ((count($a_frontend) > 1 || $last_frontend_shared) && !$first) { + ?> <tr class="<?=$textgray?>"><td colspan="7"> </td></tr> <? + } + $first = false; + $last_frontend_shared = count($a_frontend) > 1; + foreach ($a_frontend as $frontend) { + $frontendname = $frontend['name']; + $textgray = $frontend['status'] != 'active' ? " gray" : ""; + ?> + <tr class="<?=$textgray?>"> + <td class="listlr" ondblclick="document.location='haproxy_listeners_edit.php?id=<?=$frontendname;?>';"> + <? + if ($frontend['status']=='disabled'){ + $iconfn = "reject"; + } else { + $iconfn = "pass"; + }?> + <a href='javascript:getURL("?id=<?=$frontendname;?>&action=toggle&", js_callback);'> + <img id="btn_<?=$frontendname;?>" src="./themes/<?= $g['theme']; ?>/images/icons/icon_<?=$iconfn;?>.gif" width="11" height="11" border="0" + title="<?=gettext("click to toggle enable/disable this frontend");?>" alt="icon" /> + </a> + </td> + <td class="listr" style="<?=$frontend['secondary']=='yes'?"visibility:hidden;":""?>" ondblclick="document.location='haproxy_listeners_edit.php?id=<?=$frontendname;?>';"> + <?=$frontend['secondary']!='yes'?"yes":"no";?> + </td> + <td class="listr" ondblclick="document.location='haproxy_listeners_edit.php?id=<?=$frontendname;?>';"> + <? + $acls = get_frontend_acls($frontend); + $isaclset = ""; + foreach ($acls as $acl) { + $isaclset .= " " . htmlspecialchars($acl['descr']); + } + if ($isaclset) + echo "<img src=\"$img_acl\" title=\"" . gettext("acl's used") . ": {$isaclset}\" border=\"0\" />"; + + if (get_frontend_uses_ssl($frontend)) { + $cert = lookup_cert($frontend['ssloffloadcert']); + $descr = htmlspecialchars($cert['descr']); + if (is_array($frontend['ha_certificates']) && is_array($frontend['ha_certificates']['item'])) { + $certs = $frontend['ha_certificates']['item']; + if (count($certs) > 0){ + foreach($certs as $certitem){ + $cert = lookup_cert($certitem['ssl_certificate']); + $descr .= "\n".htmlspecialchars($cert['descr']); + } + } + } + echo '<img src="'.$img_cert.'" title="SSL offloading cert: '.$descr.'" alt="SSL offloading" border="0" height="16" width="16" />'; + } + + $isadvset = ""; + if ($frontend['advanced_bind']) $isadvset .= "Advanced bind: ".htmlspecialchars($frontend['advanced_bind'])."\r\n"; + if ($frontend['advanced']) $isadvset .= "Advanced pass thru setting used\r\n"; + if ($isadvset) + echo "<img src=\"$img_adv\" title=\"" . gettext("Advanced settings set") . ": {$isadvset}\" border=\"0\" />"; + + $backend_serverpool_hint = ""; + $backend_serverpool = $frontend['backend_serverpool']; + $backend = get_backend($backend_serverpool); + if ($backend && is_array($backend['ha_servers']) && is_array($backend['ha_servers']['item'])){ + $servers = $backend['ha_servers']['item']; + $backend_serverpool_hint = gettext("Servers in pool:"); + if (is_array($servers)){ + foreach($servers as $server){ + $srvstatus = $server['status']; + $status = $a_servermodes[$srvstatus]['sign']; + if (isset($server['forwardto']) && $server['forwardto'] != "") + $backend_serverpool_hint .= "\n{$status}[{$server['forwardto']}]"; + else + $backend_serverpool_hint .= "\n{$status}{$server['address']}:{$server['port']}"; + } + } + } + ?> + </td> + <td class="listr" ondblclick="document.location='haproxy_listeners_edit.php?id=<?=$frontendname;?>';"> + <?=$frontend['name'];?> + </td> + <td class="listr" ondblclick="document.location='haproxy_listeners_edit.php?id=<?=$frontendname;?>';"> + <?=$frontend['desc'];?> + </td> + <td class="listr" ondblclick="document.location='haproxy_listeners_edit.php?id=<?=$frontendname;?>';"> + <? + $first = true; + foreach($frontend['ipport'] as $addr) { + if (!$first) + print "<br/>"; + print "<div style='white-space:nowrap;'>"; + print "{$addr['addr']}:{$addr['port']}"; + if ($addr['ssl'] == 'yes') { + echo '<img src="'.$img_cert.'" title="SSL offloading" alt="SSL" border="0" height="11" width="11" />'; + } + print "</div"; + $first = false; + } + ?> + </td> + <td class="listr" ondblclick="document.location='haproxy_listeners_edit.php?id=<?=$frontendname;?>';"> + <? + if ($frontend['type'] == 'http') { + $mainfrontend = get_primaryfrontend($frontend); + $sslused = get_frontend_uses_ssl($mainfrontend); + $httpused = !get_frontend_uses_ssl_only($frontend); + if ($httpused) + echo "http"; + if ($sslused) { + echo ($httpused ? "/" : "") . "https"; + } + } else + echo $a_frontendmode[$frontend['type']]['shortname']; + ?> + </td> + <td class="listr" ondblclick="document.location='haproxy_listeners_edit.php?id=<?=$frontendname;?>';"> + <div title='<?=$backend_serverpool_hint;?>'> + <a href="haproxy_pool_edit.php?id=<?=$frontend['backend_serverpool']?>"> + <?=$frontend['backend_serverpool']?> + </a> + </div> + </td> + <!--td class="listlr" ondblclick="document.location='haproxy_listeners_edit.php?id=<?=$frontendname;?>';"> + <?=$frontend['secondary'] == 'yes' ? $frontend['primary_frontend'] : "";?> + </td--> + <td class="list" nowrap> + <table border="0" cellspacing="0" cellpadding="1"> + <tr> + <td valign="middle"><a href="haproxy_listeners_edit.php?id=<?=$frontendname;?>"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" title="<?=gettext("edit frontend");?>" width="17" height="17" border="0" /></a></td> + <td valign="middle"><a href="haproxy_listeners.php?act=del&id=<?=$frontendname;?>" onclick="return confirm('Do you really want to delete this entry?')"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" title="<?=gettext("delete frontend");?>" width="17" height="17" border="0" /></a></td> + <td valign="middle"><a href="haproxy_listeners_edit.php?dup=<?=$frontendname;?>"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" title="<?=gettext("clone frontend");?>" width="17" height="17" border="0" /></a></td> + </tr> + </table> + </td> + </tr><?php + } + } ?> + <tfoot> + <tr> + <td class="list" colspan="8"></td> + <td class="list"> + <table border="0" cellspacing="0" cellpadding="1"> + <tr> + <td valign="middle"><a href="haproxy_listeners_edit.php"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" title="<?=gettext("add new frontend");?>" width="17" height="17" border="0" /></a></td> + </tr> + </table> + </td> + </tr> + </tfoot> + </table> + </div> + </table> + </form> +<?php include("fend.inc"); ?> +</body> +</html> diff --git a/config/haproxy1_5/www/haproxy_listeners_edit.php b/config/haproxy1_5/www/haproxy_listeners_edit.php new file mode 100644 index 00000000..d8841c33 --- /dev/null +++ b/config/haproxy1_5/www/haproxy_listeners_edit.php @@ -0,0 +1,910 @@ +<?php +/* $Id: load_balancer_pool_edit.php,v 1.24.2.23 2007/03/03 00:07:09 smos Exp $ */ +/* + haproxy_listeners_edit.php + part of pfSense (https://www.pfsense.org/) + Copyright (C) 2009 Scott Ullrich <sullrich@pfsense.com> + Copyright (C) 2008 Remco Hoef <remcoverhoef@pfsense.com> + Copyright (C) 2013 PiBa-NL merging (some of the) "haproxy-devel" changes from: Marcello Coutinho <marcellocoutinho@gmail.com> + Copyright (C) 2013-2015 PiBa-NL + 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, 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. +*/ +$shortcut_section = "haproxy"; +require("guiconfig.inc"); +require_once("haproxy.inc"); +require_once("haproxy_utils.inc"); +require_once("haproxy_htmllist.inc"); +require_once("pkg_haproxy_tabs.inc"); + +/* Compatibility function for pfSense 2.0 */ +if (!function_exists("cert_get_purpose")) { + function cert_get_purpose(){ + $result = array(); + $result['server'] = "Yes"; + return $result; + } +} +/**/ + +function haproxy_js_acl_select($mode) { + global $a_acltypes; + + $seltext = ''; + foreach ($a_acltypes as $key => $expr) { + if ($expr['mode'] == '' || $expr['mode'] == $mode) + $seltext .= "<option value='" . $key . "'>" . $expr['name'] ."<\/option>"; + } + return $seltext; +} + +if (!is_array($config['installedpackages']['haproxy']['ha_backends']['item'])) { + $config['installedpackages']['haproxy']['ha_backends']['item'] = array(); +} + +$a_backend = &$config['installedpackages']['haproxy']['ha_backends']['item']; +$a_pools = &$config['installedpackages']['haproxy']['ha_pools']['item']; +if (!is_array($a_pools)) + $a_pools = array(); +uasort($a_pools, haproxy_compareByName); + +global $simplefields; +$simplefields = array('name','desc','status','secondary','primary_frontend','type','forwardfor','httpclose','extaddr','backend_serverpool', + 'max_connections','client_timeout','port','advanced_bind', + 'ssloffloadcert','dcertadv','ssloffload','ssloffloadacl','ssloffloadacladditional','sslclientcert-none','sslclientcert-invalid', + 'socket-stats', + 'dontlognull','dontlog-normal','log-separate-errors','log-detailed'); + +if (isset($_POST['id'])) + $id = $_POST['id']; +else + $id = $_GET['id']; + +if (isset($_GET['dup'])) + $id = $_GET['dup']; + +$id = get_frontend_id($id); + +if (!is_numeric($id)) +{ + //default value for new items. + $pconfig['ssloffloadacl'] = "yes"; + $new_item = array(); + $new_item['extaddr'] = "wan_ipv4"; + $new_item['extaddr_port'] = "80"; + $pconfig['a_extaddr'][] = $new_item; +} + +$servercerts = haproxy_get_certificates('server,user'); +$fields_sslCertificates=array(); +$fields_sslCertificates[0]['name']="ssl_certificate"; +$fields_sslCertificates[0]['columnheader']="Certificates"; +$fields_sslCertificates[0]['colwidth']="95%"; +$fields_sslCertificates[0]['type']="select"; +$fields_sslCertificates[0]['size']="500px"; +$fields_sslCertificates[0]['items']=&$servercerts; + +$certs_ca = haproxy_get_certificates('ca'); +$fields_caCertificates=array(); +$fields_caCertificates[0]['name']="cert_ca"; +$fields_caCertificates[0]['columnheader']="Certificates authorities"; +$fields_caCertificates[0]['colwidth']="95%"; +$fields_caCertificates[0]['type']="select"; +$fields_caCertificates[0]['size']="500px"; +$fields_caCertificates[0]['items']=&$certs_ca; + +$certs_crl = haproxy_get_crls(); +//$ca_none['']['name']="None"; +//$certs_crl = $ca_none + $certs_crl; +$fields_crlCertificates=array(); +$fields_crlCertificates[0]['name']="cert_crl"; +$fields_crlCertificates[0]['columnheader']="Certificate revocation lists"; +$fields_crlCertificates[0]['colwidth']="95%"; +$fields_crlCertificates[0]['type']="select"; +$fields_crlCertificates[0]['size']="500px"; +$fields_crlCertificates[0]['items']=&$certs_crl; + +$fields_aclSelectionList=array(); +$fields_aclSelectionList[0]['name']="name"; +$fields_aclSelectionList[0]['columnheader']="Name"; +$fields_aclSelectionList[0]['colwidth']="30%"; +$fields_aclSelectionList[0]['type']="textbox"; +$fields_aclSelectionList[0]['size']="20"; + +$fields_aclSelectionList[1]['name']="expression"; +$fields_aclSelectionList[1]['columnheader']="Expression"; +$fields_aclSelectionList[1]['colwidth']="30%"; +$fields_aclSelectionList[1]['type']="select"; +$fields_aclSelectionList[1]['size']="10"; +$fields_aclSelectionList[1]['items']=&$a_acltypes; + +$fields_aclSelectionList[2]['name']="not"; +$fields_aclSelectionList[2]['columnheader']="Not"; +$fields_aclSelectionList[2]['colwidth']="5%"; +$fields_aclSelectionList[2]['type']="checkbox"; +$fields_aclSelectionList[2]['size']="5"; + +$fields_aclSelectionList[3]['name']="value"; +$fields_aclSelectionList[3]['columnheader']="Value"; +$fields_aclSelectionList[3]['colwidth']="35%"; +$fields_aclSelectionList[3]['type']="textbox"; +$fields_aclSelectionList[3]['size']="35"; + +$interfaces = haproxy_get_bindable_interfaces(); +$interfaces_custom['custom']['name']="Use custom address:"; +$interfaces = $interfaces_custom + $interfaces; + +$fields_externalAddress=array(); +$fields_externalAddress[0]['name']="extaddr"; +$fields_externalAddress[0]['columnheader']="Listen address"; +$fields_externalAddress[0]['colwidth']="25%"; +$fields_externalAddress[0]['type']="select"; +$fields_externalAddress[0]['size']="200px"; +$fields_externalAddress[0]['items']=&$interfaces; +$fields_externalAddress[1]['name']="extaddr_custom"; +$fields_externalAddress[1]['columnheader']="Custom address"; +$fields_externalAddress[1]['colwidth']="25%"; +$fields_externalAddress[1]['type']="textbox"; +$fields_externalAddress[1]['size']="30"; +$fields_externalAddress[2]['name']="extaddr_port"; +$fields_externalAddress[2]['columnheader']="Port"; +$fields_externalAddress[2]['colwidth']="5%"; +$fields_externalAddress[2]['type']="textbox"; +$fields_externalAddress[2]['size']="5"; +$fields_externalAddress[3]['name']="extaddr_ssl"; +$fields_externalAddress[3]['columnheader']="SSL Offloading"; +$fields_externalAddress[3]['colwidth']="10%"; +$fields_externalAddress[3]['type']="checkbox"; +$fields_externalAddress[3]['size']="50px"; +$fields_externalAddress[4]['name']="extaddr_advanced"; +$fields_externalAddress[4]['columnheader']="Advanced"; +$fields_externalAddress[4]['colwidth']="20%"; +$fields_externalAddress[4]['type']="textbox"; +$fields_externalAddress[4]['size']="30"; + +if (isset($id) && $a_backend[$id]) { + $pconfig['a_acl']=&$a_backend[$id]['ha_acls']['item']; + $pconfig['a_certificates']=&$a_backend[$id]['ha_certificates']['item']; + $pconfig['clientcert_ca']=&$a_backend[$id]['clientcert_ca']['item']; + $pconfig['clientcert_crl']=&$a_backend[$id]['clientcert_crl']['item']; + $pconfig['a_extaddr']=&$a_backend[$id]['a_extaddr']['item']; + $pconfig['advanced'] = base64_decode($a_backend[$id]['advanced']); + foreach($simplefields as $stat) + $pconfig[$stat] = $a_backend[$id][$stat]; +} + +if (isset($_GET['dup'])) { + unset($id); + if ($pconfig['secondary'] != 'yes') + $pconfig['primary_frontend'] = $pconfig['name']; +} + +$changedesc = "Services: HAProxy: Frontend"; +$changecount = 0; + +if ($_POST) { + $changecount++; + + unset($input_errors); + $pconfig = $_POST; + + if ($pconfig['secondary'] != "yes") { + $reqdfields = explode(" ", "name type"); + $reqdfieldsn = explode(",", "Name,Type"); + } else { + $reqdfields = explode(" ", "name"); + $reqdfieldsn = explode(",", "Name"); + } + + $pf_version=substr(trim(file_get_contents("/etc/version")),0,3); + if ($pf_version < 2.1) + $input_errors = eval('do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors); return $input_errors;'); + else + do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors); + + if (preg_match("/[^a-zA-Z0-9\.\-_]/", $_POST['name'])) + $input_errors[] = "The field 'Name' contains invalid characters."; + + if ($pconfig['secondary'] != "yes") { + if ($_POST['max_connections'] && !is_numeric($_POST['max_connections'])) + $input_errors[] = "The field 'Max connections' value is not a number."; + + $ports = split(",", $_POST['port'] . ","); + foreach($ports as $port) + if ($port && !is_numeric($port) && !is_portoralias($port)) + $input_errors[] = "The field 'Port' value '".htmlspecialchars($port)."' is not a number or alias thereof."; + + if ($_POST['client_timeout'] !== "" && !is_numeric($_POST['client_timeout'])) + $input_errors[] = "The field 'Client timeout' value is not a number."; + } + + /* Ensure that our pool names are unique */ + for ($i=0; isset($config['installedpackages']['haproxy']['ha_backends']['item'][$i]); $i++) + if (($_POST['name'] == $config['installedpackages']['haproxy']['ha_backends']['item'][$i]['name']) && ($i != $id)) + $input_errors[] = "This frontend name has already been used. Frontend names must be unique. $i != $id"; + + $a_certificates = haproxy_htmllist_get_values($fields_sslCertificates); + $pconfig['a_certificates'] = $a_certificates; + $a_clientcert_ca = haproxy_htmllist_get_values($fields_caCertificates); + $pconfig['clientcert_ca'] = $a_clientcert_ca; + $a_clientcert_crl = haproxy_htmllist_get_values($fields_crlCertificates); + $pconfig['clientcert_crl'] = $a_clientcert_crl; + + $a_acl = haproxy_htmllist_get_values($fields_aclSelectionList); + $pconfig['a_acl'] = $a_acl; + + $a_extaddr = haproxy_htmllist_get_values($fields_externalAddress); + $pconfig['a_extaddr'] = $a_extaddr; + + + foreach($a_acl as $acl) { + $acl_name = $acl['name']; + $acl_value = $acl['value']; + + $acltype = haproxy_find_acl($acl['expression']); + if (preg_match("/[^a-zA-Z0-9\.\-_]/", $acl_name)) + $input_errors[] = "The field 'Name' contains invalid characters."; + + if (!isset($acltype['novalue'])) + if (!preg_match("/.{1,}/", $acl_value)) + $input_errors[] = "The field 'Value' is required."; + + if (!preg_match("/.{2,}/", $acl_name)) + $input_errors[] = "The field 'Name' is required with at least 2 characters."; + } + foreach($a_extaddr as $extaddr) { + $ports = explode(",",$extaddr['extaddr_port']); + foreach($ports as $port){ + if ($port && !is_numeric($port) && !is_portoralias($port)) + $input_errors[] = "The field 'Port' value '".htmlspecialchars($port)."' is not a number or alias thereof."; + } + + if ($extaddr['extaddr'] == 'custom') { + $extaddr_custom = $extaddr['extaddr_custom']; + if (empty($extaddr_custom) || (!is_ipaddroralias($extaddr_custom))) + $input_errors[] = sprintf(gettext("%s is not a valid source IP address or alias."),$extaddr_custom); + } + } + if (!$input_errors) { + $backend = array(); + if(isset($id) && $a_backend[$id]) + $backend = $a_backend[$id]; + + if($backend['name'] != "") + $changedesc .= " modified '{$backend['name']}' pool:"; + + // update references to this primary frontend + if ($backend['name'] != $_POST['name']) { + foreach($a_backend as &$frontend) { + if ($frontend['primary_frontend'] == $backend['name']) { + $frontend['primary_frontend'] = $_POST['name']; + } + } + } + + foreach($simplefields as $stat) + update_if_changed($stat, $backend[$stat], $_POST[$stat]); + + update_if_changed("advanced", $backend['advanced'], base64_encode($_POST['advanced'])); + $backend['ha_acls']['item'] = $a_acl; + $backend['ha_certificates']['item'] = $a_certificates; + $backend['clientcert_ca']['item'] = $a_clientcert_ca; + $backend['clientcert_crl']['item'] = $a_clientcert_crl; + $backend['a_extaddr']['item'] = $a_extaddr; + + if (isset($id) && $a_backend[$id]) { + $a_backend[$id] = $backend; + } else { + $a_backend[] = $backend; + } + + if ($changecount > 0) { + touch($d_haproxyconfdirty_path); + write_config($changedesc); + } + + header("Location: haproxy_listeners.php"); + exit; + } +} + +$pf_version=substr(trim(file_get_contents("/etc/version")),0,3); +if ($pf_version < 2.0) + $one_two = true; + +$closehead = false; +$pgtitle = "HAProxy: Frontend: Edit"; +include("head.inc"); + +if (!isset($_GET['dup'])) + $excludefrontend = $pconfig['name']; +$primaryfrontends = get_haproxy_frontends($excludefrontend); + +?> + <style type="text/css"> + .haproxy_mode_http{display:none;} + .haproxy_ssloffloading_show{display:none;} + .haproxy_ssloffloading_enabled{display:none;} + .haproxy_primary{} + .haproxy_secondary{display:none;} + </style> + <script type="text/javascript" src="/javascript/suggestions.js"></script> + <script type="text/javascript" src="/javascript/autosuggest.js"></script> +</head> +<body link="#0000CC" vlink="#0000CC" alink="#0000CC"> + +<?php if($one_two): ?> +<script type="text/javascript" src="/javascript/scriptaculous/prototype.js"></script> +<script type="text/javascript" src="/javascript/scriptaculous/scriptaculous.js"></script> +<?php endif; ?> + +<script type="text/javascript"> + function htmllist_get_select_options(tableId, fieldname) { + var seltext; + seltext = ""; + var type; + var secondary = d.getElementById("secondary"); + var primary_frontend = d.getElementById("primary_frontend"); + if ((secondary !== null) && (secondary.checked)) + type = primaryfrontends[primary_frontend.value]['ref']['type']; + else + type = d.getElementById("type").value; + + if (tableId == 'tableA_acltable'){ + if (type == 'health') + seltext = "<?php echo haproxy_js_acl_select('health');?>"; + else if (type == 'tcp') + seltext = "<?php echo haproxy_js_acl_select('tcp');?>"; + else if (type == 'https') + seltext = "<?php echo haproxy_js_acl_select('https');?>"; + else + seltext = "<?php echo haproxy_js_acl_select('http');?>"; + if (seltext == '') { + alert("No ACL types available in current frontend type"); + return; + } + } + if (tableId == 'tableA_sslCertificates'){ + seltext = "<?=haproxy_js_select_options($servercerts);?>"; + } + if (tableId == 'table_clientcert_ca'){ + seltext = "<?=haproxy_js_select_options($certs_ca);?>"; + } + if (tableId == 'table_clientcert_crl'){ + seltext = "<?=haproxy_js_select_options($certs_crl);?>"; + } + if (tableId == 'table_extaddr'){ + seltext = "<?=haproxy_js_select_options($interfaces);?>"; + } + return seltext; + } + + function setCSSdisplay(cssID, display) { + var ss = document.styleSheets; + for (var i=0; i<ss.length; i++) { + var rules = ss[i].cssRules || ss[i].rules; + for (var j=0; j<rules.length; j++) { + if (rules[j].selectorText === cssID) { + rules[j].style.display = display ? "" : "none"; + } + } + } + } + function updatevisibility() { + d = document; + ssl = false; + sslshow = false; + ssloffload = d.getElementById("ssloffload"); + var type; + var primary; + var secondary = d.getElementById("secondary"); + var primary_frontend = d.getElementById("primary_frontend"); + if ((secondary !== null) && (secondary.checked)) { + primary = primaryfrontends[primary_frontend.value]; + type = primary['ref']['type']; + for (i = 0; i < 99; i++) { + if (primary['ref']['a_extaddr']['item'][i] && primary['ref']['a_extaddr']['item'][i]['extaddr_ssl'] == 'yes') + sslshow = true;//ssloffload.checked; + ssl = ssloffload.checked; + } + } else { + type = d.getElementById("type").value; + for (i = 0; i < 99; i++) { + customEdit = document.getElementById("extaddr_ssl"+i); + if (customEdit && customEdit.checked) + sslshow = true; + } + ssl = sslshow; + } + + setCSSdisplay(".haproxy_ssloffloading_show", sslshow); + setCSSdisplay(".haproxy_ssloffloading_enabled", ssl); + setCSSdisplay(".haproxy_mode_http", type == "http"); + if (secondary !== null) { + setCSSdisplay(".haproxy_primary", !secondary.checked); + setCSSdisplay(".haproxy_secondary", secondary.checked); + } + + type_change(type); + + http_close = d.getElementById("httpclose").value; + http_close_description = d.getElementById("http_close_description"); + http_close_description.innerHTML=closetypes[http_close]["descr"]; + http_close_description.setAttribute('style','padding:5px; border:1px dashed #990000; background-color: #ffffff; color: #000000; font-size: 8pt; height:30px'); + http_close_description.setAttribute('style','padding:5px; border:1px dashed #990000; background-color: #ffffff; color: #000000; font-size: 8pt; height:'+http_close_description.scrollHeight+'px'); + } + + function type_change(type) { + var d, i, j, el, row; + var count = <?=count($a_acltypes);?>; + var acl = [ <?php foreach ($a_acltypes as $key => $expr) echo "'".$key."'," ?> ]; + var mode = [ <?php foreach ($a_acltypes as $key => $expr) echo "'".$expr['mode']."'," ?> ]; + + d = document; + for (i = 0; i < 99; i++) { + el = d.getElementById("acl_expression" + i); + row = d.getElementById("aclrow" + i); + if (!el) + continue; + for (j = 0; j < count; j++) { + if (acl[j] == el.value) { + if (mode[j] != '' && mode[j] != type) { + Effect.Fade(row,{ duration: 1.0 }); + } else { + Effect.Appear(row,{ duration: 1.0 }); + } + } + } + } + + for (i = 0; i < 99; i++) { + el = d.getElementById("expression" + i); + //row_v = d.getElementById("tr_view_" + i); + row_e = d.getElementById("tr_edit_" + i); + if (!el) + continue; + for (j = 0; j < count; j++) { + if (acl[j] == el.value) { + if (mode[j] != '' && mode[j] != type) { + //Effect.Fade(row_v,{ duration: 1.0 }); + Effect.Fade(row_e,{ duration: 1.0 }); + } else { + //Effect.Appear(row_v,{ duration: 1.0 }); + Effect.Appear(row_e,{ duration: 1.0 }); + } + } + } + } + + } +</script> +<?php include("fbegin.inc"); ?> +<?php if ($input_errors) print_input_errors($input_errors); ?> +<?php if($one_two): ?> +<p class="pgtitle"><?=$pgtitle?></p> +<?php endif; ?> +<form action="haproxy_listeners_edit.php" method="post" name="iform" id="iform"> +<table width="100%" border="0" cellpadding="0" cellspacing="0"> + <tr><td class="tabnavtbl"> + <?php + haproxy_display_top_tabs_active($haproxy_tab_array['haproxy'], "frontend"); + ?> + </td></tr> + <tr> + <td> + <div class="tabcont"> + <table width="100%" border="0" cellpadding="6" cellspacing="0"> + <tr> + <td colspan="2" valign="top" class="listtopic">Edit haproxy listener</td> + </tr> + <tr> + <td width="22%" valign="top" class="vncellreq">Name</td> + <td width="78%" class="vtable" colspan="2"> + <input name="name" type="text" <?if(isset($pconfig['name'])) echo "value=\"{$pconfig['name']}\"";?> size="25" maxlength="25" /> + </td> + </tr> + <tr align="left"> + <td width="22%" valign="top" class="vncell">Description</td> + <td width="78%" class="vtable" colspan="2"> + <input name="desc" type="text" <?if(isset($pconfig['desc'])) echo "value=\"{$pconfig['desc']}\"";?> size="64" /> + </td> + </tr> + <tr align="left"> + <td width="22%" valign="top" class="vncellreq">Status</td> + <td width="78%" class="vtable" colspan="2"> + <select name="status" id="status"> + <option value="active"<?php if($pconfig['status'] == "active") echo " SELECTED"; ?>>Active</option> + <option value="disabled"<?php if($pconfig['status'] == "disabled") echo " SELECTED"; ?>>Disabled</option> + </select> + </td> + </tr> + <tr align="left"> + <td width="22%" valign="top" class="vncell">Shared Frontend</td> + <td width="78%" class="vtable" colspan="2"> + <?if (count($primaryfrontends)==0){ ?> + <b>At least 1 primary frontend is needed.</b><br/><br/> + <? } else{ ?> + <input id="secondary" name="secondary" type="checkbox" value="yes" <?php if ($pconfig['secondary']=='yes') echo "checked"; ?> onclick="updatevisibility();" /> + <? } ?> + This can be used to host a second or more website on the same IP:Port combination.<br/> + Use this setting to configure multiple backends/accesslists for a single frontend.<br/> + All settings of which only 1 can exist will be hidden.<br/> + The frontend settings will be merged into 1 set of frontend configuration. + </td> + </tr> + <tr class="haproxy_secondary" align="left"> + <td width="22%" valign="top" class="vncellreq">Primary frontend</td> + <td width="78%" class="vtable" colspan="2"> + <? + echo_html_select('primary_frontend',$primaryfrontends, $pconfig['primary_frontend'],"You must first create a 'primary' frontend.","updatevisibility();"); + ?> + </td> + </tr> + <tr class="haproxy_primary"> + <td width="22%" valign="top" class="vncellreq">External address</td> + <td width="78%" class="vtable"> + <? + $counter=0; + $a_extaddr = $pconfig['a_extaddr']; + $htmllist_extadd = new HaproxyHtmlList("table_extaddr", $fields_externalAddress); + $htmllist_extadd->editmode = true; + $htmllist_extadd->Draw($a_extaddr); + ?> + <script type="text/javascript"> + function table_extaddr_row_added(tableid, rowid){ + new AutoSuggestControl(document.getElementById("extaddr_custom"+rowid), new StateSuggestions(address_array)); + new AutoSuggestControl(document.getElementById("extaddr_port"+rowid), new StateSuggestions(port_array)); + table_extaddr_listitem_change(tableid,"",rowid, null);//disables address when not set to custom. + } + + function table_extaddr_listitem_change(tableId, fieldId, rowNr, field) { + if (fieldId == "extaddr" || fieldId == "") { + field = field || document.getElementById("extaddr"+rowNr); + customEdit = document.getElementById("extaddr_custom"+rowNr); + customdisabled = field.value == "custom" ? 0 : 1; + customEdit.disabled = customdisabled; + } + if (fieldId == "extaddr_ssl") { + updatevisibility(); + } + } + + </script> + <br /> + <span class="vexpl"> + If you want this rule to apply to another IP address than the IP address of the interface chosen above, + select it here (you need to define <a href="firewall_virtual_ip.php">Virtual IP</a> addresses on the first). + Also note that if you are trying to redirect connections on the LAN select the "any" option. + + In the port to listen to, if you want to specify multiple ports, separate them with a comma (,). EXAMPLE: 80,8000 + Or to listen on both 80 and 443 create 2 rows in the table. + </span> + </td> + </tr> + <tr class="haproxy_primary" align="left"> + <td width="22%" valign="top" class="vncell">Max connections</td> + <td width="78%" class="vtable" colspan="2"> + <input name="max_connections" type="text" <?if(isset($pconfig['max_connections'])) echo "value=\"{$pconfig['max_connections']}\"";?> size="10" maxlength="10" /> + </td> + </tr> + <tr> + <td width="22%" valign="top" class="vncellreq">Backend server pool</td> + <td width="78%" class="vtable"> + + <select id="backend_serverpool" name="backend_serverpool" class="formfld"> + <?php + if (is_array($a_pools)) { + foreach ($a_pools as $p) { + $selected = $p['name'] == $pconfig['backend_serverpool'] ? 'selected' : ''; + $name = htmlspecialchars("{$p['name']}"); + echo "<option value=\"{$p['name']}\" $selected>$name</option>"; + } + } else { + echo "<option value=\"-\">-</option>"; + } + ?> + </select> + <tr class="haproxy_primary" align="left"> + <td width="22%" valign="top" class="vncellreq">Type</td> + <td width="78%" class="vtable" colspan="2"> + <select name="type" id="type" onchange="updatevisibility();"> + <option value="http"<?php if($pconfig['type'] == "http") echo " SELECTED"; ?>>HTTP / HTTPS(offloading)</option> + <option value="https"<?php if($pconfig['type'] == "https") echo " SELECTED"; ?>>SSL / HTTPS(TCP mode)</option> + <option value="tcp"<?php if($pconfig['type'] == "tcp") echo " SELECTED"; ?>>TCP</option> + <option value="health"<?php if($pconfig['type'] == "health") echo " SELECTED"; ?>>Health</option> + </select><br/> + <span class="vexpl"> + This defines the processing type of HAProxy, and will determine the availabe options for acl checks and also several other options.<br/> + Please note that for https encryption/decryption on HAProxy with a certificate the processing type needs to be set to 'http'. + </span> + </td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell">Access Control lists</td> + <td width="78%" class="vtable" colspan="2" valign="top"> + <? + $a_acl = $pconfig['a_acl']; + haproxy_htmllist("tableA_acltable", $a_acl, $fields_aclSelectionList, true); + ?> + <br/> + acl's with the same name wil be 'combined', acl's with different names will be evaluated seperately.<br/> + For more information about ACL's please see <a href='http://haproxy.1wt.eu/download/1.5/doc/configuration.txt' target='_blank'>HAProxy Documentation</a> Section 7 - Using ACL's + </td> + </tr> + <tr class="haproxy_primary"><td> </td></tr> + <tr class="haproxy_primary"> + <td colspan="2" valign="top" class="listtopic">Stats options</td> + </tr> + <tr class="haproxy_primary" align="left"> + <td width="22%" valign="top" class="vncell">Separate sockets</td> + <td width="78%" class="vtable" colspan="2"> + <input id="socket-stats" name="socket-stats" type="checkbox" value="yes" <?php if ($pconfig['socket-stats']=='yes') echo "checked"; ?> onclick='updatevisibility();' /> + Enable collecting & providing separate statistics for each socket. + </td> + </tr> + <tr class="haproxy_primary"><td> </td></tr> + <tr class="haproxy_primary"> + <td colspan="2" valign="top" class="listtopic">Logging options</td> + </tr> + <tr class="haproxy_primary" align="left"> + <td width="22%" valign="top" class="vncell">Dont log null</td> + <td width="78%" class="vtable" colspan="2"> + <input id="dontlognull" name="dontlognull" type="checkbox" value="yes" <?php if ($pconfig['dontlognull']=='yes') echo "checked"; ?> onclick='updatevisibility();' /> + A connection on which no data has been transferred will not be logged. + <div>To skip logging probes from monitoring systems that otherwise would pollute the logging. (It is generally recommended not to use this option in uncontrolled environments (eg: internet), otherwise scans and other malicious activities would not be logged.)</div> + </td> + </tr> + <tr class="haproxy_primary" align="left"> + <td width="22%" valign="top" class="vncell">Dont log normal</td> + <td width="78%" class="vtable" colspan="2"> + <input id="dontlog-normal" name="dontlog-normal" type="checkbox" value="yes" <?php if ($pconfig['dontlog-normal']=='yes') echo "checked"; ?> onclick='updatevisibility();' /> + Don't log connections in which no anomalies are found. + <div>Setting this option ensures that + normal connections, those which experience no error, no timeout, no retry nor + redispatch, will not be logged.</div> + </td> + </tr> + <tr class="haproxy_primary" align="left"> + <td width="22%" valign="top" class="vncell">Raise level for errors</td> + <td width="78%" class="vtable" colspan="2"> + <input id="log-separate-errors" name="log-separate-errors" type="checkbox" value="yes" <?php if ($pconfig['log-separate-errors']=='yes') echo "checked"; ?> onclick='updatevisibility();' /> + Change the level changes from "info" to "err" for potentially interesting information. + <div>This option makes haproxy raise the level of logs containing potentially interesting information such + as errors, timeouts, retries, redispatches, or HTTP status codes 5xx. </div> + </td> + </tr> + <tr class="haproxy_primary" align="left"> + <td width="22%" valign="top" class="vncell">Detailed logging</td> + <td width="78%" class="vtable" colspan="2"> + <input id="log-detailed" name="log-detailed" type="checkbox" value="yes" <?php if ($pconfig['log-detailed']=='yes') echo "checked"; ?> onclick='updatevisibility();' /> + If checked provides more detailed logging. + <div>Each log line turns into a much richer format including, but + not limited to, the connection timers, the session status, the connections + numbers, the frontend, backend and server name, and of course the source + address and ports. In http mode also the HTTP request and captured headers and cookies will be logged.</div> + </td> + </tr> + </table> + <br/> <br/> + <table class="haproxy_primary" width="100%" border="0" cellpadding="6" cellspacing="0"> + <tr> + <td colspan="2" valign="top" class="listtopic">Advanced settings</td> + </tr> + <tr align="left"> + <td width="22%" valign="top" class="vncell">Client timeout</td> + <td width="78%" class="vtable" colspan="2"> + <input name="client_timeout" type="text" <?if(isset($pconfig['client_timeout'])) echo "value=\"{$pconfig['client_timeout']}\"";?> size="10" maxlength="10" /> + <div>the time (in milliseconds) we accept to wait for data from the client, or for the client to accept data (default 30000).</div> + </td> + </tr> + <tr align="left" class="haproxy_mode_http"> + <td width="22%" valign="top" class="vncell">Use 'forwardfor' option</td> + <td width="78%" class="vtable" colspan="2"> + <input id="forwardfor" name="forwardfor" type="checkbox" value="yes" <?php if ($pconfig['forwardfor']=='yes') echo "checked"; ?> /> + <br/> + The 'forwardfor' option creates an HTTP 'X-Forwarded-For' header which + contains the client's IP address. This is useful to let the final web server + know what the client address was. (eg for statistics on domains)<br/> + </td> + </tr> + <tr align="left" class="haproxy_mode_http"> + <td width="22%" valign="top" class="vncell">Use 'httpclose' option</td> + <td width="78%" class="vtable" colspan="2"> + <? + echo_html_select("httpclose",$a_closetypes,$pconfig['httpclose']?$pconfig['httpclose']:"none","","updatevisibility();"); + ?><br/> + <textarea readonly="yes" cols="70" rows="3" id="http_close_description" name="http_close_description" style="padding:5px; border:1px dashed #990000; background-color: #ffffff; color: #000000; font-size: 8pt;"></textarea> + </td> + </tr> + <tr align="left"> + <td width="22%" valign="top" class="vncell">Bind pass thru</td> + <td width="78%" class="vtable" colspan="2"> + <input name="advanced_bind" type="text" <?if(isset($pconfig['advanced_bind'])) echo "value=\"".htmlspecialchars($pconfig['advanced_bind'])."\"";?> size="64" /> + <br/> + NOTE: paste text into this box that you would like to pass behind the bind option. + </td> + </tr> + <tr align="left"> + <td width="22%" valign="top" class="vncell">Advanced pass thru</td> + <td width="78%" class="vtable" colspan="2"> + <? $textrowcount = max(substr_count($pconfig['advanced'],"\n"), 2) + 2; ?> + <textarea name='advanced' rows="<?=$textrowcount;?>" cols="70" id='advanced'><?php echo htmlspecialchars($pconfig['advanced']); ?></textarea> + <br/> + NOTE: paste text into this box that you would like to pass thru. + </td> + </tr> + <tr> + <td> </td> + </tr> + </table> + <table class="haproxy_ssloffloading_show" width="100%" border="0" cellpadding="6" cellspacing="0"> + <tr> + <td colspan="2" valign="top" class="listtopic">SSL Offloading</td> + </tr> + <tr align="left"> + <td width="78%" class="vtable" colspan="2"> + SSL Offloading will reduce web servers load by maintaining and encrypting connection with users on internet while sending and retrieving data without encrytion to internal servers. + Also more ACL rules and http logging may be configured when this option is used. + Certificates can be imported into the <a href="/system_camanager.php" target="_blank">pfSense "Certificate Authority Manager"</a> + Please be aware this possibly will not work with all web applications. Some applications will require setting the SSL checkbox on the backend server configurations so the connection to the webserver will also be a encrypted connection, in that case there will be a slight overall performance loss. + </td> + </tr> + <tr align="left" class="haproxy_secondary" > + <td width="22%" valign="top" class="vncell">Use Offloading</td> + <td width="78%" class="vtable" colspan="2"> + <input id="ssloffload" name="ssloffload" type="checkbox" value="yes" <?php if ($pconfig['ssloffload']=='yes') echo "checked";?> onclick="updatevisibility();" /><strong>Specify additional certificates for this shared-frontend.</strong> + </td> + </tr> + <tr class="haproxy_ssloffloading_enabled" align="left"> + <td width="22%" valign="top" class="vncell">Certificate</td> + <td width="78%" class="vtable" colspan="2"> + <? + echo_html_select("ssloffloadcert", $servercerts, $pconfig['ssloffloadcert'], '<b>No Certificates defined.</b> <br/>Create one under <a href="system_certmanager.php">System > Cert Manager</a>.'); + ?> + <br/> + Choose the cert to use on this frontend. + <br/> + <input id="ssloffloadacl" name="ssloffloadacl" type="checkbox" value="yes" <?php if ($pconfig['ssloffloadacl']=='yes') echo "checked";?> onclick="updatevisibility();" />Add ACL for certificate CommonName. (host header matches the 'CN' of the certificate)<br/> + </td> + </tr> + <tr class="haproxy_ssloffloading_enabled"> + <td width="22%" valign="top" class="vncell">Additional certificates</td> + <td width="78%" class="vtable" colspan="2" valign="top"> + Which of these certificate will be send will be determined by haproxys SNI recognition. If the browser does not send SNI this will not work properly. (IE on XP is one example, possibly also older browsers or mobile devices) + <? + $a_certificates = $pconfig['a_certificates']; + haproxy_htmllist("tableA_sslCertificates", $a_certificates, $fields_sslCertificates); + ?> + <br/> + <input id="ssloffloadacladditional" name="ssloffloadacladditional" type="checkbox" value="yes" <?php if ($pconfig['ssloffloadacladditional']=='yes') echo "checked";?> onclick="updatevisibility();" />Add ACL for certificate CommonName. (host header matches the 'CN' of the certificate)<br/> + </td> + </tr> + <tr class="haproxy_ssloffloading_enabled haproxy_primary" align="left"> + <td width="22%" valign="top" class="vncell">Advanced ssl options</td> + <td width="78%" class="vtable" colspan="2"> + <input type='text' name='dcertadv' size="64" id='dcertadv' <?if(isset($pconfig['dcertadv'])) echo 'value="'.htmlspecialchars($pconfig['dcertadv']).'"';?> /> + <br/> + NOTE: Paste additional ssl options(without commas) to include on ssl listening options.<br/> + some options: force-sslv3, force-tlsv10 force-tlsv11 force-tlsv12 no-sslv3 no-tlsv10 no-tlsv11 no-tlsv12 no-tls-tickets + </td> + </tr> + <tr class="haproxy_ssloffloading_enabled haproxy_primary"> + <td class="vncell" colspan="2"><b>Client certificate verification options, leave all these options empty if you do not want to ask for a client certificate</b><br/> + The users that visit this site will need to load the client cert signed by one of the ca's listed below imported into their browser.</td> + </tr> + <tr class="haproxy_ssloffloading_enabled haproxy_primary" align="left"> + <td width="22%" valign="top" class="vncell">Without client cert</td> + <td width="78%" class="vtable" colspan="2"> + <input id="sslclientcert-none" name="sslclientcert-none" type="checkbox" value="yes" <?php if ($pconfig['sslclientcert-none']=='yes') echo "checked"; ?> onclick='updatevisibility();' /> + Allows clients without a certificate to connect. + <div>Make sure to add appropriate acl's to check for presence of a user certificate where needed.</div> + </td> + </tr> + <tr class="haproxy_ssloffloading_enabled haproxy_primary" align="left"> + <td width="22%" valign="top" class="vncell">Allow invalid cert</td> + <td width="78%" class="vtable" colspan="2"> + <input id="sslclientcert-invalid" name="sslclientcert-invalid" type="checkbox" value="yes" <?php if ($pconfig['sslclientcert-invalid']=='yes') echo "checked"; ?> onclick='updatevisibility();' /> + Allows client with a invalid/expired/revoked or otherwise wrong certificate to connect. + <div>Make sure to add appropriate acl's to check for valid certificates and verify errors using codes from the following list. + <a target="_blank" href="https://www.openssl.org/docs/apps/verify.html#DIAGNOSTICS">https://www.openssl.org/docs/apps/verify.html#DIAGNOSTICS</a></div> + + </td> + </tr> + <tr class="haproxy_ssloffloading_enabled haproxy_primary"> + <td width="22%" valign="top" class="vncell">Client verification CA certificates</td> + <td width="78%" class="vtable" colspan="2" valign="top"> + Client certificate will be verified against these CA certificates. + <? + $a_certificates = $pconfig['clientcert_ca']; + haproxy_htmllist("table_clientcert_ca", $a_certificates, $fields_caCertificates); + ?> + </td> + </tr> + <tr class="haproxy_ssloffloading_enabled haproxy_primary"> + <td width="22%" valign="top" class="vncell">Client verification CRL</td> + <td width="78%" class="vtable" colspan="2" valign="top"> + Client certificate will be verified against these CRL revocation lists. + <? + $a_certificates = $pconfig['clientcert_crl']; + haproxy_htmllist("table_clientcert_crl", $a_certificates, $fields_crlCertificates); + ?> + </td> + </tr> + <tr> + <td> </td> + </tr> + </table> + <table width="100%" border="0" cellpadding="6" cellspacing="0"> + <tr align="left"> + <td width="22%" valign="top"> </td> + <td width="78%"> + <input name="Submit" type="submit" class="formbtn" value="Save" /> + <input type="button" class="formbtn" value="Cancel" onclick="history.back()" /> + <?php if (isset($id) && $a_backend[$id]): ?> + <input name="id" type="hidden" value="<?=$a_backend[$id]['name'];?>" /> + <?php endif; ?> + </td> + </tr> + <tr> + <td colspan='3'> + <span class="vexpl"><b>NOTE:</b> You must add a firewall rule permitting access to this frontend!</span> + </td> + </tr> + </table> + </div></td></tr></table> + </form> +<br/> +<script type="text/javascript"> +<? + phparray_to_javascriptarray($primaryfrontends,"primaryfrontends",Array('/*', + '/*/name','/*/ref','/*/ref/type','/*/ref/a_extaddr','/*/ref/a_extaddr/item','/*/ref/a_extaddr/item/*', + '/*/ref/a_extaddr/item/*/extaddr_ssl')); + phparray_to_javascriptarray($a_closetypes,"closetypes",Array('/*','/*/name','/*/descr')); + phparray_to_javascriptarray($fields_sslCertificates,"fields_sslCertificates",Array('/*','/*/name','/*/type','/*/size','/*/items','/*/items/*','/*/items/*/*','/*/items/*/*/name')); + phparray_to_javascriptarray($fields_caCertificates,"fields_ca",Array('/*','/*/name','/*/type','/*/size','/*/items','/*/items/*','/*/items/*/*','/*/items/*/*/name')); + phparray_to_javascriptarray($fields_crlCertificates,"fields_crl",Array('/*','/*/name','/*/type','/*/size','/*/items','/*/items/*','/*/items/*/*','/*/items/*/*/name')); + phparray_to_javascriptarray($fields_aclSelectionList,"fields_acltable",Array('/*','/*/name','/*/type','/*/size','/*/items','/*/items/*','/*/items/*/*','/*/items/*/*/name')); + phparray_to_javascriptarray($fields_externalAddress,"fields_extaddr",Array('/*','/*/name','/*/type','/*/size','/*/items','/*/items/*','/*/items/*/*','/*/items/*/*/name')); +?> +</script> +<script type="text/javascript"> + totalrows = <?php echo $counter; ?>; + + var port_array = <?= json_encode(get_alias_list(array("port", "url_ports", "urltable_ports"))) ?>; + var address_array = <?= json_encode(get_alias_list(array("host", "network", "openvpn", "urltable"))) ?>; + + + for(i=0;i < <?=count($a_extaddr)?>;i++){ + new AutoSuggestControl(document.getElementById('extaddr_custom'+i), new StateSuggestions(address_array)); + new AutoSuggestControl(document.getElementById('extaddr_port'+i), new StateSuggestions(port_array)); + // Initially set fields disabled where needed + table_extaddr_listitem_change('table_extaddr','',i,null); + } + + updatevisibility(); +</script> +<?php +haproxy_htmllist_js(); +include("fend.inc"); ?> +</body> +</html> diff --git a/config/haproxy1_5/www/haproxy_pool_edit.php b/config/haproxy1_5/www/haproxy_pool_edit.php new file mode 100644 index 00000000..5e38b12d --- /dev/null +++ b/config/haproxy1_5/www/haproxy_pool_edit.php @@ -0,0 +1,1017 @@ +<?php +/* $Id: load_balancer_pool_edit.php,v 1.24.2.23 2007/03/03 00:07:09 smos Exp $ */ +/* + haproxy_pool_edit.php + part of pfSense (https://www.pfsense.org/) + Copyright (C) 2013 PiBa-NL + Copyright (C) 2009 Scott Ullrich <sullrich@pfsense.com> + Copyright (C) 2008 Remco Hoef <remcoverhoef@pfsense.com> + 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, 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. +*/ +$shortcut_section = "haproxy"; +require("guiconfig.inc"); +require_once("haproxy.inc"); +require_once("haproxy_utils.inc"); +require_once("haproxy_htmllist.inc"); +require_once("pkg_haproxy_tabs.inc"); + +if (!is_array($config['installedpackages']['haproxy']['ha_pools']['item'])) { + $config['installedpackages']['haproxy']['ha_pools']['item'] = array(); +} + +$a_pools = &$config['installedpackages']['haproxy']['ha_pools']['item']; + +$a_files = haproxy_get_fileslist(); + +if (isset($_POST['id'])) + $id = $_POST['id']; +else + $id = $_GET['id']; + +$tmp = get_backend_id($id); +if (is_numeric($tmp)) + $id = $tmp; + +if (isset($_GET['dup'])) + $id = $_GET['dup']; + +global $simplefields; +$simplefields = array( +"name","balance","transparent_clientip","transparent_interface", +"check_type","checkinter","log-health-checks","httpcheck_method","monitor_uri","monitor_httpversion","monitor_username","monitor_domain","monitor_agentport", +"agent_check","agent_port","agent_inter", +"connection_timeout","server_timeout","retries", +"stats_enabled","stats_username","stats_password","stats_uri","stats_scope","stats_realm","stats_admin","stats_node","stats_desc","stats_refresh", +"persist_stick_expire","persist_stick_tablesize","persist_stick_length","persist_stick_cookiename","persist_sticky_type", +"persist_cookie_enabled","persist_cookie_name","persist_cookie_mode","persist_cookie_cachable", +"strict_transport_security","cookie_attribute_secure" +); + +$primaryfrontends = get_haproxy_frontends(); +$none = array(); +$none['']['name']="Address+Port:"; +$primaryfrontends = $none + $primaryfrontends; + +$fields_servers=array(); +$fields_servers[0]['name']="status"; +$fields_servers[0]['columnheader']="Mode"; +$fields_servers[0]['colwidth']="5%"; +$fields_servers[0]['type']="select"; +$fields_servers[0]['size']="70px"; +$fields_servers[0]['items']=&$a_servermodes; +$fields_servers[1]['name']="name"; +$fields_servers[1]['columnheader']="Name"; +$fields_servers[1]['colwidth']="20%"; +$fields_servers[1]['type']="textbox"; +$fields_servers[1]['size']="30"; +$fields_servers[2]['name']="forwardto"; +$fields_servers[2]['columnheader']="Forwardto"; +$fields_servers[2]['colwidth']="15%"; +$fields_servers[2]['type']="select"; +$fields_servers[2]['size']="100px"; +$fields_servers[2]['items']=&$primaryfrontends; +$fields_servers[3]['name']="address"; +$fields_servers[3]['columnheader']="Address"; +$fields_servers[3]['colwidth']="10%"; +$fields_servers[3]['type']="textbox"; +$fields_servers[3]['size']="20"; +$fields_servers[4]['name']="port"; +$fields_servers[4]['columnheader']="Port"; +$fields_servers[4]['colwidth']="5%"; +$fields_servers[4]['type']="textbox"; +$fields_servers[4]['size']="5"; +$fields_servers[5]['name']="ssl"; +$fields_servers[5]['columnheader']="SSL"; +$fields_servers[5]['colwidth']="5%"; +$fields_servers[5]['type']="checkbox"; +$fields_servers[5]['size']="30"; +$fields_servers[6]['name']="weight"; +$fields_servers[6]['columnheader']="Weight"; +$fields_servers[6]['colwidth']="8%"; +$fields_servers[6]['type']="textbox"; +$fields_servers[6]['size']="5"; + +$listitem_none['']['name']="None"; + +$certs_ca = haproxy_get_certificates('ca'); +$certs_ca = $listitem_none + $certs_ca; +$certs_client = haproxy_get_certificates('server,user'); +$certs_client = $listitem_none + $certs_client; +$certs_crl = haproxy_get_crls(); +$certs_crl = $listitem_none + $certs_crl; + +$fields_servers_details=array(); +$fields_servers_details[0]['name']="sslserververify"; +$fields_servers_details[0]['columnheader']="Check certificate"; +$fields_servers_details[0]['description']="SSL servers only, The server certificate will be verified against the CA and CRL certificate configured below."; +$fields_servers_details[0]['colwidth']="5%"; +$fields_servers_details[0]['type']="checkbox"; +$fields_servers_details[0]['size']="5"; +$fields_servers_details[1]['name']="verifyhost"; +$fields_servers_details[1]['columnheader']="Certificate check CN"; +$fields_servers_details[1]['description']="SSL servers only, when set, must match the hostnames in the subject and subjectAlternateNames of the certificate provided by the server."; +$fields_servers_details[1]['colwidth']="5%"; +$fields_servers_details[1]['type']="textbox"; +$fields_servers_details[1]['size']="50"; +$fields_servers_details[2]['name']="ssl-server-ca"; +$fields_servers_details[2]['columnheader']="CA"; +$fields_servers_details[2]['description']="SSL servers only, Select the CA authority to check the server certificate against."; +$fields_servers_details[2]['colwidth']="15%"; +$fields_servers_details[2]['type']="select"; +$fields_servers_details[2]['size']="200px"; +$fields_servers_details[2]['items']=$certs_ca; +$fields_servers_details[3]['name']="ssl-server-crl"; +$fields_servers_details[3]['columnheader']="CRL"; +$fields_servers_details[3]['description']="SSL servers only, Select the CRL to check revoked certificates."; +$fields_servers_details[3]['colwidth']="15%"; +$fields_servers_details[3]['type']="select"; +$fields_servers_details[3]['size']="200px"; +$fields_servers_details[3]['items']=$certs_crl; +$fields_servers_details[4]['name']="ssl-server-clientcert"; +$fields_servers_details[4]['columnheader']="Client certificate"; +$fields_servers_details[4]['description']="SSL servers only, This certificate will be sent if the server send a client certificate request."; +$fields_servers_details[4]['colwidth']="15%"; +$fields_servers_details[4]['type']="select"; +$fields_servers_details[4]['size']="200px"; +$fields_servers_details[4]['items']=$certs_client; +$fields_servers_details[5]['name']="cookie"; +$fields_servers_details[5]['columnheader']="Cookie"; +$fields_servers_details[5]['description']="Persistence only, Used to identify server when cookie persistence is configured for the backend."; +$fields_servers_details[5]['colwidth']="10%"; +$fields_servers_details[5]['type']="textbox"; +$fields_servers_details[5]['size']="10"; +$fields_servers_details[6]['name']="maxconn"; +$fields_servers_details[6]['columnheader']="Max conn"; +$fields_servers_details[6]['description']="Tuning, If the number of incoming concurrent requests goes higher than this value, they will be queued"; +$fields_servers_details[6]['colwidth']="15%"; +$fields_servers_details[6]['type']="textbox"; +$fields_servers_details[6]['size']="10"; +$fields_servers_details[7]['name']="advanced"; +$fields_servers_details[7]['columnheader']="Advanced"; +$fields_servers_details[7]['description']="Advanced, Allows for adding custom HAProxy settings to the server. These are passed as written, use escaping where needed."; +$fields_servers_details[7]['colwidth']="15%"; +$fields_servers_details[7]['type']="textbox"; +$fields_servers_details[7]['size']="80"; + +$fields_errorfile = array(); +$fields_errorfile[0]['name']="errorcode"; +$fields_errorfile[0]['columnheader']="errorcode(s)"; +$fields_errorfile[0]['colwidth']="15%"; +$fields_errorfile[0]['type']="textbox"; +$fields_errorfile[0]['size']="70px"; +$fields_errorfile[1]['name']="errorfile"; +$fields_errorfile[1]['columnheader']="Error Page"; +$fields_errorfile[1]['colwidth']="30%"; +$fields_errorfile[1]['type']="select"; +$fields_errorfile[1]['size']="170px"; +$fields_errorfile[1]['items']=&$a_files; + +if (isset($id) && $a_pools[$id]) { + $pconfig['advanced'] = base64_decode($a_pools[$id]['advanced']); + $pconfig['advanced_backend'] = base64_decode($a_pools[$id]['advanced_backend']); + $pconfig['a_servers']=&$a_pools[$id]['ha_servers']['item']; + + foreach($simplefields as $stat) + $pconfig[$stat] = $a_pools[$id][$stat]; + + $a_errorfiles = &$a_pools[$id]['errorfiles']['item']; + if (!is_array($a_errorfiles)) $a_errorfiles = array(); +} + +if (isset($_GET['dup'])) + unset($id); + +$changedesc = "Services: HAProxy: Backend server pool: "; +$changecount = 0; + +if ($_POST) { + $changecount++; + + unset($input_errors); + $pconfig = $_POST; + + $reqdfields = explode(" ", "name"); + $reqdfieldsn = explode(",", "Name"); + + do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors); + + if ($_POST['stats_enabled']) { + $reqdfields = explode(" ", "name stats_uri"); + $reqdfieldsn = explode(",", "Name,Stats Uri"); + do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors); + if ($_POST['stats_username']) { + $reqdfields = explode(" ", "stats_password stats_realm"); + $reqdfieldsn = explode(",", "Stats Password,Stats Realm"); + do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors); + } + } + + if (preg_match("/[^a-zA-Z0-9\.\-_]/", $_POST['name'])) + $input_errors[] = "The field 'Name' contains invalid characters."; + + if ($_POST['checkinter'] !== "" && !is_numeric($_POST['checkinter'])) + $input_errors[] = "The field 'Check frequency' value is not a number."; + + if ($_POST['connection_timeout'] !== "" && !is_numeric($_POST['connection_timeout'])) + $input_errors[] = "The field 'Connection timeout' value is not a number."; + + if ($_POST['server_timeout'] !== "" && !is_numeric($_POST['server_timeout'])) + $input_errors[] = "The field 'Server timeout' value is not a number."; + + if ($_POST['retries'] !== "" && !is_numeric($_POST['retries'])) + $input_errors[] = "The field 'Retries' value is not a number."; + + // the colon ":" is invalid in the username, other than that pretty much any character can be used. + if (preg_match("/[^a-zA-Z0-9!-\/;-~ ]/", $_POST['stats_username'])) + $input_errors[] = "The field 'Stats Username' contains invalid characters."; + + // the colon ":" can also be used in the password + if (preg_match("/[^a-zA-Z0-9!-~ ]/", $_POST['stats_password'])) + $input_errors[] = "The field 'Stats Password' contains invalid characters."; + + if (preg_match("/[^a-zA-Z0-9\-_]/", $_POST['stats_node'])) + $input_errors[] = "The field 'Stats Node' contains invalid characters. Should be a string with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_)"; + + /* Ensure that our pool names are unique */ + for ($i=0; isset($config['installedpackages']['haproxy']['ha_pools']['item'][$i]); $i++) + if (($_POST['name'] == $config['installedpackages']['haproxy']['ha_pools']['item'][$i]['name']) && ($i != $id)) + $input_errors[] = "This pool name has already been used. Pool names must be unique."; + + $a_servers = haproxy_htmllist_get_values(array_merge($fields_servers,$fields_servers_details)); + foreach($a_servers as $server){ + $server_name = $server['name']; + $server_address = $server['address']; + $server_port = $server['port']; + $server_weight = $server['weight']; + + if (preg_match("/[^a-zA-Z0-9\.\-_]/", $server_name)) + $input_errors[] = "The field 'Name' contains invalid characters."; + + if (!isset($server['forwardto']) || $server['forwardto'] == "") { + if (!is_ipaddr($server_address) && !is_hostname($server_address) && !haproxy_is_frontendname($server_address)) + $input_errors[] = "The field 'Address' for server $server_name is not a valid ip address or hostname." . $server_address; + } else { + if ( ($server_address && $server_address != "") || ($server_port && !is_numeric($server_port))) { + $input_errors[] = "'Address' and 'port' should be empty when a 'Forwardto' frontend is chosen other than 'Address+Port'."; + } + } + + if (!preg_match("/.{2,}/", $server_name)) + $input_errors[] = "The field 'Name' is required (and must be at least 2 characters)."; + + if ($server_weight && !is_numeric($server_weight)) + $input_errors[] = "The field 'Weight' value is not a number."; + + if ($server_port && !is_numeric($server_port)) + $input_errors[] = "The field 'Port' value is not a number."; + } + + $a_errorfiles = haproxy_htmllist_get_values($fields_errorfile); + + if ($_POST['strict_transport_security'] !== "" && !is_numeric($_POST['strict_transport_security'])) + $input_errors[] = "The field 'Strict-Transport-Security' is not empty or a number."; + +// if (!$input_errors) { + $pool = array(); + if(isset($id) && $a_pools[$id]) + $pool = $a_pools[$id]; + + if ($pool['name'] != $_POST['name']) { + // name changed: + if (!is_array($config['installedpackages']['haproxy']['ha_backends']['item'])) { + $config['installedpackages']['haproxy']['ha_backends']['item'] = array(); + } + $a_backend = &$config['installedpackages']['haproxy']['ha_backends']['item']; + + for ( $i = 0; $i < count($a_backend); $i++) { + if ($a_backend[$i]['backend_serverpool'] == $pool['name']) + $a_backend[$i]['backend_serverpool'] = $_POST['name']; + } + } + + if($pool['name'] != "") + $changedesc .= " modified pool: '{$pool['name']}'"; + + $pool['ha_servers']['item']=$a_servers; + + update_if_changed("advanced", $pool['advanced'], base64_encode($_POST['advanced'])); + update_if_changed("advanced_backend", $pool['advanced_backend'], base64_encode($_POST['advanced_backend'])); + + global $simplefields; + foreach($simplefields as $stat) + update_if_changed($stat, $pool[$stat], $_POST[$stat]); + + if (isset($id) && $a_pools[$id]) { + $a_pools[$id] = $pool; + } else { + $a_pools[] = $pool; + } + if (!isset($input_errors)) { + if ($changecount > 0) { + touch($d_haproxyconfdirty_path); + write_config($changedesc); + /* + echo "<PRE>"; + print_r($config); + echo "</PRE>"; + */ + } + + header("Location: haproxy_pools.php"); + exit; + } + $pconfig['a_servers']=&$a_pools[$id]['ha_servers']['item']; +} + +$closehead = false; +$pgtitle = "HAProxy: Backend server pool: Edit"; +include("head.inc"); + +// 'processing' done, make all simple fields usable in html. +foreach($simplefields as $field){ + $pconfig[$field] = htmlspecialchars($pconfig[$field]); +} + +?> + <style type="text/css"> + .tableA_servers_details_visible{display:none;} + .haproxy_stats_visible{display:none;} + .haproxy_check_enabled{display:none;} + .haproxy_check_http{display:none;} + .haproxy_check_username{display:none;} + .haproxy_check_smtp{display:none;} + .haproxy_transparent_clientip{display:none;} + .haproxy_check_agent{display:none;} + .haproxy_agent_check{display:none;} + .haproxy_stick_cookiename{display:none;} + .haproxy_stick_tableused{display:none;} + .haproxy_cookie_visible{display:none;} + .haproxy_help_serverlist{display:none;} + </style> +</head> +<body link="#0000CC" vlink="#0000CC" alink="#0000CC"> +<script type="text/javascript"> + function htmllist_get_select_options(tableId, fieldname) { + if (fieldname == 'forwardto') + return "<?=haproxy_js_select_options($primaryfrontends);?>"; + else + if (fieldname == 'errorfile') + return "<?=haproxy_js_select_options($a_files);?>"; + else + return "<?=haproxy_js_select_options($a_servermodes);?>"; + } + + function clearcombo(){ + for (var i=document.iform.serversSelect.options.length-1; i>=0; i--){ + document.iform.serversSelect.options[i] = null; + } + document.iform.serversSelect.selectedIndex = -1; + } + + function setCSSdisplay(cssID, display) + { + var ss = document.styleSheets; + for (var i=0; i<ss.length; i++) { + var rules = ss[i].cssRules || ss[i].rules; + for (var j=0; j<rules.length; j++) { + if (rules[j].selectorText === cssID) { + rules[j].style.display = display ? "" : "none"; + } + } + } + } + function toggleCSSdisplay(cssID) + { + var ss = document.styleSheets; + for (var i=0; i<ss.length; i++) { + var rules = ss[i].cssRules || ss[i].rules; + for (var j=0; j<rules.length; j++) { + if (rules[j].selectorText === cssID) { + rules[j].style.display = rules[j].style.display == "none" ? "" : "none"; + } + } + } + } + + function updatevisibility() + { + d = document; + setCSSdisplay(".tableA_servers_details_visible", server_advanced_options_visible.checked); + setCSSdisplay(".haproxy_stats_visible", stats_enabled.checked); + setCSSdisplay(".haproxy_cookie_visible", persist_cookie_enabled.checked); + + check_type = d.getElementById("check_type").value; + check_type_description = d.getElementById("check_type_description"); + check_type_description.innerHTML=checktypes[check_type]["descr"]; + + persist_cookie_mode = d.getElementById("persist_cookie_mode").value; + persist_cookie_mode_description = d.getElementById("persist_cookie_mode_description"); + persist_cookie_mode_description.innerHTML=cookiemode[persist_cookie_mode]["descr"]; + persist_cookie_mode_description.setAttribute('style','padding:5px; border:1px dashed #990000; background-color: #ffffff; color: #000000; font-size: 8pt; height:30px'); + persist_cookie_mode_description.setAttribute('style','padding:5px; border:1px dashed #990000; background-color: #ffffff; color: #000000; font-size: 8pt; height:'+persist_cookie_mode_description.scrollHeight+'px'); + + setCSSdisplay(".haproxy_check_enabled", check_type != 'none'); + setCSSdisplay(".haproxy_check_http", check_type == 'HTTP'); + setCSSdisplay(".haproxy_check_username", check_type == 'MySQL' || check_type == 'PostgreSQL'); + setCSSdisplay(".haproxy_check_smtp", check_type == 'SMTP' || check_type == 'ESMTP'); + setCSSdisplay(".haproxy_check_agent", check_type == 'Agent'); + + setCSSdisplay(".haproxy_agent_check", agent_check.checked); + + transparent_clientip = d.getElementById("transparent_clientip"); + setCSSdisplay(".haproxy_transparent_clientip", transparent_clientip.checked); + + + persist_sticky_type = d.getElementById("persist_sticky_type").value; + setCSSdisplay(".haproxy_stick_tableused", persist_sticky_type != 'none'); + setCSSdisplay(".haproxy_stick_cookiename", persist_sticky_type == 'stick_rdp_cookie' || persist_sticky_type == 'stick_cookie_value'); + + cookie_example = sticky_type[persist_sticky_type]['cookiedescr']; + stick_cookiename_description = d.getElementById("stick_cookiename_description"); + stick_cookiename_description.innerHTML = cookie_example; + sticky_type_description.innerHTML = sticky_type[persist_sticky_type]['descr']; + + monitor_username = d.getElementById("monitor_username"); + sqlcheckusername = d.getElementById("sqlcheckusername"); + if(!browser_InnerText_support){ + sqlcheckusername.textContent = monitor_username.value; + } else{ + sqlcheckusername.innerText = monitor_username.value; + } + } +</script> +<?php include("fbegin.inc"); ?> +<?php if (isset($input_errors)) print_input_errors($input_errors); ?> + <form action="haproxy_pool_edit.php" method="post" name="iform" id="iform"> + + <table width="100%" border="0" cellpadding="0" cellspacing="0"> + <tr><td class="tabnavtbl"> + <?php + haproxy_display_top_tabs_active($haproxy_tab_array['haproxy'], "backend"); + ?> + </td></tr> + <tr> + <td> + <div class="tabcont"> + <table width="100%" border="0" cellpadding="6" cellspacing="0"> + <tr> + <td colspan="2" valign="top" class="listtopic">Edit HAProxy Backend server pool</td> + </tr> + <tr align="left"> + <td width="22%" valign="top" class="vncellreq">Name</td> + <td width="78%" class="vtable" colspan="2"> + <input name="name" type="text" <?if(isset($pconfig['name'])) echo "value=\"{$pconfig['name']}\"";?> size="16" maxlength="16" /> + </td> + </tr> + <tr align="left"> + <td class="vncell" colspan="3"><strong>Server list</strong><input id="server_advanced_options_visible" name="server_advanced_options_visible" type='checkbox' onclick="updatevisibility();">Show advanced options(servers need to first be saved to configure these settings)</input> + <span style="float:right;"> + Toggle serverlist help. <a onclick="toggleCSSdisplay('.haproxy_help_serverlist');" title="<?php echo gettext("Help"); ?>"><img style="vertical-align:middle" src="/themes/<?php echo $g['theme']; ?>/images/icons/icon_help.gif" border="0" alt="help" /></a> + </span> + <? + $counter=0; + $a_servers = $pconfig['a_servers']; + haproxy_htmllist("tableA_servers", $a_servers, $fields_servers, null, $fields_servers_details); + ?> + <table class="haproxy_help_serverlist" style="border:1px dashed green" cellspacing="0"> + <tr><td class="vncell"> + Mode: </td><td class="vncell">Active: server will be used normally<br/> + Backup: server is only used in load balancing when all other non-backup servers are unavailable<br/> + Disabled: server is marked down in maintenance mode<br/> + Inactive: server will not be available for use + </td></tr><tr><td class="vncell"> + Name: </td><td class="vncell">Used to as a name for the server in for example the stats<br/>EXAMPLE: MyWebServer + </td></tr><tr><td class="vncell"> + Address: </td><td class="vncell">IP or hostname(only resolved on start-up.)<br/>EXAMPLE: 192.168.1.22 , fe80::1000:2000:3000:4000%em0 , WebServer1.localdomain + </td></tr><tr><td class="vncell"> + Port: </td><td class="vncell">The port of the backend.<br/>EXAMPLE: 80 or 443<br/> + </td></tr><tr><td class="vncell"> + SSL: </td><td class="vncell">Is the backend using SSL (commonly with port 443)<br/> + </td></tr><tr><td class="vncell"> + Weight: </td><td class="vncell">A weight between 0 and 256, this setting can be used when multiple servers on different hardware need to be balanced with with a different part the traffic. A server with weight 0 wont get new traffic. Default if empty: 1 + </td></tr><tr><td class="vncell"> + Cookie: </td><td class="vncell">the value of the cookie used to identify a server (only when cookie-persistence is enabled below) + </td></tr><tr><td class="vncell"> + Advanced: </td><td class="vncell">More advanced settings like rise,fall,error-limit,send-proxy and others can be configured here.<br/>For a full list of options see the <a target="_blank" href="http://cbonte.github.io/haproxy-dconv/configuration-1.5.html#5.2">HAProxy manual: Server and default-server options</a> + </td></tr> + </table> + </td> + </tr> + <tr align="left"> + <td width="22%" valign="top" class="vncellreq">Balance</td> + <td width="78%" class="vtable" colspan="1"> + <table width="100%"> + <tr> + <td width="25%" valign="top"> + <input type="radio" name="balance" value="roundrobin"<?php if($pconfig['balance'] == "roundrobin") echo " CHECKED"; ?> />Round robin + </td> + <td> + Each server is used in turns, according to their weights. + This is the smoothest and fairest algorithm when the server's + processing time remains equally distributed. This algorithm + is dynamic, which means that server weights may be adjusted + on the fly for slow starts for instance. + </td> + </tr> + <tr> + <td width="25%" valign="top"> + <input type="radio" name="balance" value="static-rr"<?php if($pconfig['balance'] == "static-rr") echo " CHECKED"; ?> />Static Round Robin + </td> + <td> + Each server is used in turns, according to their weights. + This algorithm is as similar to roundrobin except that it is + static, which means that changing a server's weight on the + fly will have no effect. On the other hand, it has no design + limitation on the number of servers, and when a server goes + up, it is always immediately reintroduced into the farm, once + the full map is recomputed. It also uses slightly less CPU to + run (around -1%). + </td> + </tr> + <tr> + <td width="25%" valign="top"> + <input type="radio" name="balance" value="leastconn"<?php if($pconfig['balance'] == "leastconn") echo " CHECKED"; ?> />Least Connections + </td> + <td> + The server with the lowest number of connections receives the + connection. Round-robin is performed within groups of servers + of the same load to ensure that all servers will be used. Use + of this algorithm is recommended where very long sessions are + expected, such as LDAP, SQL, TSE, etc... but is not very well + suited for protocols using short sessions such as HTTP. This + algorithm is dynamic, which means that server weights may be + adjusted on the fly for slow starts for instance. + </td> + </tr> + <tr><td valign="top"><input type="radio" name="balance" value="source"<?php if($pconfig['balance'] == "source") echo " CHECKED"; ?> />Source + </td> + <td> + The source IP address is hashed and divided by the total + weight of the running servers to designate which server will + receive the request. This ensures that the same client IP + address will always reach the same server as long as no + server goes down or up. If the hash result changes due to the + number of running servers changing, many clients will be + directed to a different server. This algorithm is generally + used in TCP mode where no cookie may be inserted. It may also + be used on the Internet to provide a best-effort stickyness + to clients which refuse session cookies. This algorithm is + static, which means that changing a server's weight on the + fly will have no effect. + </td> + </tr> + </table> + </td> + </tr> + <tr align="left"> + <td width="22%" valign="top" class="vncell">Transparent ClientIP</td> + <td width="78%" class="vtable" colspan="2"> + WARNING Activating this option will load rules in IPFW and might interfere with CaptivePortal and possibly other services due to the way server return traffic must be 'captured' with a automatically created fwd rule. This also breaks directly accessing the (web)server on the ports configured above. Also a automatic sloppy pf rule is made to allow HAProxy to server traffic.<br/> + <input id="transparent_clientip" name="transparent_clientip" type="checkbox" value="yes" <?php if ($pconfig['transparent_clientip']=='yes') echo "checked"; ?> onclick='updatevisibility();' /> + Use Client-IP to connect to backend servers. + <div class="haproxy_transparent_clientip"> + + <? + $interfaces = get_configured_interface_with_descr(); + $interfaces2 = array(); + foreach($interfaces as $key => $name) + { + + $interfaces2[$key]['name'] = $name; + } + echo_html_select("transparent_interface",$interfaces2,$pconfig['transparent_interface']?$pconfig['transparent_interface']:"lan","","updatevisibility();"); + ?>Interface that will connect to the backend server. (this will generally be your LAN or OPT1(dmz) interface)<br/> + </div> + <br/> + Connect transparently to the backend server's so the connection seams to come straight from the client ip address. + To work properly this requires the reply traffic to pass through pfSense by means of correct routing.<br/> + When using IPv6 only routable ip addresses can be used, host names or link-local addresses (FE80) will not work.<br/> + (uses the option "source 0.0.0.0 usesrc clientip" or "source ipv6@ usesrc clientip") + <br/><br/> + Note : When this is enabled for any backend HAProxy will run as 'root' instead of chrooting to a lower privileged user, this reduces security in case a vulnerability is found. + </td> + </tr> + <tr align="left"> + <td width="22%" valign="top" class="vncell">Per server pass thru</td> + <td width="78%" class="vtable" colspan="2"> + <input type="text" name='advanced' id='advanced' value='<?php echo htmlspecialchars($pconfig['advanced']); ?>' size="64" /> + <br/> + NOTE: paste text into this box that you would like to pass thru. Applied to each 'server' line. + </td> + </tr> + + <tr align="left"> + <td width="22%" valign="top" class="vncell">Backend pass thru</td> + <td width="78%" class="vtable" colspan="2"> + <? $textrowcount = max(substr_count($pconfig['advanced_backend'],"\n"), 2) + 2; ?> + <textarea rows="<?=$textrowcount;?>" cols="70" name='advanced_backend' id='advanced_backend'><?php echo htmlspecialchars($pconfig['advanced_backend']); ?></textarea> + <br/> + NOTE: paste text into this box that you would like to pass thru. Applied to the backend section. + </td> + </tr> + <tr><td> </td></tr> + <tr> + <td colspan="2" valign="top" class="listtopic">Health checking</td> + </tr> + <tr align="left"> + <td width="22%" valign="top" class="vncell">Health check method</td> + <td width="78%" class="vtable" colspan="2"> + <? + echo_html_select("check_type",$a_checktypes,$pconfig['check_type']?$pconfig['check_type']:"HTTP","","updatevisibility();"); + ?><br/> + <textarea readonly="yes" cols="60" rows="2" id="check_type_description" name="check_type_description" style="padding:5px; border:1px dashed #990000; background-color: #ffffff; color: #000000; font-size: 8pt;"></textarea> + </td> + </tr> + <tr align="left" class="haproxy_check_enabled"> + <td width="22%" valign="top" class="vncell">Check frequency</td> + <td width="78%" class="vtable" colspan="2"> + <input name="checkinter" type="text" <?if(isset($pconfig['checkinter'])) echo "value=\"{$pconfig['checkinter']}\"";?> size="20" /> milliseconds + <br/>For HTTP/HTTPS defaults to 1000 if left blank. For TCP no check will be performed if left empty. + </td> + </tr> + <tr align="left" class="haproxy_check_enabled"> + <td width="22%" valign="top" class="vncell">Log checks</td> + <td width="78%" class="vtable" colspan="2"> + <input id="log-health-checks" name="log-health-checks" type="checkbox" value="yes" <?php if ($pconfig['log-health-checks']=='yes') echo "checked"; ?> onclick='updatevisibility();' /> + When this option is enabled, any change of the health check status or to the server's health will be logged. + <br/> + By default, failed health check are logged if server is UP and successful health checks are logged if server is DOWN, so the amount of additional information is limited. + </td> + </tr> + <tr align="left" class="haproxy_check_http"> + <td width="22%" valign="top" class="vncell">Http check method</td> + <td width="78%" class="vtable" colspan="2"> + <? + echo_html_select("httpcheck_method",$a_httpcheck_method,$pconfig['httpcheck_method']); + ?> + <br/>OPTIONS is the method usually best to perform server checks, HEAD and GET can also be used + </td> + </tr> + <tr align="left" class="haproxy_check_http"> + <td width="22%" valign="top" class="vncell">Http check URI</td> + <td width="78%" class="vtable" colspan="2"> + <input name="monitor_uri" type="text" <?if(isset($pconfig['monitor_uri'])) echo "value=\"{$pconfig['monitor_uri']}\"";?>size="64" /> + <br/>Defaults to / if left blank. + </td> + </tr> + <tr align="left" class="haproxy_check_http"> + <td width="22%" valign="top" class="vncell">Http check version</td> + <td width="78%" class="vtable" colspan="2"> + <input name="monitor_httpversion" type="text" <?if(isset($pconfig['monitor_httpversion'])) echo "value=\"{$pconfig['monitor_httpversion']}\"";?> size="64" /> + <br/>Defaults to "HTTP/1.0" if left blank. + Note that the Host field is mandatory in HTTP/1.1, and as a trick, it is possible to pass it + after "\r\n" following the version string like this:<br/> + "<i>HTTP/1.1\r\nHost:\ www</i>"<br/> + Also some hosts might require an accept parameter like this:<br/> + "<i>HTTP/1.0\r\nHost:\ webservername:8080\r\nAccept:\ */*</i>" + </td> + </tr> + <tr align="left" class="haproxy_check_username"> + <td width="22%" valign="top" class="vncell">Check with Username</td> + <td width="78%" class="vtable" colspan="2"> + <input name="monitor_username" id="monitor_username" type="text" <?if(isset($pconfig['monitor_username'])) echo "value=\"{$pconfig['monitor_username']}\"";?>size="64" onchange="updatevisibility();" onkeyup="updatevisibility();" /> + <br/> + This is the username which will be used when connecting to MySQL/PostgreSQL server. + <pre> +USE mysql; +CREATE USER '<span id="sqlcheckusername"></span>'@'<pfSenseIP>'; +FLUSH PRIVILEGES;</pre> + </td> + </tr> + <tr align="left" class="haproxy_check_smtp"> + <td width="22%" valign="top" class="vncell">Domain</td> + <td width="78%" class="vtable" colspan="2"> + <input name="monitor_domain" type="text" <?if(isset($pconfig['monitor_domain'])) echo "value=\"{$pconfig['monitor_domain']}\"";?> size="64" /> + </td> + </tr> + <tr align="left" class="haproxy_check_agent"> + <td width="22%" valign="top" class="vncell">Agentport</td> + <td width="78%" class="vtable" colspan="2"> + <input name="monitor_agentport" type="text" <?if(isset($pconfig['monitor_agentport'])) echo "value=\"{$pconfig['monitor_agentport']}\"";?> size="64" /> + <br/> + Fill in the TCP portnumber the healthcheck should be performed on. + </td> + </tr> + <tr><td> </td></tr> + <tr> + <td colspan="2" valign="top" class="listtopic">Agent checks</td> + </tr> + <tr align="left"> + <td width="22%" valign="top" class="vncell">Use agent checks</td> + <td width="78%" class="vtable" colspan="2"> + <input id="agent_check" name="agent_check" type="checkbox" value="yes" <?php if ($pconfig['agent_check']=='yes') echo "checked"; ?> onclick='updatevisibility();' /> + Use a TCP connection to read an ASCII string of the form 100%,75%,drain,down (more about this in the <a href='http://cbonte.github.io/haproxy-dconv/configuration-1.5.html#agent-check' target='_blank'>haproxy manual</a>) + </td> + </tr> + <tr align="left" class="haproxy_agent_check"> + <td width="22%" valign="top" class="vncell">Agent port</td> + <td width="78%" class="vtable" colspan="2"> + <input name="agent_port" type="text" <?if(isset($pconfig['agent_port'])) echo "value=\"{$pconfig['agent_port']}\"";?> size="64" /> + <br/> + Fill in the TCP portnumber the healthcheck should be performed on. + </td> + </tr> + <tr align="left" class="haproxy_agent_check"> + <td width="22%" valign="top" class="vncell">Agent interval</td> + <td width="78%" class="vtable" colspan="2"> + <input name="agent_inter" type="text" <?if(isset($pconfig['agent_inter'])) echo "value=\"{$pconfig['agent_inter']}\"";?> size="64" /> + <br/> + Interval between two agent checks, defaults to 2000 ms. + </td> + </tr> + <tr><td> </td></tr> + <tr> + <td colspan="2" valign="top" class="listtopic">Advanced settings</td> + </tr> + <tr align="left"> + <td width="22%" valign="top" class="vncell">Connection timeout</td> + <td width="78%" class="vtable" colspan="2"> + <input name="connection_timeout" type="text" <?if(isset($pconfig['connection_timeout'])) echo "value=\"{$pconfig['connection_timeout']}\"";?> size="20" /> + <div>the time (in milliseconds) we give up if the connection does not complete within (default 30000).</div> + </td> + </tr> + <tr align="left"> + <td width="22%" valign="top" class="vncell">Server timeout</td> + <td width="78%" class="vtable" colspan="2"> + <input name="server_timeout" type="text" <?if(isset($pconfig['server_timeout'])) echo "value=\"{$pconfig['server_timeout']}\"";?> size="20" /> + <div>the time (in milliseconds) we accept to wait for data from the server, or for the server to accept data (default 30000).</div> + </td> + </tr> + <tr align="left"> + <td width="22%" valign="top" class="vncell">Retries</td> + <td width="78%" class="vtable" colspan="2"> + <input name="retries" type="text" <?if(isset($pconfig['retries'])) echo "value=\"{$pconfig['retries']}\"";?> size="20" /> + <div>After a connection failure to a server, it is possible to retry, potentially +on another server. This is useful if health-checks are too rare and you don't +want the clients to see the failures. The number of attempts to reconnect is +set by the 'retries' parameter.</div> + </td> + </tr> + <tr><td> </td></tr> + <tr> + <td colspan="2" valign="top" class="listtopic">Cookie persistence</td> + </tr> + <tr align="left"> + <td width="22%" valign="top" class="vncell">Cookie Enabled</td> + <td width="78%" class="vtable" colspan="2"> + <input id="persist_cookie_enabled" name="persist_cookie_enabled" type="checkbox" value="yes" <?php if ($pconfig['persist_cookie_enabled']=='yes') echo "checked"; ?> onclick='updatevisibility();' /> + Enables cookie based persistence. (only used on 'http' frontends) + </td> + </tr> + <tr class="haproxy_cookie_visible" align="left"> + <td width="22%" valign="top" class="vncellreq">Server Cookies</td> + <td width="78%" class="vtable" colspan="2"> + <b>Make sure to configure a different cookie on every server in this backend.<b/> + </td> + </tr> + <tr class="haproxy_cookie_visible" align="left"> + <td width="22%" valign="top" class="vncellreq">Cookie Name</td> + <td width="78%" class="vtable" colspan="2"> + <input id="persist_cookie_name" name="persist_cookie_name" type="text" <?if(isset($pconfig['persist_cookie_name'])) echo "value=\"{$pconfig['persist_cookie_name']}\"";?> size="64" /><br/> + The string name to track in Set-Cookie and Cookie HTTP headers.<br/> + EXAMPLE: MyLoadBalanceCookie JSESSIONID PHPSESSID ASP.NET_SessionId + </td> + </tr> + <tr class="haproxy_cookie_visible" align="left"> + <td width="22%" valign="top" class="vncellreq">Cookie Mode</td> + <td width="78%" class="vtable" colspan="2"> + <? + echo_html_select("persist_cookie_mode",$a_cookiemode,$pconfig['persist_cookie_mode'],"","updatevisibility();"); + ?> + Determines how HAProxy inserts/prefixes/replaces or examines cookie and set-cookie headers.<br/> + EXAMPLE: with an existing PHPSESSIONID you can for example use "Session-prefix" or to create a new cookie use "Insert-silent".<br/> + <br/> + <textarea readonly="yes" cols="60" rows="2" id="persist_cookie_mode_description" name="persist_cookie_mode_description" style="padding:5px; border:1px dashed #990000; background-color: #ffffff; color: #000000; font-size: 8pt;"></textarea> + </td> + </tr> + <tr class="haproxy_cookie_visible" align="left"> + <td width="22%" valign="top" class="vncell">Cookie Cachable</td> + <td width="78%" class="vtable" colspan="2"> + <input id="persist_cookie_cachable" name="persist_cookie_cachable" type="checkbox" value="yes" <?php if ($pconfig['persist_cookie_cachable']=='yes') echo "checked"; ?> onclick='updatevisibility();' /> + Allows shared caches to cache the server response. + </td> + </tr> + <tr><td> </td></tr> + <tr> + <td colspan="2" valign="top" class="listtopic">Stick-table persistence</td> + </tr> + <tr><td class="vncell"></td><td class="vncell">These options are used to make sure seperate requests from a single client go to the same backend. This can be required for servers that keep track of for example a shopping cart.</td></tr> + <tr align="left"> + <td width="22%" valign="top" class="vncell">Stick tables</td> + <td width="78%" class="vtable" colspan="2"> + <? + echo_html_select("persist_sticky_type",$a_sticky_type,$pconfig['persist_sticky_type'],"","updatevisibility();"); + ?> + Sticktables that are kept in memory, and when matched make sure the same server will be used.<br/> + <textarea readonly="yes" cols="60" rows="2" id="sticky_type_description" name="sticky_type_description" style="padding:5px; border:1px dashed #990000; background-color: #ffffff; color: #000000; font-size: 8pt;"></textarea> + </td> + </tr> + <tr align="left" class="haproxy_stick_cookiename"> + <td width="22%" valign="top" class="vncellreq">Stick cookie name</td> + <td width="78%" class="vtable" colspan="2"> + <input name="persist_stick_cookiename" type="text" <?if(isset($pconfig['persist_stick_cookiename'])) echo "value=\"{$pconfig['persist_stick_cookiename']}\"";?> size="20" /> + Cookiename to use for sticktable<br/> + <span id="stick_cookiename_description"></span> + </td> + </tr> + <tr align="left" class="haproxy_stick_cookiename"> + <td width="22%" valign="top" class="vncellreq">Stick cookie length</td> + <td width="78%" class="vtable" colspan="2"> + <input name="persist_stick_length" type="text" <?if(isset($pconfig['persist_stick_length'])) echo "value=\"{$pconfig['persist_stick_length']}\"";?> size="20" /> + The maximum number of characters that will be stored in a "string" type stick-table<br/> + <span id="stick_cookiename_description"></span> + </td> + </tr> + <tr align="left" class="haproxy_stick_tableused"> + <td width="22%" valign="top" class="vncellreq">stick-table expire</td> + <td width="78%" class="vtable" colspan="2"> + <input name="persist_stick_expire" type="text" <?if(isset($pconfig['persist_stick_expire'])) echo "value=\"{$pconfig['persist_stick_expire']}\"";?> size="20" /> d=days h=hour m=minute s=seconds ms=miliseconds(default)<br/> + Defines the maximum duration of an entry in the stick-table since it was last created, refreshed or matched.<br/> + EXAMPLE: 30m + </td> + </tr> + <tr align="left" class="haproxy_stick_tableused"> + <td width="22%" valign="top" class="vncellreq">stick-table size</td> + <td width="78%" class="vtable" colspan="2"> + <input name="persist_stick_tablesize" type="text" <?if(isset($pconfig['persist_stick_tablesize'])) echo "value=\"{$pconfig['persist_stick_tablesize']}\"";?> size="20" /> maximum number of entries supports suffixes "k", "m", "g" for 2^10, 2^20 and 2^30 factors.<br/> + Is the maximum number of entries that can fit in the table. This value directly impacts memory usage. Count approximately + 50 bytes per entry, plus the size of a string if any.<br/> + EXAMPLE: 50k + </td> + </tr> + <tr><td> </td></tr> + <tr> + <td colspan="2" valign="top" class="listtopic">Statistics</td> + </tr> + <tr align="left"> + <td width="22%" valign="top" class="vncell">Stats Enabled</td> + <td width="78%" class="vtable" colspan="2"> + <input id="stats_enabled" name="stats_enabled" type="checkbox" value="yes" <?php if ($pconfig['stats_enabled']=='yes') echo "checked"; ?> onclick='updatevisibility();' /> + Enables the haproxy statistics page (only used on 'http' frontends) + </td> + </tr> + <tr class="haproxy_stats_visible" align="left" id='stats_uri_row'> + <td width="22%" valign="top" class="vncellreq">Stats Uri</td> + <td width="78%" class="vtable" colspan="2"> + <input id="stats_uri" name="stats_uri" type="text" <?if(isset($pconfig['stats_uri'])) echo "value=\"{$pconfig['stats_uri']}\"";?> size="64" /><br/> + This url can be used when this same backend is used for passing connections to backends<br/> + EXAMPLE: / or /haproxy?stats + </td> + </tr> + <tr class="haproxy_stats_visible" align="left" id='stats_scope_row'> + <td width="22%" valign="top" class="vncell">Stats Scope</td> + <td width="78%" class="vtable" colspan="2"> + <input id="stats_scope" name="stats_scope" type="text" <?if(isset($pconfig['stats_scope'])) echo "value=\"{$pconfig['stats_scope']}\"";?> size="64" /><br/> + Determines which frontends and backends are shown, leave empty to show all.<br/> + EXAMPLE: frontendA,backend1,backend2 + </td> + </tr> + <tr class="haproxy_stats_visible" align="left" id='stats_realm_row'> + <td width="22%" valign="top" class="vncell">Stats Realm</td> + <td width="78%" class="vtable" colspan="2"> + <input id="stats_realm" name="stats_realm" type="text" <?if(isset($pconfig['stats_realm'])) echo "value=\"{$pconfig['stats_realm']}\"";?> size="64" /><br/> + The realm is shown when authentication is requested by haproxy.<br/> + EXAMPLE: haproxystats + </td> + </tr> + <tr class="haproxy_stats_visible" align="left" id='stats_username_row'> + <td width="22%" valign="top" class="vncell">Stats Username</td> + <td width="78%" class="vtable" colspan="2"> + <input id="stats_username" name="stats_username" type="text" <?if(isset($pconfig['stats_username'])) echo "value=\"".$pconfig['stats_username']."\"";?> size="64" /> + EXAMPLE: admin + </td> + </tr> + <tr class="haproxy_stats_visible" align="left" id='stats_password_row'> + <td width="22%" valign="top" class="vncell">Stats Password</td> + <td width="78%" class="vtable" colspan="2"> + <input id="stats_password" name="stats_password" type="password" <? + if(isset($pconfig['stats_password'])) + echo "value=\"".$pconfig['stats_password']."\""; + ?> size="64" /> + EXAMPLE: 1Your2Secret3P@ssword + </td> + </tr> + <tr class="haproxy_stats_visible" align="left" id='stats_node_admin_row'> + <td width="22%" valign="top" class="vncell">Stats Admin</td> + <td width="78%" class="vtable" colspan="2"> + <input id="stats_admin" name="stats_admin" type="checkbox" value="yes" <?php if ($pconfig['stats_admin']=='yes') echo "checked"; ?> /> + Makes available the options disable/enable/softstop/softstart/killsessions from the stats page.<br/> + Note: This is not persisted when haproxy restarts. For publicly visible stats pages this should be disabled. + </td> + </tr> + <tr class="haproxy_stats_visible" align="left" id='stats_node_row'> + <td width="22%" valign="top" class="vncell">Stats Nodename</td> + <td width="78%" class="vtable" colspan="2"> + <input id="stats_node" name="stats_node" type="text" <?if(isset($pconfig['stats_node'])) echo "value=\"{$pconfig['stats_node']}\"";?> size="64" /><br/> + The short name is displayed in the stats and helps to differentiate which server in a cluster is actually serving clients. + </td> + </tr> + <tr class="haproxy_stats_visible" align="left" id='stats_desc_row'> + <td width="22%" valign="top" class="vncell">Stats Description</td> + <td width="78%" class="vtable" colspan="2"> + <input id="stats_desc" name="stats_desc" type="text" <?if(isset($pconfig['stats_desc'])) echo "value=\"{$pconfig['stats_desc']}\"";?> size="64" /><br/><br/> + The description is displayed behind the Nodename set above. + </td> + </tr> + <tr class="haproxy_stats_visible" align="left" id='stats_refresh_row'> + <td width="22%" valign="top" class="vncell">Stats Refresh</td> + <td width="78%" class="vtable" colspan="2"> + <input id="stats_refresh" name="stats_refresh" type="text" <?if(isset($pconfig['stats_refresh'])) echo "value=\"{$pconfig['stats_refresh']}\"";?> size="10" maxlength="30" /><br/> + Specify the refresh rate of the stats page in seconds, or specified time unit (us, ms, s, m, h, d). + </td> + </tr> + <tr><td> </td></tr> + <tr> + <td colspan="2" valign="top" class="listtopic">Error files</td> + </tr> + <tr class="" align="left" id='errorfiles'> + <td colspan="2" valign="top" class="vtable"> + Use these to replace the error pages that haproxy can generate by custom pages created on the files tab. + For example haproxy will generate a 503 error page when no backend is available, you can replace that page here. + <br/> + <br/> + <? + haproxy_htmllist("table_errorfile", $a_errorfiles, $fields_errorfile); + ?> + </td> + </tr> + <tr><td> </td></tr> + <tr> + <td colspan="2" valign="top" class="listtopic">Advanced</td> + </tr> + <tr class="" align="left" id='Strict-Transport-Security'> + <td width="22%" valign="top" class="vncell">Strict-Transport-Security</td> + <td width="78%" class="vtable" colspan="2"> + When configured enables "HTTP Strict Transport Security" leave empty to disable. (only used on 'http' frontends)<br/> + <b>WARNING! the domain will only work over https with a valid certificate!</b><br/> + <input id="strict_transport_security" name="strict_transport_security" type="text" <?if(isset($pconfig['strict_transport_security'])) echo "value=\"{$pconfig['strict_transport_security']}\"";?> size="20" /> Seconds<br/> + If configured clients that requested the page with this setting active will not be able to visit this domain over a unencrypted http connection. + So make sure you understand the consequence of this setting or start with a really low value.<br/> + EXAMPLE: 60 for testing if you are absolutely sure you want this 31536000 (12 months) would be good for production. + </td> + </tr> + <tr class="" align="left"> + <td width="22%" valign="top" class="vncell">Cookie protection.</td> + <td width="78%" class="vtable" colspan="2"> + <input id="cookie_attribute_secure" name="cookie_attribute_secure" type="checkbox" value="yes" <?php if ($pconfig['cookie_attribute_secure']=='yes') echo "checked"; ?> onclick='updatevisibility();' /> + Set 'secure' attribure on cookies (only used on 'http' frontends)<br/> + This configuration option sets up the Secure attribute on cookies if it has not been setup by the application server while the client was browsing the application over a ciphered connection. + </td> + </tr> + <tr><td> </td></tr> + <tr align="left"> + <td width="22%" valign="top"> </td> + <td width="78%"> + <input name="Submit" type="submit" class="formbtn" value="Save" /> + <input type="button" class="formbtn" value="Cancel" onclick="history.back()" /> + <?php if (isset($id) && $a_pools[$id]): ?> + <input name="id" type="hidden" value="<?=$id;?>" /> + <?php endif; ?> + </td> + </tr> + </table> + </div> + </td></tr></table> + </form> +<br/> +<script type="text/javascript"> +<? + phparray_to_javascriptarray($fields_servers,"fields_servers",Array('/*','/*/name','/*/type','/*/size','/*/items','/*/items/*','/*/items/*/*','/*/items/*/*/name')); + phparray_to_javascriptarray($fields_servers_details,"fields_details_servers",Array('/*','/*/name','/*/type')); + phparray_to_javascriptarray($fields_errorfile,"fields_errorfile",Array('/*','/*/name','/*/type','/*/size','/*/items','/*/items/*','/*/items/*/*','/*/items/*/*/name')); + phparray_to_javascriptarray($a_checktypes,"checktypes",Array('/*','/*/name','/*/descr')); + phparray_to_javascriptarray($a_cookiemode,"cookiemode",Array('/*','/*/name','/*/descr')); + phparray_to_javascriptarray($a_sticky_type,"sticky_type",Array('/*','/*/descr','/*/cookiedescr')); + phparray_to_javascriptarray($a_files,"a_files",Array('/*','/*/name','/*/descr')); +?> + browser_InnerText_support = (document.getElementsByTagName("body")[0].innerText != undefined) ? true : false; + + totalrows = <?php echo $counter; ?>; + updatevisibility(); +</script> +<?php +haproxy_htmllist_js(); +include("fend.inc"); ?> +</body> +</html> diff --git a/config/haproxy1_5/www/haproxy_pools.php b/config/haproxy1_5/www/haproxy_pools.php new file mode 100644 index 00000000..92235933 --- /dev/null +++ b/config/haproxy1_5/www/haproxy_pools.php @@ -0,0 +1,181 @@ +<?php +/* $Id: load_balancer_virtual_server.php,v 1.6.2.1 2006/01/02 23:46:24 sullrich Exp $ */ +/* + haproxy_pools.php + part of pfSense (https://www.pfsense.org/) + Copyright (C) 2013 PiBa-NL + Copyright (C) 2009 Scott Ullrich <sullrich@pfsense.com> + Copyright (C) 2008 Remco Hoef <remcoverhoef@pfsense.com> + 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. +*/ +$shortcut_section = "haproxy"; +require_once("guiconfig.inc"); +require_once("haproxy.inc"); +require_once("pkg_haproxy_tabs.inc"); + + +if (!is_array($config['installedpackages']['haproxy']['ha_pools']['item'])) { + $config['installedpackages']['haproxy']['ha_pools']['item'] = array(); +} +if (!is_array($config['installedpackages']['haproxy']['ha_backends']['item'])) { + $config['installedpackages']['haproxy']['ha_backends']['item'] = array(); +} + +$a_pools = &$config['installedpackages']['haproxy']['ha_pools']['item']; +$a_backends = &$config['installedpackages']['haproxy']['ha_backends']['item']; + +if ($_POST) { + $pconfig = $_POST; + + if ($_POST['apply']) { + $result = haproxy_check_and_run($savemsg, true); + if ($result) + unlink_if_exists($d_haproxyconfdirty_path); + } +} + +if ($_GET['act'] == "del") { + if (isset($a_pools[$_GET['id']])) { + unset($a_pools[$_GET['id']]); + write_config(); + touch($d_haproxyconfdirty_path); + } + header("Location: haproxy_pools.php"); + exit; +} + +$pf_version=substr(trim(file_get_contents("/etc/version")),0,3); +if ($pf_version < 2.0) + $one_two = true; + +$pgtitle = "Services: HAProxy: Backend server pools"; +include("head.inc"); + +?> +<body link="#0000CC" vlink="#0000CC" alink="#0000CC"> +<?php include("fbegin.inc"); ?> +<?php if($one_two): ?> +<p class="pgtitle"><?=$pgtitle?></p> +<?php endif; ?> +<form action="haproxy_pools.php" method="post"> +<?php if ($input_errors) print_input_errors($input_errors); ?> +<?php if ($savemsg) print_info_box($savemsg); ?> +<?php if (file_exists($d_haproxyconfdirty_path)): ?> +<?php print_info_box_np("The haproxy configuration has been changed.<br/>You must apply the changes in order for them to take effect.");?><br/> +<?php endif; ?> +<table width="100%" border="0" cellpadding="0" cellspacing="0"> + <tr><td class="tabnavtbl"> + <?php + haproxy_display_top_tabs_active($haproxy_tab_array['haproxy'], "backend"); + ?> + </td></tr> + <tr> + <td> + <div id="mainarea"> + <table class="tabcont sortable" width="100%" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td width="5%" class="listhdrr">Advanced</td> + <td width="25%" class="listhdrr">Name</td> + <td width="10%" class="listhdrr">Servers</td> + <td width="10%" class="listhdrr">Check</td> + <td width="30%" class="listhdrr">Frontend</td> + <td width="10%" class="list"></td> + </tr> +<?php + $img_adv = "/themes/{$g['theme']}/images/icons/icon_advanced.gif"; + $i = 0; + foreach ($a_pools as $pool){ + $fe_list = ""; + $sep = ""; + foreach ($a_backends as $backend) { + if($backend['backend_serverpool'] == $pool['name']) { + $fe_list .= $sep . $backend['name']; + $sep = ", "; + } + } + $textgray = $fe_list == "" ? " gray" : ""; + + if (is_array($pool['ha_servers'])) + $count = count($pool['ha_servers']['item']); + else + $count = 0; +?> + <tr class="<?=$textgray?>"> + <td class="listlr" ondblclick="document.location='haproxy_pool_edit.php?id=<?=$i;?>';"> + <? + if ($pool['stats_enabled']=='yes'){ + echo "<img src=\"./themes/{$g['theme']}/images/icons/icon_log_s.gif\"" . ' title="stats enabled" width="11" height="15" border="0" />'; + } + $isadvset = ""; + if ($pool['advanced']) $isadvset .= "Per server pass thru\r\n"; + if ($pool['advanced_backend']) $isadvset .= "Backend pass thru\r\n"; + if ($isadvset) + echo "<img src=\"$img_adv\" title=\"" . gettext("advanced settings set") . ": {$isadvset}\" border=\"0\" />"; + ?> + </td> + <td class="listlr" ondblclick="document.location='haproxy_pool_edit.php?id=<?=$i;?>';"> + <?=$pool['name'];?> + </td> + <td class="listlr" ondblclick="document.location='haproxy_pool_edit.php?id=<?=$i;?>';"> + <?=$count;?> + </td> + <td class="listlr" ondblclick="document.location='haproxy_pool_edit.php?id=<?=$i;?>';"> + <?=$a_checktypes[$pool['check_type']]['name'];?> + </td> + <td class="listlr" ondblclick="document.location='haproxy_pool_edit.php?id=<?=$i;?>';"> + <?=$fe_list;?> + </td> + <td class="list" nowrap> + <table border="0" cellspacing="0" cellpadding="1"> + <tr> + <td valign="middle"><a href="haproxy_pool_edit.php?id=<?=$i;?>"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" title="<?=gettext("edit backend");?>" width="17" height="17" border="0" /></a></td> + <td valign="middle"><a href="haproxy_pools.php?act=del&id=<?=$i;?>" onclick="return confirm('Do you really want to delete this entry?')"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" title="<?=gettext("delete backend");?>" width="17" height="17" border="0" /></a></td> + <td valign="middle"><a href="haproxy_pool_edit.php?dup=<?=$i;?>"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" title="<?=gettext("clone backend");?>" width="17" height="17" border="0" /></a></td> + </tr> + </table> + </td> + </tr> +<?php + $i++; + } +?> + <tfoot> + <tr> + <td class="list" colspan="5"></td> + <td class="list"> + <table border="0" cellspacing="0" cellpadding="1"> + <tr> + <td valign="middle"><a href="haproxy_pool_edit.php"><img src="/themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" title="<?=gettext("add new backend");?>" width="17" height="17" border="0" /></a></td> + </tr> + </table> + </td> + </tr> + </tfoot> + </table> + </div> + </table> + </form> +<?php include("fend.inc"); ?> +</body> +</html> diff --git a/config/haproxy1_5/www/haproxy_stats.php b/config/haproxy1_5/www/haproxy_stats.php new file mode 100644 index 00000000..302793b6 --- /dev/null +++ b/config/haproxy1_5/www/haproxy_stats.php @@ -0,0 +1,204 @@ +<?php +/* + haproxy_stats.php + part of pfSense (https://www.pfsense.org/) + Copyright (C) 2013 PiBa-NL + 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. +*/ +require_once("authgui.inc"); +require_once("config.inc"); +require_once("haproxy_socketinfo.inc"); + +$pconfig = $config['installedpackages']['haproxy']; +if (isset($_GET['haproxystats']) || isset($_GET['scope']) || (isset($_POST) && isset($_POST['action']))){ + if (!(isset($pconfig['enable']) && $pconfig['localstatsport'] && is_numeric($pconfig['localstatsport']))){ + print 'In the "Settings" configure a internal stats port and enable haproxy for this to be functional. Also make sure the service is running.'; + return; + } + $fail = false; + try{ + $request = ""; + if (is_array($_GET)){ + foreach($_GET as $key => $arg) + $request .= ";$key=$arg"; + } + $options = array( + 'http'=>array( + 'method'=>"POST", + 'header'=>"Accept-language: en\r\n". + "Content-type: application/x-www-form-urlencoded\r\n", + 'content'=>http_build_query($_POST) + )); + $context = stream_context_create($options); + $response = file_get_contents("http://127.0.0.1:{$pconfig['localstatsport']}/haproxy_stats.php?haproxystats=1".$request, false, $context); + if (is_array($http_response_header)){ + foreach($http_response_header as $header){ + if (strpos($header,"Refresh: ") == 0) + header($header); + } + } + $fail = $response === false; + } catch (Exception $e) { + $fail = true; + } + if ($fail) + $response = "<br/><br/>Make sure HAProxy settings are applied and HAProxy is enabled and running"; + echo $response; + exit(0); +} +require_once("guiconfig.inc"); +if (isset($_GET['showsticktablecontent'])){ + if (is_numeric($pconfig['localstats_sticktable_refreshtime'])) + header("Refresh: {$pconfig['localstats_sticktable_refreshtime']}"); +} +$shortcut_section = "haproxy"; +require_once("haproxy.inc"); +require_once("certs.inc"); +require_once("haproxy_utils.inc"); +require_once("pkg_haproxy_tabs.inc"); + +if (!is_array($config['installedpackages']['haproxy']['ha_backends']['item'])) { + $config['installedpackages']['haproxy']['ha_backends']['item'] = array(); +} +$a_frontend = &$config['installedpackages']['haproxy']['ha_backends']['item']; + +if ($_POST) { + if ($_POST['apply']) { + $result = haproxy_check_and_run($savemsg, true); + if ($result) + unlink_if_exists($d_haproxyconfdirty_path); + } +} + +$pf_version=substr(trim(file_get_contents("/etc/version")),0,3); +if ($pf_version < 2.0) + $one_two = true; + +$pgtitle = "Services: HAProxy: Stats"; +include("head.inc"); + +?> +<body link="#0000CC" vlink="#0000CC" alink="#0000CC"> +<?php include("fbegin.inc"); ?> +<form action="haproxy_stats.php" method="post"> +<?php if($one_two): ?> +<p class="pgtitle"><?=$pgtitle?></p> +<?php endif; ?> +<?php if ($input_errors) print_input_errors($input_errors); ?> +<?php if ($savemsg) print_info_box($savemsg); ?> +<?php if (file_exists($d_haproxyconfdirty_path)): ?> +<?php print_info_box_np("The haproxy configuration has been changed.<br/>You must apply the changes in order for them to take effect.");?><br/> +<?php endif; ?> +</form> +<table width="100%" border="0" cellpadding="0" cellspacing="0"> + <tr><td class="tabnavtbl"> + <?php + haproxy_display_top_tabs_active($haproxy_tab_array['haproxy'], "stats"); + ?> + </td></tr> + <tr> + <td> + <div id="mainarea"> + <table class="tabcont" width="100%" height="100%" cellspacing="0"> + <tr> + <? +if (isset($_GET['showsticktablecontent'])){ + $sticktablename = $_GET['showsticktablecontent']; +echo "<td colspan='2'>"; + echo "Contents of the sticktable: $sticktablename<br/>"; + $res = haproxy_socket_command("show table $sticktablename"); + foreach($res as $line){ + echo "<br/>".print_r($line,true); + } +echo "</td>"; +} else { +?> + <td colspan="2"> + This page contains a 'stats' page available from haproxy accessible through the pfSense gui.<br/> + <br/> + As the page is forwarded through the pfSense gui, this might cause some functionality to not work.<br/> + Though the normal haproxy stats page can be tweaked more, and doesn't use a user/pass from pfSense itself.<br/> + Some examples are configurable automatic page refresh, only showing certain servers, not providing admin options,<br/> + and can be accessed from wherever the associated frontend is accessible.(as long as rules permit access)<br/> + To use this or for simply an example how to use SSL-offloading configure stats on either a real backend while utilizing the 'stats uri'.<br/> + Or create a backend specifically for serving stats, for that you can start with the 'stats example' from the template tab.<br/> + </td> + </tr> + <tr> + <td> </td> + </tr> + <tr> + <td colspan="2" valign="top" class="listtopic">HAProxy stick-tables</td> + </tr> + <tr> + <td colspan="2" valign="top" class="vncell"> + These tables are used to store information for session persistence and can be used with ssl-session-id information, application-cookies, or other information that is used to persist a user to a server. + <table class="tabcont sortable" id="sortabletable" width="100%" cellspacing="0" cellpadding="6" border="0"> + <head> + <td class="listhdrr">Stick-table</td> + <td class="listhdrr">Type</td> + <td class="listhdrr">Size</td> + <td class="listhdrr">Used</td> + </head> + <? $tables = haproxy_get_tables(); + foreach($tables as $key => $table) { ?> + <tr> + <td class="listlr"><a href="/haproxy_stats.php?showsticktablecontent=<?=$key;?>"><?=$key;?></td> + <td class="listr"><?=$table['type'];?></td> + <td class="listr"><?=$table['size'];?></td> + <td class="listr"><?=$table['used'];?></td> + </tr> + <? } ?> + </table> + </td> + </tr> + <tr> + <td> </td> + </tr> + <tr> + <td colspan="2" valign="top" class="listtopic">HAProxy stats</td> + </tr> + <tr> + <td colspan="2" valign="top" class="vncell"><a href="/haproxy_stats.php?haproxystats=1" target="_blank">Fullscreen stats page</a></td> + </tr> + <tr> + <td colspan="2" class="listlr"> + <? if (isset($pconfig['enable']) && $pconfig['localstatsport'] && is_numeric($pconfig['localstatsport'])){?> + <iframe id="frame_haproxy_stats" width="1000px" height="1500px" seamless=1 src="/haproxy_stats.php?haproxystats=1<?=$request;?>"></iframe> + <? } else { ?> + <br/> + In the "Settings" configure a internal stats port and enable haproxy for this to be functional. Also make sure the service is running.<br/> + <br/> + <? } ?> +<?}?> + </td> + </tr> + </table> + </div> + </td> + </tr> +</table> +<?php include("fend.inc"); ?> +</body> +</html> diff --git a/config/haproxy1_5/www/haproxy_templates.php b/config/haproxy1_5/www/haproxy_templates.php new file mode 100644 index 00000000..478c83a3 --- /dev/null +++ b/config/haproxy1_5/www/haproxy_templates.php @@ -0,0 +1,220 @@ +<?php +/* + haproxy_templates.php + part of pfSense (https://www.pfsense.org/) + Copyright (C) 2014 PiBa-NL + 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. +*/ +require_once("authgui.inc"); +require_once("config.inc"); + +$pconfig = $config['installedpackages']['haproxy']; +require_once("guiconfig.inc"); +$shortcut_section = "haproxy"; +require_once("haproxy.inc"); +require_once("certs.inc"); +require_once("haproxy_utils.inc"); +require_once("pkg_haproxy_tabs.inc"); + +if (!is_array($config['installedpackages']['haproxy']['ha_backends']['item'])) { + $config['installedpackages']['haproxy']['ha_backends']['item'] = array(); +} +$a_frontend = &$config['installedpackages']['haproxy']['ha_backends']['item']; + +function haproxy_add_stats_example() { + global $config, $d_haproxyconfdirty_path; + $a_backends = &$config['installedpackages']['haproxy']['ha_pools']['item']; + $a_frontends = &$config['installedpackages']['haproxy']['ha_backends']['item']; + $webcert = haproxy_find_create_certificate("HAProxy stats default"); + + $backend = array(); + $backend["name"] = "HAProxy_stats_ssl_backend"; + $backend["stats_enabled"] = "yes"; + $backend["stats_uri"] = "/"; + $backend["stats_refresh"] = "10"; + $a_backends[] = $backend; + $changecount++; + + $frontend = array(); + $frontend["name"] = "HAProxy_stats_ssl_frontend"; + $frontend["status"] = "active"; + $frontend["type"] = "http"; + $frontend["a_extaddr"]["item"]["stats_name"]["extaddr"] = "lan_ipv4"; + $frontend["a_extaddr"]["item"]["stats_name"]["extaddr_port"] = "444"; + $frontend["a_extaddr"]["item"]["stats_name"]["extaddr_ssl"] = "yes"; + $frontend["ssloffloadcert"] = $webcert['refid']; + $frontend["backend_serverpool"] = $backend["name"]; + $a_frontends[] = $frontend; + $changecount++; + $changedesc = "add new HAProxy stats example"; + + if ($changecount > 0) { + header("Location: haproxy_listeners.php"); + echo "touching: $d_haproxyconfdirty_path"; + touch($d_haproxyconfdirty_path); + write_config($changedesc); + exit; + } +} + +function template_errorfile() { + global $config, $d_haproxyconfdirty_path, $savemsg; + + $a_files = &$config['installedpackages']['haproxy']['files']['item']; + if (!is_array($a_files)) $a_files = array(); + + $a_files_cache = haproxy_get_fileslist(); + if (!isset($a_files_cache["ExampleErrorfile"])) { + $errorfile = <<<EOD +HTTP/1.0 503 Service Unavailable +Cache-Control: no-cache +Connection: close +Content-Type: text/html + +<html> + <head> + <title>Sorry the webserver you are trying to contact is currently not available.</title> + </head> + <body style="font-family:Arial,Helvetica,sans-serif;"> + <div style="margin: 0 auto; width: 960px;"> + <h2>Sorry the webserver you are trying to contact is currently not available.</h2> + </div> +The error returned is [<i>{errorcode} {errormsg}</i>] please try again later. + </body> +</html> +EOD; + $newfile = array(); + $newfile['name'] = "ExampleErrorfile"; + $newfile['content'] = base64_encode($errorfile); + $a_files[] = $newfile; + $changecount++; + $changedesc = "Errorfile added from template"; + } else { + $savemsg = "File 'ExampleErrorfile' is already configured on the Files tab."; + } + + if ($changecount > 0) { + header("Location: haproxy_files.php"); + echo "touching: $d_haproxyconfdirty_path"; + touch($d_haproxyconfdirty_path); + write_config($changedesc); + exit; + } +} + +if (isset($_GET['add_stats_example'])) { + $templateid = $_GET['add_stats_example']; + switch ($templateid) { + case "1": + haproxy_add_stats_example(); + break; + case "2": + template_errorfile(); + break; + } +} + +if ($_POST) { + if ($_POST['apply']) { + $result = haproxy_check_and_run($savemsg, true); + if ($result) + unlink_if_exists($d_haproxyconfdirty_path); + } +} + +$pgtitle = "Services: HAProxy: Templates"; +include("head.inc"); + +?> +<body link="#0000CC" vlink="#0000CC" alink="#0000CC"> +<?php include("fbegin.inc"); ?> +<form action="haproxy_templates.php" method="post"> +<?php if($one_two): ?> +<p class="pgtitle"><?=$pgtitle?></p> +<?php endif; ?> +<?php if ($input_errors) print_input_errors($input_errors); ?> +<?php if ($savemsg) print_info_box($savemsg); ?> +<?php if (file_exists($d_haproxyconfdirty_path)): ?> +<?php print_info_box_np("The haproxy configuration has been changed.<br/>You must apply the changes in order for them to take effect.");?><br/> +<?php endif; ?> +</form> +<table width="100%" border="0" cellpadding="0" cellspacing="0"> + <tr><td class="tabnavtbl"> + <?php + haproxy_display_top_tabs_active($haproxy_tab_array['haproxy'], "templates"); + ?> + </td></tr> + <tr> + <td> + <div id="mainarea"> + <table class="tabcont" width="100%" height="100%" cellspacing="0"> + <tr> + <td colspan="2" valign="top" class="listtopic">Templates</td> + </tr> + <tr> + <td colspan="2">This page contains some templates that can be added into the haproxy configuration to possible ways to configure haproxy using this the webgui from this package.</td> + </tr> + <tr> + <td> </td> + </tr> + <tr> + <td colspan="2" valign="top" class="listtopic">Stats SSL frontent+backend</td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell"> + <a href="haproxy_templates.php?add_stats_example=1">Create configuration</a> + </td> + <td class="vtable"> + As an basic example you can use the link below to create a 'stats' frontend/backend page which offers with more options like setting user/password and 'admin mode' when you go to the backend settings.<br/> + TEMPLATE: Create stats example configuration using a frontend/backend combination with ssl<br/> + <br/> + After applying the changes made by the template use this link to visit the stats page: <a target="_blank" href="https://<?=get_interface_ip("lan");?>:444">https://pfSense-LAN-ip:444/</a> + </td> + </tr> + <tr> + <td> </td> + </tr> + <tr> + <td colspan="2" valign="top" class="listtopic">Errorfile</td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell"> + <a href="haproxy_templates.php?add_stats_example=2">Create configuration</a> + </td> + <td class="vtable"> + As an basic example of an errorfile with name 'ExampleErrorfile' will be added if it does not exist. + This file can then be used in the 'Error files' in the backend settings. + </td> + </tr> + <tr> + <td> </td> + </tr> + </table> + </div> + </td> + </tr> +</table> +<?php include("fend.inc"); ?> +</body> +</html> diff --git a/config/haproxy1_5/www/javascript/haproxy_geturl.js b/config/haproxy1_5/www/javascript/haproxy_geturl.js new file mode 100644 index 00000000..5df80646 --- /dev/null +++ b/config/haproxy1_5/www/javascript/haproxy_geturl.js @@ -0,0 +1,43 @@ +/** + * getURL is a proprietary Adobe function, but it's simplicity has made it very + * popular. If getURL is undefined we spin our own by wrapping XMLHttpRequest. + */ +if (typeof getURL == 'undefined') { + getURL = function(url, callback) { + if (!url) + throw 'No URL for getURL'; + + try { + if (typeof callback.operationComplete == 'function') + callback = callback.operationComplete; + } catch (e) {} + if (typeof callback != 'function') + throw 'No callback function for getURL "' + url + '"'; + + var http_request = null; + if (typeof XMLHttpRequest != 'undefined') { + http_request = new XMLHttpRequest(); + } + else if (typeof ActiveXObject != 'undefined') { + try { + http_request = new ActiveXObject('Msxml2.XMLHTTP'); + } catch (e) { + try { + http_request = new ActiveXObject('Microsoft.XMLHTTP'); + } catch (e) {} + } + } + if (!http_request) + throw '<?=gettext("Both getURL and XMLHttpRequest are undefined"); ?>'; + + http_request.onreadystatechange = function() { + if (http_request.readyState == 4) { + callback( { success : true, + content : http_request.responseText, + contentType : http_request.getResponseHeader("Content-Type") } ); + } + } + http_request.open('GET', url, true); + http_request.send(null); + } +} diff --git a/config/haproxy1_5/www/shortcuts/pkg_haproxy.inc b/config/haproxy1_5/www/shortcuts/pkg_haproxy.inc new file mode 100644 index 00000000..1e5c75c2 --- /dev/null +++ b/config/haproxy1_5/www/shortcuts/pkg_haproxy.inc @@ -0,0 +1,11 @@ +<?php + +global $shortcuts; + +$shortcuts['haproxy'] = array(); +$shortcuts['haproxy']['main'] = "haproxy_global.php"; +$shortcuts['haproxy']['log'] = "diag_logs.php"; +$shortcuts['haproxy']['status'] = "status_services.php"; +$shortcuts['haproxy']['service'] = "HAProxy"; + +?> diff --git a/config/haproxy1_5/www/widgets/widgets/haproxy.widget.php b/config/haproxy1_5/www/widgets/widgets/haproxy.widget.php new file mode 100644 index 00000000..5d664e81 --- /dev/null +++ b/config/haproxy1_5/www/widgets/widgets/haproxy.widget.php @@ -0,0 +1,282 @@ +<?php +/* + Copyright (C) 2013 PiBa-NL + Copyright 2011 Thomas Schaefer - Tomschaefer.org + Copyright 2011 Marcello Coutinho + Part of pfSense widgets (www.pfsense.org) + + 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. +*/ +/* + Some mods made from pfBlocker widget to make this for HAProxy on Pfsense + Copyleft 2012 by jvorhees +*/ +require_once("guiconfig.inc"); +require_once("pfsense-utils.inc"); +require_once("functions.inc"); +require_once("haproxy_socketinfo.inc"); +$first_time = false; +if (!is_array($config["widgets"]["haproxy"])) { + $first_time = true; + $config["widgets"]["haproxy"] = array(); +} +$a_config = &$config["widgets"]["haproxy"]; + +$getupdatestatus=false; +if(!empty($_GET['getupdatestatus'])) { + $getupdatestatus=true; +} + +#Backends/Servers Actions if asked +if(!empty($_GET['act']) and !empty($_GET['be']) and !empty($_GET['srv'])) { + $backend = $_GET['be']; + $server = $_GET['srv']; + $enable = $_GET['act'] == 'start' ? true : false; + haproxy_set_server_enabled($backend, $server, $enable); +} + +$simplefields = array("haproxy_widget_timer","haproxy_widget_showfrontends","haproxy_widget_showclients","haproxy_widget_showclienttraffic"); +if ($_POST) { + foreach($simplefields as $fieldname) + $a_config[$fieldname] = $_POST[$fieldname]; + + write_config("Updated traffic graph settings via dashboard."); + header("Location: /"); + exit(0); +} + +// Set default values +if (!$a_config['haproxy_widget_timer']) { + $a_config['haproxy_widget_timer'] = 5000; + $a_config['haproxy_widget_showfrontends'] = 'no'; + $a_config['haproxy_widget_showclients'] = 'yes'; + $a_config['haproxy_widget_showclienttraffic'] = 'no'; +} + +$refresh_rate = $a_config['haproxy_widget_timer']; +$show_frontends = $a_config['haproxy_widget_showfrontends']=='yes'; +$show_clients = $a_config['haproxy_widget_showclients']=='yes'; +$show_clients_traffic = $a_config['haproxy_widget_showclienttraffic']=='yes'; + +$out="<img src ='/themes/{$g['theme']}/images/icons/icon_interface_down.gif'>"; +$in="<img src ='/themes/{$g['theme']}/images/icons/icon_interface_up.gif'>"; +$running="<img src ='/themes/{$g['theme']}/images/icons/icon_pass.gif'>"; +$stopped="<img src ='/themes/{$g['theme']}/images/icons/icon_block.gif'>"; +$log="<img src ='/themes/{$g['theme']}/images/icons/icon_log.gif'>"; +$start="<img src ='/themes/{$g['theme']}/images/icons/icon_service_start.gif' title='Enable this backend/server'>"; +$stop="<img src ='/themes/{$g['theme']}/images/icons/icon_service_stop.gif' title='Disable this backend/server'>"; + +$clients=array(); +$clientstraffic=array(); + +$statistics = haproxy_get_statistics(); +$frontends = $statistics['frontends']; +$backends = $statistics['backends']; +$servers = $statistics['servers']; + +if ($show_clients == "YES") { + $clients = haproxy_get_clients($show_clients_traffic == "YES"); +} +if (!$getupdatestatus) { +?> +<div id="haproxy-settings" name="haproxy-settings" class="widgetconfigdiv" style="display:none;"> +<form action="/widgets/widgets/haproxy.widget.php" method="post" name="iform" id="iform"> + <table> + <tr><td> + Refresh Interval:</td><td> + <input id="haproxy_widget_timer" name="haproxy_widget_timer" type="text" value="<?=$a_config['haproxy_widget_timer']?>"/></td> + </tr><tr> + <td>Show frontends:</td><td> + <input id="haproxy_widget_showfrontends" name="haproxy_widget_showfrontends" type="checkbox" value="yes" <?php if ($a_config['haproxy_widget_showfrontends']=='yes') echo "checked"; ?>/></td> + </tr><tr> + <td>Show clients:</td> + <td><input id="haproxy_widget_showclients" name="haproxy_widget_showclients" type="checkbox" value="yes" <?php if ($a_config['haproxy_widget_showclients']=='yes') echo "checked"; ?>/> + Note: showing clients increases CPU/memory usage. + </td> + </tr><tr> + <td>Show client traffic:</td> + <td><input id="haproxy_widget_showclienttraffic" name="haproxy_widget_showclienttraffic" type="checkbox" value="yes" <?php if ($a_config['haproxy_widget_showclienttraffic']=='yes') echo "checked"; ?>/> + Note: showing client traffic considerably increases CPU/memory usage. + </td> + </tr></table> + <br> + <input id="submit" name="submit" type="submit" onclick="return updatePref();" class="formbtn" value="Save Settings" /> +</form> +</div> +<div name="haproxy_content" id="haproxy_content"> +<? +} + +echo "<table style=\"padding-top:0px; padding-bottom:0px; padding-left:0px; padding-right:0px\" width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\""; +#Frontends +if ($show_frontends == "YES") { + print "<tr><td class=\"widgetsubheader\" colspan=\"4\"><strong>FrontEnd(s)</strong></td></tr>"; + print "<tr><td class=\"listlr\"><strong>Name</strong></td>"; + print "<td class=\"listlr\"><strong>Sessions</strong><br>(cur/max)</td>"; + print "<td class=\"listlr\" colspan=\"2\"><strong><center>Status</center></strong></td></tr>"; + + foreach ($frontends as $fe => $fedata){ + print "<tr><td class=\"listlr\">".$fedata['pxname']."</td>"; + print "<td class=\"listlr\">".$fedata['scur']." / ".$fedata['slim']."</td>"; + if ($fedata['status'] == "OPEN") { + $fedata['status'] = $running." ".$fedata['status']; + } else { + $fedata['status'] = $stopped." ".$fedata['status']; + } + print "<td class=\"listlr\" colspan=\"2\"><center>".$fedata['status']."</center></td></tr>"; + } + + print "<tr height=\"6\"><td colspan=\"4\"></td></tr>"; +} + +#Backends/Servers w/o clients +print "<tr><td class=\"widgetsubheader\" colspan=\"4\"><strong>Backend(s)/Server(s)</strong></td></tr>"; +print "<tr><td class=\"listlr\"><strong>Backend(s)</strong><br> Server(s)"; +if ($show_clients == "YES") { + print "<br> <font color=\"blue\"><i>Client(s) addr:port</i></font>"; +} +print "</td>"; +print "<td class=\"listlr\"><strong>Sessions</strong><br>(cur/max)<br>"; +if ($show_clients == "YES" and $show_clients_traffic != "YES") { + print "<font color=\"blue\">age/id</font>"; +} elseif ($show_clients == "YES" and $show_clients_traffic == "YES") { + print "<font color=\"blue\">age/traffic i/o</font>"; +} +print "</td>"; +print "<td class=\"listlr\" colspan=\"2\"><strong><center>Status<br>/<br>Actions</center></strong></td>"; + +foreach ($backends as $be => $bedata) { + if ($bedata['status'] == "UP") { + $statusicon = $in; + $besess = $bedata['scur']." / ".$bedata['slim']; + $bename = $bedata['pxname']; + } else { + $statusicon = $out; + $besess = "<strong><font color=\"red\">".$bedata['status']."</font></strong>"; + $bename = "<font color=\"red\">".$bedata['pxname']."</font>"; + } + $icondetails = " onmouseover=\"this.title='".$bedata['status']."'\""; + print "<tr height=\"4\"><td bgcolor=\"#B1B1B1\" colspan=\"4\"></td></tr>"; + print "<tr><td class=\"listlr\"><strong>".$bename."</strong></td>"; + print "<td class=\"listlr\">".$besess."</td>"; + print "<td class=\"listlr\"$icondetails><center>".$statusicon."</center></td>"; + print "<td class=\"listlr\"> </td></tr>"; + + foreach ($servers as $srv => $srvdata) { + if ($srvdata['pxname'] == $bedata['pxname']) { + if ($srvdata['status'] == "UP") { + $nextaction = "stop"; + $statusicon = $in; + $acticon = $stop; + $srvname = $srvdata['svname']; + } elseif ($srvdata['status'] == "no check") { + $nextaction = "stop"; + $statusicon = $in; + $acticon = $stop; + $srvname = $srvdata['svname']; + $srvdata['scur'] = "<font color=\"blue\">no check</font>"; + } elseif ($srvdata['status'] == "MAINT") { + $nextaction = "start"; + $statusicon = $out; + $acticon = $start; + $srvname = "<font color=\"blue\">".$srvdata['svname']."</font>"; + $srvdata['scur'] = "<font color=\"blue\">".$srvdata['status']."</font>"; + } else { + $nextaction = "stop"; + $statusicon = $out; + $acticon = $stop; + $srvname = "<font color=\"red\">".$srvdata['svname']."</font>"; + $srvdata['scur'] = "<font color=\"red\">".$srvdata['status']."</font>"; + } + $icondetails = " onmouseover=\"this.title='".$srvdata['status']."'\""; + print "<tr><td class=\"listlr\"> ".$srvname."</td>"; + print "<td class=\"listlr\">".$srvdata['scur']."</td>"; + print "<td class=\"listlr\"$icondetails><center>".$statusicon."</center></td>"; + print "<td class=\"listlr\"><center><a onclick=\"control_haproxy('".$nextaction."','".$bedata['pxname']."','".$srvdata['svname']."');\">".$acticon."</a></center></td></tr>"; + + if ($show_clients == "YES") { + foreach ($clients as $cli => $clidata) { + if ($clidata['be'] == $bedata['pxname'] && $clidata['srv'] == $srvdata['svname']) { + print "<tr><td class=\"listlr\"> <font color=\"blue\"><i>".$clidata['src']."</i></font> <a href=\"diag_dns.php?host=".$clidata['srcip']."\" title=\"Reverse Resolve with DNS\">".$log."</a></td>"; + if ($show_clients_traffic == "YES") { + $clientstraffic[0] = format_bytes($clidata['session_datareq']); + $clientstraffic[1] = format_bytes($clidata['session_datares']); + print "<td class=\"listlr\" colspan=\"3\"><font color=\"blue\">".$clidata['age']." / ".$clientstraffic[0]." / ".$clientstraffic[1]."</font></td></tr>"; + } else { + print "<td class=\"listlr\" colspan=\"3\"><font color=\"blue\">".$clidata['age']." / ".$clidata['sessid']."</font></td></tr>"; + } + } + } + } + } + } +} + +echo "</table>"; +if (!$getupdatestatus) +{ + echo "</div>"; +?> +<script language="javascript" type="text/javascript"> + d = document; + selectIntLink = "haproxy-configure"; + textlink = d.getElementById(selectIntLink); + textlink.style.display = "inline"; +</script> +<script type="text/javascript"> + function getstatusgetupdate() { + var url = "/widgets/widgets/haproxy.widget.php"; + var pars = 'getupdatestatus=yes'; + var myAjax = new Ajax.Request( + url, + { + method: 'get', + parameters: pars, + onComplete: activitycallback_haproxy + }); + } + function getstatus_haproxy() { + getstatusgetupdate(); + setTimeout('getstatus_haproxy()', <?= $refresh_rate ?>); + } + function activitycallback_haproxy(transport) { + $('haproxy_content').innerHTML = transport.responseText; + } + setTimeout('getstatus_haproxy()', <?= $refresh_rate ?>); +</script> +<script type="text/javascript"> + function control_haproxy(act,be,srv) { + var url = "/widgets/widgets/haproxy.widget.php"; + var pars = 'act='+act+'&be='+be+'&srv='+srv; + var myAjax = new Ajax.Request( + url, + { + method: 'get', + parameters: pars, + //onComplete: activitycallback_haproxy + onComplete: getstatusgetupdate + }); + } +</script> +<? +} +?>
\ No newline at end of file diff --git a/config/lightsquid/sqstat.class.php b/config/lightsquid/sqstat.class.php index 5707e051..88a5cfce 100644 --- a/config/lightsquid/sqstat.class.php +++ b/config/lightsquid/sqstat.class.php @@ -202,8 +202,12 @@ class squidstat{ } if ($connection) { # username field is avaible in Squid 2.6 stable + # peer changed to remote in Squid 3.2 or later + # me changed to local in Squid 3.2 or later if(substr($v,0,9) == "username ") $parsed["con"][$connection]["username"] = substr($v, 9); + if(substr($v,0,7) == "remote:") $parsed["con"][$connection]["peer"] = substr($v, 8); if(substr($v,0,5) == "peer:") $parsed["con"][$connection]["peer"] = substr($v, 6); + if(substr($v,0,6) == "local:") $parsed["con"][$connection]["me"] = substr($v, 7); if(substr($v,0,3) == "me:") $parsed["con"][$connection]["me"] = substr($v, 4); if(substr($v,0,4) == "uri ") $parsed["con"][$connection]["uri"] = substr($v, 4); if(substr($v,0,10) == "delay_pool") $parsed["con"][$connection]["delay_pool"] = substr($v, 11); diff --git a/config/ntopng/ntopng.xml b/config/ntopng/ntopng.xml index b656e483..9382912a 100644 --- a/config/ntopng/ntopng.xml +++ b/config/ntopng/ntopng.xml @@ -39,7 +39,7 @@ ]]> </copyright> <name>ntopng</name> - <version>1.1 v0.1</version> + <version>1.2 v0.5</version> <title>Diagnostics: ntopng Settings</title> <savetext>Change</savetext> <aftersaveredirect>pkg_edit.php?xml=ntopng.xml</aftersaveredirect> @@ -96,7 +96,12 @@ <field> <fielddescr>DNS Mode</fielddescr> <fieldname>dns_mode</fieldname> - <description>Configures how name resolution is handled</description> + <description> + Configures how name resolution is handled<br/><br/> + Additionally, GeoIP Data can provide location information about IP addresses.<br/> + This product includes GeoLite data created by MaxMind, available from <a href="http://www.maxmind.com">http://www.maxmind.com</a>.<br/> + <input type="submit" name="Submit" value="Update GeoIP Data"> + </description> <type>select</type> <default_value>0</default_value> <options> @@ -121,13 +126,22 @@ <field> <fielddescr>Historical Data Storage</fielddescr> <fieldname>dump_flows</fieldname> - <description>Turn historical data storages on</description> + <description>Enable historical data storage</description> + <type>checkbox</type> + </field> + <field> + <fielddescr>Disable Alerts</fielddescr> + <fieldname>disable_alerts</fieldname> + <description>Disables all alerts generated by ntopng, such as flooding notifications</description> <type>checkbox</type> </field> </fields> <custom_php_global_functions> <![CDATA[ function sync_package_ntopng() { + if ($_POST['Submit'] == "Update GeoIP Data") { + return; + } conf_mount_rw(); config_lock(); global $config; @@ -185,7 +199,12 @@ if ($ntopng_config['dump_flows'] >= on) { $dump_flows = "-F"; } - + + // Disable alerts + if ($ntopng_config['disable_alerts'] >= on) { + $disable_alerts = "-H"; + } + $pf_version=substr(trim(file_get_contents("/etc/version")),0,3); if ($pf_version >= 2.2) { $redis_path = "/usr/pbi/ntopng-" . php_uname("m") . "/local/bin"; @@ -199,7 +218,7 @@ // Add support for --data-dir /somewhere, --httpdocs-dir /somewhereelse, // --dump-timeline (on/off) --http-port, --https-port - $start .= "\t/usr/local/bin/ntopng -d /var/db/ntopng -G /var/run/ntopng.pid -s -e {$dump_flows} {$ifaces} {$dns_mode} {$aggregations} {$local_networks} &"; + $start .= "\t/usr/local/bin/ntopng -d /var/db/ntopng -G /var/run/ntopng.pid -s -e {$disable_alerts} {$dump_flows} {$ifaces} {$dns_mode} {$aggregations} {$local_networks} &"; write_rcfile(array( "file" => "ntopng.sh", "start" => $start, @@ -211,6 +230,7 @@ // Wait for ntopng to shut down cleanly. sleep(20); } + ntopng_fixup_geoip(); start_service("ntopng"); sleep(2); @@ -222,6 +242,30 @@ conf_mount_ro(); config_unlock(); } + function ntopng_update_geoip() { + mwexec("/usr/pbi/ntopng-" . php_uname("m") . "/bin/ntopng-geoipupdate.sh"); + ntopng_fixup_geoip(); + restart_service("ntopng"); + } + function ntopng_fixup_geoip() { + $target_dir = "/usr/pbi/ntopng-" . php_uname("m") . "/local/share/ntopng/httpdocs/geoip"; + $source_dir = "/usr/pbi/ntopng-" . php_uname("m") . "/share/ntopng"; + + foreach(glob("{$source_dir}/Geo*.dat*") as $geofile) { + /* Decompress if needed. */ + if (substr($geofile, -3, 3) == ".gz") { + mwexec("/usr/bin/gzip -d " . escapeshellarg($geofile)); + } + } + + /* Use a separate glob since the filenames could have changed since the last run */ + foreach(glob("{$source_dir}/Geo*.dat*") as $geofile) { + $target_file = $target_dir . '/' . basename($geofile); + if (!file_exists($target_file)) { + symlink($geofile, $target_file); + } + } + } ]]> </custom_php_global_functions> <custom_add_php_command> @@ -232,7 +276,7 @@ </custom_php_resync_config_command> <custom_php_install_command> <![CDATA[ - mwexec_bg("/usr/pbi/ntopng-" . php_uname("m") . "/bin/geoipupdate.sh"); + ntopng_update_geoip(); sync_package_ntopng(); ]]> </custom_php_install_command> @@ -246,6 +290,9 @@ $input_errors[] = "You must provide (and confirm) ntopng's password."; if ($_POST['password'] != $_POST['passwordagain']) $input_errors[] = "The provided passwords did not match."; + if ($_POST['Submit'] == "Update GeoIP Data") { + ntopng_update_geoip(); + } } ]]> </custom_php_validation_command> diff --git a/config/openvpn-client-export/openvpn-client-export.inc b/config/openvpn-client-export/openvpn-client-export.inc index f635bbd0..16ccb6a4 100755 --- a/config/openvpn-client-export/openvpn-client-export.inc +++ b/config/openvpn-client-export/openvpn-client-export.inc @@ -40,7 +40,7 @@ require_once("pfsense-utils.inc"); global $current_openvpn_version, $current_openvpn_version_rev; $current_openvpn_version = "2.3.6"; -$current_openvpn_version_rev = "01"; +$current_openvpn_version_rev = "03"; function openvpn_client_export_install() { global $current_openvpn_version; diff --git a/config/openvpn-client-export/openvpn-client-export.xml b/config/openvpn-client-export/openvpn-client-export.xml index 15986428..42a3c327 100755 --- a/config/openvpn-client-export/openvpn-client-export.xml +++ b/config/openvpn-client-export/openvpn-client-export.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" ?> <packagegui> <name>OpenVPN Client Export</name> - <version>1.2.15</version> + <version>1.2.16</version> <title>OpenVPN Client Export</title> <include_file>/usr/local/pkg/openvpn-client-export.inc</include_file> <backup_file></backup_file> diff --git a/config/pfblockerng/geoipupdate.sh b/config/pfblockerng/geoipupdate.sh index 302f81f5..dc6f2af6 100644 --- a/config/pfblockerng/geoipupdate.sh +++ b/config/pfblockerng/geoipupdate.sh @@ -1,7 +1,7 @@ #!/bin/sh # # pfBlockerNG MaxMind GeoLite GeoIP Updater Script - By BBcan177@gmail.com -# Copyright (C) 2014 BBcan177@gmail.com +# Copyright (C) 2015 BBcan177@gmail.com # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License Version 2 as diff --git a/config/pfblockerng/pfblockerng.inc b/config/pfblockerng/pfblockerng.inc index 6ee9592a..1a1c87a2 100644 --- a/config/pfblockerng/pfblockerng.inc +++ b/config/pfblockerng/pfblockerng.inc @@ -3,7 +3,7 @@ pfBlockerNG.inc pfBlockerNG - Copyright (C) 2014 BBcan177@gmail.com + Copyright (C) 2015 BBcan177@gmail.com All rights reserved. part of the Postfix package for pfSense @@ -226,8 +226,11 @@ function pfb_create_suppression_file() { if ($pfb['found']) { $pfb_suppress = str_replace(" ", "\n", $config['aliases']['alias'][$pfb_id]['address']); - if (!empty($pfb_suppress)) + if (!empty($pfb_suppress)) { @file_put_contents("{$pfb['supptxt']}",$pfb_suppress, LOCK_EX); + } else { + unlink_if_exists("{$pfb['supptxt']}"); + } } else { # Delete Suppression File if Alias is Empty. unlink_if_exists("{$pfb['supptxt']}"); diff --git a/config/pfblockerng/pfblockerng.js b/config/pfblockerng/pfblockerng.js index cef0ce3b..e1c1ca20 100644 --- a/config/pfblockerng/pfblockerng.js +++ b/config/pfblockerng/pfblockerng.js @@ -1,6 +1,6 @@ /* pfBlockerNG update engine */ -// Part of pfBlockerNG by BBCan177@gmail.com (c) 2014 +// Part of pfBlockerNG by BBCan177@gmail.com (c) 2015 // // Javascript and Integration modifications by J. Nieuwenhuizen diff --git a/config/pfblockerng/pfblockerng.php b/config/pfblockerng/pfblockerng.php index 1dec1520..8c0c478d 100644 --- a/config/pfblockerng/pfblockerng.php +++ b/config/pfblockerng/pfblockerng.php @@ -3,7 +3,7 @@ pfBlockerNG.php pfBlockerNG - Copyright (C) 2014 BBcan177@gmail.com + Copyright (C) 2015 BBcan177@gmail.com All rights reserved. Based upon pfBlocker by @@ -12,7 +12,7 @@ Hour Schedule Convertor code by Snort Package - Copyright (c) 2014 Bill Meeks + Copyright (c) 2015 Bill Meeks Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -696,7 +696,7 @@ $xml = <<<EOF pfblockerng_{$cont_name}.xml pfBlockerNG - Copyright (C) 2014 BBcan177@gmail.com + Copyright (C) 2015 BBcan177@gmail.com All rights reserved. Based upon pfblocker for pfSense @@ -1001,7 +1001,7 @@ $xmlrep = <<<EOF pfBlockerNG_Reputation.xml pfBlockerNG - Copyright (C) 2014 BBcan177@gmail.com + Copyright (C) 2015 BBcan177@gmail.com All rights reserved. Based upon pfblocker for pfSense @@ -1480,4 +1480,4 @@ EOF; // Unset Arrays unset ($roptions4, $et_options, $xmlrep); } -?> +?>
\ No newline at end of file diff --git a/config/pfblockerng/pfblockerng.sh b/config/pfblockerng/pfblockerng.sh index fd0a2f4a..e010a6e5 100644 --- a/config/pfblockerng/pfblockerng.sh +++ b/config/pfblockerng/pfblockerng.sh @@ -1,6 +1,6 @@ #!/bin/sh # pfBlockerNG IP Reputation Script - By BBcan177@gmail.com - 04-12-14 -# Copyright (C) 2014 BBcan177@gmail.com +# Copyright (C) 2015 BBcan177@gmail.com # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License Version 2 as diff --git a/config/pfblockerng/pfblockerng.widget.php b/config/pfblockerng/pfblockerng.widget.php index 647017ff..229e084b 100644 --- a/config/pfblockerng/pfblockerng.widget.php +++ b/config/pfblockerng/pfblockerng.widget.php @@ -3,7 +3,7 @@ pfBlockerNG.widget.php pfBlockerNG - Copyright (C) 2014 BBcan177@gmail.com + Copyright (C) 2015 BBcan177@gmail.com All rights reserved. Based Upon pfblocker : diff --git a/config/pfblockerng/pfblockerng.xml b/config/pfblockerng/pfblockerng.xml index bdfecd96..6f7e34ec 100644 --- a/config/pfblockerng/pfblockerng.xml +++ b/config/pfblockerng/pfblockerng.xml @@ -10,7 +10,7 @@ pfBlockerNG.xml pfBlockerNG - Copyright (C) 2014 BBcan177@gmail.com + Copyright (C) 2015 BBcan177@gmail.com All rights reserved. Based upon pfblocker for pfSense @@ -456,7 +456,7 @@ <fieldname>credits</fieldname> <type>info</type> <description><![CDATA[<strong> - pfBlockerNG</strong> Created in 2014 by <a target=_new href='https://forum.pfsense.org/index.php?action=profile;u=238481'>BBcan177.</a> + pfBlockerNG</strong> Created in 2015 by <a target=_new href='https://forum.pfsense.org/index.php?action=profile;u=238481'>BBcan177.</a> <br /><br />Based upon pfBlocker by Marcello Coutinho and Tom Schaefer.<br /> Country Database GeoLite distributed under the Creative Commons Attribution-ShareAlike 3.0 Unported License by: MaxMind Inc. @ <a target=_new href='http://www.maxmind.com'>MaxMind.com</a>. diff --git a/config/pfblockerng/pfblockerng_alerts.php b/config/pfblockerng/pfblockerng_alerts.php index dd968bfc..c67420b9 100644 --- a/config/pfblockerng/pfblockerng_alerts.php +++ b/config/pfblockerng/pfblockerng_alerts.php @@ -3,14 +3,14 @@ pfBlockerNG_Alerts.php pfBlockerNG - Copyright (C) 2014 BBcan177@gmail.com + Copyright (C) 2015 BBcan177@gmail.com All rights reserved. Portions of this code are based on original work done for pfSense from the following contributors: Parts based on works from Snort_alerts.php - Copyright (C) 2014 Bill Meeks + Copyright (C) 2015 Bill Meeks All rights reserved. Javascript Hostname Lookup modifications by J. Nieuwenhuizen diff --git a/config/pfblockerng/pfblockerng_diag_dns.php b/config/pfblockerng/pfblockerng_diag_dns.php index b2f07464..b44bc71c 100644 --- a/config/pfblockerng/pfblockerng_diag_dns.php +++ b/config/pfblockerng/pfblockerng_diag_dns.php @@ -3,7 +3,7 @@ pfBlockerNG_diag_dns.php pfBlockerNG - Copyright (C) 2014 BBcan177@gmail.com + Copyright (C) 2015 BBcan177@gmail.com All rights reserved. Original Code by: @@ -47,11 +47,11 @@ if (is_array($config['aliases']['alias'])) { } $aliasname = str_replace(array(".","-"), "_", $host); $alias_exists = false; -$counter=0; -foreach($a_aliases as $a) { - if($a['name'] == $aliasname) { +$counter = 0; +foreach ($a_aliases as $a) { + if ($a['name'] == $aliasname) { $alias_exists = true; - $id=$counter; + $id = $counter; } $counter++; } @@ -65,36 +65,39 @@ if ($pfs_version > '2.2') { $cmd = '/usr/bin/dig'; } - -if(isset($_POST['create_alias']) && (is_hostname($host) || is_ipaddr($host))) { - if($_POST['override']) +if (isset($_POST['create_alias']) && (is_hostname($host) || is_ipaddr($host))) { + if ($_POST['override']) { $override = true; + } $resolved = gethostbyname($host); $type = "hostname"; - if($resolved) { + if ($resolved) { $resolved = array(); exec("{$cmd} {$host_esc} A | /usr/bin/grep {$host_esc} | /usr/bin/grep -v ';' | /usr/bin/awk '{ print $5 }'", $resolved); $isfirst = true; - foreach($resolved as $re) { - if($re <> "") { - if(!$isfirst) + foreach ($resolved as $re) { + if ($re <> "") { + if (!$isfirst) { $addresses .= " "; + } $addresses .= rtrim($re) . "/32"; $isfirst = false; } } $newalias = array(); - if($override) + if ($override) { $alias_exists = false; - if($alias_exists == false) { + } + if ($alias_exists == false) { $newalias['name'] = $aliasname; $newalias['type'] = "network"; $newalias['address'] = $addresses; $newalias['descr'] = "Created from Diagnostics-> DNS Lookup"; - if($override) + if ($override) { $a_aliases[$id] = $newalias; - else + } else { $a_aliases[] = $newalias; + } write_config(); $createdalias = true; } @@ -118,8 +121,9 @@ if ($_POST) { exec("/usr/bin/grep nameserver /etc/resolv.conf | /usr/bin/cut -f2 -d' '", $dns_servers); foreach ($dns_servers as $dns_server) { $query_time = exec("{$cmd} {$host_esc} " . escapeshellarg("@" . trim($dns_server)) . " | /usr/bin/grep Query | /usr/bin/cut -d':' -f2"); - if($query_time == "") + if ($query_time == "") { $query_time = gettext("No response"); + } $new_qt = array(); $new_qt['dns_server'] = $dns_server; $new_qt['query_time'] = $query_time; @@ -137,18 +141,20 @@ if ($_POST) { $type = "ip"; $resolved = gethostbyaddr($host); $ipaddr = $host; - if ($host != $resolved) + if ($host != $resolved) { $hostname = $resolved; + } } elseif (is_hostname($host)) { $type = "hostname"; $resolved = gethostbyname($host); - if($resolved) { + if ($resolved) { $resolved = array(); exec("{$cmd} {$host_esc} A | /usr/bin/grep {$host_esc} | /usr/bin/grep -v ';' | /usr/bin/awk '{ print $5 }'", $resolved); } $hostname = $host; - if ($host != $resolved) + if ($host != $resolved) { $ipaddr = $resolved[0]; + } } if ($host == $resolved) { @@ -157,6 +163,11 @@ if ($_POST) { } } +if ( ($_POST['host']) && ($_POST['dialog_output']) ) { + display_host_results ($host,$resolved,$dns_speeds); + exit; +} + function display_host_results ($address,$hostname,$dns_speeds) { $map_lengths = function($element) { return strlen($element[0]); }; @@ -179,12 +190,12 @@ function display_host_results ($address,$hostname,$dns_speeds) { include("head.inc"); ?> <body link="#0000CC" vlink="#0000CC" alink="#0000CC"> <?php include("fbegin.inc"); ?> -<table width="100%" border="0" cellpadding="0" cellspacing="0"> +<table width="100%" border="0" cellpadding="0" cellspacing="0" summary="pfblockerng diag dns"> <tr> <td> <?php if ($input_errors) print_input_errors($input_errors); ?> <form action="/pfblockerng/pfblockerng_diag_dns.php" method="post" name="iform" id="iform"> - <table width="100%" border="0" cellpadding="6" cellspacing="0"> + <table width="100%" border="0" cellpadding="6" cellspacing="0" summary="tabcont"> <tr> <td colspan="2" valign="top" class="listtopic"> <?=gettext("Resolve DNS hostname or IP");?></td> </tr> @@ -192,68 +203,67 @@ include("head.inc"); ?> <td width="22%" valign="top" class="vncellreq"><?=gettext("Hostname or IP");?></td> <td width="78%" class="vtable"> <?=$mandfldhtml;?> - <table> + <table summary="results"> <tr><td valign="top"> - <input name="host" type="text" class="formfld" id="host" size="20" value="<?=htmlspecialchars($host);?>"> + <input name="host" type="text" class="formfld unknown" id="host" size="20" value="<?=htmlspecialchars($host);?>"> </td> - <td> <?php if ($resolved && $type) { ?> - = <font size="+1"> + <td valign="middle"> = </td><td> + <font size="+1"> <?php $found = 0; - if(is_array($resolved)) { - foreach($resolved as $hostitem) { - if($hostitem <> "") { - echo $hostitem . "<br/>"; + if (is_array($resolved)) { + foreach ($resolved as $hostitem) { + if ($hostitem <> "") { + echo $hostitem . "<br />"; $found++; } } } else { - echo $resolved; - } - if($found > 0) { ?> - <br/><font size='-2'> - <?PHP if($alias_exists) { ?> + echo $resolved; + } + if ($found > 0) { ?> + <br /></font><font size='-2'> + <?php if ($alias_exists) { ?> An alias already exists for the hostname <?= htmlspecialchars($host) ?>. <br /> <input type="hidden" name="override" value="true"/> <input type="submit" name="create_alias" value="Overwrite Alias"/> - <?PHP } else { - if(!$createdalias) { ?> + <?php } else { + if (!$createdalias) { ?> <input type="submit" name="create_alias" value="Create Alias from These Entries"/> - <?PHP } else { ?> + <?php } else { ?> Alias created with name <?= htmlspecialchars($newalias['name']) ?> - <?PHP } + <?php } } } ?> - <font size="-1"> - <? } ?> - </td></tr></table> - </td> + <?php } ?> + </font></td></tr></table> + </td> </tr> -<?php if($_POST): ?> +<?php if ($_POST): ?> <tr> - <td width="22%" valign="top" class="vncell"><?=gettext("Resolution time per server");?></td> - <td width="78%" class="vtable"> - <table width="170" border="1" cellpadding="2" style="border-width: 1px 1px 1px 1px; border-collapse: collapse;"> + <td width="22%" valign="top" class="vncell"><?=gettext("Resolution time per server");?></td> + <td width="78%" class="vtable"> + <table width="170" border="0" cellpadding="6" cellspacing="0" summary="resolution time"> <tr> - <td> - <b><?=gettext("Server");?></b> + <td class="listhdrr"> + <?=gettext("Server");?> </td> - <td> - <b><?=gettext("Query time");?></b> + <td class="listhdrr"> + <?=gettext("Query time");?> </td> </tr> <?php - if(is_array($dns_speeds)) - foreach($dns_speeds as $qt): + if (is_array($dns_speeds)) + foreach ($dns_speeds as $qt): ?> <tr> - <td> + <td class="listlr"> <?=$qt['dns_server']?> </td> - <td> + <td class="listr"> <?=$qt['query_time']?> </td> </tr> @@ -261,58 +271,59 @@ include("head.inc"); ?> endforeach; ?> </table> - </td> + </td> </tr> <?php endif; ?> <?php if (!$input_errors && $ipaddr) { ?> <tr> - - <td width="22%" valign="top" class="vncell"><?=gettext("More Information:");?></td> + <td width="22%" valign="top" class="vncell"><?=gettext("More Information:");?></td> <td width="78%" class="vtable"> - <a target="_new" href ="/diag_ping.php?host=<?=htmlspecialchars($host)?>&interface=wan&count=3"><?=gettext("Ping");?></a> <br/> + <a target="_new" href ="/diag_ping.php?host=<?=htmlspecialchars($host)?>&interface=wan&count=3"><?=gettext("Ping");?></a> <br /> <a target="_new" href ="/diag_traceroute.php?host=<?=htmlspecialchars($host)?>&ttl=18"><?=gettext("Traceroute");?></a> <p/> - <?=gettext("NOTE: The following links are to external services, so their reliability cannot be guaranteed.");?><br/><br/> + <?=gettext("NOTE: The following links are to external services, so their reliability cannot be guaranteed.");?><br/><br /> <a target="_new" href="http://private.dnsstuff.com/tools/whois.ch?ip=<?php echo $ipaddr; ?>"><?=gettext("IP WHOIS @ DNS Stuff");?></a><br /> <a target="_new" href="http://private.dnsstuff.com/tools/ipall.ch?ip=<?php echo $ipaddr; ?>"><?=gettext("IP Info @ DNS Stuff");?></a> - <?=gettext("NOTE: The following links are to external services, so their reliability cannot be guaranteed.");?><br/><br/> - <a target="_new" href="http://kb.bothunter.net/ipInfo/nowait.php?IP=<?php echo $ipaddr; ?>"><?=gettext("BOTHunter");?></a><br/> - <a target="_new" href="http://www.ipvoid.com/scan/<?php echo $ipaddr; ?>/"><?=gettext("IPVOID");?></a><br/> - <a target="_new" href="http://www.tcpiputils.com/browse/ip-address/<?php echo $ipaddr; ?>/"><?=gettext("TCPUtils");?></a><br/> - <a target="_new" href="https://www.herdprotect.com/ip-address-<?php echo $ipaddr; ?>.aspx"><?=gettext("Herd Protect");?></a><br/> - <a target="_new" href="https://www.senderbase.org/lookup/ip/?search_string=<?php echo $ipaddr; ?>"><?=gettext("SenderBase");?></a><br/> - <a target="_new" href="http://www.ip-tracker.org/locator/ip-lookup.php?ip=<?php echo $ipaddr; ?>"><?=gettext("IP Tracker");?></a><br/> + <?=gettext("NOTE: The following links are to external services, so their reliability cannot be guaranteed.");?><br /><br /> + <a target="_new" href="http://kb.bothunter.net/ipInfo/nowait.php?IP=<?php echo $ipaddr; ?>"><?=gettext("BOTHunter");?></a><br /> + <a target="_new" href="http://www.ipvoid.com/scan/<?php echo $ipaddr; ?>/"><?=gettext("IPVOID");?></a><br /> + <a target="_new" href="http://www.tcpiputils.com/browse/ip-address/<?php echo $ipaddr; ?>/"><?=gettext("TCPUtils");?></a><br /> + <a target="_new" href="https://www.herdprotect.com/ip-address-<?php echo $ipaddr; ?>.aspx"><?=gettext("Herd Protect");?></a><br /> + <a target="_new" href="https://www.senderbase.org/lookup/ip/?search_string=<?php echo $ipaddr; ?>"><?=gettext("SenderBase");?></a><br /> + <a target="_new" href="http://www.ip-tracker.org/locator/ip-lookup.php?ip=<?php echo $ipaddr; ?>"><?=gettext("IP Tracker");?></a><br /> - <a target="_new" href="https://www.fortiguard.com/ip_rep/index.php?data=/<?php echo $ipaddr; ?>?"><?=gettext("FortiGuard");?></a><br/> - <a target="_new" href="https://www.projecthoneypot.org/ip_<?php echo $ipaddr; ?>"><?=gettext("Project HoneyPot");?></a><br/> - <a target="_new" href="https://www.virustotal.com/en/ip-address/<?php echo $ipaddr; ?>/information"><?=gettext("VirusTotal Info");?></a><br/> - <a target="_new" href="https://www.mcafee.com/threat-intelligence/ip/default.aspx?ip=<?php echo $ipaddr; ?>"><?=gettext("McAfee Threat Center");?></a><br/> - <a target="_new" href="http://sitecheck2.sucuri.net/results/<?php echo $ipaddr; ?>"><?=gettext("Securi SiteCheck");?></a><br/> - <a target="_new" href="https://www.dshield.org/ipinfo.html?IP=<?php echo $ipaddr; ?>"><?=gettext("DShield Threat Lookup");?></a><br/> - <a target="_new" href="https://isc.sans.edu/ipinfo.html?ip=<?php echo $ipaddr; ?>"><?=gettext("Internet Storm Center");?></a><br/> - <a target="_new" href="https://www.mywot.com/en/scorecard/<?php echo $ipaddr; ?>"><?=gettext("Web of Trust (WOT) Scorecard");?></a><br/> - <a target="_new" href="https://quttera.com/sitescan/<?php echo $ipaddr; ?>"><?=gettext("Quattera");?></a><br/> - <a target="_new" href="https://www.iblocklist.com/search.php?string=<?php echo $ipaddr; ?>"><?=gettext("I-Block List");?></a><br/> + <a target="_new" href="https://www.fortiguard.com/ip_rep/index.php?data=/<?php echo $ipaddr; ?>?"><?=gettext("FortiGuard");?></a><br /> + <a target="_new" href="https://www.projecthoneypot.org/ip_<?php echo $ipaddr; ?>"><?=gettext("Project HoneyPot");?></a><br /> + <a target="_new" href="https://www.virustotal.com/en/ip-address/<?php echo $ipaddr; ?>/information"><?=gettext("VirusTotal Info");?></a><br /> + <a target="_new" href="https://www.mcafee.com/threat-intelligence/ip/default.aspx?ip=<?php echo $ipaddr; ?>"><?=gettext("McAfee Threat Center");?></a><br /> + <a target="_new" href="http://sitecheck2.sucuri.net/results/<?php echo $ipaddr; ?>"><?=gettext("Securi SiteCheck");?></a><br /> + <a target="_new" href="https://www.dshield.org/ipinfo.html?IP=<?php echo $ipaddr; ?>"><?=gettext("DShield Threat Lookup");?></a><br /> + <a target="_new" href="https://isc.sans.edu/ipinfo.html?ip=<?php echo $ipaddr; ?>"><?=gettext("Internet Storm Center");?></a><br /> + <a target="_new" href="https://www.mywot.com/en/scorecard/<?php echo $ipaddr; ?>"><?=gettext("Web of Trust (WOT) Scorecard");?></a><br /> + <a target="_new" href="https://quttera.com/sitescan/<?php echo $ipaddr; ?>"><?=gettext("Quattera");?></a><br /> + <a target="_new" href="https://www.iblocklist.com/search.php?string=<?php echo $ipaddr; ?>"><?=gettext("I-Block List");?></a><br /> <p/> - <?=gettext("NOTE: Mail Server DNSRBL Lookups");?><br/><br/> - <a target="_new" href="https://senderscore.org/lookup.php?lookup=<?php echo $ipaddr; ?>&ipLookup=Go"><?=gettext("SenderScore");?></a><br/> - <a target="_new" href="http://www.spamhaus.org/query/bl?ip=<?php echo $ipaddr; ?>"><?=gettext("Spamhaus Blocklist");?></a><br/> - <a target="_new" href="http://www.spamcop.net/w3m?action=checkblock&ip=<?php echo $ipaddr; ?>"><?=gettext("SPAMcop Blocklist");?></a><br/> - <a target="_new" href="http://multirbl.valli.org/lookup/<?php echo $ipaddr; ?>.html"><?=gettext("multirbl RBL Lookup");?></a><br/> - <a target="_new" href="http://mxtoolbox.com/SuperTool.aspx?action=blacklist%3a<?php echo $ipaddr; ?>&run=toolpage"><?=gettext("MXToolbox");?></a><br/> + <?=gettext("NOTE: Mail Server DNSRBL Lookups");?><br /><br /> + <a target="_new" href="https://senderscore.org/lookup.php?lookup=<?php echo $ipaddr; ?>&ipLookup=Go"><?=gettext("SenderScore");?></a><br /> + <a target="_new" href="http://www.spamhaus.org/query/bl?ip=<?php echo $ipaddr; ?>"><?=gettext("Spamhaus Blocklist");?></a><br /> + <a target="_new" href="http://www.spamcop.net/w3m?action=checkblock&ip=<?php echo $ipaddr; ?>"><?=gettext("SPAMcop Blocklist");?></a><br /> + <a target="_new" href="http://multirbl.valli.org/lookup/<?php echo $ipaddr; ?>.html"><?=gettext("multirbl RBL Lookup");?></a><br /> + <a target="_new" href="http://mxtoolbox.com/SuperTool.aspx?action=blacklist%3a<?php echo $ipaddr; ?>&run=toolpage"><?=gettext("MXToolbox");?></a><br /> </td> </tr> <?php } ?> <tr> - <td width="22%" valign="top"> </td> - <td width="78%"> - <br/> - <input name="Submit" type="submit" class="formbtn" value="<?=gettext("DNS Lookup");?>"> + <td width="22%" valign="top"> </td> + <td width="78%"> + <br /> + <input name="Submit" type="submit" class="formbtn" value="<?=gettext("DNS Lookup");?>"> </td> </tr> </table> -</td></tr></table> </form> -<?php include("fend.inc"); ?>
\ No newline at end of file +</td></tr></table> +<?php include("fend.inc"); ?> +</body> +</html>
\ No newline at end of file diff --git a/config/pfblockerng/pfblockerng_log.php b/config/pfblockerng/pfblockerng_log.php index 74f513a2..4c25ce29 100644 --- a/config/pfblockerng/pfblockerng_log.php +++ b/config/pfblockerng/pfblockerng_log.php @@ -3,7 +3,7 @@ pfBlockerNG_Log.php pfBlockerNG - Copyright (c) 2014 BBcan177@gmail.com + Copyright (c) 2015 BBcan177@gmail.com All rights reserved. Portions of this code are based on original work done for the @@ -17,7 +17,7 @@ All rights reserved. Adapted for Suricata by: - Copyright (C) 2014 Bill Meeks + Copyright (C) 2015 Bill Meeks All rights reserved. Javascript and Integration modifications by J. Nieuwenhuizen diff --git a/config/pfblockerng/pfblockerng_sync.xml b/config/pfblockerng/pfblockerng_sync.xml index 00186af8..f6cee305 100644 --- a/config/pfblockerng/pfblockerng_sync.xml +++ b/config/pfblockerng/pfblockerng_sync.xml @@ -10,7 +10,7 @@ pfBlockerNG_sync.xml pfBlockerNG - Copyright (C) 2014 BBcan177@gmail.com + Copyright (C) 2015 BBcan177@gmail.com All rights reserved. Based upon pfblocker for pfSense diff --git a/config/pfblockerng/pfblockerng_top20.xml b/config/pfblockerng/pfblockerng_top20.xml index ccaf68a0..db898112 100644 --- a/config/pfblockerng/pfblockerng_top20.xml +++ b/config/pfblockerng/pfblockerng_top20.xml @@ -10,7 +10,7 @@ pfBlockerNG_Top20.xml pfBlockerNG - Copyright (C) 2014 BBcan177@gmail.com + Copyright (C) 2015 BBcan177@gmail.com All rights reserved. Based upon pfblocker for pfSense diff --git a/config/pfblockerng/pfblockerng_update.php b/config/pfblockerng/pfblockerng_update.php index 99480900..f3a18231 100644 --- a/config/pfblockerng/pfblockerng_update.php +++ b/config/pfblockerng/pfblockerng_update.php @@ -3,7 +3,7 @@ /* pfBlockerNG_Update.php pfBlockerNG - Copyright (C) 2014 BBcan177@gmail.com + Copyright (C) 2015 BBcan177@gmail.com All rights reserved. Portions of this code are based on original work done for diff --git a/config/pfblockerng/pfblockerng_v4lists.xml b/config/pfblockerng/pfblockerng_v4lists.xml index 6df839ed..febfd597 100644 --- a/config/pfblockerng/pfblockerng_v4lists.xml +++ b/config/pfblockerng/pfblockerng_v4lists.xml @@ -9,7 +9,7 @@ pfBlockerNG_v4lists.xml pfBlockerNG - Copyright (C) 2014 BBcan177@gmail.com + Copyright (C) 2015 BBcan177@gmail.com All rights reserved. Based upon pfblocker for pfSense diff --git a/config/pfblockerng/pfblockerng_v6lists.xml b/config/pfblockerng/pfblockerng_v6lists.xml index 15d788cf..10a866c0 100644 --- a/config/pfblockerng/pfblockerng_v6lists.xml +++ b/config/pfblockerng/pfblockerng_v6lists.xml @@ -9,7 +9,7 @@ pfBlockerNG_v6lists.xml pfBlockerNG - Copyright (C) 2014 BBcan177@gmail.com + Copyright (C) 2015 BBcan177@gmail.com All rights reserved. Based upon pfblocker for pfSense diff --git a/config/phpservice/phpservice.xml b/config/phpservice/phpservice.xml index 44999496..eb7e670e 100644 --- a/config/phpservice/phpservice.xml +++ b/config/phpservice/phpservice.xml @@ -56,6 +56,9 @@ <rcfile>phpservice.sh</rcfile> <executable>phpservice</executable> <description>PHP run from a command line as a service.</description> + <custom_php_service_status_command> + exec("/bin/pgrep -f phpservice"); + </custom_php_service_status_command> </service> <tabs> <tab> @@ -118,4 +121,4 @@ <custom_php_deinstall_command> phpservice_deinstall_command(); </custom_php_deinstall_command> -</packagegui>
\ No newline at end of file +</packagegui> diff --git a/config/quagga_ospfd/quagga_ospfd.inc b/config/quagga_ospfd/quagga_ospfd.inc index 3b5c153d..140bac8a 100644 --- a/config/quagga_ospfd/quagga_ospfd.inc +++ b/config/quagga_ospfd/quagga_ospfd.inc @@ -422,7 +422,7 @@ function quagga_get_carp_status_by_ip($ipaddr) { return $status; } -function quagga_plugin_carp($pluginparams) { +function quagga_ospfd_plugin_carp($pluginparams) { global $config; require_once("service-utils.inc"); // Called when a CARP interface changes state diff --git a/config/quagga_ospfd/quagga_ospfd.xml b/config/quagga_ospfd/quagga_ospfd.xml index 5de2e3f8..617b5da0 100644 --- a/config/quagga_ospfd/quagga_ospfd.xml +++ b/config/quagga_ospfd/quagga_ospfd.xml @@ -1,6 +1,6 @@ <packagegui> <name>quagga_ospfd</name> - <version>0.6.4</version> + <version>0.6.5</version> <title>Services: Quagga OSPFd</title> <include_file>/usr/local/pkg/quagga_ospfd.inc</include_file> <aftersaveredirect>pkg_edit.php?xml=quagga_ospfd.xml&id=0</aftersaveredirect> diff --git a/config/siproxd/siproxd.inc b/config/siproxd/siproxd.inc index d76f79d3..d9830fb2 100644 --- a/config/siproxd/siproxd.inc +++ b/config/siproxd/siproxd.inc @@ -32,7 +32,8 @@ if(!function_exists("filter_configure")) require_once("service-utils.inc"); // Check to find out on which system the package is running -if (substr(trim(file_get_contents("/etc/version")),0,3) == "2.0") { +$pfs_version = substr(trim(file_get_contents("/etc/version")),0,3); +if ($pfs_version == "2.0") { define('SIPROXD', '/usr/local'); } else { define('SIPROXD', '/usr/pbi/siproxd-' . php_uname("m")); @@ -108,7 +109,7 @@ function siproxd_generate_rules($type) { } function sync_package_siproxd() { - global $config; + global $config, $pfs_version; // put the constant to a variable $varSIPROXD = SIPROXD; @@ -250,9 +251,14 @@ function sync_package_siproxd() { fclose($fout); + if ($pfs_version == '2.2') + $bin_dir='bin'; + else + $bin_dir='sbin'; + write_rcfile(array( "file" => "siproxd.sh", - "start" => "$varSIPROXD/sbin/siproxd -c $varSIPROXD/etc/siproxd.conf &", + "start" => "$varSIPROXD/{$bin_dir}/siproxd -c $varSIPROXD/etc/siproxd.conf &", "stop" => "/usr/bin/killall -9 siproxd" ) ); diff --git a/config/snort/snort.xml b/config/snort/snort.xml index 60573130..1f1a7d24 100755 --- a/config/snort/snort.xml +++ b/config/snort/snort.xml @@ -46,8 +46,8 @@ <requirements>None</requirements> <faq>Currently there are no FAQ items provided.</faq> <name>Snort</name> - <version>2.9.7.0</version> - <title>Services:2.9.7.0 pkg v3.2.3</title> + <version>2.9.7.2</version> + <title>Services:2.9.7.2 pkg v3.2.4</title> <include_file>/usr/local/pkg/snort/snort.inc</include_file> <menu> <name>Snort</name> diff --git a/config/snort/snort_defs.inc b/config/snort/snort_defs.inc index 43ecada6..906dd465 100644 --- a/config/snort/snort_defs.inc +++ b/config/snort/snort_defs.inc @@ -50,7 +50,7 @@ if (!defined("SNORT_BIN_VERSION")) { if (!empty($snortver[0])) define("SNORT_BIN_VERSION", $snortver[0]); else - define("SNORT_BIN_VERSION", "2.9.7.0"); + define("SNORT_BIN_VERSION", "2.9.7.2"); } if (!defined("SNORT_SID_MODS_PATH")) define('SNORT_SID_MODS_PATH', "{$g['vardb_path']}/snort/sidmods/"); diff --git a/config/snort/snort_generate_conf.php b/config/snort/snort_generate_conf.php index 1d56fc13..297e833b 100644 --- a/config/snort/snort_generate_conf.php +++ b/config/snort/snort_generate_conf.php @@ -895,7 +895,7 @@ EOD; /* def AppID preprocessor */ $appid_memcap = $snortcfg['sf_appid_mem_cap'] * 1024 * 1024; -$appid_params = "app_detector_dir " . SNORT_APPID_ODP_PATH . ", \\\n\tmemcap {$appid_memcap}"; +$appid_params = "app_detector_dir " . rtrim(SNORT_APPID_ODP_PATH, '/') . ", \\\n\tmemcap {$appid_memcap}"; if ($snortcfg['sf_appid_statslog'] == "on") { $appid_params .= ", \\\n\tapp_stats_filename app-stats.log"; $appid_params .= ", \\\n\tapp_stats_period {$snortcfg['sf_appid_stats_period']}"; diff --git a/config/snort/snort_migrate_config.php b/config/snort/snort_migrate_config.php index de8ac308..941a8151 100644 --- a/config/snort/snort_migrate_config.php +++ b/config/snort/snort_migrate_config.php @@ -533,7 +533,7 @@ unset($r); // Log a message if we changed anything if ($updated_cfg) { - $config['installedpackages']['snortglobal']['snort_config_ver'] = "3.2.3"; + $config['installedpackages']['snortglobal']['snort_config_ver'] = "3.2.4"; log_error("[Snort] Settings successfully migrated to new configuration format..."); } else diff --git a/config/snort/snort_post_install.php b/config/snort/snort_post_install.php index 7ab8b3db..f93f1c87 100644 --- a/config/snort/snort_post_install.php +++ b/config/snort/snort_post_install.php @@ -263,8 +263,8 @@ if (stristr($config['widgets']['sequence'], "snort_alerts-container") === FALSE) $config['widgets']['sequence'] .= ",{$snort_widget_container}"; /* Update Snort package version in configuration */ -$config['installedpackages']['snortglobal']['snort_config_ver'] = "3.2.3"; -write_config("Snort pkg v3.2.3: post-install configuration saved."); +$config['installedpackages']['snortglobal']['snort_config_ver'] = "3.2.4"; +write_config("Snort pkg v3.2.4: post-install configuration saved."); /* Done with post-install, so clear flag */ unset($g['snort_postinstall']); diff --git a/config/snort/snort_rulesets.php b/config/snort/snort_rulesets.php index c29b1810..90ce1e7d 100755 --- a/config/snort/snort_rulesets.php +++ b/config/snort/snort_rulesets.php @@ -452,7 +452,7 @@ if ($savemsg) { <tr> <td width="5%" class="listr" style="text-align: center;"> <img src="../themes/<?=$g['theme'];?>/images/icons/icon_advanced.gif" width="11" height="11" border="0" title="<?=gettext("Auto-managed by settings on SID Mgmt tab");?>" /></td> - <td colspan="5" class="listr"><a href='suricata_rules.php?id=<?=$id;?>&openruleset=<?=$community_rules_file;?>'><?=gettext("{$msg_community}");?></a></td> + <td colspan="5" class="listr"><a href='snort_rules.php?id=<?=$id;?>&openruleset=<?=$community_rules_file;?>'><?=gettext("{$msg_community}");?></a></td> </tr> <?php else: ?> <tr> @@ -465,7 +465,7 @@ if ($savemsg) { <tr> <td width="5%" class="listr" style="text-align: center;"> <input type="checkbox" name="toenable[]" value="<?=$community_rules_file;?>" checked="checked"/></td> - <td colspan="5" class="listr"><a href='suricata_rules.php?id=<?=$id;?>&openruleset=<?=$community_rules_file;?>'><?php echo gettext("{$msg_community}"); ?></a></td> + <td colspan="5" class="listr"><a href='snort_rules.php?id=<?=$id;?>&openruleset=<?=$community_rules_file;?>'><?php echo gettext("{$msg_community}"); ?></a></td> </tr> <?php else: ?> <tr> @@ -531,7 +531,7 @@ if ($savemsg) { sort($snortrules); $i = count($emergingrules); if ($i < count($snortsorules)) - $i = count(snortsorules); + $i = count($snortsorules); if ($i < count($snortrules)) $i = count($snortrules); diff --git a/config/squid3/34/squid.inc b/config/squid3/34/squid.inc index 69a50125..cce9bddd 100755 --- a/config/squid3/34/squid.inc +++ b/config/squid3/34/squid.inc @@ -639,19 +639,19 @@ function squid_validate_reverse($post, &$input_errors) { $input_errors[] = 'The field \'external FQDN\' must contain a valid domain name'; $port = trim($post['reverse_http_port']); - preg_match("/(\d+)/",`sysctl net.inet.ip.portrange.first`,$portrange); + preg_match("/(\d+)/",`sysctl net.inet.ip.portrange.reservedhigh`,$portrange); if (!empty($port) && !is_port($port)) $input_errors[] = 'The field \'reverse HTTP port\' must contain a valid port number'; - if (!empty($port) && is_port($port) && $port < $portrange[1]){ - $input_errors[] = "The field 'reverse HTTP port' must contain a port number higher than net.inet.ip.portrange.first sysctl value({$portrange[1]})."; - $input_errors[] = "To listen on low ports, change portrange.first sysctl value to 0 on system tunable options and restart squid daemon."; + if (!empty($port) && is_port($port) && $port <= $portrange[1]){ + $input_errors[] = "The field 'reverse HTTP port' must contain a port number higher than net.inet.ip.portrange.reservedhigh sysctl value({$portrange[1]})."; + $input_errors[] = "To listen on low ports, change portrange.reservedhigh sysctl value to 0 on system tunable options and restart squid daemon."; } $port = trim($post['reverse_https_port']); if (!empty($port) && !is_port($port)) $input_errors[] = 'The field \'reverse HTTPS port\' must contain a valid port number'; - if (!empty($port) && is_port($port) && $port < $portrange[1]){ - $input_errors[] = "The field 'reverse HTTPS port' must contain a port number higher than net.inet.ip.portrange.first sysctl value({$portrange[1]})."; - $input_errors[] = "To listen on low ports, change portrange.first sysctl value to 0 on system tunable options and restart squid daemon."; + if (!empty($port) && is_port($port) && $port <= $portrange[1]){ + $input_errors[] = "The field 'reverse HTTPS port' must contain a port number higher than net.inet.ip.portrange.reservedhigh sysctl value({$portrange[1]})."; + $input_errors[] = "To listen on low ports, change portrange.reservedhigh sysctl value to 0 on system tunable options and restart squid daemon."; } if ($post['reverse_ssl_cert'] == 'none') $input_errors[] = 'A valid certificate for the external interface must be selected'; diff --git a/config/squidGuard/squidguard.xml b/config/squidGuard/squidguard.xml index 3a77edf3..7f3036ba 100644 --- a/config/squidGuard/squidguard.xml +++ b/config/squidGuard/squidguard.xml @@ -6,7 +6,7 @@ <requirements>Describe your package requirements here</requirements> <faq>Currently there are no FAQ items provided.</faq> <name>squidguardgeneral</name> - <version>1.4_4 pkg v.1.9.8</version> + <version>1.4_7 pkg v.1.9.11</version> <title>Proxy filter SquidGuard: General settings</title> <include_file>/usr/local/pkg/squidguard.inc</include_file> <!-- Installation --> diff --git a/config/squidGuard/squidguard_configurator.inc b/config/squidGuard/squidguard_configurator.inc index d3448c5d..38104c89 100644 --- a/config/squidGuard/squidguard_configurator.inc +++ b/config/squidGuard/squidguard_configurator.inc @@ -91,11 +91,20 @@ define('CONFIG_SG_HEADER', " # ------------------------------------------------------------------------------ # squid config options # ------------------------------------------------------------------------------ + +$pf_version=substr(trim(file_get_contents("/etc/version")),0,3); + define('REDIRECTOR_OPTIONS_REM', '# squidGuard options'); -define('REDIRECTOR_PROGRAM_OPT', 'redirect_program'); -define('REDIRECT_BYPASS_OPT', 'redirector_bypass'); define('REDIRECT_CHILDREN_OPT', 'url_rewrite_children'); -define('REDIRECTOR_PROCESS_COUNT', '5'); # redirector processes count will started +if ($pf_version >= 2.2) { + define('REDIRECTOR_PROGRAM_OPT', 'url_rewrite_program'); + define('REDIRECT_BYPASS_OPT', 'url_rewrite_bypass'); + define('REDIRECTOR_PROCESS_COUNT', '16 startup=8 idle=4 concurrency=0'); +} else { + define('REDIRECTOR_PROGRAM_OPT', 'redirect_program'); + define('REDIRECT_BYPASS_OPT', 'redirector_bypass'); + define('REDIRECTOR_PROCESS_COUNT', '5'); +} # ------------------------------------------------------------------------------ # squidguard config options @@ -111,7 +120,7 @@ define('REDIRECT_URL_ARGS', '&a=%a&n=%n&i=%i&s=%s&t=%t&u=%u'); # squidguard system constants # ------------------------------------------------------------------------------ -$pf_version=substr(trim(file_get_contents("/etc/version")),0,3); + if ($pf_version > 2.0) { if (file_exists('/usr/pbi/squidguard-squid3-' . php_uname("m"))) define('SQUIDGUARD_LOCALBASE', '/usr/pbi/squidguard-squid3-' . php_uname("m")); diff --git a/config/sudo/sudo.inc b/config/sudo/sudo.inc index a69d9211..a8107029 100644 --- a/config/sudo/sudo.inc +++ b/config/sudo/sudo.inc @@ -28,6 +28,7 @@ */ require_once("config.inc"); +global $pfs_version; $pfs_version = substr(trim(file_get_contents("/etc/version")),0,3); switch ($pfs_version) { case "1.2": @@ -84,8 +85,11 @@ function sudo_install() { } function sudo_write_config() { - global $config; + global $config, $pfs_version; $sudoers = ""; + if ($pfs_version == "2.2") { + mwexec_bg("/sbin/ldconfig -m /usr/pbi/sudo-" . php_uname("m") . "/local/lib/"); + } conf_mount_rw(); $sudoconf = "Plugin sudoers_policy " . SUDO_LIBEXEC_DIR . "/sudoers.so\n"; diff --git a/config/sudo/sudo.xml b/config/sudo/sudo.xml index 2fccab24..069606ba 100644 --- a/config/sudo/sudo.xml +++ b/config/sudo/sudo.xml @@ -3,7 +3,7 @@ <description>Sudo Command Control</description> <requirements>None</requirements> <name>sudo</name> - <version>0.2.1</version> + <version>0.2.5</version> <title>Sudo - Shell Command Privilege Delegation Utility</title> <include_file>/usr/local/pkg/sudo.inc</include_file> <menu> diff --git a/config/vnstat2/vnstat2.inc b/config/vnstat2/vnstat2.inc index f248083e..c875be52 100644 --- a/config/vnstat2/vnstat2.inc +++ b/config/vnstat2/vnstat2.inc @@ -63,8 +63,8 @@ function change_vnstat_conf(){ $config['installedpackages']['vnstat2']['config'][0]['vnstat_phpfrontend'] = $_POST['vnstat_phpfrontend']; write_conf_f(); write_config(); - $no_vnstat_phpfrontend = $config['installedpackages']['vnstat2']['config'][0]['vnstat_phpfrontend']; - if ($no_vnstat_phpfrontend == "on"){ + + if ($config['installedpackages']['vnstat2']['config'][0]['vnstat_phpfrontend'] == "on"){ vnstat_php_frontend(); } else { @@ -195,12 +195,10 @@ function vnstat_install_config() { } vnstat_link_config(); // Add MonthRotate value to config.xml and write /usr/local/etc/vnstat.conf - $no_monthrotate = $config['installedpackages']['vnstat2']['config'][0]['monthrotate']; - if ($no_monthrotate == ""){ + if ($config['installedpackages']['vnstat2']['config'][0]['monthrotate'] == ""){ $config['installedpackages']['vnstat2']['config'][0]['monthrotate'] = "1"; } - $no_vnstat_phpfrontend = $config['installedpackages']['vnstat2']['config'][0]['vnstat_phpfrontend']; - if ($no_vnstat_phpfrontend == "on"){ + if ($config['installedpackages']['vnstat2']['config'][0]['vnstat_phpfrontend'] == "on"){ vnstat_php_frontend(); } write_conf_f(); @@ -214,7 +212,7 @@ function vnstat_install_config() { function vnstat_php_frontend(){ global $config; // Copy vnstat_php_frontend to www - exec("cp -a /usr/local/pkg/vnstat2/vnstat_php_frontend/. /usr/local/www/vnstat2/"); + exec("/bin/cp -a /usr/local/pkg/vnstat2/vnstat_php_frontend/. /usr/local/www/vnstat2/"); // Find information to be writing in config.php // $iface_list_array_items exec("ls /conf/vnstat/ | grep -v '\.'", $vnstat_nic_in); diff --git a/pkg_config.10.xml b/pkg_config.10.xml index c0883adf..cc2d91e0 100644 --- a/pkg_config.10.xml +++ b/pkg_config.10.xml @@ -117,8 +117,8 @@ <category>Firewall</category> <pkginfolink>https://forum.pfsense.org/index.php?topic=86212.0</pkginfolink> <config_file>https://packages.pfsense.org/packages/config/pfblockerng/pfblockerng.xml</config_file> - <version>1.05</version> - <status>Beta</status> + <version>1.06</version> + <status>Stable</status> <required_version>2.2</required_version> <maintainer>BBCan177@gmail.com</maintainer> <configurationfile>pfblockerng.xml</configurationfile> @@ -130,6 +130,27 @@ </build_pbi> </package> <package> + <name>haproxy-1_5</name> + <pkginfolink>https://doc.pfsense.org/index.php/haproxy_package</pkginfolink> + <descr><![CDATA[The Reliable, High Performance TCP/HTTP(S) Load Balancer<br /> + This package implements the TCP, HTTP and HTTPS balancing features from haproxy.<br /> + Supports ACLs for smart backend switching.]]></descr> + <website>http://haproxy.1wt.eu/</website> + <category>Services</category> + <version>1.5.11 pkg v 0.23</version> + <status>Release</status> + <required_version>2.2</required_version> + <config_file>https://packages.pfsense.org/packages/config/haproxy1_5/haproxy.xml</config_file> + <configurationfile>haproxy.xml</configurationfile> + <depends_on_package_pbi>haproxy-devel-1.5.11-##ARCH##.pbi</depends_on_package_pbi> + <build_pbi> + <ports_before>security/openssl</ports_before> + <custom_name>haproxy-devel</custom_name> + <port>/usr/ports/net/haproxy</port> + </build_pbi> + <build_options>WITH_OPENSSL_PORT=yes;OPTIONS_UNSET_FORCE=PCRE DPCRE;OPTIONS_SET_FORCE=OPENSSL SPCRE</build_options> + </package> + <package> <name>haproxy-devel</name> <pkginfolink>https://doc.pfsense.org/index.php/haproxy_package</pkginfolink> <descr><![CDATA[The Reliable, High Performance TCP/HTTP(S) Load Balancer<br /> @@ -137,12 +158,12 @@ Supports ACLs for smart backend switching.]]></descr> <website>http://haproxy.1wt.eu/</website> <category>Services</category> - <version>1.5.9 pkg v 0.20</version> + <version>1.5.11 pkg v 0.23</version> <status>Release</status> <required_version>2.2</required_version> <config_file>https://packages.pfsense.org/packages/config/haproxy-devel/haproxy.xml</config_file> <configurationfile>haproxy.xml</configurationfile> - <depends_on_package_pbi>haproxy-devel-1.5.9-##ARCH##.pbi</depends_on_package_pbi> + <depends_on_package_pbi>haproxy-devel-1.5.11-##ARCH##.pbi</depends_on_package_pbi> <build_pbi> <ports_before>security/openssl</ports_before> <custom_name>haproxy-devel</custom_name> @@ -242,7 +263,7 @@ <ports_before>databases/redis databases/gdbm net/GeoIP x11-fonts/font-util x11-fonts/webfonts graphics/graphviz</ports_before> <port>net/ntopng</port> </build_pbi> - <version>1.2.1 v0.3</version> + <version>1.2.1 v0.5</version> <status>ALPHA</status> <required_version>2.2</required_version> <config_file>https://packages.pfsense.org/packages/config/ntopng/ntopng.xml</config_file> @@ -281,7 +302,7 @@ <category>Services</category> <pkginfolink>https://doc.pfsense.org/index.php/PHPService</pkginfolink> <config_file>https://packages.pfsense.org/packages/config/phpservice/phpservice.xml</config_file> - <version>0.4.1</version> + <version>0.4.2</version> <status>Beta</status> <required_version>2.2</required_version> <maintainer>markjcrane@gmail.com</maintainer> @@ -332,14 +353,14 @@ <website>http://www.snort.org</website> <descr>Snort is an open source network intrusion prevention and detection system (IDS/IPS). Combining the benefits of signature, protocol, and anomaly-based inspection.</descr> <category>Security</category> - <depends_on_package_pbi>snort-2.9.7.0-##ARCH##.pbi</depends_on_package_pbi> + <depends_on_package_pbi>snort-2.9.7.2-##ARCH##.pbi</depends_on_package_pbi> <build_pbi> <port>security/snort</port> <ports_after>security/barnyard2</ports_after> </build_pbi> <build_options>barnyard2_UNSET=ODBC PGSQL PRELUDE;barnyard2_SET=GRE IPV6 MPLS MYSQL PORT_PCAP BRO;snort_SET=PERFPROFILE SOURCEFIRE GRE IPV6 NORMALIZER APPID;snort_UNSET=PULLEDPORK FILEINSPECT HA;perl_SET=THREADS</build_options> <config_file>https://packages.pfsense.org/packages/config/snort/snort.xml</config_file> - <version>2.9.7.0 pkg v3.2.3</version> + <version>2.9.7.2 pkg v3.2.4</version> <required_version>2.2</required_version> <status>Stable</status> <configurationfile>/snort.xml</configurationfile> @@ -460,12 +481,12 @@ <descr>Proxy for handling NAT of multiple SIP devices to a single public IP.</descr> <category>Services</category> <config_file>https://packages.pfsense.org/packages/config/siproxd/siproxd.xml</config_file> - <depends_on_package_pbi>siproxd-0.8.0-##ARCH##.pbi</depends_on_package_pbi> + <depends_on_package_pbi>siproxd-0.8.0_1-##ARCH##.pbi</depends_on_package_pbi> <pkginfolink>https://doc.pfsense.org/index.php/Siproxd_package</pkginfolink> <build_pbi> <port>net/siproxd</port> </build_pbi> - <version>0.8.0_2 pkg v1.0.2</version> + <version>0.8.0_1 pkg v1.0.3</version> <status>Beta</status> <required_version>2.2</required_version> <configurationfile>siproxd.xml</configurationfile> @@ -490,7 +511,7 @@ <descr>High performance web proxy report (LightSquid). Proxy realtime stat (SQStat). Requires squid HTTP proxy.</descr> <website>http://lightsquid.sf.net/</website> <category>Network Report</category> - <version>1.8.2 pkg v.2.35</version> + <version>1.8.2 pkg v.2.36</version> <maintainer>dv_serg@mail.ru</maintainer> <depends_on_package_pbi>lightsquid-1.8_2-##ARCH##.pbi</depends_on_package_pbi> <build_pbi> @@ -767,7 +788,7 @@ On pfSense docs there is a how-to which could help you on porting users.]]></descr> <pkginfolink>https://doc.pfsense.org/index.php/FreeRADIUS_2.x_package</pkginfolink> <category>System</category> - <version>2.1.12_1/2.2.6_3 pkg v1.6.10</version> + <version>2.2.6_3 pkg v1.6.11</version> <status>RC1</status> <required_version>2.2</required_version> <maintainer>nachtfalkeaw@web.de</maintainer> @@ -893,7 +914,7 @@ <pkginfolink>https://forum.pfsense.org/index.php/topic,48347.0.html</pkginfolink> <website>http://www.squid-cache.org/</website> <category>Network</category> - <version>3.4.10_2 pkg 0.2.6</version> + <version>3.4.10_2 pkg 0.2.7</version> <status>beta</status> <required_version>2.2</required_version> <maintainer>marcellocoutinho@gmail.com fernando@netfilter.com.br seth.mos@dds.nl mfuchs77@googlemail.com jimp@pfsense.org</maintainer> @@ -969,7 +990,7 @@ <website>http://www.squidGuard.org/</website> <maintainer>dv_serg@mail.ru</maintainer> <category>Network Management</category> - <version>1.4_7 pkg v.1.9.10</version> + <version>1.4_7 pkg v.1.9.11</version> <status>Beta</status> <required_version>2.2</required_version> <depends_on_package_pbi>squidguard-1.4_7-##ARCH##.pbi</depends_on_package_pbi> @@ -1007,7 +1028,7 @@ <depends_on_package_pbi>zip-3.0_1-##ARCH##.pbi p7zip-9.20.1_2-##ARCH##.pbi</depends_on_package_pbi> <build_port_path>/usr/ports/archivers/p7zip</build_port_path> <build_port_path>/usr/ports/archivers/zip</build_port_path> - <version>1.2.15</version> + <version>1.2.16</version> <status>RELEASE</status> <required_version>2.2</required_version> <config_file>https://packages.pfsense.org/packages/config/openvpn-client-export/openvpn-client-export.xml</config_file> @@ -1167,7 +1188,7 @@ <name>Quagga OSPF</name> <descr>OSPF routing protocol using Quagga -- WARNING! Installs files to the same place as OpenBGPD. Installing both will break things.</descr> <maintainer>jimp@pfsense.org</maintainer> - <version>0.99.22.3.1_2 v0.6.4</version> + <version>0.99.22.3.1_2 v0.6.5</version> <category>Routing</category> <status>BETA</status> <depends_on_package_pbi>quagga-0.99.23.1_2-##ARCH##.pbi</depends_on_package_pbi> @@ -1387,7 +1408,7 @@ <pkginfolink>https://doc.pfsense.org/index.php/Sudo_Package</pkginfolink> <descr><![CDATA[sudo allows delegation of privileges to users in the shell so commands can be run as other users, such as root.]]></descr> <category>Security</category> - <version>0.2.3</version> + <version>0.2.5</version> <status>Beta</status> <required_version>2.2</required_version> <config_file>https://packages.pfsense.org/packages/config/sudo/sudo.xml</config_file> @@ -1396,7 +1417,7 @@ <build_pbi> <port>security/sudo</port> </build_pbi> - <depends_on_package_pbi>sudo-1.8.11p1-##ARCH##.pbi</depends_on_package_pbi> + <depends_on_package_pbi>sudo-1.8.12-##ARCH##.pbi</depends_on_package_pbi> </package> <package> <name>Service Watchdog</name> @@ -1431,7 +1452,7 @@ <descr>Set of programs for controlling APC UPS.</descr> <category>Services</category> <config_file>https://packages.pfsense.org/packages/config/apcupsd/apcupsd.xml</config_file> - <version>apcupsd-3.14.12_1 pkg v0.3.3</version> + <version>apcupsd-3.14.12_1 pkg v0.3.4</version> <status>BETA</status> <required_version>2.2</required_version> <configurationfile>apcupsd.xml</configurationfile> @@ -1476,5 +1497,16 @@ <build_options>barnyard2_UNSET=ODBC PGSQL PRELUDE;barnyard2_SET=GRE IPV6 MPLS MYSQL PORT_PCAP BRO;suricata_SET=IPFW PORTS_PCAP GEOIP JSON NSS LUAJIT HTP_PORT;suricata_UNSET=PRELUDE TESTS SC LUA</build_options> <depends_on_package_pbi>suricata-2.0.6-##ARCH##.pbi</depends_on_package_pbi> </package> + <package> + <name>FTP Client Proxy</name> + <descr><![CDATA[Basic FTP Client Proxy using ftp-proxy from FreeBSD]]></descr> + <maintainer>jimp@pfsense.org</maintainer> + <version>0.2</version> + <category>Services</category> + <status>Beta</status> + <config_file>https://packages.pfsense.org/packages/config/ftpproxy/ftpproxy.xml</config_file> + <required_version>2.2</required_version> + <configurationfile>ftpproxy.xml</configurationfile> + </package> </packages> </pfsensepkgs> diff --git a/pkg_config.8.xml b/pkg_config.8.xml index ba0ba5e3..ceddd5e0 100644 --- a/pkg_config.8.xml +++ b/pkg_config.8.xml @@ -159,6 +159,30 @@ <depends_on_package_pbi>haproxy-1.4.24-i386.pbi</depends_on_package_pbi> </package> <package> + <name>haproxy-1_5</name> + <pkginfolink>https://doc.pfsense.org/index.php/haproxy_package</pkginfolink> + <descr><![CDATA[The Reliable, High Performance TCP/HTTP(S) Load Balancer<br /> + This package implements the TCP, HTTP and HTTPS balancing features of haproxy.<br /> + Supports ACLs for smart backend switching.]]></descr> + <website>http://haproxy.1wt.eu/</website> + <category>Services</category> + <version>1.5.3 pkg v 0.23</version> + <status>Release</status> + <required_version>2.1</required_version> + <config_file>https://packages.pfsense.org/packages/config/haproxy1_5/haproxy.xml</config_file> + <configurationfile>haproxy.xml</configurationfile> + <depends_on_package_base_url>https://files.pfsense.org/packages/8/All/</depends_on_package_base_url> + <depends_on_package>haproxy-1.4.22.tbz</depends_on_package> + <depends_on_package_pbi>haproxy-devel-1.5.3-i386.pbi</depends_on_package_pbi> + <build_port_path>/usr/ports/net/haproxy-devel</build_port_path> + <build_pbi> + <ports_before>security/openssl</ports_before> + <custom_name>haproxy-devel</custom_name> + <port>/usr/ports/net/haproxy-devel</port> + </build_pbi> + <build_options>WITH_OPENSSL_PORT=yes;OPTIONS_UNSET_FORCE=PCRE DPCRE;OPTIONS_SET=OPENSSL SPCRE</build_options> + </package> + <package> <name>haproxy-devel</name> <pkginfolink>https://doc.pfsense.org/index.php/haproxy_package</pkginfolink> <descr><![CDATA[The Reliable, High Performance TCP/HTTP(S) Load Balancer<br /> @@ -166,7 +190,7 @@ Supports ACLs for smart backend switching.]]></descr> <website>http://haproxy.1wt.eu/</website> <category>Services</category> - <version>1.5.3 pkg v 0.20</version> + <version>1.5.3 pkg v 0.23</version> <status>Release</status> <required_version>2.1</required_version> <config_file>https://packages.pfsense.org/packages/config/haproxy-devel/haproxy.xml</config_file> @@ -365,7 +389,7 @@ <ports_before>databases/redis databases/gdbm net/GeoIP x11-fonts/font-util x11-fonts/webfonts graphics/graphviz</ports_before> <port>net/ntopng</port> </build_pbi> - <version>1.1 v0.3</version> + <version>1.1 v0.5</version> <status>ALPHA</status> <required_version>2.1.4</required_version> <config_file>https://packages.pfsense.org/packages/config/ntopng/ntopng.xml</config_file> @@ -407,7 +431,7 @@ <pkginfolink>https://doc.pfsense.org/index.php/PHPService</pkginfolink> <config_file>https://packages.pfsense.org/packages/config/phpservice/phpservice.xml</config_file> <depends_on_package_base_url>https://files.pfsense.org/packages/8/All/</depends_on_package_base_url> - <version>0.4.1</version> + <version>0.4.2</version> <status>Beta</status> <required_version>1.2.1</required_version> <maintainer>markjcrane@gmail.com</maintainer> @@ -462,14 +486,14 @@ <descr>Snort is an open source network intrusion prevention and detection system (IDS/IPS). Combining the benefits of signature, protocol, and anomaly-based inspection.</descr> <category>Security</category> <depends_on_package_base_url>https://files.pfsense.org/packages/8/All/</depends_on_package_base_url> - <depends_on_package_pbi>snort-2.9.7.0-i386.pbi</depends_on_package_pbi> + <depends_on_package_pbi>snort-2.9.7.2-i386.pbi</depends_on_package_pbi> <build_pbi> <port>security/snort</port> <ports_after>security/barnyard2</ports_after> </build_pbi> <build_options>barnyard2_UNSET=ODBC PGSQL PRELUDE;barnyard2_SET=GRE IPV6 MPLS MYSQL PORT_PCAP BRO;snort_SET=PERFPROFILE SOURCEFIRE GRE IPV6 NORMALIZER APPID;snort_UNSET=PULLEDPORK FILEINSPECT HA;perl_SET=THREADS</build_options> <config_file>https://packages.pfsense.org/packages/config/snort/snort.xml</config_file> - <version>2.9.7.0 pkg v3.2.3</version> + <version>2.9.7.2 pkg v3.2.4</version> <required_version>2.1</required_version> <status>Stable</status> <configurationfile>/snort.xml</configurationfile> @@ -613,7 +637,7 @@ <depends_on_package_pbi>siproxd-0.8.0-i386.pbi</depends_on_package_pbi> <pkginfolink>https://doc.pfsense.org/index.php/Siproxd_package</pkginfolink> <build_port_path>/usr/ports/net/siproxd</build_port_path> - <version>0.8.0_2 pkg v1.0.2</version> + <version>0.8.0_1 pkg v1.0.3</version> <status>Beta</status> <required_version>1.2.1</required_version> <configurationfile>siproxd.xml</configurationfile> @@ -1017,7 +1041,7 @@ On pfSense docs there is a how-to which could help you on porting users.]]></descr> <pkginfolink>https://doc.pfsense.org/index.php/FreeRADIUS_2.x_package</pkginfolink> <category>System</category> - <version>2.1.12_1/2.2.5_3 pkg v1.6.10</version> + <version>2.2.5_3 pkg v1.6.11</version> <status>RC1</status> <required_version>2.1</required_version> <maintainer>nachtfalkeaw@web.de</maintainer> @@ -1377,7 +1401,7 @@ <depends_on_package_pbi>zip-3.0-i386.pbi p7zip-9.20.1-i386.pbi</depends_on_package_pbi> <build_port_path>/usr/ports/archivers/p7zip</build_port_path> <build_port_path>/usr/ports/archivers/zip</build_port_path> - <version>1.2.15</version> + <version>1.2.16</version> <status>RELEASE</status> <required_version>2.0</required_version> <config_file>https://packages.pfsense.org/packages/config/openvpn-client-export/openvpn-client-export.xml</config_file> @@ -1606,7 +1630,7 @@ <name>Quagga OSPF</name> <descr>OSPF routing protocol using Quagga -- WARNING! Installs files to the same place as OpenBGPD. Installing both will break things.</descr> <maintainer>jimp@pfsense.org</maintainer> - <version>0.99.22.3 v0.6.4</version> + <version>0.99.22.3 v0.6.5</version> <category>Routing</category> <status>BETA</status> <depends_on_package_base_url>https://files.pfsense.org/packages/8/All/</depends_on_package_base_url> @@ -1859,7 +1883,7 @@ <descr>Set of programs for controlling APC UPS.</descr> <category>Services</category> <config_file>https://packages.pfsense.org/packages/config/apcupsd/apcupsd.xml</config_file> - <version>apcupsd-3.14.10_1 pkg v0.3.3</version> + <version>apcupsd-3.14.10_1 pkg v0.3.4</version> <status>BETA</status> <required_version>2.0</required_version> <configurationfile>apcupsd.xml</configurationfile> diff --git a/pkg_config.8.xml.amd64 b/pkg_config.8.xml.amd64 index 77370a5e..59338187 100644 --- a/pkg_config.8.xml.amd64 +++ b/pkg_config.8.xml.amd64 @@ -146,6 +146,30 @@ <depends_on_package_pbi>haproxy-1.4.24-amd64.pbi</depends_on_package_pbi> </package> <package> + <name>haproxy-1_5</name> + <pkginfolink>https://doc.pfsense.org/index.php/haproxy_package</pkginfolink> + <descr><![CDATA[The Reliable, High Performance TCP/HTTP(S) Load Balancer<br /> + This package implements the TCP, HTTP and HTTPS balancing features of haproxy.<br /> + Supports ACLs for smart backend switching.]]></descr> + <website>http://haproxy.1wt.eu/</website> + <category>Services</category> + <version>1.5.3 pkg v 0.23</version> + <status>Release</status> + <required_version>2.1</required_version> + <config_file>https://packages.pfsense.org/packages/config/haproxy1_5/haproxy.xml</config_file> + <configurationfile>haproxy.xml</configurationfile> + <depends_on_package_base_url>https://files.pfsense.org/packages/amd64/8/All/</depends_on_package_base_url> + <depends_on_package>haproxy-1.4.22.tbz</depends_on_package> + <depends_on_package_pbi>haproxy-devel-1.5.3-amd64.pbi</depends_on_package_pbi> + <build_port_path>/usr/ports/net/haproxy-devel</build_port_path> + <build_pbi> + <ports_before>security/openssl</ports_before> + <custom_name>haproxy-devel</custom_name> + <port>/usr/ports/net/haproxy-devel</port> + </build_pbi> + <build_options>WITH_OPENSSL_PORT=yes;OPTIONS_UNSET_FORCE=PCRE DPCRE;OPTIONS_SET=OPENSSL SPCRE</build_options> + </package> + <package> <name>haproxy-devel</name> <pkginfolink>https://doc.pfsense.org/index.php/haproxy_package</pkginfolink> <descr><![CDATA[The Reliable, High Performance TCP/HTTP(S) Load Balancer<br /> @@ -153,7 +177,7 @@ Supports ACLs for smart backend switching.]]></descr> <website>http://haproxy.1wt.eu/</website> <category>Services</category> - <version>1.5.3 pkg v 0.20</version> + <version>1.5.3 pkg v 0.23</version> <status>Release</status> <required_version>2.1</required_version> <config_file>https://packages.pfsense.org/packages/config/haproxy-devel/haproxy.xml</config_file> @@ -352,7 +376,7 @@ <ports_before>databases/redis databases/gdbm net/GeoIP x11-fonts/font-util x11-fonts/webfonts graphics/graphviz</ports_before> <port>net/ntopng</port> </build_pbi> - <version>1.1 v0.3</version> + <version>1.1 v0.5</version> <status>ALPHA</status> <required_version>2.1.4</required_version> <config_file>https://packages.pfsense.org/packages/config/ntopng/ntopng.xml</config_file> @@ -394,7 +418,7 @@ <pkginfolink>https://doc.pfsense.org/index.php/PHPService</pkginfolink> <config_file>https://packages.pfsense.org/packages/config/phpservice/phpservice.xml</config_file> <depends_on_package_base_url>https://files.pfsense.org/packages/amd64/8/All/</depends_on_package_base_url> - <version>0.4.1</version> + <version>0.4.2</version> <status>Beta</status> <required_version>1.2.1</required_version> <maintainer>markjcrane@gmail.com</maintainer> @@ -449,14 +473,14 @@ <descr>Snort is an open source network intrusion prevention and detection system (IDS/IPS). Combining the benefits of signature, protocol, and anomaly-based inspection.</descr> <category>Security</category> <depends_on_package_base_url>https://files.pfsense.org/packages/amd64/8/All/</depends_on_package_base_url> - <depends_on_package_pbi>snort-2.9.7.0-amd64.pbi</depends_on_package_pbi> + <depends_on_package_pbi>snort-2.9.7.2-amd64.pbi</depends_on_package_pbi> <build_pbi> <port>security/snort</port> <ports_after>security/barnyard2</ports_after> </build_pbi> <build_options>barnyard2_UNSET=ODBC PGSQL PRELUDE;barnyard2_SET=GRE IPV6 MPLS MYSQL PORT_PCAP BRO;snort_SET=PERFPROFILE SOURCEFIRE GRE IPV6 NORMALIZER APPID;snort_UNSET=PULLEDPORK FILEINSPECT HA;perl_SET=THREADS</build_options> <config_file>https://packages.pfsense.org/packages/config/snort/snort.xml</config_file> - <version>2.9.7.0 pkg v3.2.3</version> + <version>2.9.7.2 pkg v3.2.4</version> <required_version>2.1</required_version> <status>Stable</status> <configurationfile>/snort.xml</configurationfile> @@ -600,7 +624,7 @@ <depends_on_package_pbi>siproxd-0.8.0-amd64.pbi</depends_on_package_pbi> <pkginfolink>https://doc.pfsense.org/index.php/Siproxd_package</pkginfolink> <build_port_path>/usr/ports/net/siproxd</build_port_path> - <version>0.8.0_2 pkg v1.0.2</version> + <version>0.8.0_1 pkg v1.0.3</version> <status>Beta</status> <required_version>1.2.1</required_version> <configurationfile>siproxd.xml</configurationfile> @@ -1004,7 +1028,7 @@ On pfSense docs there is a how-to which could help you on porting users.]]></descr> <pkginfolink>https://doc.pfsense.org/index.php/FreeRADIUS_2.x_package</pkginfolink> <category>System</category> - <version>2.1.12_1/2.2.5_3 pkg v1.6.10</version> + <version>2.2.5_3 pkg v1.6.11</version> <status>RC1</status> <required_version>2.1</required_version> <maintainer>nachtfalkeaw@web.de</maintainer> @@ -1364,7 +1388,7 @@ <depends_on_package_pbi>zip-3.0-amd64.pbi p7zip-9.20.1-amd64.pbi</depends_on_package_pbi> <build_port_path>/usr/ports/archivers/p7zip</build_port_path> <build_port_path>/usr/ports/archivers/zip</build_port_path> - <version>1.2.15</version> + <version>1.2.16</version> <status>RELEASE</status> <required_version>2.0</required_version> <config_file>https://packages.pfsense.org/packages/config/openvpn-client-export/openvpn-client-export.xml</config_file> @@ -1593,7 +1617,7 @@ <name>Quagga OSPF</name> <descr>OSPF routing protocol using Quagga -- WARNING! Installs files to the same place as OpenBGPD. Installing both will break things.</descr> <maintainer>jimp@pfsense.org</maintainer> - <version>0.99.22.3 v0.6.4</version> + <version>0.99.22.3 v0.6.5</version> <category>Routing</category> <status>BETA</status> <depends_on_package_base_url>https://files.pfsense.org/packages/amd64/8/All/</depends_on_package_base_url> @@ -1846,7 +1870,7 @@ <descr>Set of programs for controlling APC UPS.</descr> <category>Services</category> <config_file>https://packages.pfsense.org/packages/config/apcupsd/apcupsd.xml</config_file> - <version>apcupsd-3.14.10_1 pkg v0.3.3</version> + <version>apcupsd-3.14.10_1 pkg v0.3.4</version> <status>BETA</status> <required_version>2.0</required_version> <configurationfile>apcupsd.xml</configurationfile> |