aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorthompsa <andy@fud.org.nz>2010-03-04 15:58:00 +1300
committerthompsa <andy@fud.org.nz>2010-03-04 15:58:00 +1300
commitc7c6a092ff24b9a988299545d791e8e020d84861 (patch)
tree0df1178d923bdc90ab9c65418b0b367c358c845c
parentc8509026e1d946817b93b7231d7b58dedcc3b33e (diff)
downloadpfsense-packages-c7c6a092ff24b9a988299545d791e8e020d84861.tar.gz
pfsense-packages-c7c6a092ff24b9a988299545d791e8e020d84861.tar.bz2
pfsense-packages-c7c6a092ff24b9a988299545d791e8e020d84861.zip
Merge the conflicting frontend bind addresses into one, allowing ACL
rules to choose the backend. Non-conflicting entries should not be affected.
-rw-r--r--config/haproxy-dev/haproxy.inc391
1 files changed, 230 insertions, 161 deletions
diff --git a/config/haproxy-dev/haproxy.inc b/config/haproxy-dev/haproxy.inc
index a799cd48..275ea8ab 100644
--- a/config/haproxy-dev/haproxy.inc
+++ b/config/haproxy-dev/haproxy.inc
@@ -58,44 +58,6 @@ $a_acltypes[] = array('name' => 'path_contains', 'descr' => 'Path contains',
$a_acltypes[] = array('name' => 'source_ip', 'descr' => 'Source IP',
'mode' => '', 'syntax' => 'src');
-function haproxy_find_acl($name) {
- global $a_acltypes;
-
- /* XXX why is this broken from xmlsync? */
- if (!$a_acltypes) {
- $a_acltypes = array();
- $a_acltypes[] = array('name' => 'host_starts_with', 'descr' => 'Host starts with',
- 'mode' => 'http', 'syntax' => 'hdr_beg(host) -i');
- $a_acltypes[] = array('name' => 'host_ends_with', 'descr' => 'Host ends with',
- 'mode' =>'http', 'syntax' => 'hdr_end(host) -i');
- $a_acltypes[] = array('name' => 'host_matches', 'descr' => 'Host matches',
- 'mode' =>'http', 'syntax' => 'hdr(host) -i');
- $a_acltypes[] = array('name' => 'host_regex', 'descr' => 'Host regex',
- 'mode' =>'http', 'syntax' => 'hdr_reg(host) -i');
- $a_acltypes[] = array('name' => 'host_contains', 'descr' => 'Host contains',
- 'mode' => 'http', 'syntax' => 'hdr_dir(host) -i');
- $a_acltypes[] = array('name' => 'path_starts_with', 'descr' => 'Path starts with',
- 'mode' => 'http', 'syntax' => 'path_beg -i');
- $a_acltypes[] = array('name' => 'path_ends_with', 'descr' => 'Path ends with',
- 'mode' => 'http', 'syntax' => 'path_end -i');
- $a_acltypes[] = array('name' => 'path_matches', 'descr' => 'Path matches',
- 'mode' => 'http', 'syntax' => 'path -i');
- $a_acltypes[] = array('name' => 'path_regex', 'descr' => 'Path regex',
- 'mode' => 'http', 'syntax' => 'path_reg -i');
- $a_acltypes[] = array('name' => 'path_contains', 'descr' => 'Path contains',
- 'mode' => 'http', 'syntax' => 'path_dir -i');
- $a_acltypes[] = array('name' => 'source_ip', 'descr' => 'Source IP',
- 'mode' => '', 'syntax' => 'src');
- }
-
- if($a_acltypes) {
- foreach ($a_acltypes as $acl) {
- if ($acl['name'] == $name)
- return $acl;
- }
- }
-}
-
function haproxy_custom_php_deinstall_command() {
exec("rm /usr/local/sbin/haproxy");
exec("rm /usr/local/pkg/haproxy.inc");
@@ -158,6 +120,131 @@ EOD;
exec("/usr/local/etc/rc.d/haproxy.sh start");
}
+function haproxy_find_acl($name) {
+ global $a_acltypes;
+
+ /* XXX why is this broken from xmlsync? */
+ if (!$a_acltypes) {
+ $a_acltypes = array();
+ $a_acltypes[] = array('name' => 'host_starts_with', 'descr' => 'Host starts with',
+ 'mode' => 'http', 'syntax' => 'hdr_beg(host) -i');
+ $a_acltypes[] = array('name' => 'host_ends_with', 'descr' => 'Host ends with',
+ 'mode' =>'http', 'syntax' => 'hdr_end(host) -i');
+ $a_acltypes[] = array('name' => 'host_matches', 'descr' => 'Host matches',
+ 'mode' =>'http', 'syntax' => 'hdr(host) -i');
+ $a_acltypes[] = array('name' => 'host_regex', 'descr' => 'Host regex',
+ 'mode' =>'http', 'syntax' => 'hdr_reg(host) -i');
+ $a_acltypes[] = array('name' => 'host_contains', 'descr' => 'Host contains',
+ 'mode' => 'http', 'syntax' => 'hdr_dir(host) -i');
+ $a_acltypes[] = array('name' => 'path_starts_with', 'descr' => 'Path starts with',
+ 'mode' => 'http', 'syntax' => 'path_beg -i');
+ $a_acltypes[] = array('name' => 'path_ends_with', 'descr' => 'Path ends with',
+ 'mode' => 'http', 'syntax' => 'path_end -i');
+ $a_acltypes[] = array('name' => 'path_matches', 'descr' => 'Path matches',
+ 'mode' => 'http', 'syntax' => 'path -i');
+ $a_acltypes[] = array('name' => 'path_regex', 'descr' => 'Path regex',
+ 'mode' => 'http', 'syntax' => 'path_reg -i');
+ $a_acltypes[] = array('name' => 'path_contains', 'descr' => 'Path contains',
+ 'mode' => 'http', 'syntax' => 'path_dir -i');
+ $a_acltypes[] = array('name' => 'source_ip', 'descr' => 'Source IP',
+ 'mode' => '', 'syntax' => 'src');
+ }
+
+ if($a_acltypes) {
+ foreach ($a_acltypes as $acl) {
+ if ($acl['name'] == $name)
+ return $acl;
+ }
+ }
+}
+
+function write_backend($fd, $name, $pool, $frontend) {
+ if($pool['status'] != 'active' || !is_array($pool['ha_servers']['item']))
+ continue;
+
+ fwrite ($fd, "backend " . $name . "\n");
+ if($pool['cookie_name'] && strtolower($frontend['type']) == "http")
+ fwrite ($fd, "\tcookie\t\t\t" . $pool['cookie_name'] . " insert indirect\n");
+
+ // https is an alias for tcp for clarity purpouses
+ if(strtolower($frontend['type']) == "https") {
+ $backend_type = "tcp";
+ $httpchk = "ssl-hello-chk";
+ } else {
+ $backend_type = $frontend['type'];
+ $httpchk = "httpchk";
+ }
+
+ fwrite ($fd, "\tmode\t\t\t" . $backend_type . "\n");
+
+ if($frontend['balance'])
+ fwrite ($fd, "\tbalance\t\t\t" . $frontend['balance'] . "\n");
+
+ if($frontend['connection_timeout'])
+ fwrite ($fd, "\tcontimeout\t\t" . $frontend['connection_timeout'] . "\n");
+
+ if($frontend['server_timeout'])
+ fwrite ($fd, "\tsrvtimeout\t\t" . $frontend['server_timeout'] . "\n");
+
+ if($frontend['retries'])
+ fwrite ($fd, "\tretries\t\t\t" . $frontend['retries'] . "\n");
+
+ if($frontend['stats_enabled']=='yes') {
+ fwrite ($fd, "\tstats\t\t\tenable\n");
+ if($frontend['stats_uri'])
+ fwrite ($fd, "\tstats\t\t\turi ".$frontend['stats_uri']."\n");
+ if($frontend['stats_realm'])
+ fwrite ($fd, "\tstats\t\t\trealm " . $frontend['stats_realm'] . "\n");
+ else
+ fwrite ($fd, "\tstats\t\t\trealm .\n");
+ fwrite ($fd, "\tstats\t\t\tauth " . $frontend['stats_username'].":". $frontend['stats_password']."\n");
+ }
+
+ $uri = $pool['monitor_uri'];
+ if ($pool['monitor_uri'])
+ $uri = $pool['monitor_uri'];
+ else
+ $uri = "/";
+ fwrite ($fd, "\toption\t\t\t{$httpchk} HEAD " . $uri . " HTTP/1.0\n");
+
+ if($pool['cookie'] && strtolower($frontend['type']) == "http")
+ $cookie = " cookie {$pool['cookie']} ";
+ else
+ $cookie = "";
+ if($pool['advanced']) {
+ $advanced = base64_decode($pool['advanced']);
+ $advanced_txt = " " . $advanced;
+ } else {
+ $advanced_txt = "";
+ }
+ if($pool['checkinter'])
+ $checkinter = "check inter {$pool['checkinter']}";
+ else
+ $checkinter = "check inter 1000";
+
+ $a_servers = &$pool['ha_servers']['item'];
+ foreach($a_servers as $be) {
+ if(!$be['port']) {
+ // the listener can specify a default port
+ $be['port'] = $frontend['svrport'];
+ }
+ if(!$be['port']) {
+ // last resort, use the frontend port
+ $ports = split(",", "{$frontend['port']},");
+ $be['port'] = $ports[0];
+ }
+ if (!$be['name'])
+ $be['name'] = $be['address'];
+ if($be['backup']) {
+ $isbackup = "backup";
+ } else {
+ $isbackup = "";
+ }
+ fwrite ($fd, "\tserver\t\t\t" . $be['name'] . " " . $be['address'].":" . $be['port'] . " $cookie " . " $checkinter $isbackup weight " . $be['weight'] . "{$advanced_txt}\n");
+ }
+ fwrite ($fd, "\n");
+}
+
function haproxy_configure() {
global $config, $g;
@@ -187,17 +274,52 @@ function haproxy_configure() {
fwrite ($fd, "\n");
}
- // Construct and write out configuration file
+ // Try and get a unique array for address:port as frontends can duplicate
+ $a_bind = array();
if(is_array($a_backends)) {
foreach ($a_backends as $backend) {
-
if($backend['status'] != 'active')
continue;
- // Define our backend name
- $backendinfo = "listen {$backend['name']}\n";
+ if(!$backend['pool'])
+ continue;
+
+ $bname = $backend['extaddr'] . ":" . $backend['port'];
+ if (!is_array($a_bind[$bname])) {
+ $a_bind[$bname] = array();
+ $a_bind[$bname]['config'] = array();
+ // Settings which are constant for a merged frontend
+ $a_bind[$bname]['name'] = $backend['name'];
+ $a_bind[$bname]['defaultpool'] = $backend['pool'] . "_" . strtolower($backend['type']);
+ $a_bind[$bname]['extaddr'] = $backend['extaddr'];
+ $a_bind[$bname]['port'] = $backend['port'];
+ }
+ $bind = &$a_bind[$bname];
+
+ // Overwrite ?
+ $bind['type'] = $backend['type'];
+ $bind['forwardfor'] = $backend['forwardfor'];
+ $bind['httpclose'] = $backend['httpclose'];
+ $bind['max_connections'] = $backend['max_connections'];
+ $bind['client_timeout'] = $backend['client_timeout'];
+ $bind['advanced'] = $backend['advanced'];
+
+ // pointer to each backend
+ $bind['config'][] = $backend;
+ }
+ }
+
+ $a_pendingpl = array();
+
+ // Construct and write out configuration file
+ if(is_array($a_bind)) {
+ foreach ($a_bind as $bind) {
+ if (count($bind['config']) > 1)
+ $frontendinfo = "frontend {$bind['name']}-merged\n";
+ else
+ $frontendinfo = "frontend {$bind['name']}\n";
// Prepare ports for processing by splitting
- $portss = "{$backend['port']},";
+ $portss = "{$bind['port']},";
$ports = split(",", $portss);
// Initialize variable
@@ -206,30 +328,30 @@ function haproxy_configure() {
// Process and add bind directives for ports
foreach($ports as $port) {
if($port) {
- if($backend['extaddr'] == "any")
+ if($bind['extaddr'] == "any")
$listenip .= "\tbind\t\t\t0.0.0.0:{$port}\n";
- elseif($backend['extaddr'])
- $listenip .= "\tbind\t\t\t{$backend['extaddr']}:{$port}\n";
+ elseif($bind['extaddr'])
+ $listenip .= "\tbind\t\t\t{$bind['extaddr']}:{$port}\n";
else
$listenip .= "\tbind\t\t\t" . get_current_wan_address('wan') . ":{$port}\n";
}
}
- fwrite ($fd, "{$backendinfo}");
+ fwrite ($fd, "{$frontendinfo}");
fwrite ($fd, "{$listenip}");
// Advanced pass thru
- if($backend['advanced']) {
- $advanced = base64_decode($backend['advanced']);
+ if($bind['advanced']) {
+ $advanced = base64_decode($bind['advanced']);
fwrite($fd, "\t" . $advanced . "\n");
}
// https is an alias for tcp for clarity purpouses
- if(strtolower($backend['type']) == "https") {
+ if(strtolower($bind['type']) == "https") {
$backend_type = "tcp";
$httpchk = "ssl-hello-chk";
} else {
- $backend_type = $backend['type'];
+ $backend_type = $bind['type'];
$httpchk = "httpchk";
}
@@ -237,134 +359,81 @@ function haproxy_configure() {
fwrite ($fd, "\tlog\t\t\tglobal\n");
fwrite ($fd, "\toption\t\t\tdontlognull\n");
- if($backend['httpclose'])
+ if($bind['httpclose'])
fwrite ($fd, "\toption\t\t\thttpclose\n");
- if($backend['forwardfor'])
+ if($bind['forwardfor'])
fwrite ($fd, "\toption\t\t\tforwardfor\n");
- if($backend['max_connections'])
- fwrite ($fd, "\tmaxconn\t\t\t" . $backend['max_connections'] . "\n");
-
- if($backend['client_timeout'])
- fwrite ($fd, "\tclitimeout\t\t" . $backend['client_timeout'] . "\n");
-
- if($backend['balance'])
- fwrite ($fd, "\tbalance\t\t\t" . $backend['balance'] . "\n");
-
- if($backend['connection_timeout'])
- fwrite ($fd, "\tcontimeout\t\t" . $backend['connection_timeout'] . "\n");
-
- if($backend['server_timeout'])
- fwrite ($fd, "\tsrvtimeout\t\t" . $backend['server_timeout'] . "\n");
+ if($bind['max_connections'])
+ fwrite ($fd, "\tmaxconn\t\t\t" . $bind['max_connections'] . "\n");
- if($backend['retries'])
- fwrite ($fd, "\tretries\t\t\t" . $backend['retries'] . "\n");
+ if($bind['client_timeout'])
+ fwrite ($fd, "\tclitimeout\t\t" . $bind['client_timeout'] . "\n");
- if($backend['stats_enabled']=='yes') {
- fwrite ($fd, "\tstats\t\t\tenable\n");
- if($backend['stats_uri'])
- fwrite ($fd, "\tstats\t\t\turi ".$backend['stats_uri']."\n");
- if($backend['stats_realm'])
- fwrite ($fd, "\tstats\t\t\trealm " . $backend['stats_realm'] . "\n");
- else
- fwrite ($fd, "\tstats\t\t\trealm .\n");
- fwrite ($fd, "\tstats\t\t\tauth " . $backend['stats_username'].":". $backend['stats_password']."\n");
- }
-
- $a_acl=&$backend['ha_acls']['item'];
- if(!is_array($a_acl))
- $a_acl=array();
+ fwrite ($fd, "\tdefault_backend\t\t" . $bind['defaultpool'] . "\n");
+
+ // Combine the rest of the listener configs
+ foreach ($bind['config'] as $bconfig) {
+ $a_acl=&$bconfig['ha_acls']['item'];
+ if(!is_array($a_acl))
+ $a_acl=array();
- foreach ($a_acl as $entry) {
- $acl = haproxy_find_acl($entry['expression']);
- if (!$acl)
- continue;
+ $poolname = $bconfig['pool'] . "_" . strtolower($bconfig['type']);
+ if (!isset($a_pendingpl[$poolname])) {
+ $a_pendingpl[$poolname] = array();
+ $a_pendingpl[$poolname]['name'] = $poolname;
+ $a_pendingpl[$poolname]['frontend'] = $bconfig;
+ }
- // Filter out acls for different modes
- if ($acl['mode'] != '' && $acl['mode'] != strtolower($backend['type']))
- continue;
+ foreach ($a_acl as $entry) {
+ $acl = haproxy_find_acl($entry['expression']);
+ if (!$acl)
+ continue;
- if ($acl['syntax'] != '')
- $expr = $acl['syntax'] . " " . $entry['value'];
- else
- $expr = $entry['expression'] . " " . $entry['value'];
+ // Filter out acls for different modes
+ if ($acl['mode'] != '' && $acl['mode'] != strtolower($bind['type']))
+ continue;
- fwrite ($fd, "\tacl\t\t\t".$entry['name']."\t".$expr."\n");
- }
+ if ($acl['syntax'] != '')
+ $expr = $acl['syntax'] . " " . $entry['value'];
+ else
+ $expr = $entry['expression'] . " " . $entry['value'];
- if (is_array($a_pools)) {
- foreach ($a_pools as $pool) {
- if ($backend['pool'] == $pool['name'] && is_array($pool['ha_servers']['item'])) {
- if($pool['status'] != 'active')
- continue;
- if($pool['cookie_name'] && strtolower($backend['type']) == "http")
- fwrite ($fd, "\tcookie\t\t\t" . $pool['cookie_name'] . " insert indirect\n");
-
- $uri = $pool['monitor_uri'];
- if ($pool['monitor_uri'])
- $uri = $pool['monitor_uri'];
- else
- $uri = "/";
- fwrite ($fd, "\toption\t\t\t{$httpchk} HEAD " . $uri . " HTTP/1.0\n");
-
- if($pool['cookie'] && strtolower($backend['type']) == "http")
- $cookie = " cookie {$pool['cookie']} ";
- else
- $cookie = "";
- if($pool['advanced']) {
- $advanced = base64_decode($pool['advanced']);
- $advanced_txt = " " . $advanced;
- } else {
- $advanced_txt = "";
- }
- if($pool['checkinter'])
- $checkinter = "check inter {$pool['checkinter']}";
- else
- $checkinter = "check inter 1000";
-
- $a_servers = &$pool['ha_servers']['item'];
- foreach($a_servers as $be) {
- if(!$be['port']) {
- // the listener can specify a default port
- $be['port'] = $backend['svrport'];
- }
- if(!$be['port']) {
- // last resort, use the frontend port
- $ports = split(",", "{$backend['port']},");
- $be['port'] = $ports[0];
- }
- if (!$be['name'])
- $be['name'] = $be['address'];
- if($be['backup']) {
- $isbackup = "backup";
- } else {
- $isbackup = "";
- }
- fwrite ($fd, "\tserver\t\t\t" . $be['name'] . " " . $be['address'].":" . $be['port'] . " $cookie " . " $checkinter $isbackup weight " . $be['weight'] . "{$advanced_txt}\n");
- }
-
- }
+ fwrite ($fd, "\tacl\t\t\t".$entry['name']."\t".$expr."\n");
+ fwrite ($fd, "\tuse_backend\t\t$poolname if " . $entry['name'] . "\n");
}
+
}
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']);
+ }
+ if (is_array($a_pendingpl) && is_array($a_pools)) {
+ foreach ($a_pendingpl as $pending) {
+ foreach ($a_pools as $pool) {
+ if ($pending['frontend']['pool'] == $pool['name']) {
+ write_backend($fd, $pending['name'], $pool, $pending['frontend']);
+ }
}
}
}
+ 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);