aboutsummaryrefslogtreecommitdiffstats
path: root/config/haproxy-devel
diff options
context:
space:
mode:
Diffstat (limited to 'config/haproxy-devel')
-rw-r--r--config/haproxy-devel/haproxy.inc699
-rw-r--r--config/haproxy-devel/haproxy.xml20
-rw-r--r--config/haproxy-devel/haproxy_files.php176
-rw-r--r--config/haproxy-devel/haproxy_htmllist.inc423
-rw-r--r--config/haproxy-devel/haproxy_listeners.php135
-rw-r--r--config/haproxy-devel/haproxy_listeners_edit.php188
-rw-r--r--config/haproxy-devel/haproxy_pool_edit.php42
-rw-r--r--config/haproxy-devel/haproxy_stats.php71
-rw-r--r--config/haproxy-devel/haproxy_templates.php220
-rw-r--r--config/haproxy-devel/haproxy_utils.inc26
-rw-r--r--config/haproxy-devel/pkg/haproxy_upgrade_config.inc174
-rw-r--r--config/haproxy-devel/pkg_haproxy_tabs.inc3
-rw-r--r--config/haproxy-devel/www/javascript/haproxy_geturl.js43
13 files changed, 1649 insertions, 571 deletions
diff --git a/config/haproxy-devel/haproxy.inc b/config/haproxy-devel/haproxy.inc
index 07086bd5..e9b0f9e3 100644
--- a/config/haproxy-devel/haproxy.inc
+++ b/config/haproxy-devel/haproxy.inc
@@ -1,7 +1,7 @@
<?php
/*
haproxy.inc
- Copyright (C) 2013 PiBa-NL
+ Copyright (C) 2013-2015 PiBa-NL
Copyright (C) 2009 Scott Ullrich <sullrich@pfsense.com>
Copyright (C) 2008 Remco Hoef
All rights reserved.
@@ -38,6 +38,13 @@ require_once("haproxy_xmlrpcsyncclient.inc");
$d_haproxyconfdirty_path = $g['varrun_path'] . "/haproxy.conf.dirty";
+global $a_frontendmode;
+$a_frontendmode = array();
+$a_frontendmode['http'] = array('name' => "http / https(offloading)", 'shortname' => "http/https");
+$a_frontendmode['https'] = array('name' => "ssl / https(TCP mode)", 'shortname' => "ssl/https");
+$a_frontendmode['tcp'] = array('name' => "tcp", 'shortname' => "tcp");
+$a_frontendmode['health'] = array('name' => "health", 'shortname' => "health");
+
global $a_acltypes;
$a_acltypes = array();
$a_acltypes["host_starts_with"] = array('name' => 'Host starts with:',
@@ -84,6 +91,8 @@ $a_acltypes["ssl_sni_starts_with"] = array('name' => 'Server Name Indication TLS
'mode' => 'https', 'syntax' => 'req.ssl_sni -m beg -i %1$s', 'advancedoptions' => "tcp-request content accept if { req.ssl_hello_type 1 }");
$a_acltypes["ssl_sni_ends_with"] = array('name' => 'Server Name Indication TLS extension ends with:', 'inspect-delay' => '5',
'mode' => 'https', 'syntax' => 'req.ssl_sni -m end -i %1$s', 'advancedoptions' => "tcp-request content accept if { req.ssl_hello_type 1 }");
+$a_acltypes["ssl_sni_regex"] = array('name' => 'Server Name Indication TLS extension regex:', 'inspect-delay' => '5',
+ 'mode' => 'https', 'syntax' => 'req.ssl_sni -m reg -i %1$s', 'advancedoptions' => "tcp-request content accept if { req.ssl_hello_type 1 }");
$a_acltypes["custom"] = array('name' => 'Custom acl:',
'mode' => '', 'syntax' => '%1$s');
@@ -187,6 +196,19 @@ $a_sticky_type['stick_rdp_cookie'] = array('name' => 'Stick on RDP-cookie',
'descr' => "Uses a RDP-Cookie send by the mstsc client, note that not all clients send this.",
'cookiedescr' => 'EXAMPLE: msts or mstshash');
+
+global $a_error;
+$a_error = array();
+$a_error['200'] = array('descr' => "stats or monitoring requests");
+$a_error['400'] = array('descr' => "request invalid or too large");
+$a_error['401'] = array('descr' => "authentication is required to perform the action");
+$a_error['403'] = array('descr' => "request is forbidden");
+$a_error['408'] = array('descr' => "timeout before the request is complete");
+$a_error['500'] = array('descr' => "internal error");
+$a_error['502'] = array('descr' => "server response invalid or blocked");
+$a_error['503'] = array('descr' => "no server was available to handle the request");
+$a_error['504'] = array('descr' => "timeout before the server responds");
+
if(!function_exists('group_ports')){
// function group_ports() is present in pfSense 2.2 in util.inc
/* create ranges of sequential port numbers (200:215) and remove duplicates */
@@ -237,10 +259,11 @@ function group_ports($ports) {
return $result;
}
}
-
+
function haproxy_portoralias_to_list($port_or_alias) {
// input: a port or aliasname: 80 https MyPortAlias
// returns: a array of ports and portranges 80 443 8000:8010
+
global $aliastable;
$portresult = array();
if (alias_get_type($port_or_alias) == "port") {
@@ -253,15 +276,39 @@ function haproxy_portoralias_to_list($port_or_alias) {
return $portresult;
} else if (is_portrange($port_or_alias)) {
return (array)$port_or_alias;
- } else if (is_port($port_or_alias)) {
- if (getservbyname($port_or_alias, "tcp"))
- return (array)getservbyname($port_or_alias, "tcp");
- if (getservbyname($port_or_alias, "udp"))
- return (array)getservbyname($port_or_alias, "udp");
- return (array)$port_or_alias;
+ } else {
+ $ports = explode(",", $port_or_alias);
+ foreach($ports as $port){
+ if (is_port($port)) {
+ if (getservbyname($port, "tcp"))
+ $port = getservbyname($port, "tcp");
+ if (getservbyname($port, "udp"))
+ $port = getservbyname($port, "udp");
+ $portresult[] = $port;
+ }
+ }
+ return $portresult;
}
- else
- return null;
+}
+function haproxy_addressoralias_to_list($address_or_alias) {
+ global $aliastable;
+ $result = array();
+ $alias_type = alias_get_type($address_or_alias);
+ if (!empty($alias_type)) {
+ $alias = $aliastable[$address_or_alias];
+ if ($alias_type == "url") {
+ $result = explode(' ',$alias);
+ } else
+ if ($alias_type == "network") {
+ //$result = explode(' ',$alias);
+ } else
+ if ($alias_type == "host") {
+ $result = explode(' ',$alias);
+ }
+ } else {
+ $result[] = $address_or_alias;
+ }
+ return $result;
}
function haproxy_hostoralias_to_list($host_or_alias) {
@@ -274,6 +321,20 @@ function haproxy_hostoralias_to_list($host_or_alias) {
return $result;
}
+function haproxy_get_fileslist() {
+ // returns the files array with 'keys'.
+ $result = array();
+ global $config;
+ // create a copy to not modify the original 'keyless' array
+ $a_files = $config['installedpackages']['haproxy']['files']['item'];
+ if (!is_array($a_files)) $a_files = array();
+ foreach($a_files as $file) {
+ $key = $file['name'];
+ $result[$key] = $file;
+ }
+ return $result;
+}
+
function haproxy_custom_php_deinstall_command() {
global $static_output;
$static_output .= "HAProxy, running haproxy_custom_php_deinstall_command()\n";
@@ -364,111 +425,11 @@ EOD;
$static_output .= "HAProxy, update configuration\n";
update_output_window($static_output);
-
- $writeconfigupdate = false;
- /* Do XML upgrade from haproxy 0.31 to haproxy-dev */
- if (is_array($config['installedpackages']['haproxy']['ha_servers'])) {
- $static_output .= "HAProxy, Do XML upgrade from haproxy 0.31 to haproxy-dev\n";
- update_output_window($static_output);
-
- /* We have an old config */
- $config['installedpackages']['haproxy']['ha_pools']['item'] = array();
- $a_global = &$config['installedpackages']['haproxy'];
- $a_backends = &$config['installedpackages']['haproxy']['ha_backends']['item'];
- $a_oldservers = &$config['installedpackages']['haproxy']['ha_servers']['item'];
- $a_pools = &$config['installedpackages']['haproxy']['ha_pools']['item'];
-
- foreach ($a_backends as $id => $be) {
- $a_backends[$id]['status'] = 'active';
- }
- $id = 0;
- foreach ($a_oldservers as $oldserver) {
- $pool=$oldserver;
- /* make server sub array */
- $server=array();
- $server['name'] = $oldserver['name'];
- $server['address'] = $oldserver['address'];
- $server['port'] = $oldserver['port'];
- $server['weight'] = $oldserver['weight'];
- $a_servers=array();
- $a_servers[]=$server;
- /* set new pool */
- $pool['name'] = "pool$id";
- $id++;
- $pool['ha_servers']['item']=$a_servers;
- /* link to frontend */
- foreach ($a_backends as $id => $be) {
- if ($a_backends[$id]['name'] == $oldserver['backend']) {
- $a_backends[$id]['backend_serverpool'] = $pool['name'];
- $pool['monitor_uri'] = $be['monitor_uri'];
- unset($a_backends[$id]['monitor_uri']);
- break;
- }
- }
- unset($pool['backend']);
- unset($pool['address']);
- unset($pool['port']);
- unset($pool['weight']);
- $a_pools[] = $pool;
- }
- unset($config['installedpackages']['haproxy']['ha_servers']);
- $writeconfigupdate = true;
- }
-
- /* XML update to: pkg v1.3 and 'pool' changed to 'backend_serverpool' because 'pool' was added to listtags() in xmlparse.inc */
- if (is_arrayset($config,'installedpackages','haproxy','ha_backends','item',0,'pool')) {
- $static_output .= "HAProxy, Do XML upgrade, change to backend_serverpool from pool array\n";
- update_output_window($static_output);
-
- foreach($config['installedpackages']['haproxy']['ha_backends']['item'] as &$frontend)
- {
- $backend_serverpool = $frontend['pool'][0];
- $frontend['backend_serverpool'] = $backend_serverpool;
- unset($frontend['pool']);
- }
- $writeconfigupdate = true;
- }
- //also move setting for existing 2.0 installations as only the new variable is used
- if (is_arrayset($config,'installedpackages','haproxy','ha_backends','item',0) &&
- isset($config['installedpackages']['haproxy']['ha_backends']['item'][0]['pool'])) {
- $static_output .= "HAProxy, Do XML upgrade, change to backend_serverpool from pool\n";
- update_output_window($static_output);
- foreach($config['installedpackages']['haproxy']['ha_backends']['item'] as &$frontend)
- {
- $backend_serverpool = $frontend['pool'];
- $frontend['backend_serverpool'] = $backend_serverpool;
- unset($frontend['pool']);
- }
- $writeconfigupdate = true;
- }
- // update config to "haproxy-devel 1.5-dev19 pkg v0.5"
- if(is_arrayset($config,'installedpackages','haproxy','ha_backends','item')) {
- $static_output .= "HAProxy, Do XML upgrade, update frontend options\n";
- update_output_window($static_output);
- foreach ($config['installedpackages']['haproxy']['ha_backends']['item'] as &$bind) {
- if($bind['httpclose'] && $bind['httpclose'] == "yes" ) {
- $bind['httpclose'] = "httpclose";
- $writeconfigupdate = true;
- }
- if (!$bind['extaddr']){
- $bind['extaddr'] = "wan_ipv4";
- $writeconfigupdate = true;
- }
- if ($bind['extaddr'] == "localhost"){
- $bind['extaddr'] = "localhost_ipv4";
- $writeconfigupdate = true;
- }
- if ($bind['extaddr'] == "any"){
- $bind['extaddr'] = "any_ipv4";
- $writeconfigupdate = true;
- }
- }
- }
- if ($writeconfigupdate) {
- $static_output .= "HAProxy, write updated config\n";
- update_output_window($static_output);
- write_config("HAProxy, update xml config version");
- }
+
+ // call from external file, so it is surely from the newly downloaded version
+ // this avoids a problem with php cache that loaded haproxy.inc during uninstalling the old version
+ require_once('haproxy_upgrade_config.inc');
+ haproxy_upgrade_config();
$static_output .= "HAProxy, conf_mount_ro\n";
update_output_window($static_output);
@@ -527,6 +488,17 @@ function haproxy_install_cron($should_install) {
}
}
+function haproxy_find_backend($backendname) {
+ global $config;
+ $a_backends = &$config['installedpackages']['haproxy']['ha_pools']['item'];
+ foreach ($a_backends as &$backend) {
+ if ($backend['name'] == $backendname) {
+ return $backend;
+ }
+ }
+ return null;
+}
+
function haproxy_find_acl($name) {
global $a_acltypes;
if($a_acltypes) {
@@ -537,14 +509,16 @@ function haproxy_find_acl($name) {
}
}
-function write_backend($configpath, $fd, $name, $pool, $frontend) {
+function write_backend($configpath, $fd, $name, $pool, $backendsettings) {
+ $frontend = $backendsettings['frontend'];
+ $ipversion = $backendsettings['ipversion'];
+
if(!is_array($pool['ha_servers']['item']) && !$pool['stats_enabled']=='yes')
return;
- global $a_checktypes, $a_cookiemode;
+ global $a_checktypes, $a_cookiemode, $a_files_cache, $a_error;
$a_servers = &$pool['ha_servers']['item'];
$frontendtype = $frontend['type'];
- $frontend_ip = haproxy_interface_ip($frontend['extaddr']);
fwrite ($fd, "backend " . $name . "\n");
// https is an alias for tcp for clarity purposes
@@ -604,6 +578,23 @@ function write_backend($configpath, $fd, $name, $pool, $frontend) {
fwrite ($fd, "\tstats\t\t\tscope " . $scope_item . "\n");
}
}
+
+ if (is_arrayset($pool,'errorfiles','item')) {
+ foreach($pool['errorfiles']['item'] as $errorfile) {
+ if (!is_array($a_files_cache))// load only once
+ $a_files_cache = haproxy_get_fileslist();
+ $file = $errorfile['errorfile'];
+ $errorcodes = explode(",",$errorfile['errorcode']);
+ foreach($errorcodes as $errorcode) {
+ $filename = "$configpath/errorfile_{$name}_{$errorcode}_{$file}";
+ $content = base64_decode($a_files_cache[$file]['content']);
+ $content = str_replace('{errormsg}', $a_error[$errorcode]['descr'], $content);
+ $content = str_replace('{errorcode}', $errorcode, $content);
+ file_put_contents($filename, $content);
+ fwrite ($fd, "\terrorfile\t\t\t" . $errorcode ." " . $filename . "\n");
+ }
+ }
+ }
}
switch($pool["persist_sticky_type"]) {
@@ -678,11 +669,18 @@ function write_backend($configpath, $fd, $name, $pool, $frontend) {
$pool['retries'] = 3;
fwrite ($fd, "\tretries\t\t\t" . $pool['retries'] . "\n");
- if ($pool['transparent_clientip']) {
- if (is_ipaddrv4($frontend_ip))
- fwrite ($fd, "\tsource 0.0.0.0 usesrc clientip\n");
- else
- fwrite ($fd, "\tsource ipv6@ usesrc clientip\n");
+ $addrprefix = "";
+ $dnsquerytype = "A,AAAA";
+ if ($pool['transparent_clientip'] == 'yes') {
+ if ($ipversion == "ipv6") {
+ $addrprefix = "ipv6@";
+ $dnsquerytype = "AAAA";
+ }
+ if ($ipversion == "ipv4") {
+ $addrprefix = "ipv4@";
+ $dnsquerytype = "A";
+ }
+ fwrite ($fd, "\tsource $addrprefix usesrc clientip\n");
}
$uri = $pool['monitor_uri'];
@@ -710,8 +708,7 @@ function write_backend($configpath, $fd, $name, $pool, $frontend) {
$advanced_txt = "";
}
- if ($check_type != 'none')
- {
+ if ($check_type != 'none') {
if($pool['checkinter'])
$checkinter = " check inter {$pool['checkinter']}";
else
@@ -722,8 +719,7 @@ function write_backend($configpath, $fd, $name, $pool, $frontend) {
if ($pool['agent_check'])
$agentcheck = " agent-check agent-inter {$pool['agent_inter']} agent-port {$pool['agent_port']}";
- if (is_array($a_servers))
- {
+ if (is_array($a_servers)) {
foreach($a_servers as $be) {
if ($be['status'] == "inactive")
continue;
@@ -784,13 +780,37 @@ function write_backend($configpath, $fd, $name, $pool, $frontend) {
$maxconn = " maxconn " . $be['maxconn'];
}
+ $servers = array();
if ($be['forwardto'] && $be['forwardto'] != "") {
- $server = "/{$be['forwardto']}.socket send-proxy-v2-ssl-cn";
- } else
- $server = $be['address'].":" . $be['port'];
-
-
- fwrite ($fd, "\tserver\t\t\t" . $be['name'] . " " . $server . "$ssl$cookie$checkinter$checkport$agentcheck $isbackup$weight$maxconn$cafile$crlfile$verifynone$verifyhost$crtfile{$advanced_txt} {$be['advanced']}\n");
+ $servers[] = "/{$be['forwardto']}.socket send-proxy-v2-ssl-cn";
+ } else {
+ if (is_ipaddr($be['address'])) {
+ $servers[] = $be['address'];
+ } else if (is_hostname($be['address'])) {
+ $dnsresult_servers = haproxy_utils::query_dns($be['address'], $dnsquerytype);
+ foreach($dnsresult_servers as $dnsresult_server){
+ $servers[] = $dnsresult_server['data'];
+ }
+ }
+ }
+ $counter = 0;
+ foreach($servers as $server) {
+ if (is_ipaddr($server)) {
+ // skip ipv4 servers when using transparent client ip with ipv6 backend servers, and vice versa
+ if ($ipversion == "ipv4" && !is_ipaddrv4($server))
+ continue;
+ if ($ipversion == "ipv6" && !is_ipaddrv6($server))
+ continue;
+ if (isset($be['port']))
+ $server = $server . ":" . $be['port'];
+ }
+ $servername = $be['name'];
+ if (count($servers) > 1) {
+ $servername .= "_" . $counter;
+ }
+ fwrite ($fd, "\tserver\t\t\t" . $servername . " " . $server . "$ssl$cookie$checkinter$checkport$agentcheck $isbackup$weight$maxconn$cafile$crlfile$verifynone$verifyhost$crtfile{$advanced_txt} {$be['advanced']}\n");
+ $counter++;
+ }
}
}
fwrite ($fd, "\n");
@@ -875,6 +895,9 @@ function haproxy_write_certificate_fullchain($filename, $certid, $append = false
function haproxy_writeconf($configpath) {
global $config;
+ global $aliastable;
+ if (!isset($aliastable))
+ alias_make_table($config);
$chroot_dir = "/tmp/haproxy_chroot"; // can contain socket to forward connection from backend to frontend. "/var/empty"
make_dirs($chroot_dir);
@@ -928,7 +951,7 @@ function haproxy_writeconf($configpath) {
$localstatsport = $a_global['localstatsport'];
if ($localstatsport){
fwrite ($fd, "listen HAProxyLocalStats\n");
- fwrite ($fd, "\tbind 127.0.0.1:$localstatsport\n");
+ fwrite ($fd, "\tbind 127.0.0.1:$localstatsport name localstats\n");
fwrite ($fd, "\tmode http\n");
fwrite ($fd, "\tstats enable\n");
if (is_numeric($a_global['localstats_refreshtime']))
@@ -951,7 +974,8 @@ function haproxy_writeconf($configpath) {
if(!$frontend['backend_serverpool'])
continue;
$primaryfrontend = get_primaryfrontend($frontend);
- $bname = get_frontend_ipport($frontend);
+
+ $bname = $primaryfrontend['name'];
if (!is_array($a_bind[$bname])) {
$a_bind[$bname] = array();
$a_bind[$bname] = $primaryfrontend;
@@ -959,12 +983,14 @@ function haproxy_writeconf($configpath) {
}
//check ssl info
- if (strtolower($primaryfrontend['type']) == "http" && $frontend['ssloffload']){
+ $ssl = get_frontend_uses_ssl($frontend);
+
+ if ($ssl) {
//ssl crt ./server.pem ca-file ./ca.crt verify optional crt-ignore-err all crl-file ./ca_crl.pem
- $filename = "$configpath/{$frontend['name']}.{$frontend['port']}.pem";
+ $filename = "$configpath/{$frontend['name']}.pem";
$ssl_crt = " crt $filename";
haproxy_write_certificate_fullchain($filename, $frontend['ssloffloadcert']);
- $subfolder = "$configpath/{$frontend['name']}.{$frontend['port']}";
+ $subfolder = "$configpath/{$frontend['name']}";
$certs = $frontend['ha_certificates']['item'];
if (is_array($certs)){
if (count($certs) > 0){
@@ -1008,33 +1034,35 @@ function haproxy_writeconf($configpath) {
else
$frontendinfo = "frontend {$bind['name']}\n";
- $advancedextra = array();
+ fwrite ($fd, "{$frontendinfo}");
+ $allow_none = false;
+ $advancedextra = array();
$ca_file = "";
$first = true;
if (is_array($bind['clientcert_ca']['item'])){
+ $filename = "$configpath/clientca_{$bind['name']}.pem";
foreach($bind['clientcert_ca']['item'] as $ca){
- $filename = "$configpath/clientca_{$bind['name']}.pem";
- haproxy_write_certificate_crt($filename, $ca['cert_ca'], false, !$first);
- $first = false;
+ if (!empty($ca['cert_ca'])){
+ haproxy_write_certificate_crt($filename, $ca['cert_ca'], false, !$first);
+ $first = false;
+ } else
+ $allow_none = true;
}
- $ca_file = " ca-file $filename verify optional";
+ $verify = $allow_none ? "verify optional" : "verify required";
+ $ca_file = " ca-file $filename $verify";
}
$crl_file = "";
$first = true;
if (is_array($bind['clientcert_crl']['item'])){
+ $filename = "$configpath/clientcrl_{$bind['name']}.pem";
foreach($bind['clientcert_crl']['item'] as $ca){
- $filename = "$configpath/clientcrl_{$bind['name']}.pem";
haproxy_write_certificate_crl($filename, $ca['cert_crl'], !$first);
$first = false;
}
$crl_file = " crl-file $filename";
}
- // Prepare ports for processing by splitting
- $portss = "{$bind['port']},";
- $ports = split(",", $portss);
-
if($bind['type'] == "http") {
// ssl offloading is only possible in http mode.
$ssl_info = $bind['ssl_info'].$ca_file.$crl_file;
@@ -1043,27 +1071,22 @@ function haproxy_writeconf($configpath) {
$ssl_info = "";
$advanced_bind = "";
}
- // Initialize variable
- $listenip = "";
+ $useipv4 = false;
+ $useipv6 = false;
// Process and add bind directives for ports
- $ip = haproxy_interface_ip($bind['extaddr']);
- if ($ip){
- foreach($ports as $alias_or_port) {
- if($alias_or_port) {
- $portsnumeric = group_ports(haproxy_portoralias_to_list($alias_or_port));
- foreach($portsnumeric as $portnumeric) {
- $portnumeric = str_replace(":","-",$portnumeric);
- $listenip .= "\tbind\t\t\t$ip:{$portnumeric} {$ssl_info} {$advanced_bind}\n";
- }
- }
- }
+ $bindips = get_frontend_bindips($bind);
+ $listenip = "";
+ foreach($bindips as $bindip) {
+ $ssl = $bindip['extaddr_ssl'] == 'yes' ? $ssl_info : "";
+ $listenip .= "\tbind\t\t\t{$bindip['addr']}:{$bindip['port']} name {$bindip['addr']}:{$bindip['port']} {$ssl} {$advanced_bind} {$bindip['extaddr_advanced']}\n";
+ $useipv4 |= is_ipaddrv4($bindip['addr']);
+ $useipv6 |= is_ipaddrv6($bindip['addr']);
}
-
- fwrite ($fd, "{$frontendinfo}");
fwrite ($fd, "{$listenip}");
+
if (use_frontend_as_unixsocket($bind['name'])){
- fwrite ($fd, "\tbind /tmp/haproxy_chroot/{$bind['name']}.socket accept-proxy {$ssl_info} {$advanced_bind}\n");
+ fwrite ($fd, "\tbind /tmp/haproxy_chroot/{$bind['name']}.socket name unixsocket accept-proxy {$ssl_info} {$advanced_bind}\n");
}
// Advanced pass thru
@@ -1086,12 +1109,14 @@ function haproxy_writeconf($configpath) {
fwrite ($fd, "\tmode\t\t\t" . $backend_type . "\n");
fwrite ($fd, "\tlog\t\t\tglobal\n");
+ if ($bind['socket-stats'] == 'yes')
+ fwrite ($fd, "\toption\t\t\tsocket-stats\n");
if ($bind['dontlognull'] == 'yes')
- fwrite ($fd, "\toption\t\t\tdontlognull\n");
+ fwrite ($fd, "\toption\t\t\tdontlognull\n");
if ($bind['dontlog-normal'] == 'yes')
fwrite ($fd, "\toption\t\t\tdontlog-normal\n");
if ($bind['log-separate-errors'] == 'yes')
- fwrite ($fd, "\toption\t\t\tlog-separate-errors\n");
+ fwrite ($fd, "\toption\t\t\tlog-separate-errors\n");
if ($bind['log-detailed'] == 'yes'){
if ($backend_type == 'http')
fwrite ($fd, "\toption\t\t\thttplog\n");
@@ -1099,17 +1124,15 @@ function haproxy_writeconf($configpath) {
fwrite ($fd, "\toption\t\t\ttcplog\n");
}
- if ($backend_type == 'http')
- {
+ if ($backend_type == 'http') {
if($bind['httpclose'] && $bind['httpclose'] != "none" )
fwrite ($fd, "\toption\t\t\t{$bind['httpclose']}\n");
if($bind['forwardfor']) {
fwrite ($fd, "\toption\t\t\tforwardfor\n");
- if($bind['ssloffload'] == "yes")
- fwrite ($fd, "\treqadd X-Forwarded-Proto:\ https\n");
- else
- fwrite ($fd, "\treqadd X-Forwarded-Proto:\ http\n");
+ fwrite ($fd, "\tacl https ssl_fc\n");
+ fwrite ($fd, "\treqadd X-Forwarded-Proto:\ http if !https\n");
+ fwrite ($fd, "\treqadd X-Forwarded-Proto:\ https if https\n");
}
}
@@ -1124,24 +1147,41 @@ function haproxy_writeconf($configpath) {
// Combine the rest of the frontend configs
$default_backend = "";
+ $config_acls = "";
+ $config_usebackends = "";
+
+ $transparent_clientip = false;
+ foreach ($bind['config'] as $frontend) {
+ $backend = haproxy_find_backend($frontend['backend_serverpool']);
+ if ($backend["transparent_clientip"] == 'yes') {
+ $transparent_clientip = true;
+ break;
+ }
+ }
+ if ($transparent_clientip && $useipv4 && $useipv6) {
+ // set the src_is_ipv4 acl if needed.
+ $config_acls .= "\tacl\t\t\tsrc_is_ipv4\tsrc 0.0.0.0/0\n";
+ }
+
$inspectdelay = 0;
$i = 0;
foreach ($bind['config'] as $frontend) {
$a_acl = get_frontend_acls($frontend);
- $poolname = $frontend['backend_serverpool'] . "_" . strtolower($bind['type']);
-
- if (!isset($a_pendingpl[$poolname])) {
- $a_pendingpl[$poolname] = array();
- $a_pendingpl[$poolname]['name'] = $poolname;
- $a_pendingpl[$poolname]['backend'] = $frontend['backend_serverpool'];
- $a_pendingpl[$poolname]['frontend'] = $bind;
- }
+ $backend = haproxy_find_backend($frontend['backend_serverpool']);
+ $transparent_clientip = $backend["transparent_clientip"] == 'yes';
- // Write this out once, and must be before any backend config text
- if (($default_backend == "" || $frontend['secondary'] != 'yes') && count($a_acl) == 0 ) {
- $default_backend = $poolname;
- }
+ $ipv = array();
+ if ($transparent_clientip) {
+ if ($useipv4 && $useipv6) {
+ $ipv["ipv4"]['acl'] = " src_is_ipv4 ";
+ $ipv["ipv6"]['acl'] = " !src_is_ipv4 ";
+ } else if ($useipv6)
+ $ipv["ipv6"]['acl'] = " ";
+ else
+ $ipv["ipv4"]['acl'] = " ";
+ } else
+ $ipv["ipvANY"]['acl'] = " ";
// combine acl's with same name to allow for 'combined checks' to check for example hostname and fileextension together..
$a_acl_combine = array();
@@ -1150,48 +1190,91 @@ function haproxy_writeconf($configpath) {
$a_acl_combine[$name][] = $entry['ref'];
}
- foreach ($a_acl_combine as $a_usebackend) {
- $aclnames = "";
- foreach ($a_usebackend as $entry) {
- $acl = haproxy_find_acl($entry['expression']);
- if (!$acl)
- continue;
-
- // Filter out acls for different modes
- if ($acl['mode'] != '' && $acl['mode'] != strtolower($bind['type']))
- continue;
- if (($entry['expression'] == "source_ip") && is_alias($entry['value'])) {
- $filename = "$configpath/ipalias_{$entry['value']}.lst";
- $listitems = haproxy_hostoralias_to_list($entry['value']);
- $fd_alias = fopen("$filename", "w");
- foreach($listitems as $item)
- fwrite($fd_alias, $item."\r\n");
- fclose($fd_alias);
- $expr = "src -f $filename";
- } else
- $expr = sprintf($acl['syntax'],$entry['value'],$poolname);
-
- $aclname = $i . "_" . $entry['name'];
- $aclnames .= $aclname." ";
- fwrite ($fd, "\tacl\t\t\t" . $aclname . "\t" . $expr . "\n");
-
- if ($acl['inspect-delay'] != '')
- $inspectdelay = $acl['inspect-delay'];
-
- if ($acl['advancedoptions'] != '')
- $advancedextra[$acl['syntax']] = $acl['advancedoptions']."\n";
- $i++;
+ $y = 0;
+ foreach($ipv as $ipversion => $ipversionoptions) {
+ $certacls = array();
+ $useracls = array();
+ $poolname = $frontend['backend_serverpool'] . "_" . strtolower($bind['type'])."_".$ipversion;
+ if (!isset($a_pendingpl[$poolname])) {
+ $a_pendingpl[$poolname] = array();
+ $a_pendingpl[$poolname]['name'] = $poolname;
+ $a_pendingpl[$poolname]['backend'] = $frontend['backend_serverpool'];
+ $a_pendingpl[$poolname]['frontend'] = $bind;
+ $a_pendingpl[$poolname]['ipversion'] = $ipversion;
}
- fwrite ($fd, "\tuse_backend\t\t" . $poolname . " if " . $aclnames . "\n");
+
+ // Write this out once, and must be before any backend config text
+ if (($default_backend == "" || $frontend['secondary'] != 'yes') && count($a_acl) == 0 ) {
+ $default_backend = $poolname;
+ }
+
+ foreach ($a_acl_combine as $a_usebackend) {
+ $aclnames = "";
+ foreach ($a_usebackend as $entry) {
+ $acl = haproxy_find_acl($entry['expression']);
+ if (!$acl)
+ continue;
+
+ // Filter out acls for different modes
+ if ($acl['mode'] != '' && $acl['mode'] != strtolower($bind['type']))
+ continue;
+ if (($entry['expression'] == "source_ip") && is_alias($entry['value'])) {
+ $filename = "$configpath/ipalias_{$entry['value']}.lst";
+ $listitems = haproxy_hostoralias_to_list($entry['value']);
+ $fd_alias = fopen("$filename", "w");
+ foreach($listitems as $item)
+ fwrite($fd_alias, $item."\r\n");
+ fclose($fd_alias);
+ $expr = "src -f $filename";
+ } else
+ $expr = sprintf($acl['syntax'],$entry['value'],$poolname);
+
+ $not = $entry['not'] == "yes" ? "!" : "";
+
+ $aclname = $i . "_" . $entry['name'];
+ if ($entry['certacl'])
+ $certacls[] = $aclname . " ";
+ else
+ $useracls[$y] .= $not . $aclname . " ";
+
+ $config_acls .= "\tacl\t\t\t" . $aclname . "\t" . $expr . "\n";
+
+ if ($acl['inspect-delay'] != '')
+ $inspectdelay = $acl['inspect-delay'];
+
+ if ($acl['advancedoptions'] != '')
+ $advancedextra[$acl['syntax']] = $acl['advancedoptions']."\n";
+ $i++;
+ }
+ $y++;
+ }
+
+ if (count($certacls) == 0) $certacls[] = ""; // add empty item to enter foreach loop at least once.
+ if (count($useracls) == 0) $useracls[] = ""; // add empty item to enter foreach loop at least once.
+ $backendacl = "";
+ foreach($useracls as $useracl)
+ foreach($certacls as $certacl)
+ $backendacl .= "|| {$useracl}{$certacl}{$ipversionoptions['acl']}";
+ $backendacl = substr($backendacl, 3);
+ $config_usebackends .= "\tuse_backend\t\t" . $poolname . " if " . $backendacl . "\n";
+ //$config_usebackends .= "\tuse_backend\t\t" . $poolname . " if " . $backendacl . "\n";
}
}
- if ($default_backend)
- fwrite ($fd, "\tdefault_backend\t\t" . $default_backend . "\n");
if ($inspectdelay > 0)
fwrite ($fd, "\ttcp-request inspect-delay\t" . $inspectdelay . "\n");
+
+ // Write acl's first, so they may be used by advanced text options written by user.
+ fwrite ($fd, $config_acls);
+
foreach($advancedextra as $extra)
fwrite ($fd, "\t".$extra."\n");
+
+ // Write backends after advanced options so custom use_backend rules can be applied first.
+ fwrite ($fd, $config_usebackends);
+ if ($default_backend)
+ fwrite ($fd, "\tdefault_backend\t\t" . $default_backend . "\n");
+
fwrite ($fd, "\n");
}
}
@@ -1200,7 +1283,7 @@ function haproxy_writeconf($configpath) {
foreach ($a_pendingpl as $pending) {
foreach ($a_backends as $pool) {
if ($pending['backend'] == $pool['name']) {
- write_backend($configpath, $fd, $pending['name'], $pool, $pending['frontend']);
+ write_backend($configpath, $fd, $pending['name'], $pool, $pending);
}
}
}
@@ -1392,8 +1475,7 @@ function haproxy_plugin_certificates($pluginparams) {
$result['certificatelist'] = array();
// return a array of used certificates.
foreach($config['installedpackages']['haproxy']['ha_backends']['item'] as &$frontend) {
- $mainfrontend = get_primaryfrontend($frontend);
- if (strtolower($mainfrontend['type']) == "http" && $mainfrontend['ssloffload']) {
+ if (get_frontend_uses_ssl($frontend)) {
if ($frontend['ssloffloadacl']){
$item = array();
$cert = $frontend['ssloffloadcert'];
@@ -1581,12 +1663,65 @@ function get_primaryfrontend($frontend) {
return $mainfrontend;
}
-function get_frontend_ipport($frontend,$userfriendly=false) {
+function get_frontend_ipport($frontend, $userfriendly=false) {
$mainfrontend = get_primaryfrontend($frontend);
- $result = haproxy_interface_ip($mainfrontend['extaddr'], $userfriendly);
- if ($userfriendly and is_ipaddrv6($result))
- $result = "[{$result}]";
- return $result . ":" . $mainfrontend['port'];
+ $result = array();
+ if (!is_arrayset($mainfrontend,"a_extaddr","item"))
+ return $result;
+ foreach($mainfrontend['a_extaddr']['item'] as $extaddr) {
+ if ($extaddr['extaddr'] == 'custom'){
+ $addr = $extaddr['extaddr_custom'];
+ } else {
+ $addr = haproxy_interface_ip($extaddr['extaddr'], $userfriendly);
+ }
+ if ($userfriendly and is_ipaddrv6($addr))
+ $addr = "[{$addr}]";
+
+ $port = $extaddr['extaddr_port'];
+ $newitem = array();
+ $newitem['addr'] = $addr;
+ $newitem['port'] = $port;
+ $newitem['ssl'] = $extaddr['extaddr_ssl'];
+ $result[$addr.$port] = $newitem;
+ }
+ ksort($result);
+ return $result;
+}
+
+function get_frontend_bindips($frontend) {
+ $mainfrontend = get_primaryfrontend($frontend);
+ $result = array();
+ if (!is_arrayset($mainfrontend,"a_extaddr","item"))
+ return $result;
+ foreach($mainfrontend['a_extaddr']['item'] as $extaddr) {
+ $a_ip = array();
+ if (isset($extaddr['extaddr']) && $extaddr['extaddr'] != "custom") {
+ $a_ip[] = haproxy_interface_ip($extaddr['extaddr']);
+ } else {
+ $iporalias = $extaddr['extaddr_custom'];
+ $a_ip = haproxy_addressoralias_to_list($iporalias);
+ }
+ if ($extaddr['extaddr_ssl'] == 'yes')
+ $ssl = $ssl_info;
+ else
+ $ssl = "";
+
+ foreach($a_ip as $ip) {
+ $portsnumeric = group_ports(haproxy_portoralias_to_list($extaddr['extaddr_port']));
+ if (is_array($portsnumeric)) {
+ foreach($portsnumeric as $portnumeric) {
+ $portnumeric = str_replace(":","-",$portnumeric);
+ $newitem = array();
+ $newitem['addr'] = $ip;
+ $newitem['port'] = $portnumeric;
+ $newitem['extaddr_ssl'] = $extaddr['extaddr_ssl'];
+ $newitem['extaddr_advanced'] = $extaddr['extaddr_advanced'];
+ $result[] = $newitem;
+ }
+ }
+ }
+ }
+ return $result;
}
function haproxy_check_config() {
@@ -1599,17 +1734,20 @@ function haproxy_check_config() {
foreach($a_backends as $frontend) {
if (($frontend['status'] != 'active') || ($frontend['secondary'] == 'yes'))
continue;
- $ipport = get_frontend_ipport($frontend);
- if (isset($activefrontends[$ipport]))
- $issues['P_'.$ipport] = "Multiple primary frontends with IP:Port \"$ipport\"";
- else
- $activefrontends[$ipport] = true;
+ $ipports = get_frontend_ipport($frontend);
+ foreach($ipports as $ipport) {
+ $id = "{$ipport['addr']}:{$ipport['port']}";
+ if (isset($activefrontends[$id]))
+ $issues['P_'.$id] = "Multiple primary frontends with IP:Port \"$id\", use Shared-Frontends instead.";
+ else
+ $activefrontends[$id] = true;
+ }
}
foreach($a_backends as $frontend) {
if (($frontend['status'] != 'active') || ($frontend['secondary'] != 'yes'))
continue;
- $ipport = get_frontend_ipport($frontend);
- if (!isset($activefrontends[$ipport]))
+ $mainfrontend = get_primaryfrontend($frontend);
+ if (!isset($mainfrontend))
$issues['S_'.$frontend['name']] = "Secondary frontend \"{$frontend['name']}\" without active primary frontend.";
}
foreach ($issues as $item)
@@ -1621,6 +1759,8 @@ function get_haproxy_frontends($excludeitem="") {
global $config;
$a_frontend = &$config['installedpackages']['haproxy']['ha_backends']['item'];
$result = array();
+ if(!is_array($a_frontend))
+ return $result;
foreach($a_frontend as &$frontend)
{
if ($frontend['secondary'])
@@ -1628,17 +1768,62 @@ function get_haproxy_frontends($excludeitem="") {
if ($frontend['name'] == $excludeitem)
continue;
- $serveradress = "{$frontend['extaddr']}:{$frontend['port']}";
- $result[$frontend['name']]['name'] = "{$frontend['name']} - {$frontend['type']} ({$serveradress})";
+ $serveraddress = get_frontend_ipport($frontend, true);
+ $serveradresstext = null;
+ foreach($serveraddress as $addr) {
+ $serveradresstext .=($serveradresstext == null ? "" : ", ") . "{$addr['addr']}:{$addr['port']}";
+ }
+ $result[$frontend['name']]['name'] = "{$frontend['name']} - {$frontend['type']} ({$serveradresstext})";
$result[$frontend['name']]['ref'] = &$frontend;
}
uasort($result, haproxy_compareByName);
return $result;
}
-function generate_cert_acl($crt, $defaultport, $nondefaultport){
- // The host header send by a browser will contain the portnumber when a nondefault port is used for the server side.
+function get_frontend_uses_ssl($frontend) {
+ $mainfrontend = get_primaryfrontend($frontend);
+ $ssl = false;
+ if (is_arrayset($mainfrontend,'a_extaddr','item')) {
+ foreach($mainfrontend['a_extaddr']['item'] as $extaddr) {
+ if ($extaddr['extaddr_ssl'] == 'yes') {
+ $ssl = true;
+ break;
+ }
+ }
+ }
+ if ($mainfrontend['name'] != $frontend['name'])
+ $ssl = $ssl && $frontend['ssloffload'] == 'yes';
+ return $ssl;
+}
+
+function get_frontend_uses_ssl_only($frontend) {
+ $mainfrontend = get_primaryfrontend($frontend);
+ if (is_arrayset($mainfrontend,'a_extaddr','item')) {
+ foreach($mainfrontend['a_extaddr']['item'] as $extaddr) {
+ if ($extaddr['extaddr_ssl'] != 'yes')
+ return false;
+ }
+ }
+ return true;
+}
+function haproxy_get_cert_acl($cert) {
+ $acl_item = array();
+
+ $cert_cn = cert_get_cn($cert['crt']);
+ $descr = haproxy_escape_acl_name($cert['descr']);
+ unset($cert);
+ $is_wildcard = substr($cert_cn, 0, 2) == "*.";
+ $cert_cn_regex = str_replace(".", "\.", $cert_cn); // escape '.' in regex.
+ $wild_regex = "";
+ if ($is_wildcard) {
+ $cert_cn_regex = "([^\.]*)" . substr($cert_cn_regex, 1);// match only subdomains directly under the wildcard
+ }
+ $cert_cn_regex = "^{$cert_cn_regex}(:([0-9]){1,5})?$";// match both with and without port.
+
+ $acl_item['descr'] = "Certificate ACL matches: {$cert_cn}";
+ $acl_item['ref'] = array('name' => "{$aclname}_{$descr}",'expression' => 'host_regex', 'value' => $cert_cn_regex, 'certacl' => true);
+ return $acl_item;
}
function get_frontend_acls($frontend) {
@@ -1655,7 +1840,7 @@ function get_frontend_acls($frontend) {
// Filter out acls for different modes
if ($acl['mode'] != '' && $acl['mode'] != strtolower($mainfrontend['type']))
continue;
-
+ $not = $entry['not'] == "yes" ? "not " : "";
$acl_item = array();
$acl_item['descr'] = $acl['name'] . ": " . $entry['value'];
$acl_item['ref'] = $entry;
@@ -1664,7 +1849,7 @@ function get_frontend_acls($frontend) {
}
}
- if (strtolower($mainfrontend['type']) == "http" && $mainfrontend['ssloffload']) {
+ if (get_frontend_uses_ssl($frontend)) {
$a_acl = &$frontend['ha_acls']['item'];
if(!is_array($a_acl))
$a_acl=array();
@@ -1674,44 +1859,14 @@ function get_frontend_acls($frontend) {
if (ifset($frontend['ssloffloadacl']) == 'yes' || ifset($frontend['ssloffloadaclnondefault']) == 'yes') {
$cert = lookup_cert($frontend['ssloffloadcert']);
- $cert_cn = cert_get_cn($cert['crt']);
- $descr = haproxy_escape_acl_name($cert['descr']);
- unset($cert);
-
- $acl_item = array();
- if (ifset($frontend['ssloffloadacl']) == 'yes' && ifset($frontend['ssloffloadaclnondefault']) == 'yes') {
- $acl_item['descr'] = "Certificate ACL match regex: ^{$cert_cn}(:([0-9]){1,5})?$";
- $acl_item['ref'] = array('name' => "{$aclname}_{$descr}",'expression' => 'host_regex', 'value' => "^{$cert_cn}(:([0-9]){1,5})?$");
- } elseif (ifset($frontend['ssloffloadaclnondefault']) == 'yes') {
- $acl_item['descr'] = "Certificate ACL starts with: {$cert_cn}:";
- $acl_item['ref'] = array('name' => "{$aclname}_{$descr}",'expression' => 'host_starts_with', 'value' => $cert_cn.":");
- } else {
- $acl_item['descr'] = "Certificate ACL match: {$cert_cn}";
- $acl_item['ref'] = array('name' => "{$aclname}_{$descr}",'expression' => 'host_matches', 'value' => $cert_cn);
- }
- $result[] = $acl_item;
+ $result[] = haproxy_get_cert_acl($cert);
}
- if (ifset($frontend['ssloffloadacladditional']) == 'yes' || ifset($frontend['ssloffloadacladditionalnondefault']) == 'yes') {
+ if (ifset($frontend['ssloffloadacladditional']) == 'yes') {
$certs = $frontend['ha_certificates']['item'];
if (is_array($certs)){
foreach($certs as $certref){
$cert = lookup_cert($certref['ssl_certificate']);
- $cert_cn = cert_get_cn($cert['crt']);
- $descr = haproxy_escape_acl_name($cert['descr']);
- unset($cert);
-
- $acl_item = array();
- if (ifset($frontend['ssloffloadacladditional']) == 'yes' && ifset($frontend['ssloffloadacladditionalnondefault']) == 'yes') {
- $acl_item['descr'] = "Certificate ACL match regex: ^{$cert_cn}(:([0-9]){1,5})?$";
- $acl_item['ref'] = array('name' => "{$aclname}_{$descr}",'expression' => 'host_regex', 'value' => "^({$cert_cn}(($)|(:.*)))");
- } elseif (ifset($frontend['ssloffloadacladditionalnondefault']) == 'yes') {
- $acl_item['descr'] = "Certificate ACL starts with: {$cert_cn}:";
- $acl_item['ref'] = array('name' => "{$aclname}_{$descr}",'expression' => 'host_starts_with', 'value' => $cert_cn.":");
- } else {
- $acl_item['descr'] = "Certificate ACL match: {$cert_cn}";
- $acl_item['ref'] = array('name' => "{$aclname}_{$descr}",'expression' => 'host_matches', 'value' => $cert_cn);
- }
- $result[] = $acl_item;
+ $result[] = haproxy_get_cert_acl($cert);
}
}
}
diff --git a/config/haproxy-devel/haproxy.xml b/config/haproxy-devel/haproxy.xml
index acd934a7..27199ee4 100644
--- a/config/haproxy-devel/haproxy.xml
+++ b/config/haproxy-devel/haproxy.xml
@@ -90,6 +90,11 @@
<additional_files_needed>
<prefix>/usr/local/www/</prefix>
<chmod>077</chmod>
+ <item>https://packages.pfsense.org/packages/config/haproxy-devel/haproxy_files.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>077</chmod>
<item>https://packages.pfsense.org/packages/config/haproxy-devel/haproxy_pools.php</item>
</additional_files_needed>
<additional_files_needed>
@@ -103,6 +108,11 @@
<item>https://packages.pfsense.org/packages/config/haproxy-devel/haproxy_stats.php</item>
</additional_files_needed>
<additional_files_needed>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>077</chmod>
+ <item>https://packages.pfsense.org/packages/config/haproxy-devel/haproxy_templates.php</item>
+ </additional_files_needed>
+ <additional_files_needed>
<prefix>/usr/local/pkg/</prefix>
<chmod>077</chmod>
<item>https://packages.pfsense.org/packages/config/haproxy-devel/haproxy_socketinfo.inc</item>
@@ -137,6 +147,16 @@
<chmod>077</chmod>
<item>https://packages.pfsense.org/packages/config/haproxy-devel/pkg_haproxy_tabs.inc</item>
</additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>077</chmod>
+ <item>https://packages.pfsense.org/packages/config/haproxy-devel/pkg/haproxy_upgrade_config.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/javascript/</prefix>
+ <chmod>077</chmod>
+ <item>https://packages.pfsense.org/packages/config/haproxy-devel/www/javascript/haproxy_geturl.js</item>
+ </additional_files_needed>
<custom_delete_php_command>
</custom_delete_php_command>
<custom_add_php_command>
diff --git a/config/haproxy-devel/haproxy_files.php b/config/haproxy-devel/haproxy_files.php
new file mode 100644
index 00000000..4946a7be
--- /dev/null
+++ b/config/haproxy-devel/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>
+ &nbsp;
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <?
+ $counter=0;
+ $fileslist->Draw($a_files);
+ ?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ &nbsp;
+ </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/haproxy-devel/haproxy_htmllist.inc b/config/haproxy-devel/haproxy_htmllist.inc
index 404e9fab..f873028e 100644
--- a/config/haproxy-devel/haproxy_htmllist.inc
+++ b/config/haproxy-devel/haproxy_htmllist.inc
@@ -34,193 +34,267 @@
require_once("config.inc");
require_once("haproxy_utils.inc");
-function haproxy_htmllist_get_values($html_list){
- $values = array();
- for($x=0; $x<99; $x++) {
- $value = array();
- $add_item = false;
- foreach($html_list as $item){
- $itemname = $item['name'];
- $value[$itemname] = $_POST[$itemname.$x];
- $add_item |= isset($_POST[$itemname.$x]);
+class HaproxyHtmlList
+{
+ /*
+ javascript 'events':
+ <tableId>_row_added(tableId, rowNr)
+ <tableId>_field_changed(tableId, rowNr, fieldId, field)
+ */
+
+ private $tablename = "";
+ private $fields = array();
+ public $editmode = false;
+ public $fields_details = null;
+ public $keyfield = "";
+
+ public function HaproxyHtmlList($tablename, $fields){
+ $this->tablename = $tablename;
+ $this->fields = $fields;
+ }
+
+ public function Draw($data){
+ $this->haproxy_htmllist($data, $this->fields, $this->editmode, $this->fields_details);
+ }
+
+ function haproxy_htmllist_get_values(){
+ $values = array();
+ for($x=0; $x<99; $x++) {
+ $value = array();
+ $add_item = false;
+ foreach($this->fields as $item){
+ $itemname = $item['name'];
+ $value[$itemname] = $_POST[$itemname.$x];
+ if ($item['type'] == 'textarea')
+ $value[$itemname] = base64_encode($value[$itemname]);
+ $add_item |= isset($_POST[$itemname.$x]);
+ }
+ if ($add_item) {
+ if ($this->keyfield != "") {
+ if (isset($_POST[$this->tablename."_key".$x]))
+ $key = $_POST[$this->tablename."_key".$x];
+ else
+ $key = $_POST[$this->keyfield.$x];
+
+ } else
+ $key = "";
+
+ if (isset($values[$key]))
+ $values[] = $value;
+ else
+ $values[$key] = $value;
+ }
}
- if ($add_item)
- $values[] = $value;
+ return $values;
}
- return $values;
-}
-function haproxy_htmllist_drawcell($item, $itemvalue, $editable, $itemnamenr = "") {
- $itemtype = $item['type'];
- if ($editable) {
+ private function haproxy_htmllist_drawcell($item, $itemvalue, $editable, $itemname, $counter) {
+ $itemnamenr = $itemname . $counter;
$itemtype = $item['type'];
- if ($itemtype == "select"){
- echo_html_select($itemnamenr, $item['items'], $itemvalue,"","updatevisibility();", "width:{$item['size']}");
- } else
- if ($itemtype == "checkbox"){
- $checked = $itemvalue=='yes' ? " checked" : "";
- echo "<input name='$itemnamenr' id='$itemnamenr' type='checkbox'$checked value='yes' size='{$item['size']}' />";
- } else
- echo "<input name='$itemnamenr' id='$itemnamenr' type='text' value='{$itemvalue}' size='{$item['size']}' />";
- } else {
- if ($itemtype == "select"){
- echo $item['items'][$itemvalue]['name'];
- } else
- if ($itemtype == "checkbox"){
- echo $itemvalue=='yes' ? gettext('yes') : gettext('no');
- } else
- echo $itemvalue;
+ if ($editable) {
+ $itemtype = $item['type'];
+ if ($itemtype == "select"){
+ echo_html_select($itemnamenr, $item['items'], $itemvalue,"","html_listitem_change(\"{$this->tablename}\",\"{$itemname}\",\"{$counter}\",this);", "width:{$item['size']}");
+ } else
+ if ($itemtype == "checkbox"){
+ $checked = $itemvalue=='yes' ? " checked" : "";
+ echo "<input onclick='html_listitem_change(\"{$this->tablename}\",\"{$itemname}\",\"{$counter}\",this);' name='$itemnamenr' id='$itemnamenr' type='checkbox'$checked value='yes' size='{$item['size']}' />";
+ } else
+ if ($itemtype == "textarea"){
+ echo "<textarea name='$itemnamenr' id='$itemnamenr' type='text' cols='{$item['size']}' rows='10'>";
+ echo htmlspecialchars(base64_decode($itemvalue));
+ echo "</textarea>";
+ } else
+ echo "<input name='$itemnamenr' id='$itemnamenr' type='text' value='{$itemvalue}' size='{$item['size']}' />";
+ } else {
+ if ($itemtype == "select"){
+ echo $item['items'][$itemvalue]['name'];
+ } else
+ if ($itemtype == "checkbox"){
+ echo $itemvalue=='yes' ? gettext('yes') : gettext('no');
+ } else
+ if ($itemtype == "textarea"){
+ echo htmlspecialchars(base64_decode($itemvalue));
+ } else
+ echo htmlspecialchars($itemvalue);
+ }
}
-}
-function haproxy_htmllist($tablename,$rowvalues,$items,$editstate=false,$itemdetails=null){
- global $g, $counter;
- echo "<table class='' width='100%' cellpadding='0' cellspacing='0' id='$tablename'>
- <tr>";
- foreach($items as $item){
- echo "<td width='{$item['colwidth']}' class='listhdrr'>{$item['columnheader']}</td>";
- }
- echo "<td width='5%' class=''></td>
- </tr>";
- if (is_array($rowvalues)){
- foreach($rowvalues as $value){
- if (!$editstate) {
- echo "<tr id='tr_view_$counter' ondblclick='editRow($counter); return false;' >";
- $leftitem = true;
- foreach($items as $item) {
- $tdclass = $leftitem ? "vtable listlr" : "vtable listr";
- echo "<td class='$tdclass'>";
+ function haproxy_htmllist($rowvalues,$items,$editstate=false,$itemdetails=null){
+ $tablename = $this->tablename;
+ global $g, $counter;
+ echo "<table class='' width='100%' cellpadding='0' cellspacing='0' id='$tablename'>
+ <tr>";
+ foreach($items as $item){
+ echo "<td width='{$item['colwidth']}' class='listhdrr'>{$item['columnheader']}</td>";
+ }
+ echo "<td width='5%' class=''></td>
+ </tr>";
+ if (is_array($rowvalues)){
+ foreach($rowvalues as $keyid => $value){
+ if ($this->keyfield != "") {
+ if (preg_match("/[^0-9]/", $keyid))
+ $itemvalue = $keyid;
+ else
+ $itemvalue = $value[$this->keyfield];
+ $key = "<input name='{$tablename}_key{$counter}' id='{$tablename}_key{$counter}' type='hidden' value='{$itemvalue}'>";
+ } else
+ $key = "";
+
+ if (!$editstate) {
+ echo "<tr id='tr_view_$counter' ondblclick='editRow($counter); return false;' >";
+ $leftitem = true;
+ foreach($items as $item) {
+ $tdclass = $leftitem ? "vtable listlr" : "vtable listr";
+ echo "<td class='$tdclass'>";
+ $itemname = $item['name'];
+ $itemvalue = $value[$itemname];
+ if (isset($item['customdrawcell'])) {
+ $item['customdrawcell']($item, $itemvalue, false);
+ } else
+ $this->haproxy_htmllist_drawcell($item, $itemvalue, false, $itemname, $counter);
+ echo "</td>";
+ $leftitem = false;
+
+ }
+ echo "
+ <td class='list'>
+ <table border='0' cellspacing='0' cellpadding='1'><tr>
+ <td valign='middle'>
+ <img src='/themes/{$g['theme']}/images/icons/icon_e.gif' title='edit entry' width='17' height='17' border='0' onclick='editRow($counter); return false;' />
+ </td>
+ <td valign='middle'>
+ <img src='/themes/{$g['theme']}/images/icons/icon_x.gif' title='delete entry' width='17' height='17' border='0' onclick='deleteRow($counter, \"$tablename\"); return false;' />
+ </td>
+ <td valign='middle'>
+ <img src='/themes/{$g['theme']}/images/icons/icon_plus.gif' title='duplicate entry' width='17' height='17' border='0' onclick='dupRow($counter, \"$tablename\"); return false;' />
+ </td></tr></table>
+ </td>";
+ echo "</tr>";
+ }
+ $displaystyle = $editstate ? "" : "display: none;";
+ echo "<tr id='tr_edit_$counter' style='$displaystyle'>";
+ foreach($items as $item){
$itemname = $item['name'];
- $itemvalue = $value[$itemname];
+ $itemvalue = $value[$itemname];
+ echo "<td class='vtable'>".$key;
if (isset($item['customdrawcell'])) {
- $item['customdrawcell']($item, $itemvalue, false);
+ $item['customdrawcell']($item, $itemvalue, true, $item['name'].$counter);
} else
- haproxy_htmllist_drawcell($item, $itemvalue, false);
+ $this->haproxy_htmllist_drawcell($item, $itemvalue, true, $itemname, $counter);
echo "</td>";
- $leftitem = false;
+ $key = "";
}
echo "
<td class='list'>
<table border='0' cellspacing='0' cellpadding='1'><tr>
<td valign='middle'>
- <img src='/themes/{$g['theme']}/images/icons/icon_e.gif' title='edit entry' width='17' height='17' border='0' onclick='editRow($counter); return false;' />
- </td>
- <td valign='middle'>
- <img src='/themes/{$g['theme']}/images/icons/icon_x.gif' title='delete entry' width='17' height='17' border='0' onclick='deleteRow($counter, \"$tablename\"); return false;' />
+ <img src='/themes/{$g['theme']}/images/icons/icon_x.gif' title='delete entry' width='17' height='17' border='0' onclick='removeRow(this); return false;' />
</td>
<td valign='middle'>
<img src='/themes/{$g['theme']}/images/icons/icon_plus.gif' title='duplicate entry' width='17' height='17' border='0' onclick='dupRow($counter, \"$tablename\"); return false;' />
</td></tr></table>
</td>";
echo "</tr>";
- }
- $displaystyle = $editstate ? "" : "display: none;";
- echo "<tr id='tr_edit_$counter' style='$displaystyle'>";
- foreach($items as $item){
- $itemname = $item['name'];
- $itemvalue = $value[$itemname];
- $itemnamenr = $itemname . $counter;
- echo "<td class='vtable'>";
- if (isset($item['customdrawcell'])) {
- $item['customdrawcell']($item, $itemvalue, true, $itemnamenr);
- } else
- haproxy_htmllist_drawcell($item, $itemvalue, true, $itemnamenr);
- echo "</td>";
- }
- echo "
- <td class='list'>
- <table border='0' cellspacing='0' cellpadding='1'><tr>
- <td valign='middle'>
- <img src='/themes/{$g['theme']}/images/icons/icon_x.gif' title='delete entry' width='17' height='17' border='0' onclick='removeRow(this); return false;' />
- </td>
- <td valign='middle'>
- <img src='/themes/{$g['theme']}/images/icons/icon_plus.gif' title='duplicate entry' width='17' height='17' border='0' onclick='dupRow($counter, \"$tablename\"); return false;' />
- </td></tr></table>
- </td>";
- echo "</tr>";
- if (isset($itemdetails)) {
- $colspan = count($items)-1;
- echo "<tr id='tr_viewdetail_$counter'>";
- ?>
- <td class='vtable listlr' style='border-bottom-width: medium;vertical-align:top;'>
- <div style="position:relative;float:right;width:11px;height:11px;">
- <a onclick="htmltable_toggle_details('<?="htmltable_{$tablename}_{$counter}_details"?>')">
- <img id="htmltable_<?="{$tablename}_{$counter}"?>_details_off" alt="Expand advanced server settings"
- src="tree/plus.gif" style="clip:rect(19px 13px 30px 2px); top:-19px;position:absolute;"/>
- </a>
- </div>
- </td>
- <?
- echo "<td class='vtable listr' colspan='$colspan' style='border-bottom-width: medium;'>";
- $itemnr = 0;
- echo "<div id='htmltable_{$tablename}_{$counter}_details_view'>";
- $itemcount = count($itemdetails);
- foreach($itemdetails as $item) {
- echo "<div style='float: left;padding-right: 2px;'>";
- $tdclass = "";//$leftitem ? "vtable listlr" : "vtable listr";
- echo $item['columnheader'] . ": ";
- $itemname = $item['name'];
- $itemvalue = $value[$itemname];
- if (isset($item['customdrawcell'])) {
- $item['customdrawcell']($item, $itemvalue, false);
- } else
- haproxy_htmllist_drawcell($item, $itemvalue, false);
- $leftitem = false;
- $itemnr++;
- if ($itemcount != $itemnr)
- echo ", ";
+ if (isset($itemdetails)) {
+ $colspan = count($items)-1;
+ echo "<tr id='tr_viewdetail_$counter'>";
+ ?>
+ <td class='vtable listlr' style='border-bottom-width: medium;vertical-align:top;'>
+ <div style="position:relative;float:right;width:11px;height:11px;">
+ <a onclick="htmltable_toggle_details('<?="htmltable_{$tablename}_{$counter}_details"?>')">
+ <img id="htmltable_<?="{$tablename}_{$counter}"?>_details_off" alt="Expand advanced server settings"
+ src="tree/plus.gif" style="clip:rect(19px 13px 30px 2px); top:-19px;position:absolute;"/>
+ </a>
+ </div>
+ </td>
+ <?
+ echo "<td class='vtable listr' colspan='$colspan' style='border-bottom-width: medium;'>";
+ $itemnr = 0;
+ echo "<div id='htmltable_{$tablename}_{$counter}_details_view'>";
+ $itemcount = count($itemdetails);
+ foreach($itemdetails as $item) {
+ echo "<div style='float: left;padding-right: 2px;'>";
+ $tdclass = "";//$leftitem ? "vtable listlr" : "vtable listr";
+ echo $item['columnheader'] . ": ";
+ $itemname = $item['name'];
+ $itemvalue = $value[$itemname];
+ if (isset($item['customdrawcell'])) {
+ $item['customdrawcell']($item, $itemvalue, false);
+ } else
+ $this->haproxy_htmllist_drawcell($item, $itemvalue, false, $itemname, $counter);
+ $leftitem = false;
+ $itemnr++;
+ if ($itemcount != $itemnr)
+ echo ", ";
+ echo "</div>";
+ }
+ echo "</div>";
+ echo "<div id='htmltable_{$tablename}_{$counter}_details_edit' style='display:none;'>";
+ echo "<table class='tabcont' style='border-collapse:collapse' border='1' cellspacing='0' >";
+ $leftitem = true;
+ foreach($itemdetails as $item) {
+ echo "<tr id='tr_edititemdetails_$counter' ondblclick='editRow($counter); return false;'>";
+ $tdclass = "";//$leftitem ? "vtable listlr" : "vtable listr";
+ echo "<td style='border-right:0' class='$tdclass'>";
+ echo "{$item['columnheader']}: ";
+ echo "</td>";
+ echo "<td style='border-left:0' class='$tdclass'>";
+ $itemname = $item['name'];
+ $itemvalue = $value[$itemname];
+ echo "{$item['description']}<br/>";
+ if (isset($item['customdrawcell'])) {
+ $item['customdrawcell']($item, $itemvalue, true, $itemname . $counter);
+ } else
+ $this->haproxy_htmllist_drawcell($item, $itemvalue, true, $itemname, $counter);
+ echo "</td>";
+ $leftitem = false;
+ echo "</tr>";
+ }
+ echo "</table>";
echo "</div>";
- }
- echo "</div>";
- echo "<div id='htmltable_{$tablename}_{$counter}_details_edit' style='display:none;'>";
- echo "<table class='tabcont' style='border-collapse:collapse' border='1' cellspacing='0' >";
- $leftitem = true;
- foreach($itemdetails as $item) {
- echo "<tr id='tr_edititemdetails_$counter' ondblclick='editRow($counter); return false;'>";
- $tdclass = "";//$leftitem ? "vtable listlr" : "vtable listr";
- echo "<td style='border-right:0' class='$tdclass'>";
- echo "{$item['columnheader']}: ";
echo "</td>";
- echo "<td style='border-left:0' class='$tdclass'>";
- $itemname = $item['name'];
- $itemvalue = $value[$itemname];
- $itemnamenr = $itemname . $counter;
- echo "{$item['description']}<br/>";
- if (isset($item['customdrawcell'])) {
- $item['customdrawcell']($item, $itemvalue, true, $itemnamenr);
- } else
- haproxy_htmllist_drawcell($item, $itemvalue, true, $itemnamenr);
+ echo "</tr>";
+ }
+ if (isset($itemdetails)) {
+ $colspan = count($items)-1;
+ echo "<tr id='htmltable_{$tablename}_{$counter}_details' style='$displaystyle' >";
+ echo "<td class='vtable listlr' style='border-bottom-width: medium;'> </td>";
+ echo "<td class='vtable listr' colspan='$colspan' style='border-bottom-width: medium;'>";
echo "</td>";
- $leftitem = false;
- echo "</tr>";
+ echo "</tr>";
}
- echo "</table>";
- echo "</div>";
- echo "</td>";
- echo "</tr>";
- }
- if (isset($itemdetails)) {
- $colspan = count($items)-1;
- echo "<tr id='htmltable_{$tablename}_{$counter}_details' style='$displaystyle' >";
- echo "<td class='vtable listlr' style='border-bottom-width: medium;'> </td>";
- echo "<td class='vtable listr' colspan='$colspan' style='border-bottom-width: medium;'>";
- echo "</td>";
- echo "</tr>";
- }
-
-
-
- $counter++;
+
+ $counter++;
+ }
}
+ echo "</table>
+ <a onclick='javascript:addRowTo(\"$tablename\"); return false;' href='#'>
+ <img border='0' src='/themes/{$g['theme']}/images/icons/icon_plus.gif' alt='' title='add another entry' />
+ </a>";
}
- echo "</table>
- <a onclick='javascript:addRowTo(\"$tablename\"); return false;' href='#'>
- <img border='0' src='/themes/{$g['theme']}/images/icons/icon_plus.gif' alt='' title='add another entry' />
- </a>";
+}
+
+function haproxy_htmllist($tablename,$rowvalues,$items,$editstate=false,$itemdetails=null){
+ $list = new HaproxyHtmlList($tablename, $items);
+ $list->haproxy_htmllist($rowvalues, $items, $editstate, $itemdetails);
+}
+
+function haproxy_htmllist_get_values($html_list){
+ $list = new HaproxyHtmlList("-", $html_list);
+ return $list->haproxy_htmllist_get_values();
}
function haproxy_htmllist_js(){
-?><script type="text/javascript">
+?><script type="text/javascript">
+ function html_listitem_change(tableId, fieldId, rowNr, field) {
+ javascript_event = tableId + "_listitem_change";
+ var fn = window[javascript_event];
+ if (typeof fn === 'function'){
+ fn(tableId, fieldId, rowNr, field);
+ }
+ }
+
function htmllist_get_select_items(prefix,tableId) {
var items;
var i = tableId.lastIndexOf('_');
@@ -248,14 +322,21 @@ function haproxy_htmllist_js(){
td.innerHTML="<input size='" + items[i]['size'] + "' name='" + items[i]['name'] + totalrows +
"' id='" + items[i]['name'] + totalrows +
"'><\/input> ";
+ } else if(items[i]['type'] == 'textarea') {
+ td.innerHTML="<textarea cols='" + items[i]['size'] + "' rows='30' name='" + items[i]['name'] + totalrows +
+ "' id='" + items[i]['name'] + totalrows +
+ "'><\/textarea> ";
} else if(items[i]['type'] == 'select') {
seltext = htmllist_get_select_options(tableId, items[i]['name']);
td.innerHTML="<select style='width:" + items[i]['size'] + "' name='" + items[i]['name'] + totalrows +
- "' id='" + items[i]['name'] + totalrows +
- "'>" + seltext + "<\/select> ";
+ "' id='" + items[i]['name'] + totalrows + "' "+
+ "onchange='html_listitem_change(\""+tableId+"\",\""+items[i]['name']+"\",\""+totalrows+"\",this);' " +
+ ">" + seltext + "<\/select> ";
} else {
- td.innerHTML="<input type='checkbox' name='" + items[i]['name'] + totalrows +
- "' id='" + items[i]['name'] + totalrows + "' value='yes'><\/input> ";
+ td.innerHTML="<input type='checkbox' name='" + items[i]['name'] + totalrows +"'"+
+ "id='" + items[i]['name'] + totalrows + "' "+
+ "onclick='html_listitem_change(\""+tableId+"\",\""+items[i]['name']+"\",\""+totalrows+"\",this);' " +
+ "value='yes'><\/input> ";
}
tr.appendChild(td);
}
@@ -290,6 +371,12 @@ function haproxy_htmllist_js(){
td.appendChild(btable);
tr.appendChild(td);
tbody.appendChild(tr);
+
+ javascript_row_added = tableId + "_row_added";
+ var fn = window[javascript_row_added];
+ if (typeof fn === 'function'){
+ fn(tableId, totalrows);
+ }
});
})();
function dupRow(rowId, tableId) {
@@ -316,6 +403,11 @@ function haproxy_htmllist_js(){
else
newEl.value = dupEl.value;
}
+ javascript_row_added = tableId + "_row_added";
+ var fn = window[javascript_row_added];
+ if (typeof fn === 'function'){
+ fn(tableId, totalrows);
+ }
}
function editRow(num) {
var trview = document.getElementById('tr_view_' + num);
@@ -327,9 +419,12 @@ function haproxy_htmllist_js(){
var view = document.getElementById("tr_view_" + rowId);
var viewdetail = document.getElementById("tr_viewdetail_" + rowId);
var edit = document.getElementById("tr_edit_" + rowId);
- view.parentNode.removeChild(view);
- viewdetail.parentNode.removeChild(viewdetail);
- edit.parentNode.removeChild(edit);
+ if (view)
+ view.parentNode.removeChild(view);
+ if (viewdetail)
+ viewdetail.parentNode.removeChild(viewdetail);
+ if (edit)
+ edit.parentNode.removeChild(edit);
}
function removeRow(el) {
var cel;
diff --git a/config/haproxy-devel/haproxy_listeners.php b/config/haproxy-devel/haproxy_listeners.php
index 1deabdbb..ef7e01c4 100644
--- a/config/haproxy-devel/haproxy_listeners.php
+++ b/config/haproxy-devel/haproxy_listeners.php
@@ -3,7 +3,7 @@
/*
haproxy_listeners.php
part of pfSense (https://www.pfsense.org/)
- Copyright (C) 2013 PiBa-NL
+ 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.
@@ -36,11 +36,34 @@ 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;
@@ -70,10 +93,6 @@ if ($_GET['act'] == "del") {
}
}
-$pf_version=substr(trim(file_get_contents("/etc/version")),0,3);
-if ($pf_version < 2.0)
- $one_two = true;
-
$pgtitle = "Services: HAProxy: Frontends";
include("head.inc");
@@ -81,14 +100,37 @@ include("head.inc");
<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
<?php include("fbegin.inc"); ?>
<form action="haproxy_listeners.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; ?>
+<?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
@@ -100,6 +142,7 @@ include("head.inc");
<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>
@@ -107,7 +150,7 @@ include("head.inc");
<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="20%" class="listhdrr">Parent</td-->
<td width="5%" class="list"></td>
</tr>
<?php
@@ -124,10 +167,11 @@ include("head.inc");
$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[$ipport][] = $frontend2;
+ $a_frontend_grouped[$mainname][] = $frontend2;
}
ksort($a_frontend_grouped);
@@ -142,16 +186,29 @@ include("head.inc");
if ((count($a_frontend) > 1 || $last_frontend_shared) && !$first) {
?> <tr class="<?=$textgray?>"><td colspan="7">&nbsp;</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" style="<?=$frontend['secondary']=='yes'?"visibility:hidden;":""?>" ondblclick="document.location='haproxy_listeners_edit.php?id=<?=$frontendname;?>';">
+ <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;?>&amp;action=toggle&amp;", 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="listlr" ondblclick="document.location='haproxy_listeners_edit.php?id=<?=$frontendname;?>';">
+ <td class="listr" ondblclick="document.location='haproxy_listeners_edit.php?id=<?=$frontendname;?>';">
<?
$acls = get_frontend_acls($frontend);
$isaclset = "";
@@ -161,7 +218,7 @@ include("head.inc");
if ($isaclset)
echo "<img src=\"$img_acl\" title=\"" . gettext("acl's used") . ": {$isaclset}\" border=\"0\" />";
- if (strtolower($frontend['type']) == "http" && $frontend['ssloffload']) {
+ 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'])) {
@@ -182,8 +239,9 @@ include("head.inc");
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 );
+ $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:");
@@ -198,28 +256,53 @@ include("head.inc");
}
?>
</td>
- <td class="listlr" ondblclick="document.location='haproxy_listeners_edit.php?id=<?=$frontendname;?>';">
+ <td class="listr" ondblclick="document.location='haproxy_listeners_edit.php?id=<?=$frontendname;?>';">
<?=$frontend['name'];?>
</td>
- <td class="listlr" ondblclick="document.location='haproxy_listeners_edit.php?id=<?=$frontendname;?>';">
+ <td class="listr" ondblclick="document.location='haproxy_listeners_edit.php?id=<?=$frontendname;?>';">
<?=$frontend['desc'];?>
</td>
- <td class="listlr" ondblclick="document.location='haproxy_listeners_edit.php?id=<?=$frontendname;?>';">
- <?=str_replace(" ","&nbsp;",$frontend['ipport']);?>
+ <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="listlr" ondblclick="document.location='haproxy_listeners_edit.php?id=<?=$frontendname;?>';">
- <?=$frontend['type']?>
+ <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="listlr" ondblclick="document.location='haproxy_listeners_edit.php?id=<?=$frontendname;?>';">
+ <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;?>';">
+ <!--td class="listlr" ondblclick="document.location='haproxy_listeners_edit.php?id=<?=$frontendname;?>';">
<?=$frontend['secondary'] == 'yes' ? $frontend['primary_frontend'] : "";?>
- </td>
+ </td-->
<td class="list" nowrap>
<table border="0" cellspacing="0" cellpadding="1">
<tr>
diff --git a/config/haproxy-devel/haproxy_listeners_edit.php b/config/haproxy-devel/haproxy_listeners_edit.php
index d243ffb1..a13eca80 100644
--- a/config/haproxy-devel/haproxy_listeners_edit.php
+++ b/config/haproxy-devel/haproxy_listeners_edit.php
@@ -6,6 +6,7 @@
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
@@ -63,12 +64,15 @@ if (!is_array($config['installedpackages']['haproxy']['ha_backends']['item'])) {
$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','ssloffloadcert','dcertadv','ssloffload','ssloffloadacl','ssloffloadaclnondefault','advanced_bind',
'ssloffloadacladditional','ssloffloadacladditionalnondefault',
+ 'socket-stats',
'dontlognull','dontlog-normal','log-separate-errors','log-detailed');
if (isset($_POST['id']))
@@ -85,6 +89,10 @@ 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');
@@ -97,7 +105,7 @@ $fields_sslCertificates[0]['size']="500px";
$fields_sslCertificates[0]['items']=&$servercerts;
$certs_ca = haproxy_get_certificates('ca');
-$ca_none['']['name']="None";
+$ca_none['']['name']="(None), allows for client without a (valid) certificate to connect. Make sure to add appropriate acl's.";
$certs_ca = $ca_none + $certs_ca;
$fields_caCertificates=array();
$fields_caCertificates[0]['name']="cert_ca";
@@ -108,8 +116,8 @@ $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;
+//$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";
@@ -132,17 +140,56 @@ $fields_aclSelectionList[1]['type']="select";
$fields_aclSelectionList[1]['size']="10";
$fields_aclSelectionList[1]['items']=&$a_acltypes;
-$fields_aclSelectionList[2]['name']="value";
-$fields_aclSelectionList[2]['columnheader']="Value";
-$fields_aclSelectionList[2]['colwidth']="35%";
-$fields_aclSelectionList[2]['type']="textbox";
-$fields_aclSelectionList[2]['size']="35";
+$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];
@@ -164,8 +211,8 @@ if ($_POST) {
$pconfig = $_POST;
if ($pconfig['secondary'] != "yes") {
- $reqdfields = explode(" ", "name type port");
- $reqdfieldsn = explode(",", "Name,Type,Port");
+ $reqdfields = explode(" ", "name type");
+ $reqdfieldsn = explode(",", "Name,Type");
} else {
$reqdfields = explode(" ", "name");
$reqdfieldsn = explode(",", "Name");
@@ -208,6 +255,10 @@ if ($_POST) {
$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'];
@@ -247,6 +298,7 @@ if ($_POST) {
$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;
@@ -275,7 +327,6 @@ include("head.inc");
if (!isset($_GET['dup']))
$excludefrontend = $pconfig['name'];
$primaryfrontends = get_haproxy_frontends($excludefrontend);
-$interfaces = haproxy_get_bindable_interfaces();
?>
<style type="text/css">
@@ -329,6 +380,9 @@ $interfaces = haproxy_get_bindable_interfaces();
if (tableId == 'table_clientcert_crl'){
seltext = "<?=haproxy_js_select_options($certs_crl);?>";
}
+ if (tableId == 'table_extaddr'){
+ seltext = "<?=haproxy_js_select_options($interfaces);?>";
+ }
return seltext;
}
@@ -343,20 +397,26 @@ $interfaces = haproxy_get_bindable_interfaces();
}
}
}
-
function updatevisibility() {
d = document;
+ ssl = false;
ssloffload = d.getElementById("ssloffload");
+ for (i = 0; i < 99; i++) {
+ customEdit = document.getElementById("extaddr_ssl"+i);
+ if (customEdit && customEdit.checked)
+ ssl = true;
+ }
var type;
var secondary = d.getElementById("secondary");
var primary_frontend = d.getElementById("primary_frontend");
- if ((secondary !== null) && (secondary.checked))
+ if ((secondary !== null) && (secondary.checked)) {
type = primaryfrontends[primary_frontend.value]['ref']['type'];
- else
+ ssl = ssloffload.checked;
+ } else
type = d.getElementById("type").value;
- setCSSdisplay(".haproxy_ssloffloading_enabled", ssloffload.checked);
+ setCSSdisplay(".haproxy_ssloffloading_enabled", ssl);
setCSSdisplay(".haproxy_mode_http", type == "http");
if (secondary !== null) {
setCSSdisplay(".haproxy_primary", !secondary.checked);
@@ -481,25 +541,45 @@ $interfaces = haproxy_get_bindable_interfaces();
<tr class="haproxy_primary">
<td width="22%" valign="top" class="vncellreq">External address</td>
<td width="78%" class="vtable">
- <?
- echo_html_select('extaddr', $interfaces, $pconfig['extaddr']);
- ?>
+ <?
+ $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="vncellreq">External port</td>
- <td width="78%" class="vtable" colspan="2">
- <input name="port" id="port" type="text" <?if(isset($pconfig['port'])) echo "value=\"{$pconfig['port']}\"";?> size="10" maxlength="500" />
- <div>The port to listen to. To specify multiple ports, separate with a comma (,). EXAMPLE: 80,8000</div>
- </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" />
@@ -526,8 +606,8 @@ $interfaces = haproxy_get_bindable_interfaces();
<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</option>
- <option value="https"<?php if($pconfig['type'] == "https") echo " SELECTED"; ?>>HTTPS</option>
+ <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/>
@@ -541,7 +621,6 @@ $interfaces = haproxy_get_bindable_interfaces();
<td width="22%" valign="top" class="vncell">Access Control lists</td>
<td width="78%" class="vtable" colspan="2" valign="top">
<?
- $counter=0;
$a_acl = $pconfig['a_acl'];
haproxy_htmllist("tableA_acltable", $a_acl, $fields_aclSelectionList, true);
?>
@@ -552,6 +631,17 @@ $interfaces = haproxy_get_bindable_interfaces();
</tr>
<tr class="haproxy_primary"><td>&nbsp;</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 &amp; providing separate statistics for each socket.
+ </td>
+ </tr>
+ <tr class="haproxy_primary"><td>&nbsp;</td></tr>
+ <tr class="haproxy_primary">
<td colspan="2" valign="top" class="listtopic">Logging options</td>
</tr>
<tr class="haproxy_primary" align="left">
@@ -613,10 +703,6 @@ $interfaces = haproxy_get_bindable_interfaces();
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/>
- <br/>
- It is important to note that as long as HAProxy does not support keep-alive connections,
- only the first request of a connection will receive the header. For this reason,
- it is important to ensure that option httpclose is set when using this option.
</td>
</tr>
<tr align="left" class="haproxy_mode_http">
@@ -649,21 +735,24 @@ $interfaces = haproxy_get_bindable_interfaces();
<td>&nbsp;</td>
</tr>
</table>
- <table class="haproxy_mode_http" width="100%" border="0" cellpadding="6" cellspacing="0">
+ <table class="haproxy_ssloffloading_enabled" 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="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>Use Offloading</strong>
- <br/>
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">
@@ -671,10 +760,9 @@ $interfaces = haproxy_get_bindable_interfaces();
echo_html_select("ssloffloadcert", $servercerts, $pconfig['ssloffloadcert'], '<b>No Certificates defined.</b> <br/>Create one under <a href="system_certmanager.php">System &gt; Cert Manager</a>.');
?>
<br/>
- NOTE: choose the cert to use on this frontend.
+ 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 'CN')<br/>
- <input id="ssloffloadaclnondefault" name="ssloffloadaclnondefault" type="checkbox" value="yes" <?php if ($pconfig['ssloffloadaclnondefault']=='yes') echo "checked";?> onclick="updatevisibility();" />Add ACL for certificate CommonName for nondefault ports. (host header starts with 'CN:')
+ <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">
@@ -686,8 +774,7 @@ $interfaces = haproxy_get_bindable_interfaces();
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 'CN')<br/>
- <input id="ssloffloadacladditionalnondefault" name="ssloffloadacladditionalnondefault" type="checkbox" value="yes" <?php if ($pconfig['ssloffloadacladditionalnondefault']=='yes') echo "checked";?> onclick="updatevisibility();" />Add ACL for certificate CommonName for nondefault ports. (host header starts with 'CN:')
+ <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">
@@ -700,7 +787,8 @@ $interfaces = haproxy_get_bindable_interfaces();
</td>
</tr>
<tr class="haproxy_ssloffloading_enabled haproxy_primary">
- <td class="vncell" colspan="2"><b>Client certificate verification options, leave this empty if you do want to ask for a client certificate</b></td>
+ <td class="vncell" colspan="2"><b>Client certificate verification options, leave this 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">
<td width="22%" valign="top" class="vncell">Client verification CA certificates</td>
@@ -754,14 +842,24 @@ $interfaces = haproxy_get_bindable_interfaces();
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; ?>;
- updatevisibility();
- var customarray = <?= json_encode(get_alias_list(array("port", "url_ports", "urltable_ports"))) ?>;
- var oTextbox1 = new AutoSuggestControl(document.getElementById("port"), new StateSuggestions(customarray));
+ 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();
diff --git a/config/haproxy-devel/haproxy_pool_edit.php b/config/haproxy-devel/haproxy_pool_edit.php
index 30079847..5e38b12d 100644
--- a/config/haproxy-devel/haproxy_pool_edit.php
+++ b/config/haproxy-devel/haproxy_pool_edit.php
@@ -42,6 +42,8 @@ if (!is_array($config['installedpackages']['haproxy']['ha_pools']['item'])) {
$a_pools = &$config['installedpackages']['haproxy']['ha_pools']['item'];
+$a_files = haproxy_get_fileslist();
+
if (isset($_POST['id']))
$id = $_POST['id'];
else
@@ -172,6 +174,19 @@ $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']);
@@ -179,6 +194,9 @@ if (isset($id) && $a_pools[$id]) {
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']))
@@ -269,6 +287,8 @@ if ($_POST) {
$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.";
@@ -356,6 +376,9 @@ foreach($simplefields as $field){
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);?>";
}
@@ -767,7 +790,7 @@ set by the 'retries' parameter.</div>
<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 PHPSESSIONID ASP.NET_SessionId
+ EXAMPLE: MyLoadBalanceCookie JSESSIONID PHPSESSID ASP.NET_SessionId
</td>
</tr>
<tr class="haproxy_cookie_visible" align="left">
@@ -920,6 +943,21 @@ set by the 'retries' parameter.</div>
</tr>
<tr><td>&nbsp;</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>&nbsp;</td></tr>
+ <tr>
<td colspan="2" valign="top" class="listtopic">Advanced</td>
</tr>
<tr class="" align="left" id='Strict-Transport-Security'>
@@ -961,9 +999,11 @@ set by the 'retries' parameter.</div>
<?
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;
diff --git a/config/haproxy-devel/haproxy_stats.php b/config/haproxy-devel/haproxy_stats.php
index 10dd136a..302793b6 100644
--- a/config/haproxy-devel/haproxy_stats.php
+++ b/config/haproxy-devel/haproxy_stats.php
@@ -32,6 +32,10 @@ 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 = "";
@@ -79,48 +83,6 @@ if (!is_array($config['installedpackages']['haproxy']['ha_backends']['item'])) {
}
$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);
@@ -177,31 +139,16 @@ echo "</td>";
<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,<br/>
- 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)<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'.
- Or create a backend specifically for serving stats, for that you can start with the 'stats example' template below.<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>&nbsp;</td>
</tr>
<tr>
- <td colspan="2" valign="top" class="listtopic">Stats example template</td>
- </tr>
- <tr>
- <td width="22%" valign="top" class="vncell">Example</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/>
- <a href="haproxy_stats.php?add_stats_example=1">TEMPLATE: Create stats example configuration using a frontend/backend combination with ssl</a><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>&nbsp;</td>
- </tr>
- <tr>
<td colspan="2" valign="top" class="listtopic">HAProxy stick-tables</td>
</tr>
<tr>
@@ -241,7 +188,7 @@ echo "</td>";
<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.<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/>
<? } ?>
<?}?>
diff --git a/config/haproxy-devel/haproxy_templates.php b/config/haproxy-devel/haproxy_templates.php
new file mode 100644
index 00000000..478c83a3
--- /dev/null
+++ b/config/haproxy-devel/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>&nbsp;</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>&nbsp;</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>&nbsp;</td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/haproxy-devel/haproxy_utils.inc b/config/haproxy-devel/haproxy_utils.inc
index 08906bb0..4b945c06 100644
--- a/config/haproxy-devel/haproxy_utils.inc
+++ b/config/haproxy-devel/haproxy_utils.inc
@@ -2,7 +2,7 @@
/*
haproxy_utils.php
part of pfSense (https://www.pfsense.org/)
- Copyright (C) 2013 PiBa-NL
+ Copyright (C) 2013-2015 PiBa-NL
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -35,6 +35,30 @@ require_once("config.inc");
class haproxy_utils {
public static $pf_version;
+
+ public function query_dns($host, $querytype="A,AAAA", $dnsserver = "127.0.0.1") {
+ $result = array();
+ $host = trim($host, " \t\n\r\0\x0B[];\"'");
+ $host_esc = escapeshellarg($host);
+ $types = explode(',',$querytype);
+ foreach($types as $type){
+ $resolved = gethostbyname($host);
+ if($resolved) {
+ $resolved = array();
+ if (haproxy_utils::$pf_version < '2.2')
+ exec("/usr/bin/dig {$host_esc} $type @$dnsserver | /usr/bin/grep {$host_esc} | /usr/bin/grep -v ';' | /usr/bin/awk '{ print $5 }'", $resolved);
+ else
+ exec("/usr/bin/drill {$host_esc} $type @$dnsserver | /usr/bin/grep {$host_esc} | /usr/bin/grep -v ';' | /usr/bin/awk '{ print $5 }'", $resolved);
+ foreach($resolved as $item) {
+ $newitem = array();
+ $newitem["typeid"] = $type;
+ $newitem["data"] = $item;
+ $result[] = $newitem;
+ }
+ }
+ }
+ return $result;
+ }
}
haproxy_utils::$pf_version = substr(trim(file_get_contents("/etc/version")),0,3);
diff --git a/config/haproxy-devel/pkg/haproxy_upgrade_config.inc b/config/haproxy-devel/pkg/haproxy_upgrade_config.inc
new file mode 100644
index 00000000..9dd575dd
--- /dev/null
+++ b/config/haproxy-devel/pkg/haproxy_upgrade_config.inc
@@ -0,0 +1,174 @@
+<?php
+/*
+ haproxy.inc
+ Copyright (C) 2015 PiBa-NL
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require_once("pkg-utils.inc");
+
+function haproxy_upgrade_config() {
+ global $config, $static_output;
+ // for future config upgrades.
+ // make sure the version stays 'comparable'
+ if (is_arrayset($config,'installedpackages','haproxy') && isset($config['installedpackages']['haproxy']['configversion']))
+ $configversion = $config['installedpackages']['haproxy']['configversion'];
+ else
+ $configversion = "00.12";
+
+ $static_output .= "HAProxy, from version $configversion\n";
+ update_output_window($static_output);
+
+ $writeconfigupdate = false;
+ if ($configversion < "00.13") {
+ /* Do XML upgrade from haproxy 0.31 to haproxy-dev */
+ if (is_array($config['installedpackages']['haproxy']['ha_servers'])) {
+ $static_output .= "HAProxy, Do XML upgrade from haproxy 0.31 to haproxy-dev\n";
+ update_output_window($static_output);
+
+ /* We have an old config */
+ $config['installedpackages']['haproxy']['ha_pools']['item'] = array();
+ $a_global = &$config['installedpackages']['haproxy'];
+ $a_backends = &$config['installedpackages']['haproxy']['ha_backends']['item'];
+ $a_oldservers = &$config['installedpackages']['haproxy']['ha_servers']['item'];
+ $a_pools = &$config['installedpackages']['haproxy']['ha_pools']['item'];
+
+ foreach ($a_backends as $id => $be) {
+ $a_backends[$id]['status'] = 'active';
+ }
+ $id = 0;
+ foreach ($a_oldservers as $oldserver) {
+ $pool=$oldserver;
+ /* make server sub array */
+ $server=array();
+ $server['name'] = $oldserver['name'];
+ $server['address'] = $oldserver['address'];
+ $server['port'] = $oldserver['port'];
+ $server['weight'] = $oldserver['weight'];
+ $a_servers=array();
+ $a_servers[]=$server;
+ /* set new pool */
+ $pool['name'] = "pool$id";
+ $id++;
+ $pool['ha_servers']['item']=$a_servers;
+ /* link to frontend */
+ foreach ($a_backends as $id => $be) {
+ if ($a_backends[$id]['name'] == $oldserver['backend']) {
+ $a_backends[$id]['backend_serverpool'] = $pool['name'];
+ $pool['monitor_uri'] = $be['monitor_uri'];
+ unset($a_backends[$id]['monitor_uri']);
+ break;
+ }
+ }
+ unset($pool['backend']);
+ unset($pool['address']);
+ unset($pool['port']);
+ unset($pool['weight']);
+ $a_pools[] = $pool;
+ }
+ unset($config['installedpackages']['haproxy']['ha_servers']);
+ $writeconfigupdate = true;
+ }
+
+ /* XML update to: pkg v1.3 and 'pool' changed to 'backend_serverpool' because 'pool' was added to listtags() in xmlparse.inc */
+ if (is_arrayset($config,'installedpackages','haproxy','ha_backends','item',0,'pool')) {
+ $static_output .= "HAProxy, Do XML upgrade, change to backend_serverpool from pool array\n";
+ update_output_window($static_output);
+
+ foreach($config['installedpackages']['haproxy']['ha_backends']['item'] as &$frontend)
+ {
+ $backend_serverpool = $frontend['pool'][0];
+ $frontend['backend_serverpool'] = $backend_serverpool;
+ unset($frontend['pool']);
+ }
+ $writeconfigupdate = true;
+ }
+ //also move setting for existing 2.0 installations as only the new variable is used
+ if (is_arrayset($config,'installedpackages','haproxy','ha_backends','item',0) &&
+ isset($config['installedpackages']['haproxy']['ha_backends']['item'][0]['pool'])) {
+ $static_output .= "HAProxy, Do XML upgrade, change to backend_serverpool from pool\n";
+ update_output_window($static_output);
+ foreach($config['installedpackages']['haproxy']['ha_backends']['item'] as &$frontend)
+ {
+ $backend_serverpool = $frontend['pool'];
+ $frontend['backend_serverpool'] = $backend_serverpool;
+ unset($frontend['pool']);
+ }
+ $writeconfigupdate = true;
+ }
+ // update config to "haproxy-devel 1.5-dev19 pkg v0.5"
+ if(is_arrayset($config,'installedpackages','haproxy','ha_backends','item')) {
+ $static_output .= "HAProxy, Do XML upgrade, update frontend options\n";
+ update_output_window($static_output);
+ foreach ($config['installedpackages']['haproxy']['ha_backends']['item'] as &$bind) {
+ if($bind['httpclose'] && $bind['httpclose'] == "yes" ) {
+ $bind['httpclose'] = "httpclose";
+ $writeconfigupdate = true;
+ }
+ if (!$bind['extaddr']){
+ $bind['extaddr'] = "wan_ipv4";
+ $writeconfigupdate = true;
+ }
+ if ($bind['extaddr'] == "localhost"){
+ $bind['extaddr'] = "localhost_ipv4";
+ $writeconfigupdate = true;
+ }
+ if ($bind['extaddr'] == "any"){
+ $bind['extaddr'] = "any_ipv4";
+ $writeconfigupdate = true;
+ }
+ }
+ }
+ }
+ if ($configversion < "00.13") {
+ // update config to "haproxy-devel 1.5-dev19 pkg v0.13"
+ foreach ($config['installedpackages']['haproxy']['ha_backends']['item'] as &$bind) {
+ if (isset($bind['extaddr'])) {
+ $new['extaddr'] = $bind['extaddr'];
+ $new['extaddr_port'] = $bind['port'];
+ $new['extaddr_ssl'] = $bind['ssloffload'];
+ $bind['a_extaddr']['item'][] = $new;
+ }
+ unset($bind['extaddr']);
+ unset($bind['port']);
+ //unset($bind['ssloffload']);
+ }
+ $configversion = "00.13";
+ }
+ if ($configversion < "00.16") {
+ $static_output .= "HAProxy, 00.16\n";
+ $static_output .= "HAProxy, NOTICE: Changes to certificate acl's might need adjusting current config accordingly.\n";
+ $static_output .= "HAProxy, NOTICE: Certificate acls are now combined with user acls.\n";
+ update_output_window($static_output);
+ $configversion = "00.16";
+ }
+
+ $writeconfigupdate = $config['installedpackages']['haproxy']['configversion'] <> $configversion;
+ if ($writeconfigupdate) {
+ $config['installedpackages']['haproxy']['configversion'] = $configversion;
+ $static_output .= "HAProxy, write updated config to version: $configversion\n";
+ update_output_window($static_output);
+ write_config("HAProxy, update xml config version");
+ }
+}
diff --git a/config/haproxy-devel/pkg_haproxy_tabs.inc b/config/haproxy-devel/pkg_haproxy_tabs.inc
index 8cb280f8..a74ee20a 100644
--- a/config/haproxy-devel/pkg_haproxy_tabs.inc
+++ b/config/haproxy-devel/pkg_haproxy_tabs.inc
@@ -12,7 +12,10 @@ $haproxy_tab_array['haproxy'] = array();
$haproxy_tab_array['haproxy']['settings'] = Array(name => "Settings", url => "haproxy_global.php");
$haproxy_tab_array['haproxy']['frontend'] = Array(name => "Frontend", url => "haproxy_listeners.php");
$haproxy_tab_array['haproxy']['backend'] = Array(name => "Backend", url => "haproxy_pools.php");
+$haproxy_tab_array['haproxy']['files'] = Array(name => "Files", url => "haproxy_files.php");
$haproxy_tab_array['haproxy']['stats'] = Array(name => "Stats", url => "haproxy_stats.php");
+$haproxy_tab_array['haproxy']['statsfs'] = Array(name => "Stats FS", url => "haproxy_stats.php?haproxystats=1");
+$haproxy_tab_array['haproxy']['templates'] = Array(name => "Templates", url => "haproxy_templates.php");
function haproxy_display_top_tabs_active($top_tabs, $activetab) {
$tab_array = array();
diff --git a/config/haproxy-devel/www/javascript/haproxy_geturl.js b/config/haproxy-devel/www/javascript/haproxy_geturl.js
new file mode 100644
index 00000000..5df80646
--- /dev/null
+++ b/config/haproxy-devel/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);
+ }
+}