From 68f850e299f234fa0837467a4a0eb31b9c1f97b9 Mon Sep 17 00:00:00 2001 From: Marcello Coutinho Date: Tue, 3 Dec 2013 03:08:55 -0200 Subject: haproxy-full - move sync to its own tab, add sync to configured backup server change some fields position add shortcut info to haproxy on pfsense 2.1 --- config/haproxy-legacy/haproxy.inc | 121 ++++++++--- config/haproxy-legacy/haproxy.xml | 10 + config/haproxy-legacy/haproxy_frontends.php | 3 +- config/haproxy-legacy/haproxy_frontends_edit.php | 247 +++++++++++++---------- config/haproxy-legacy/haproxy_global.php | 74 +------ config/haproxy-legacy/haproxy_servers.php | 3 +- config/haproxy-legacy/haproxy_servers_edit.php | 39 +++- config/haproxy-legacy/haproxy_sync.xml | 146 ++++++++++++++ config/haproxy-legacy/pkg_haproxy.inc | 11 + 9 files changed, 439 insertions(+), 215 deletions(-) create mode 100644 config/haproxy-legacy/haproxy_sync.xml create mode 100755 config/haproxy-legacy/pkg_haproxy.inc (limited to 'config/haproxy-legacy') diff --git a/config/haproxy-legacy/haproxy.inc b/config/haproxy-legacy/haproxy.inc index dfbec28c..47dc5474 100644 --- a/config/haproxy-legacy/haproxy.inc +++ b/config/haproxy-legacy/haproxy.inc @@ -1,6 +1,7 @@ Copyright (C) 2008 Remco Hoef All rights reserved. @@ -28,6 +29,7 @@ */ /* include all configuration functions */ +$shortcut_section = "haproxy"; require_once("functions.inc"); require_once("pkg-utils.inc"); require_once("notices.inc"); @@ -40,6 +42,31 @@ function haproxy_custom_php_deinstall_command() { exec("rm /usr/local/www/haproxy*"); } +function migrate_old_sync_config(){ + global $g, $config; + //move Sync HAProxy configuration (if enabled) + $write_config=0; + if(is_array($config['installedpackages']['haproxy'])){ + $haproxy_cfg=$config['installedpackages']['haproxy']; + if (isset($haproxy_cfg['enablesync'])) { + for($si=1;$si<=3;$si++){ + if($haproxy_cfg['synchost'.$si]) { + $config['installedpackages']['haproxysync']['config'][0]['row'][]=array('enabless'=>'ON', + 'ipaddress'=>$haproxy_cfg['synchost'.$si], + 'username'=> 'admin', + 'password'=> $haproxy_cfg['syncpassword']); + unset($config['installedpackages']['haproxy']['synchost'.$si]); + $write_config++; + } + } + } + } + if ($write_config > 0){ + unset($config['installedpackages']['haproxy']['enablesync']); + unset($config['installedpackages']['haproxy']['syncpassword']); + write_config("Haproxy - Migrate old sync config from global to sync tab."); + } +} function haproxy_custom_php_install_command() { global $g, $config; conf_mount_rw(); @@ -90,7 +117,7 @@ EOD; fwrite($fd, $haproxy); fclose($fd); exec("chmod a+rx /usr/local/etc/rc.d/haproxy.sh"); - + migrate_old_sync_config(); conf_mount_ro(); exec("/usr/local/etc/rc.d/haproxy.sh start"); @@ -274,26 +301,11 @@ function haproxy_configure() { } fwrite ($fd, "\n"); } - // Sync HAProxy configuration (if enabled) - if(isset($config['installedpackages']['haproxy']['enablesync'])) { - if($config['installedpackages']['haproxy']['synchost1']) { - haproxy_do_xmlrpc_sync($config['installedpackages']['haproxy']['synchost1'], - $config['installedpackages']['haproxy']['syncpassword']); - } - if($config['installedpackages']['haproxy']['synchost2']) { - haproxy_do_xmlrpc_sync($config['installedpackages']['haproxy']['synchost2'], - $config['installedpackages']['haproxy']['syncpassword']); - } - if($config['installedpackages']['haproxy']['synchost3']) { - haproxy_do_xmlrpc_sync($config['installedpackages']['haproxy']['synchost3'], - $config['installedpackages']['haproxy']['syncpassword']); - } - } } // create config file fclose($fd); - + $freebsd_version = substr(trim(`uname -r`), 0, 1); if(!file_exists("/usr/bin/limits")) { exec("fetch -q -o /usr/bin/limits http://files.pfsense.org/extras/{$freebsd_version}/limits"); @@ -301,7 +313,7 @@ function haproxy_configure() { } exec("/usr/bin/limits -n 300014"); - + // reload haproxy if(isset($a_global['enable'])) { if(is_process_running('haproxy')) { @@ -309,13 +321,69 @@ function haproxy_configure() { } else { exec("/usr/local/sbin/haproxy -f /var/etc/haproxy.cfg -p /var/run/haproxy.pid -D"); } + haproxy_sync_on_changes(); return (0); } else { + haproxy_sync_on_changes(); return (1); } } -function haproxy_do_xmlrpc_sync($sync_to_ip, $password) { +/* Uses XMLRPC to synchronize the changes to a remote node */ +function haproxy_sync_on_changes() { + global $config, $g; + if (is_array($config['installedpackages']['haproxysync']['config'])){ + $haproxy_sync=$config['installedpackages']['haproxysync']['config'][0]; + $synctimeout = $haproxy_sync['synctimeout']; + $synconchanges = $haproxy_sync['synconchanges']; + switch ($synconchanges){ + case "manual": + if (is_array($haproxy_sync['row'])){ + $rs=$haproxy_sync['row']; + } + else{ + log_error("[haproxy] xmlrpc sync is enabled but there is no hosts to push haproxy config."); + return; + } + break; + case "auto": + if (is_array($config['installedpackages']['carpsettings']) && is_array($config['installedpackages']['carpsettings']['config'])){ + $system_carp=$config['installedpackages']['carpsettings']['config'][0]; + $rs[0]['ipaddress']=$system_carp['synchronizetoip']; + $rs[0]['username']=$system_carp['username']; + $rs[0]['password']=$system_carp['password']; + $rs[0]['enabless']=true; + if (! is_ipaddr($system_carp['synchronizetoip'])){ + log_error("[haproxy] xmlrpc sync is enabled but there is no system backup hosts to push haproxy config."); + return; + } + } + else{ + log_error("[haproxy] xmlrpc sync is enabled but there is no system backup hosts to push haproxy config."); + return; + } + break; + default: + return; + break; + } + if (is_array($rs)){ + log_error("[haproxy] xmlrpc sync is starting."); + foreach($rs as $sh){ + $sync_to_ip = $sh['ipaddress']; + if($sh['username']) + $username = $sh['username']; + else + $username = 'admin'; + if($sh['password'] && $sh['ipaddress'] && $sh['enabless']) + haproxy_do_xmlrpc_sync($sh['ipaddress'], $username, $sh['password'],$synctimeout); + } + log_error("[haproxy] xmlrpc sync is ending."); + } + } +} + +function haproxy_do_xmlrpc_sync($sync_to_ip, $username="admin", $password,$synctimeout="30") { global $config, $g; if(!$password) @@ -323,6 +391,7 @@ function haproxy_do_xmlrpc_sync($sync_to_ip, $password) { if(!$sync_to_ip) return; + // Do not allow syncing to self. $donotsync = false; @@ -379,18 +448,18 @@ function haproxy_do_xmlrpc_sync($sync_to_ip, $password) { $method = 'pfsense.merge_installedpackages_section_xmlrpc'; $msg = new XML_RPC_Message($method, $params); $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port); - $cli->setCredentials('admin', $password); + $cli->setCredentials($username, $password); if($g['debug']) $cli->setDebug(1); - /* send our XMLRPC message and timeout after 250 seconds */ - $resp = $cli->send($msg, "250"); + /* send our XMLRPC message and timeout after $synctimeout seconds */ + $resp = $cli->send($msg, $synctimeout); if(!$resp) { $error = "A communications error occurred while attempting HAProxy XMLRPC sync with {$url}:{$port}."; log_error($error); file_notice("sync_settings", $error, "HAProxy Settings Sync", ""); } elseif($resp->faultCode()) { $cli->setDebug(1); - $resp = $cli->send($msg, "250"); + $resp = $cli->send($msg, $synctimeout); $error = "An error code was received while attempting HAProxy XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); log_error($error); file_notice("sync_settings", $error, "HAProxy Settings Sync", ""); @@ -412,15 +481,15 @@ function haproxy_do_xmlrpc_sync($sync_to_ip, $password) { log_error("HAProxy XMLRPC reload data {$url}:{$port}."); $msg = new XML_RPC_Message($method, $params); $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port); - $cli->setCredentials('admin', $password); - $resp = $cli->send($msg, "250"); + $cli->setCredentials($username, $password); + $resp = $cli->send($msg, $synctimeout); if(!$resp) { $error = "A communications error occurred while attempting HAProxy XMLRPC sync with {$url}:{$port} (pfsense.exec_php)."; log_error($error); file_notice("sync_settings", $error, "HAProxy Settings Reload", ""); } elseif($resp->faultCode()) { $cli->setDebug(1); - $resp = $cli->send($msg, "250"); + $resp = $cli->send($msg, $synctimeout); $error = "An error code was received while attempting HAProxy XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); log_error($error); file_notice("sync_settings", $error, "HAProxy Settings Sync", ""); diff --git a/config/haproxy-legacy/haproxy.xml b/config/haproxy-legacy/haproxy.xml index 556a1178..33b1913d 100644 --- a/config/haproxy-legacy/haproxy.xml +++ b/config/haproxy-legacy/haproxy.xml @@ -64,6 +64,11 @@ 077 http://www.pfsense.com/packages/config/haproxy-legacy/haproxy.inc + + /usr/local/pkg/ + 077 + http://www.pfsense.com/packages/config/haproxy-legacy/haproxy_sync.inc + /usr/local/www/ 077 @@ -89,6 +94,11 @@ 077 http://www.pfsense.com/packages/config/haproxy-legacy/haproxy_servers_edit.php + + /usr/local/www/shortcuts/ + 0755 + http://www.pfsense.org/packages/config/haproxy-legacy/pkg_haproxy.inc + diff --git a/config/haproxy-legacy/haproxy_frontends.php b/config/haproxy-legacy/haproxy_frontends.php index d50133b8..e97fbc7b 100755 --- a/config/haproxy-legacy/haproxy_frontends.php +++ b/config/haproxy-legacy/haproxy_frontends.php @@ -28,7 +28,7 @@ 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"); $d_haproxyconfdirty_path = $g['varrun_path'] . "/haproxy.conf.dirty"; @@ -92,6 +92,7 @@ include("head.inc"); $tab_array[] = array("Settings", false, "haproxy_global.php"); $tab_array[] = array("Frontends", true, "haproxy_frontends.php"); $tab_array[] = array("Servers", false, "haproxy_servers.php"); + $tab_array[] = array("Sync", false, "pkg_edit.php?xml=haproxy_sync.xml"); display_top_tabs($tab_array); ?> diff --git a/config/haproxy-legacy/haproxy_frontends_edit.php b/config/haproxy-legacy/haproxy_frontends_edit.php index 548cf612..99391fe9 100755 --- a/config/haproxy-legacy/haproxy_frontends_edit.php +++ b/config/haproxy-legacy/haproxy_frontends_edit.php @@ -3,6 +3,7 @@ /* haproxy_frontends_edit.php part of pfSense (http://www.pfsense.com/) + Copyright (C) 2013 Marcello Coutinho Copyright (C) 2009 Scott Ullrich Copyright (C) 2008 Remco Hoef All rights reserved. @@ -28,7 +29,7 @@ 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"); $d_haproxyconfdirty_path = $g['varrun_path'] . "/haproxy.conf.dirty"; @@ -113,12 +114,14 @@ if ($_POST) { if (!$_POST['retries'] && is_numeric($_POST['retries'])) $input_errors[] = "The field 'Retries' value is not a number."; + + if ($_POST['stats_enabled'] == "yes"){ + if (preg_match("/[^a-zA-Z0-9\.\-_]/", $_POST['stats_username'])) + $input_errors[] = "The field 'Stats Username' contains invalid characters."; - if (preg_match("/[^a-zA-Z0-9\.\-_]/", $_POST['stats_username'])) - $input_errors[] = "The field 'Stats Username' contains invalid characters."; - - 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_password'])) + $input_errors[] = "The field 'Stats Password' contains invalid characters."; + } if (!is_numeric($_POST['max_connections'])) $input_errors[] = "The field 'Max connections' value is not a number."; @@ -391,7 +394,21 @@ include("head.inc");

- +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -530,14 +622,14 @@ set by the 'retries' parameter (2).> > @@ -565,7 +657,7 @@ set by the 'retries' parameter (2).> @@ -577,56 +669,7 @@ set by the 'retries' parameter (2). Example: / or /index.php or /index.html or /testmypage.cgi - - - - - - - - - - - - - - - - - + @@ -679,30 +722,12 @@ set by the 'retries' parameter (2). */ ?> - - - - - - - - - - - + + + + @@ -718,12 +743,14 @@ set by the 'retries' parameter (2). -
 
+
+ +
+
+ @@ -407,30 +424,6 @@ include("head.inc"); size="64"> - - - - - - - - - - - - - + + + + + + + + + +
Edit haproxy backend
Connection timeout - size="64"> -
the time (in milliseconds) we give up if the connection does not complete within (30000).
-
Server timeout - size="64"> -
the time (in milliseconds) we accept to wait for data from the server, or for the server to accept data (30000).
-
Retries - size="64"> -
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 (2).
-
Type @@ -441,7 +434,43 @@ set by the 'retries' parameter (2).
Port + size="6" maxlength="500"> +
The port to listen to. To specify multiple ports, separate with a comma (,). EXAMPLE: 80,443
+
Listen address + +
+ + 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 Virtual IP addresses on the first). + Also note that if you are trying to redirect connections on the LAN select the "any" option.
+ While using carp, select localhost and forward via NAT. +
+
Balance @@ -506,6 +535,69 @@ set by the 'retries' parameter (2).
Use 'forwardfor' option + > +
+ 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) +
Use 'httpclose' option + > +
+ The 'httpclose' option removes any 'Connection' header both ways, and + adds a 'Connection: close' header in each direction. This makes it easier to + disable HTTP keep-alive than the previous 4-rules block. +
Connection limits
Connection timeout + size="64"> +
the time (in milliseconds) we give up if the connection does not complete within (30000).
+
Server timeout + size="64"> +
the time (in milliseconds) we accept to wait for data from the server, or for the server to accept data (30000).
+
Retries + size="6"> +
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 (2).
+
Max connections + size="10" maxlength="10"> +
Client timeout + size="10" maxlength="10"> +
the time (in milliseconds) we accept to wait for data from the client, or for the client to accept data (30000).
+
Backend stats
Stats Enabled
Stats Username - size="64"> + size="25">
Stats Password - size="64"> + size="25">
Stats Refresh - size="10" maxlength="30">
+ size="6" maxlength="30">
Specify the refresh rate of the stats page in seconds, or specified time unit (us, ms, s, m, h, d).
Port - size="30" maxlength="500"> -
The port to listen to. To specify multiple ports, separate with a comma (,). EXAMPLE: 80,443
-
External address - -
- - 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 Virtual IP addresses on the first). - Also note that if you are trying to redirect connections on the LAN select the "any" option.
- While using carp, select localhost and forward via NAT. -
-
Max connections - size="10" maxlength="10"> -
Client timeout - size="10" maxlength="10"> -
the time (in milliseconds) we accept to wait for data from the client, or for the client to accept data (30000).
-
Use 'forwardfor' option - > -
- 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) -
Use 'httpclose' option - > -
- The 'httpclose' option removes any 'Connection' header both ways, and - adds a 'Connection: close' header in each direction. This makes it easier to - disable HTTP keep-alive than the previous 4-rules block. -
Advanced pass thru - +
Advanced pass thru
+
NOTE: paste text into this box that you would like to pass thru.
NOTE: You must add a firewall rule permitting access to this frontend!
+ +