Merge pull request #680 from fraenki/haproxy_270_plus

net/haproxy: support for cookie-based persistence
This commit is contained in:
Frank Wall 2018-05-19 13:16:40 +02:00 committed by GitHub
commit 1ccf276c08
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 144 additions and 12 deletions

View file

@ -1,5 +1,5 @@
PLUGIN_NAME= haproxy
PLUGIN_VERSION= 2.6
PLUGIN_VERSION= 2.7
PLUGIN_COMMENT= Reliable, high performance TCP/HTTP load balancer
PLUGIN_DEPENDS= haproxy-devel
PLUGIN_MAINTAINER= opnsense@moov.de

View file

@ -105,6 +105,39 @@
<help><![CDATA[The number of consecutive successful health checks before a server is considered as available.]]></help>
<advanced>true</advanced>
</field>
<field>
<label>Persistence</label>
<type>header</type>
</field>
<field>
<id>backend.persistence</id>
<label>Persistence type</label>
<type>dropdown</type>
<help><![CDATA[Choose how HAProxy should track user-to-server mappings. Stick-table persistence works with all protocols, but is broken in multi-process and multithreaded modes. Cookie-based persistence only works with HTTP/HTTPS protocols.]]></help>
</field>
<field>
<label>Cookie-based persistence</label>
<type>header</type>
<style>persistence_table table_persistence_cookie</style>
</field>
<field>
<id>backend.persistence_cookiemode</id>
<label>Cookie handling</label>
<type>dropdown</type>
<help><![CDATA[Usually it is better to reuse an existing cookie. In this case HAProxy prefixes the cookie with the required information. See the <a target="_blank" href="http://cbonte.github.io/haproxy-dconv/1.8/configuration.html#4.2-cookie">HAProxy documentation</a> for a full description.]]></help>
</field>
<field>
<id>backend.persistence_cookiename</id>
<label>Cookie name</label>
<type>text</type>
<help><![CDATA[Cookie name to use for persistence.]]></help>
</field>
<field>
<id>backend.persistence_stripquotes</id>
<label>Strip quotes</label>
<type>checkbox</type>
<help><![CDATA[Enable to automatically strip quotes from the cookie value. Some broken HTTP clients add quotes, which breaks persistence.]]></help>
</field>
<field>
<label>Stick-table persistence</label>
<type>header</type>

View file

@ -1,6 +1,6 @@
<model>
<mount>//OPNsense/HAProxy</mount>
<version>2.2.0</version>
<version>2.3.0</version>
<description>
the HAProxy load balancer
</description>
@ -686,14 +686,40 @@
<ValidationMessage>Please specify a value between 1 and 100.</ValidationMessage>
<Required>N</Required>
</healthCheckRise>
<persistence type="OptionField">
<Required>N</Required>
<default>sticktable</default>
<OptionValues>
<sticktable>Stick-table persistence [default]</sticktable>
<cookie>Cookie-based persistence (HTTP/HTTPS only)</cookie>
</OptionValues>
</persistence>
<persistence_cookiemode type="OptionField">
<Required>Y</Required>
<default>piggyback</default>
<OptionValues>
<piggyback>Piggyback on existing cookie</piggyback>
<new>Insert new cookie</new>
</OptionValues>
</persistence_cookiemode>
<persistence_cookiename type="TextField">
<default>SRVCOOKIE</default>
<Required>N</Required>
<mask>/^([0-9a-zA-Z\.,_\-:]){1,1024}$/u</mask>
<ValidationMessage>Does not look like a valid cookie name (most special characters are not allowed).</ValidationMessage>
</persistence_cookiename>
<persistence_stripquotes type="BooleanField">
<default>1</default>
<Required>Y</Required>
</persistence_stripquotes>
<stickiness_pattern type="OptionField">
<Required>N</Required>
<default>sourceipv4</default>
<OptionValues>
<sourceipv4>Stick on Source-IP [default]</sourceipv4>
<sourceipv6>Stick on Source-IPv6</sourceipv6>
<cookievalue>Stick on existing Cookie value</cookievalue>
<rdpcookie>Stick on RDP-Cookie</rdpcookie>
<sourceipv4>Source-IP [default]</sourceipv4>
<sourceipv6>Source-IPv6</sourceipv6>
<cookievalue>Existing cookie value</cookievalue>
<rdpcookie>RDP-Cookie</rdpcookie>
</OptionValues>
</stickiness_pattern>
<stickiness_dataTypes type="OptionField">
@ -835,6 +861,9 @@
</backends>
<servers>
<server type="ArrayField">
<id type="UniqueIdField">
<Required>Y</Required>
</id>
<name type="TextField">
<mask>/^([0-9a-zA-Z._]){1,255}$/u</mask>
<ValidationMessage>Should be a string between 1 and 255 characters.</ValidationMessage>

