From b07bce1a7b918ade438851b60a25372abdef7908 Mon Sep 17 00:00:00 2001 From: PiBa-NL Date: Sun, 16 Feb 2014 21:04:47 +0100 Subject: haproxy-devel, integrated stats page with stick-table info WebGUI --- config/haproxy-devel/haproxy.inc | 15 ++ config/haproxy-devel/haproxy.xml | 10 + config/haproxy-devel/haproxy_global.php | 25 ++- config/haproxy-devel/haproxy_listeners.php | 8 +- config/haproxy-devel/haproxy_listeners_edit.php | 8 +- config/haproxy-devel/haproxy_pool_edit.php | 8 +- config/haproxy-devel/haproxy_pools.php | 8 +- config/haproxy-devel/haproxy_socketinfo.inc | 25 ++- config/haproxy-devel/haproxy_stats.php | 256 ++++++++++++++++++++++++ config/haproxy-devel/pkg_haproxy_tabs.inc | 25 +++ 10 files changed, 356 insertions(+), 32 deletions(-) create mode 100644 config/haproxy-devel/haproxy_stats.php create mode 100644 config/haproxy-devel/pkg_haproxy_tabs.inc (limited to 'config/haproxy-devel') diff --git a/config/haproxy-devel/haproxy.inc b/config/haproxy-devel/haproxy.inc index 5e798dc2..bcadcfd9 100644 --- a/config/haproxy-devel/haproxy.inc +++ b/config/haproxy-devel/haproxy.inc @@ -627,6 +627,21 @@ function haproxy_writeconf($configpath) { } } fwrite ($fd, "\n"); + + $localstatsport = $a_global['localstatsport']; + if ($localstatsport){ + fwrite ($fd, "listen HAProxyLocalStats\n"); + fwrite ($fd, "\tbind 127.0.0.1:$localstatsport\n"); + fwrite ($fd, "\tmode http\n"); + fwrite ($fd, "\tstats enable\n"); + fwrite ($fd, "\tstats refresh 10\n"); + fwrite ($fd, "\tstats admin if TRUE\n"); + fwrite ($fd, "\tstats uri /haproxy_stats.php?haproxystats=1\n"); + fwrite ($fd, "\ttimeout client 5000\n"); + fwrite ($fd, "\ttimeout connect 5000\n"); + fwrite ($fd, "\ttimeout server 5000\n"); + fwrite ($fd, "\n"); + } } // Try and get a unique array for address:port as frontends can duplicate diff --git a/config/haproxy-devel/haproxy.xml b/config/haproxy-devel/haproxy.xml index 6b25dd46..bbc32575 100644 --- a/config/haproxy-devel/haproxy.xml +++ b/config/haproxy-devel/haproxy.xml @@ -89,6 +89,11 @@ 077 http://www.pfsense.com/packages/config/haproxy-devel/haproxy_pool_edit.php + + /usr/local/www/ + 077 + http://www.pfsense.com/packages/config/haproxy-devel/haproxy_stats.php + /usr/local/pkg/ 077 @@ -119,6 +124,11 @@ 0755 http://www.pfsense.org/packages/config/haproxy-devel/pkg_haproxy.inc + + /usr/local/pkg/ + 077 + http://www.pfsense.com/packages/config/haproxy-devel/pkg_haproxy_tabs.inc + diff --git a/config/haproxy-devel/haproxy_global.php b/config/haproxy-devel/haproxy_global.php index 0a92cde7..8264558f 100755 --- a/config/haproxy-devel/haproxy_global.php +++ b/config/haproxy-devel/haproxy_global.php @@ -34,6 +34,7 @@ require_once("guiconfig.inc"); require_once("haproxy.inc"); require_once("haproxy_utils.inc"); require_once("globals.inc"); +require_once("pkg_haproxy_tabs.inc"); if (!is_array($config['installedpackages']['haproxy'])) $config['installedpackages']['haproxy'] = array(); @@ -65,6 +66,9 @@ if ($_POST) { 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."; /*if($_POST['synchost1'] && !is_ipaddr($_POST['synchost1'])) $input_errors[] = "Synchost1 needs to be an IPAddress."; @@ -86,6 +90,7 @@ if ($_POST) { $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; touch($d_haproxyconfdirty_path); @@ -106,6 +111,7 @@ $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']; @@ -148,12 +154,7 @@ function enable_change(enable_change) { @@ -338,6 +339,18 @@ function enable_change(enable_change) {   + + + + + + + diff --git a/config/haproxy-devel/haproxy_listeners.php b/config/haproxy-devel/haproxy_listeners.php index 3ff53cea..2a1f12e6 100644 --- a/config/haproxy-devel/haproxy_listeners.php +++ b/config/haproxy-devel/haproxy_listeners.php @@ -34,6 +34,7 @@ require_once("guiconfig.inc"); 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(); @@ -91,12 +92,7 @@ include("head.inc");
Stats tab, 'internal' stats port
Internal stats port + size="10" maxlength="5" /> EXAMPLE: 2200
+ 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. +
Global Advanced pass thru
diff --git a/config/haproxy-devel/haproxy_listeners_edit.php b/config/haproxy-devel/haproxy_listeners_edit.php index 3c62ec3a..bd0f93d5 100644 --- a/config/haproxy-devel/haproxy_listeners_edit.php +++ b/config/haproxy-devel/haproxy_listeners_edit.php @@ -34,6 +34,7 @@ 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")) { @@ -373,12 +374,7 @@ $interfaces = haproxy_get_bindable_interfaces();
diff --git a/config/haproxy-devel/haproxy_pool_edit.php b/config/haproxy-devel/haproxy_pool_edit.php index 93fa20dc..4eb280ca 100644 --- a/config/haproxy-devel/haproxy_pool_edit.php +++ b/config/haproxy-devel/haproxy_pool_edit.php @@ -34,6 +34,7 @@ require("guiconfig.inc"); require_once("haproxy.inc"); require_once("haproxy_utils.inc"); require_once("haproxy_htmllist.inc"); +require_once("pkg_haproxy_tabs.inc"); $d_haproxyconfdirty_path = $g['varrun_path'] . "/haproxy.conf.dirty"; @@ -325,12 +326,7 @@ foreach($simplefields as $field){
diff --git a/config/haproxy-devel/haproxy_pools.php b/config/haproxy-devel/haproxy_pools.php index 39009633..01655006 100644 --- a/config/haproxy-devel/haproxy_pools.php +++ b/config/haproxy-devel/haproxy_pools.php @@ -32,6 +32,7 @@ $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'])) { @@ -86,12 +87,7 @@ include("head.inc");
diff --git a/config/haproxy-devel/haproxy_socketinfo.inc b/config/haproxy-devel/haproxy_socketinfo.inc index eeaba8b6..5c6e847d 100644 --- a/config/haproxy-devel/haproxy_socketinfo.inc +++ b/config/haproxy-devel/haproxy_socketinfo.inc @@ -57,15 +57,36 @@ function haproxy_set_server_enabled($backend, $server, $enable) {//"enable be/se return haproxy_socket_command("$enablecommand server $backend/$server"); } +function haproxy_get_tables(){// "show table" + $result = array(); + $cmdresult = haproxy_socket_command("show table"); + foreach($cmdresult as $line) { + if (trim($line) == "") + continue; + list($table,$type,$size,$used) = explode(",", $line); + $table = explode(":", $table); + $type = explode(":", $type); + $size = explode(":", $size); + $used = explode(":", $used); + $newtable = array(); + $tablename = trim($table[1]); + $newtable['type'] = trim($type[1]); + $newtable['size'] = $size[1]; + $newtable['used'] = $used[1]; + $result[$tablename] = $newtable; + } + return $result; +} + function haproxy_get_statistics(){// "show stat" $result = array(); $frontends=array(); $backends=array(); $servers=array(); - $result = haproxy_socket_command("show stat"); + $cmdresult = haproxy_socket_command("show stat"); - foreach($result as $line) { + foreach($cmdresult as $line) { list($pxname,$svname,$qcur,$qmax,$scur,$smax,$slim,$stot,$bin,$bout,$dreq,$dresp,$ereq,$econ,$eresp,$wretr,$wredis,$status,$weight,$act,$bck,$chkfail,$chkdown,$lastchg,$downtime,$qlimit,$pid,$iid,$sid,$throttle,$lbtot,$tracked,$type,$rate,$rate_lim,$rate_max,$check_status,$check_code,$check_duration,$hrsp_1xx,$hrsp_2xx,$hrsp_3xx,$hrsp_4xx,$hrsp_5xx,$hrsp_other,$hanafail,$req_rate,$req_rate_max,$req_tot,$cli_abrt,$srv_abrt,$comp_in,$comp_out,$comp_byp,$comp_rsp) = explode(",", $line); #Retrieve data switch ($svname) { diff --git a/config/haproxy-devel/haproxy_stats.php b/config/haproxy-devel/haproxy_stats.php new file mode 100644 index 00000000..8ad04c92 --- /dev/null +++ b/config/haproxy-devel/haproxy_stats.php @@ -0,0 +1,256 @@ + $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 = "

Make sure HAProxy settings are applied and HAProxy is enabled and running"; + echo $response; + exit(0); +} +require_once("guiconfig.inc"); +if (isset($_GET['showsticktablecontent'])){ + header("Refresh: 2"); +} +$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["port"] = "444"; + $frontend["extaddr"] = "lan_ipv4"; + $frontend["ssloffload"] = "yes"; + $frontend["ssloffloadcert"] = $webcert['refid']; + $frontend["backend_serverpool"] = $backend["name"]; + $a_frontends[] = $frontend; + $changecount++; + $changedesc = "add new HAProxy stats example"; + + if ($changecount > 0) { + echo "touching: $d_haproxyconfdirty_path"; + touch($d_haproxyconfdirty_path); + write_config($changedesc); + } +} + +if (isset($_GET['add_stats_example'])) { + haproxy_add_stats_example(); + write_config(); + touch($d_haproxyconfdirty_path); + header("Location: haproxy_listeners.php"); + exit; +} + +if ($_POST) { + if ($_POST['apply']) { + $result = haproxy_check_and_run($savemsg, true); + if ($result) + unlink_if_exists($d_haproxyconfdirty_path); + } +} + +$pfSversion = str_replace("\n", "", file_get_contents("/etc/version")); +if(strstr($pfSversion, "1.2")) + $one_two = true; + +$pgtitle = "Services: HAProxy: Stats"; +include("head.inc"); + +?> + + + + +

+ + + + +You must apply the changes in order for them to take effect.");?>
+ + +
+ + + + +
+ +
+
+ + + "; + echo "TESTJe
"; + $res = haproxy_socket_command("show table $sticktablename"); + foreach($res as $line){ + echo "
".print_r($line,true); + } +echo ""; +} else { +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ This page contains a 'stats' page available from haproxy accessible through the pfSense gui.
+
+ As the page is forwarded through the pfSense gui, this might cause some functionality to not work.
+ Though the normal haproxy stats page can be tweaked more, and doesn't use a user/pass from pfSense itself.
+ Some examples are configurable automatic page refresh,
+ only showing certain servers, not providing admin options, and can be accessed from wherever the associated frontend is accessible.(as long as rules permit access)
+ 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'. + Or create a backend specifically for serving stats, for that you can start with the 'stats example' template below.
+
 
Stats example template
Example + 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.
+ TEMPLATE: Create stats example configuration using a frontend/backend combination with ssl
+
+ After applying the changes made by the template use this link to visit the stats page: :444">https://pfSense-LAN-ip:444/ +
 
HAProxy stick-tables
+ 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) { ?> + + + + + + + +
Stick-tableTypeSizeUsed
+
 
HAProxy stats
Fullscreen stats page
+ + + +
+ In the "Settings" configure a internal stats port and enable haproxy for this to be functional.
+
+ + +
+
+
+ + + diff --git a/config/haproxy-devel/pkg_haproxy_tabs.inc b/config/haproxy-devel/pkg_haproxy_tabs.inc new file mode 100644 index 00000000..8cb280f8 --- /dev/null +++ b/config/haproxy-devel/pkg_haproxy_tabs.inc @@ -0,0 +1,25 @@ + "Settings", url => "haproxy_global.php"); +$haproxy_tab_array['haproxy']['frontend'] = Array(name => "Frontend", url => "haproxy_listeners.php"); +$haproxy_tab_array['haproxy']['backend'] = Array(name => "Backend", url => "haproxy_pools.php"); +$haproxy_tab_array['haproxy']['stats'] = Array(name => "Stats", url => "haproxy_stats.php"); + +function haproxy_display_top_tabs_active($top_tabs, $activetab) { + $tab_array = array(); + foreach($top_tabs as $key => $tab_item){ + $tab_array[] = array($tab_item['name'], $key == $activetab, $tab_item['url']); + } + display_top_tabs($tab_array); +} + +?> -- cgit v1.2.3 From 46ea54e1b550fcac78752b70f3419a0bf1eb7ec4 Mon Sep 17 00:00:00 2001 From: PiBa-NL Date: Sun, 16 Feb 2014 21:26:05 +0100 Subject: haproxy-devel, add missing function haproxy_find_create_certificate(..) --- config/haproxy-devel/haproxy.inc | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'config/haproxy-devel') diff --git a/config/haproxy-devel/haproxy.inc b/config/haproxy-devel/haproxy.inc index bcadcfd9..20f6847c 100644 --- a/config/haproxy-devel/haproxy.inc +++ b/config/haproxy-devel/haproxy.inc @@ -1233,4 +1233,25 @@ function haproxy_escape_acl_name($aclname) { return preg_replace_callback('([^A-Za-z0-9\._\-\:])', function($match){return "_".dechex(ord($match[0]));}, $aclname); } +function haproxy_find_create_certificate($certificatename) { + global $g; + $cert = lookup_cert_by_name($certificatename); + if (is_array($cert)) + return $cert; + global $config; + $a_cert =& $config['cert']; + $cert = array(); + $cert['refid'] = uniqid(); + $cert['descr'] = gettext($certificatename); + mwexec("/usr/local/bin/openssl genrsa 1024 > {$g['tmp_path']}/ssl.key"); + mwexec("/usr/local/bin/openssl req -new -x509 -nodes -sha256 -days 2000 -key {$g['tmp_path']}/ssl.key > {$g['tmp_path']}/ssl.crt"); + $crt = file_get_contents("{$g['tmp_path']}/ssl.crt"); + $key = file_get_contents("{$g['tmp_path']}/ssl.key"); + unlink("{$g['tmp_path']}/ssl.key"); + unlink("{$g['tmp_path']}/ssl.crt"); + cert_import($cert, $crt, $key); + $a_cert[] = $cert; + return $cert; +} + ?> -- cgit v1.2.3