aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--config/haproxy-devel/haproxy.inc123
-rw-r--r--config/haproxy-devel/haproxy.xml15
-rwxr-xr-xconfig/haproxy-devel/haproxy_global.php8
-rw-r--r--config/haproxy-devel/haproxy_listeners.php8
-rw-r--r--config/haproxy-devel/haproxy_pool_edit.php35
-rw-r--r--config/haproxy-devel/haproxy_pools.php8
6 files changed, 161 insertions, 36 deletions
diff --git a/config/haproxy-devel/haproxy.inc b/config/haproxy-devel/haproxy.inc
index 89103ef8..0f6de3de 100644
--- a/config/haproxy-devel/haproxy.inc
+++ b/config/haproxy-devel/haproxy.inc
@@ -422,6 +422,9 @@ function write_backend($fd, $name, $pool, $frontend) {
$pool['retries'] = 3;
fwrite ($fd, "\tretries\t\t\t" . $pool['retries'] . "\n");
+ if ($pool['transparent_clientip'])
+ fwrite ($fd, "\tsource 0.0.0.0 usesrc clientip\n");
+
if($pool['stats_enabled']=='yes') {
fwrite ($fd, "\tstats\t\t\tenable\n");
if($pool['stats_uri'])
@@ -505,13 +508,17 @@ function write_backend($fd, $name, $pool, $frontend) {
}
function haproxy_configure() {
+ global $g;
// reload haproxy
- haproxy_writeconf();
+ haproxy_writeconf("{$g['varetc_path']}/haproxy.cfg");
return haproxy_check_run(1);
}
-function haproxy_check_writtenconfig_error(&$messages) {
- $retval = exec("haproxy -c -V -f /var/etc/haproxy.cfg 2>&1", $output, $err);
+function haproxy_check_and_run(&$messages, $reload) {
+ global $g;
+ $configname = "{$g['varetc_path']}/haproxy.cfg";
+ haproxy_writeconf("$configname.new");
+ $retval = exec("haproxy -c -V -f $configname.new 2>&1", $output, $err);
$messages = "";
if ($err > 1)
$messages = "<h2><strong>FATAL ERROR CODE: $err while starting haproxy</strong></h2>";
@@ -523,17 +530,24 @@ function haproxy_check_writtenconfig_error(&$messages) {
foreach($output as $line)
$messages .= "<br/>" . htmlspecialchars($line) . "\n";
}
- return (strstr($retval, "Configuration file is valid"));
+ $ok = strstr($retval, "Configuration file is valid");
+ if ($ok && $reload) {
+ global $haproxy_run_message;
+ exec("mv $configname.new $configname");
+ $ok = haproxy_check_run(1) == 0;
+ $messages = $haproxy_run_message;
+ }
+ return $ok;
}
-function haproxy_writeconf() {
- global $config, $g;
+function haproxy_writeconf($configfile) {
+ global $config;
$a_global = &$config['installedpackages']['haproxy'];
$a_backends = &$config['installedpackages']['haproxy']['ha_backends']['item'];
$a_pools = &$config['installedpackages']['haproxy']['ha_pools']['item'];
- $fd = fopen("{$g['varetc_path']}/haproxy.cfg", "w");
+ $fd = fopen($configfile, "w");
if(is_array($a_global)) {
fwrite ($fd, "global\n");
@@ -541,7 +555,10 @@ function haproxy_writeconf() {
if($a_global['remotesyslog'])
fwrite ($fd, "\tlog\t\t\t{$a_global['remotesyslog']}\t{$a_global['logfacility']}\t{$a_global['loglevel']}\n");
fwrite ($fd, "\tstats socket /tmp/haproxy.socket level admin\n");
- fwrite ($fd, "\tuid\t\t\t80\n");
+
+ if(!use_transparent_clientip_proxying())
+ fwrite ($fd, "\tuid\t\t\t80\n");
+
fwrite ($fd, "\tgid\t\t\t80\n");
// Set numprocs if defined or use system default (#cores)
if($a_global['nbproc'])
@@ -831,13 +848,91 @@ function haproxy_is_running() {
return $running;
}
+
+function haproxy_load_modules() {
+ // On FreeBSD 8 ipfw is needed to allow 'transparent' proxying (getting reply's to a non-local ip to pass back to the client-socket)..
+ // On FreeBSD 9 it is probably possible to do the same with the pf option "divert-reply"
+ mute_kernel_msgs();
+ if (!is_module_loaded("ipfw.ko")) {
+ mwexec("/sbin/kldload ipfw");
+ /* make sure ipfw is not on pfil hooks */
+ mwexec("/sbin/sysctl net.inet.ip.pfil.inbound=\"pf\" net.inet6.ip6.pfil.inbound=\"pf\"" .
+ " net.inet.ip.pfil.outbound=\"pf\" net.inet6.ip6.pfil.outbound=\"pf\"");
+ }
+ /* Activate layer2 filtering */
+ mwexec("/sbin/sysctl net.link.ether.ipfw=1");
+ unmute_kernel_msgs();
+}
+
+function use_transparent_clientip_proxying() {
+ global $config;
+ $a_backends = &$config['installedpackages']['haproxy']['ha_pools']['item'];
+ foreach ($a_backends as $backend) {
+ if ($backend["transparent_clientip"] == 'yes') {
+ return true;
+ break;
+ }
+ }
+ return false;
+}
+
+function load_ipfw_rules() {
+ // On FreeBSD 8 pf does not support "divert-reply" so ipfw is needed.
+ global $g, $config;
+ $ipfw_zone_haproxy = "haproxy";
+
+ $a_backends = &$config['installedpackages']['haproxy']['ha_pools']['item'];
+
+ haproxy_load_modules();
+
+ $transparent_backends = array();
+ foreach ($a_backends as $backend) {
+ if ($backend["transparent_clientip"] != 'yes')
+ continue;
+ $real_if = get_real_interface($backend["transparent_interface"]);
+ $a_servers = &$backend['ha_servers']['item'];
+ foreach($a_servers as $server) {
+ if (is_array($a_servers)) {
+
+ foreach($a_servers as $be) {
+ if (!$be['status'] == "inactive")
+ continue;
+ if (!is_ipaddr($be['address']))
+ continue;
+ $item = array();
+ $item['address'] = $be['address'];
+ $item['port'] = $be['port'];
+ $item['interface'] = $real_if;//"em0";
+ $transparent_backends[] = $item;
+ }
+ }
+ }
+ }
+ mwexec("/usr/local/sbin/ipfw_context -a $ipfw_zone_haproxy", true);
+ mwexec("/usr/local/sbin/ipfw_context -a $ipfw_zone_haproxy -n em0", true);
+ $rulenum = 64000; // why that high? captiveportal.inc also does it...
+ $rules = "flush\n";
+ foreach($transparent_backends as $transparent_be) {
+ $rules .= "add $rulenum fwd localhost tcp from {$transparent_be["address"]} {$transparent_be["port"]} to any in recv {$transparent_be["interface"]}\n";
+ $rulenum++;
+ }
+
+
+ file_put_contents("{$g['tmp_path']}/ipfw_{$ipfw_zone_haproxy}.haproxy.rules", $rules);
+ mwexec("/usr/local/sbin/ipfw_context -s $ipfw_zone_haproxy", true);
+ mwexec("/sbin/ipfw -x $ipfw_zone_haproxy -q {$g['tmp_path']}/ipfw_{$ipfw_zone_haproxy}.haproxy.rules", true);
+}
+
function haproxy_check_run($reload) {
- global $config, $g;
+ global $config, $g, $haproxy_run_message;
$a_global = &$config['installedpackages']['haproxy'];
exec("/usr/bin/limits -n 300014");
+ if(use_transparent_clientip_proxying())
+ load_ipfw_rules();
+
if(isset($a_global['enable'])) {
if (isset($a_global['carpdev'])) {
$status = get_carp_interface_status($a_global['carpdev']);
@@ -856,16 +951,18 @@ function haproxy_check_run($reload) {
return (0);
if (haproxy_is_running()) {
- exec("/usr/local/sbin/haproxy -f /var/etc/haproxy.cfg -p /var/run/haproxy.pid -st `cat /var/run/haproxy.pid`");
+ exec("/usr/local/sbin/haproxy -f /var/etc/haproxy.cfg -p /var/run/haproxy.pid -st `cat /var/run/haproxy.pid` 2>&1", $output, $errcode);
} else {
- exec("/usr/local/sbin/haproxy -f /var/etc/haproxy.cfg -p /var/run/haproxy.pid -D");
+ exec("/usr/local/sbin/haproxy -f /var/etc/haproxy.cfg -p /var/run/haproxy.pid -D 2>&1", $output, $errcode);
}
- return (0);
+ foreach($output as $line)
+ $haproxy_run_message .= "<br/>" . htmlspecialchars($line) . "\n";
+ return ($errcode);
} else {
if ($reload && haproxy_is_running()) {
exec("/bin/pkill -F /var/run/haproxy.pid haproxy");
}
- return (1);
+ return (0);
}
}
diff --git a/config/haproxy-devel/haproxy.xml b/config/haproxy-devel/haproxy.xml
index 39ec183e..0d03527c 100644
--- a/config/haproxy-devel/haproxy.xml
+++ b/config/haproxy-devel/haproxy.xml
@@ -89,6 +89,21 @@
<chmod>077</chmod>
<item>http://www.pfsense.com/packages/config/haproxy-devel/haproxy_pool_edit.php</item>
</additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/haproxy-devel/haproxy_socketinfo.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/widgets/include/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/haproxy-devel/haproxy.widget.inc</item>
+ </additional_files_needed>
+ <additional_files_needed>
+ <prefix>/usr/local/www/widgets/widgets/</prefix>
+ <chmod>077</chmod>
+ <item>http://www.pfsense.com/packages/config/haproxy-devel/haproxy.widget.php</item>
+ </additional_files_needed>
<custom_delete_php_command>
</custom_delete_php_command>
<custom_add_php_command>
diff --git a/config/haproxy-devel/haproxy_global.php b/config/haproxy-devel/haproxy_global.php
index 2ff65c0e..7ff0fb65 100755
--- a/config/haproxy-devel/haproxy_global.php
+++ b/config/haproxy-devel/haproxy_global.php
@@ -42,13 +42,7 @@ if ($_POST) {
$pconfig = $_POST;
if ($_POST['apply']) {
- $retval = 0;
- config_lock();
- $retval = haproxy_configure();
- config_unlock();
-
- $result = haproxy_check_writtenconfig_error($messages);
- $savemsg = $messages;
+ $result = haproxy_check_and_run($savemsg, true);
if ($result)
unlink_if_exists($d_haproxyconfdirty_path);
} else {
diff --git a/config/haproxy-devel/haproxy_listeners.php b/config/haproxy-devel/haproxy_listeners.php
index 03262c48..d634ded4 100644
--- a/config/haproxy-devel/haproxy_listeners.php
+++ b/config/haproxy-devel/haproxy_listeners.php
@@ -42,13 +42,7 @@ if ($_POST) {
$pconfig = $_POST;
if ($_POST['apply']) {
- $retval = 0;
- config_lock();
- $retval = haproxy_configure();
- config_unlock();
-
- $result = haproxy_check_writtenconfig_error($messages);
- $savemsg = $messages;
+ $result = haproxy_check_and_run($savemsg, true);
if ($result)
unlink_if_exists($d_haproxyconfdirty_path);
}
diff --git a/config/haproxy-devel/haproxy_pool_edit.php b/config/haproxy-devel/haproxy_pool_edit.php
index a1a3c69e..e282504a 100644
--- a/config/haproxy-devel/haproxy_pool_edit.php
+++ b/config/haproxy-devel/haproxy_pool_edit.php
@@ -50,7 +50,7 @@ if (isset($_GET['dup']))
global $simplefields;
$simplefields = array(
-"name","cookie","balance",
+"name","cookie","balance","transparent_clientip","transparent_interface",
"check_type","checkinter","httpcheck_method","monitor_uri","monitor_httpversion","monitor_username","monitor_domain","monitor_agentport",
"connection_timeout","server_timeout","retries",
"stats_enabled","stats_username","stats_password","stats_uri","stats_realm","stats_admin","stats_node_enabled","stats_node","stats_desc","stats_refresh");
@@ -235,6 +235,8 @@ foreach($simplefields as $field){
.haproxy_check_http{display:none;}
.haproxy_check_username{display:none;}
.haproxy_check_smtp{display:none;}
+ .haproxy_transparent_clientip{display:none;}
+ .haproxy_check_agent{display:none;}
</style>
<script language="javascript">
function clearcombo(){
@@ -271,6 +273,9 @@ foreach($simplefields as $field){
setCSSdisplay(".haproxy_check_smtp", check_type == 'SMTP' || check_type == 'ESMTP');
setCSSdisplay(".haproxy_check_agent", check_type == 'Agent');
+ transparent_clientip = d.getElementById("transparent_clientip");
+ setCSSdisplay(".haproxy_transparent_clientip", transparent_clientip.checked);
+
monitor_username = d.getElementById("monitor_username");
sqlcheckusername = d.getElementById("sqlcheckusername");
if(!browser_InnerText_support){
@@ -486,6 +491,32 @@ foreach($simplefields as $field){
</table>
</td>
</tr>
+ <tr align="left" style="display:none;">
+ <td width="22%" valign="top" class="vncell">Transparent ClientIP</td>
+ <td width="78%" class="vtable" colspan="2">
+ <input id="transparent_clientip" name="transparent_clientip" type="checkbox" value="yes" <?php if ($pconfig['transparent_clientip']=='yes') echo "checked"; ?> onclick='updatevisibility();'>
+ Use Client-IP to connect to backend servers.
+ <div class="haproxy_transparent_clientip">
+
+ <?
+ $interfaces = get_configured_interface_with_descr();
+ $interfaces2 = array();
+ foreach($interfaces as $key => $name)
+ {
+
+ $interfaces2[$key]['name'] = $name;
+ }
+ echo_html_select("transparent_interface",$interfaces2,$pconfig['transparent_interface']?$pconfig['transparent_interface']:"lan","","updatevisibility();");
+ ?>Interface that will connect to the backend server. (this will generally be your LAN or OPT1(dmz) interface)<br/>
+ </div>
+ <br/>
+ Connect transparently to the backend server's so the connection seams to come straight from the client ip address.
+ For proper workings this requires the reply's traffic to pass through pfSense by means of correct routing.
+ (uses the option "source 0.0.0.0 usesrc clientip")
+ <br/><br/>
+ Note : When this is enabled for a single backend HAProxy will run as 'root', which reduces security.
+ </td>
+ </tr>
<tr align="left">
<td width="22%" valign="top" class="vncell">Per server pass thru</td>
<td width="78%" class="vtable" colspan="2">
@@ -514,7 +545,7 @@ foreach($simplefields as $field){
<td width="22%" valign="top" class="vncell">Health check method</td>
<td width="78%" class="vtable" colspan="2">
<?
- echo_html_select("check_type",$a_checktypes,$pconfig['check_type']?$pconfig['check_type']:"HTML","","updatevisibility();");
+ echo_html_select("check_type",$a_checktypes,$pconfig['check_type']?$pconfig['check_type']:"HTTP","","updatevisibility();");
?><br/>
<textarea readonly="yes" cols="60" rows="2" id="check_type_description" name="check_type_description" style="padding:5px; border:1px dashed #990000; background-color: #ffffff; color: #000000; font-size: 8pt;"></textarea>
</td>
diff --git a/config/haproxy-devel/haproxy_pools.php b/config/haproxy-devel/haproxy_pools.php
index cd3899e6..2d0189a5 100644
--- a/config/haproxy-devel/haproxy_pools.php
+++ b/config/haproxy-devel/haproxy_pools.php
@@ -47,13 +47,7 @@ if ($_POST) {
$pconfig = $_POST;
if ($_POST['apply']) {
- $retval = 0;
- config_lock();
- $retval = haproxy_configure();
- config_unlock();
-
- $result = haproxy_check_writtenconfig_error($messages);
- $savemsg = $messages;
+ $result = haproxy_check_and_run($savemsg, true);
if ($result)
unlink_if_exists($d_haproxyconfdirty_path);
}