Merge pull request #5201 from fraenki/haproxy_500

net/haproxy: additions for release 5.0
This commit is contained in:
Frank Wall
2026-02-08 23:00:07 +01:00
committed by GitHub
5 changed files with 162 additions and 78 deletions

View File

@@ -27,7 +27,8 @@ Added:
* add support for GPC/GPT/SC to conditions and rules (#1123, #5109)
* add support for SSL SNI expression to servers (#3756)
* add column "mode" to servers overview (#4632)
* add support for loading mapfiles in conditions
* add support for loading mapfiles in conditions and rules
* add support for sample fetches in rules
Fixed:
* Maintenance tab "SSL Certificates" not working with only one cert

View File

@@ -266,6 +266,27 @@
<type>text</type>
<help><![CDATA[Specify the value for the URL parameter.]]></help>
</field>
<field>
<label>Parameters</label>
<type>header</type>
<style>expression_table table_var</style>
</field>
<field>
<id>acl.var_comparison</id>
<label>Comparison</label>
<type>dropdown</type>
</field>
<field>
<id>acl.var</id>
<label>Variable</label>
<type>text</type>
<help><![CDATA[The name of a variable, followed by an optional default value, e.g. (req.rate_limit) or (req.rate_limit,10).]]></help>
</field>
<field>
<id>acl.var_value</id>
<label>Value</label>
<type>text</type>
</field>
<field>
<label>Parameters</label>
<type>header</type>
@@ -1788,4 +1809,10 @@
<type>dropdown</type>
<help><![CDATA[Load patterns from a map file.]]></help>
</field>
<field>
<id>acl.converter</id>
<label>Converter</label>
<type>text</type>
<help><![CDATA[Transforms or processes the output of a sample fetch (e.g. variable, mapping, arithmetic, string manipulation) and passes the result to the next converter or final evaluation. Make more complex conditions possible, e.g. acl rate_abuse var(req.rate_limit),sub(req.request_rate) lt 0.]]></help>
</field>
</form>

View File

@@ -325,4 +325,22 @@
<type>text</type>
<help><![CDATA[Refers to the number of the Stick Counter, e.g. 0 or 1 when using sc0 or sc1 respectively. This value will be ignored in rules that do not support SC.]]></help>
</field>
<field>
<id>action.mapfile</id>
<label>Mapfile</label>
<type>dropdown</type>
<help><![CDATA[Load patterns from a map file.]]></help>
</field>
<field>
<id>action.map_default</id>
<label>Map default value</label>
<type>text</type>
<help><![CDATA[When a map file is specified, this is the default value.]]></help>
</field>
<field>
<id>action.sample_fetch</id>
<label>Sample fetch</label>
<type>text</type>
<help><![CDATA[Extracts a value from the request or connection context (e.g. path, header, source IP) to be used as input for converters or matching rules. May be used in combination with set-var and map files to create more complex rules, e.g.<br/>http-request set-var(req.rate_limit) path,map_beg(/path/to/mapfile,20)</br>http-request set-var(req.request_rate) base32+src,table_http_req_rate()]]></help>
</field>
</form>

View File

@@ -1951,6 +1951,7 @@
<ssl_sni_sub>ssl_sni_sub SNI TLS extension contains (TCP request content inspection)</ssl_sni_sub>
<stopping>stopping HAProxy process is currently stopping</stopping>
<url_param>url_param URL parameter contains</url_param>
<var>var Compare the value of a variable</var>
<wait_end>wait_end Inspection period is over</wait_end>
<custom_acl>Custom condition (option pass-through)</custom_acl>
</OptionValues>
@@ -2076,6 +2077,25 @@
<Mask>/^.{1,4096}$/u</Mask>
<Required>N</Required>
</url_param_value>
<var type="TextField">
<Mask>/^.{1,4096}$/u</Mask>
<Required>N</Required>
</var>
<var_value type="TextField">
<Mask>/^.{1,4096}$/u</Mask>
<Required>N</Required>
</var_value>
<var_comparison type="OptionField">
<Required>N</Required>
<Default>gt</Default>
<OptionValues>
<gt>greater than</gt>
<ge>greater equal</ge>
<eq>equal</eq>
<lt>less than</lt>
<le>less equal</le>
</OptionValues>
</var_comparison>
<ssl_c_verify_code type="IntegerField">
<MinimumValue>0</MinimumValue>
<MaximumValue>500000</MaximumValue>
@@ -3467,6 +3487,10 @@
<ValidationMessage>Related mapfile item not found</ValidationMessage>
<Required>N</Required>
</mapfile>
<converter type="TextField">
<Mask>/^.{1,4096}$/u</Mask>
<Required>N</Required>
</converter>
</acl>
</acls>
<actions>
@@ -4142,6 +4166,25 @@
<ValidationMessage>Please specify a value between 0 and 99.</ValidationMessage>
<Required>N</Required>
</sc_number>
<mapfile type="ModelRelationField">
<Model>
<template>
<source>OPNsense.HAProxy.HAProxy</source>
<items>mapfiles.mapfile</items>
<display>name</display>
</template>
</Model>
<ValidationMessage>Related mapfile item not found</ValidationMessage>
<Required>N</Required>
</mapfile>
<map_default type="TextField">
<Mask>/^.{1,4096}$/u</Mask>
<Required>N</Required>
</map_default>
<sample_fetch type="TextField">
<Mask>/^.{1,4096}$/u</Mask>
<Required>N</Required>
</sample_fetch>
</action>
</actions>
<luas>

View File

@@ -171,59 +171,44 @@
# ERROR: missing parameters
{% endif %}
{% elif acl_data.expression == 'hdr' %}
{% do acl_options.append('hdr(host)') %}
{% if acl_data.caseSensitive|default('0') == '0' %}
{% do acl_options.append('-i') %}
{% endif %}
{% if acl_data.hdr|default("") != "" %}
{% do acl_options.append('hdr(host)') %}
{% if acl_data.caseSensitive|default('0') == '0' %}
{% do acl_options.append('-i') %}
{% endif %}
{% do acl_options.append(acl_data.hdr) %}
{% else %}
{% set acl_enabled = '0' %}
# ERROR: missing parameters
{% endif %}
{% elif acl_data.expression == 'hdr_beg' %}
{% do acl_options.append('hdr_beg(host)') %}
{% if acl_data.caseSensitive|default('0') == '0' %}
{% do acl_options.append('-i') %}
{% endif %}
{% if acl_data.hdr_beg|default("") != "" %}
{% do acl_options.append('hdr_beg(host)') %}
{% if acl_data.caseSensitive|default('0') == '0' %}
{% do acl_options.append('-i') %}
{% endif %}
{% do acl_options.append(acl_data.hdr_beg) %}
{% else %}
{% set acl_enabled = '0' %}
# ERROR: missing parameters
{% endif %}
{% elif acl_data.expression == 'hdr_end' %}
{% do acl_options.append('hdr_end(host)') %}
{% if acl_data.caseSensitive|default('0') == '0' %}
{% do acl_options.append('-i') %}
{% endif %}
{% if acl_data.hdr_end|default("") != "" %}
{% do acl_options.append('hdr_end(host)') %}
{% if acl_data.caseSensitive|default('0') == '0' %}
{% do acl_options.append('-i') %}
{% endif %}
{% do acl_options.append(acl_data.hdr_end) %}
{% else %}
{% set acl_enabled = '0' %}
# ERROR: missing parameters
{% endif %}
{% elif acl_data.expression == 'hdr_reg' %}
{% do acl_options.append('hdr_reg(host)') %}
{% if acl_data.caseSensitive|default('0') == '0' %}
{% do acl_options.append('-i') %}
{% endif %}
{% if acl_data.hdr_reg|default("") != "" %}
{% do acl_options.append('hdr_reg(host)') %}
{% if acl_data.caseSensitive|default('0') == '0' %}
{% do acl_options.append('-i') %}
{% endif %}
{% do acl_options.append(acl_data.hdr_reg) %}
{% else %}
{% set acl_enabled = '0' %}
# ERROR: missing parameters
{% endif %}
{% elif acl_data.expression == 'hdr_sub' %}
{% do acl_options.append('hdr_sub(host)') %}
{% if acl_data.caseSensitive|default('0') == '0' %}
{% do acl_options.append('-i') %}
{% endif %}
{% if acl_data.hdr_sub|default("") != "" %}
{% do acl_options.append('hdr_sub(host)') %}
{% if acl_data.caseSensitive|default('0') == '0' %}
{% do acl_options.append('-i') %}
{% endif %}
{% do acl_options.append(acl_data.hdr_sub) %}
{% else %}
{% set acl_enabled = '0' %}
# ERROR: missing parameters
{% endif %}
{% elif acl_data.expression == 'http_auth' %}
{% if acl_data.allowedUsers|default("") != "" or acl_data.allowedGroups|default("") != "" %}
@@ -253,70 +238,52 @@
# ERROR: missing parameters
{% endif %}
{% elif acl_data.expression == 'path' %}
{% do acl_options.append('path') %}
{% if acl_data.caseSensitive|default('0') == '0' %}
{% do acl_options.append('-i') %}
{% endif %}
{% if acl_data.path|default("") != "" %}
{% do acl_options.append('path') %}
{% if acl_data.caseSensitive|default('0') == '0' %}
{% do acl_options.append('-i') %}
{% endif %}
{% do acl_options.append(acl_data.path) %}
{% else %}
{% set acl_enabled = '0' %}
# ERROR: missing parameters
{% endif %}
{% elif acl_data.expression == 'path_beg' %}
{% do acl_options.append('path_beg') %}
{% if acl_data.caseSensitive|default('0') == '0' %}
{% do acl_options.append('-i') %}
{% endif %}
{% if acl_data.path_beg|default("") != "" %}
{% do acl_options.append('path_beg') %}
{% if acl_data.caseSensitive|default('0') == '0' %}
{% do acl_options.append('-i') %}
{% endif %}
{% do acl_options.append(acl_data.path_beg) %}
{% else %}
{% set acl_enabled = '0' %}
# ERROR: missing parameters
{% endif %}
{% elif acl_data.expression == 'path_dir' %}
{% do acl_options.append('path_dir') %}
{% if acl_data.caseSensitive|default('0') == '0' %}
{% do acl_options.append('-i') %}
{% endif %}
{% if acl_data.path_dur|default("") != "" %}
{% do acl_options.append('path_dir') %}
{% if acl_data.caseSensitive|default('0') == '0' %}
{% do acl_options.append('-i') %}
{% endif %}
{% do acl_options.append(acl_data.path_dir) %}
{% else %}
{% set acl_enabled = '0' %}
# ERROR: missing parameters
{% endif %}
{% elif acl_data.expression == 'path_end' %}
{% do acl_options.append('path_end') %}
{% if acl_data.caseSensitive|default('0') == '0' %}
{% do acl_options.append('-i') %}
{% endif %}
{% if acl_data.path_end|default("") != "" %}
{% do acl_options.append('path_end') %}
{% if acl_data.caseSensitive|default('0') == '0' %}
{% do acl_options.append('-i') %}
{% endif %}
{% do acl_options.append(acl_data.path_end) %}
{% else %}
{% set acl_enabled = '0' %}
# ERROR: missing parameters
{% endif %}
{% elif acl_data.expression == 'path_reg' %}
{% do acl_options.append('path_reg') %}
{% if acl_data.caseSensitive|default('0') == '0' %}
{% do acl_options.append('-i') %}
{% endif %}
{% if acl_data.path_reg|default("") != "" %}
{% do acl_options.append('path_reg') %}
{% if acl_data.caseSensitive|default('0') == '0' %}
{% do acl_options.append('-i') %}
{% endif %}
{% do acl_options.append(acl_data.path_reg) %}
{% else %}
{% set acl_enabled = '0' %}
# ERROR: missing parameters
{% endif %}
{% elif acl_data.expression == 'path_sub' %}
{% do acl_options.append('path_sub') %}
{% if acl_data.caseSensitive|default('0') == '0' %}
{% do acl_options.append('-i') %}
{% endif %}
{% if acl_data.path_sub|default("") != "" %}
{% do acl_options.append('path_sub') %}
{% if acl_data.caseSensitive|default('0') == '0' %}
{% do acl_options.append('-i') %}
{% endif %}
{% do acl_options.append(acl_data.path_sub) %}
{% else %}
{% set acl_enabled = '0' %}
# ERROR: missing parameters
{% endif %}
{% elif acl_data.expression == 'sc_bytes_in_rate' %}
{% if acl_data.sc_number|default("") != "" and acl_data.sc_bytes_in_rate|default("") != "" %}
@@ -1414,6 +1381,18 @@
{% set acl_enabled = '0' %}
# ERROR: missing parameters
{% endif %}
{% elif acl_data.expression == 'var' %}
{% if acl_data.var|default("") != "" and acl_data.var_value|default("") != "" %}
{% if acl_data.converter|default("") != "" %}
{% set converter_data = ',' ~ acl_data.converter %}
{% else %}
{% set converter_data = '' %}
{% endif %}
{% do acl_options.append('var' ~ acl_data.var ~ converter_data ~ ' ' ~ acl_data.var_comparison ~ ' ' ~ acl_data.var_value) %}
{% else %}
{% set acl_enabled = '0' %}
# ERROR: missing parameters
{% endif %}
{# # handle boolean ACL types that do not require any input #}
{% elif acl_data.expression in acl_boolean_types %}
{% do acl_options.append(acl_data.expression) %}
@@ -1670,6 +1649,22 @@
{% set action_enabled = '0' %}
{% do global_action_options.append('# ERROR: unsupported rule type ' ~ action_data.type) %}
{% endif %}
{# # Add sample fetch to map file config. #}
{% if action_data.mapfile|default("") != "" %}
{% set mapfile_data = helpers.getUUID(action_data.mapfile) %}
{% set mapfile_path = '/tmp/haproxy/mapfiles/' ~ mapfile_data.id ~ '.txt' %}
{% set mapfile_config = 'map_' ~ mapfile_data.type %}
{% if action_data.map_default|default("") != "" %}
{% set mapfile_default = ',' ~ action_data.map_default %}
{% endif %}
{% if action_data.sample_fetch|default("") != "" %}
{% set mapfile_sf = action_data.sample_fetch ~ ',' %}
{% endif %}
{% do action_options.append(mapfile_sf ~ mapfile_config ~ '(' ~ mapfile_path ~ mapfile_default ~ ')') %}
{# # Add/append sample fetch. #}
{% elif action_data.sample_fetch|default("") != "" %}
{% do action_options.append(action_data.sample_fetch) %}
{% endif %}
{# # Is this rule enabled in the GUI? #}
{% if action_data.enabled|default('') == '1' %}
{# # check if action is valid #}