diff options
Diffstat (limited to 'config/haproxy1_5/www')
-rw-r--r-- | config/haproxy1_5/www/haproxy_files.php | 176 | ||||
-rw-r--r-- | config/haproxy1_5/www/haproxy_global.php | 500 | ||||
-rw-r--r-- | config/haproxy1_5/www/haproxy_listeners.php | 338 | ||||
-rw-r--r-- | config/haproxy1_5/www/haproxy_listeners_edit.php | 910 | ||||
-rw-r--r-- | config/haproxy1_5/www/haproxy_pool_edit.php | 1017 | ||||
-rw-r--r-- | config/haproxy1_5/www/haproxy_pools.php | 181 | ||||
-rw-r--r-- | config/haproxy1_5/www/haproxy_stats.php | 204 | ||||
-rw-r--r-- | config/haproxy1_5/www/haproxy_templates.php | 220 | ||||
-rw-r--r-- | config/haproxy1_5/www/javascript/haproxy_geturl.js | 43 | ||||
-rw-r--r-- | config/haproxy1_5/www/shortcuts/pkg_haproxy.inc | 11 | ||||
-rw-r--r-- | config/haproxy1_5/www/widgets/widgets/haproxy.widget.php | 282 |
11 files changed, 3882 insertions, 0 deletions
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 |