View file

@ -0,0 +1,44 @@
<?php
/**
* Copyright (C) 2018 Frank Wall
*
* 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.
*
*/
namespace OPNsense\HAProxy\Migrations;
use OPNsense\Base\BaseModelMigration;
class M2_7_0 extends BaseModelMigration
{
public function run($model)
{
// Persistence is a separate option now.
foreach ($model->getNodeByReference('backends.backend')->__items as $backend) {
if (isset($backend->stickiness_pattern)) {
$backend->persistence = 'sticktable';
}
}
}
}

View file

@ -176,6 +176,13 @@ POSSIBILITY OF SUCH DAMAGE.
$("."+service_id).show();
});
$("#backend\\.healthCheckEnabled").change();
$("#backend\\.persistence").change(function(){
var persistence_id = 'table_persistence_' + $(this).val();
$(".persistence_table").hide();
$("."+persistence_id).show();
});
$("#backend\\.persistence").change();
})
// hook into on-show event for dialog to extend layout.

View file

@ -578,18 +578,28 @@
tcp-request connection track-sc0 {{proxy.stickiness_counter_key}}
{%- endif -%}
{%- endif -%}
{# # stick-table persistence (backends only) #}
{%- if backend == True -%}
{%- if proxy.stickiness_pattern == "cookievalue" %}
{% endif %}
{# # persistence (backends only) #}
{%- if backend == True -%}
{%- if proxy.persistence|default("") == "cookie" %}
{# # cookie-based persistence #}
{%- if proxy.persistence_cookiemode|default("") == "piggyback" %}
cookie {{proxy.persistence_cookiename}} prefix
{%- elif proxy.persistence_cookiemode|default("") == "new" %}
cookie {{proxy.persistence_cookiename}} insert indirect nocache
{%- endif -%}
{% elif proxy.persistence|default("") == "sticktable" %}
{# # stick-table persistence #}
{%- if proxy.stickiness_pattern|default("") == "cookievalue" %}
stick store-response res.cook({{proxy.stickiness_cookiename}})
stick on req.cook({{proxy.stickiness_cookiename}})
{%- elif proxy.stickiness_pattern == "rdpcookie" %}
{%- elif proxy.stickiness_pattern|default("") == "rdpcookie" %}
stick on req.rdp_cookie(mstshash)
{%- elif proxy.stickiness_pattern != '' %}
{%- elif proxy.stickiness_pattern|default("") != '' %}
stick on src
{%- endif -%}
{%- endif -%}
{% endif %}
{%- endif -%}
{% else %}
# ERROR: StickTableConfig called with empty data
{% endif %}
@ -779,6 +789,11 @@ frontend {{frontend.name}}
{% if frontend.defaultBackend|default("") != "" %}
{% set backend_data = helpers.getUUID(frontend.defaultBackend) %}
default_backend {{backend_data.name}}
{# # check if persistence-related workaround is enabled #}
{% if backend_data.persistence|default("") == 'cookie' and backend_data.persistence_stripquotes|default("") == '1' %}
# remove quotes from persistence cookie
http-request replace-header Cookie '^(.*?; )?({{backend_data.persistence_cookiename}}=)"([^;"]*)"(;.*)?$' \1\2\3\4
{% endif %}
{% endif %}
{% if frontend.forwardFor == '1' %}
option forwardfor
@ -1094,6 +1109,10 @@ backend {{backend.name}}
{% do server_options.append('send-proxy-v2') %}
{% do server_options.append('check-send-proxy') %}
{% endif %}
{# # cookie-based persistence #}
{% if backend.persistence|default("") == "cookie" %}
{% do server_options.append('cookie ' ~ server_data.id|replace(".", "")) %}
{% endif %}
{# # server advanced options #}
{% if server_data.advanced|default("") != "" %}
{% do server_options.append(server_data.advanced) %}