net/haproxy: add support for cookie-based persistence

This commit is contained in:
Frank Wall 2018-05-19 02:01:11 +02:00
parent 6df8c67e03
commit 3e356f642a
4 changed files with 99 additions and 11 deletions

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

@ -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) %}