This commit is contained in:
Frank Wall 2026-02-18 12:21:50 +03:00 committed by GitHub
commit 209ffd1173
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 141 additions and 21 deletions

View file

@ -1,5 +1,5 @@
PLUGIN_NAME= haproxy
PLUGIN_VERSION= 5.0
PLUGIN_VERSION= 5.1
PLUGIN_COMMENT= Reliable, high performance TCP/HTTP load balancer
PLUGIN_DEPENDS= haproxy py${PLUGIN_PYTHON}-haproxy-cli
PLUGIN_MAINTAINER= opnsense@moov.de

View file

@ -6,6 +6,15 @@ very high loads while needing persistence or Layer7 processing.
Plugin Changelog
================
5.1
Added:
* more conditions have support for converters
* add support for mapfile URLs (#4825)
Fixed:
* migration fails if a http-request/-response "lua" rule is configured
5.0
WARNING: This is a new major release, which may result in

View file

@ -21,6 +21,12 @@
<id>mapfile.content</id>
<label>Content</label>
<type>textbox</type>
<help><![CDATA[Paste the content of your map file here. See the <a target="_blank" href="http://docs.haproxy.org/3.2/configuration.html#map">HAProxy documentation</a> for a full description.]]></help>
<help><![CDATA[Paste the content of the map file here. See the <a target="_blank" href="http://docs.haproxy.org/3.2/configuration.html#map">HAProxy documentation</a> for a full description.]]></help>
</field>
<field>
<id>mapfile.url</id>
<label>Download URL</label>
<type>text</type>
<help><![CDATA[A URL from which the map file will be downloaded. The contents will be cached until next reload/restart of HAProxy. If the download fails, then the specified content will be used instead. In order to enable automatic updates of map files, setup a cron job that periodically reloads HAProxy.]]></help>
</field>
</form>

View file

@ -3646,6 +3646,7 @@
<do-log>do-log</do-log>
<do-resolve>do-resolve</do-resolve>
<early-hint>early-hint</early-hint>
<lua>lua</lua>
<normalize-uri>normalize-uri</normalize-uri>
<redirect>redirect</redirect>
<reject>reject</reject>
@ -3689,7 +3690,7 @@
<track-sc1>track-sc1</track-sc1>
<track-sc2>track-sc2</track-sc2>
<unset-var>unset-var</unset-var>
<use-service>use-service</use-service>
<use-service>use-service - use a lua service</use-service>
<wait-for-body>wait-for-body</wait-for-body>
<wait-for-handshake>wait-for-handshake</wait-for-handshake>
</OptionValues>
@ -3711,6 +3712,7 @@
<del-map>del-map</del-map>
<deny>deny</deny>
<do-log>do-log</do-log>
<lua>lua</lua>
<redirect>redirect</redirect>
<replace-header>replace-header</replace-header>
<replace-value>replace-value</replace-value>
@ -3804,7 +3806,7 @@
<content_track-sc1>content track-sc1</content_track-sc1>
<content_track-sc2>content track-sc2</content_track-sc2>
<content_unset-var>content unset-var</content_unset-var>
<content_use-service>content use-service</content_use-service>
<content_use-service>content use-service - use a lua service</content_use-service>
<inspect-delay>inspect-delay</inspect-delay>
<session_accept>session accept</session_accept>
<session_attach-srv>session attach-srv</session_attach-srv>
@ -4363,8 +4365,12 @@
</OptionValues>
</type>
<content type="TextField">
<Required>Y</Required>
<Required>N</Required>
</content>
<url type="UrlField">
<Mask>/^.{1,4096}$/u</Mask>
<Required>N</Required>
</url>
</mapfile>
</mapfiles>
<groups>

View file

@ -2,7 +2,7 @@
<?php
/*
* Copyright (C) 2016-2018 Frank Wall
* Copyright (C) 2016-2026 Frank Wall
* Copyright (C) 2015 Deciso B.V.
* All rights reserved.
*
@ -41,12 +41,56 @@ if (isset($configObj->OPNsense->HAProxy->mapfiles)) {
foreach ($configObj->OPNsense->HAProxy->mapfiles->children() as $mapfile) {
$mf_name = (string)$mapfile->name;
$mf_id = (string)$mapfile->id;
$mf_url = (string)$mapfile->url;
if ($mf_id != "") {
$mf_content = htmlspecialchars_decode(str_replace("\r", "", (string)$mapfile->content));
$mf_filename = $export_path . $mf_id . ".txt";
file_put_contents($mf_filename, $mf_content);
chmod($mf_filename, 0600);
echo "map file exported to " . $mf_filename . "\n";
// Download file from URL (if URL was provided).
try {
if ($mf_url == "") {
throw new \Exception("no URL provided");
}
$fp = fopen($mf_filename, 'wb');
if ($fp === false) {
throw new \Exception("unable to open {$mf_filename} for writing");
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $mf_url);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
curl_setopt($ch, CURLOPT_FAILONERROR, true);
curl_setopt($ch, CURLOPT_FILE, $fp);
if (!curl_exec($ch)) {
throw new \Exception("download error: " . curl_error($ch));
}
echo "map file downloaded to " . $mf_filename . "\n";
} catch (\Exception $e) {
// Show error message only if URL was specified.
if ($mf_url != "") {
echo "download of map file failed, error: " . $e->getMessage() . "\n";
echo "trying to fill map file with fallback content\n";
$mf_content = "# NOTE: Download failed, this is the fallback content.\n";
} else {
$mf_content = '';
}
// Write contents to map file.
// This is also used as a fallback if map file download fails.
$mf_content = $mf_content . htmlspecialchars_decode(str_replace("\r", "", (string)$mapfile->content));
file_put_contents($mf_filename, $mf_content);
echo "map file exported to " . $mf_filename . "\n";
} finally {
if (isset($ch)) {
curl_close($ch);
}
if (isset($fp) && is_resource($fp)) {
fclose($fp);
}
chmod($mf_filename, 0600);
chown($mf_filename, 'www');
}
}
}
}

View file

@ -448,7 +448,12 @@
{% else %}
{% set table_data = '' %}
{% endif %}
{% do acl_options.append('sc_conn_cnt(' ~ acl_data.sc_number ~ table_data ~ ') ' ~ acl_data.sc_conn_cnt_comparison ~ ' ' ~ acl_data.sc_conn_cnt) %}
{% if acl_data.converter|default("") != "" %}
{% set converter_data = ',' ~ acl_data.converter %}
{% else %}
{% set converter_data = '' %}
{% endif %}
{% do acl_options.append('sc_conn_cnt(' ~ acl_data.sc_number ~ table_data ~ ')' ~ converter_data ~ ' ' ~ acl_data.sc_conn_cnt_comparison ~ ' ' ~ acl_data.sc_conn_cnt) %}
{% else %}
{% set acl_enabled = '0' %}
# ERROR: missing parameters
@ -460,7 +465,12 @@
{% else %}
{% set table_data = '' %}
{% endif %}
{% do acl_options.append('sc_conn_cur(' ~ acl_data.sc_number ~ table_data ~ ') ' ~ acl_data.sc_conn_cur_comparison ~ ' ' ~ acl_data.sc_conn_cur) %}
{% if acl_data.converter|default("") != "" %}
{% set converter_data = ',' ~ acl_data.converter %}
{% else %}
{% set converter_data = '' %}
{% endif %}
{% do acl_options.append('sc_conn_cur(' ~ acl_data.sc_number ~ table_data ~ ')' ~ converter_data ~ ' ' ~ acl_data.sc_conn_cur_comparison ~ ' ' ~ acl_data.sc_conn_cur) %}
{% else %}
{% set acl_enabled = '0' %}
# ERROR: missing parameters
@ -472,7 +482,12 @@
{% else %}
{% set table_data = '' %}
{% endif %}
{% do acl_options.append('sc_conn_rate(' ~ acl_data.sc_number ~ table_data ~ ') ' ~ acl_data.sc_conn_rate_comparison ~ ' ' ~ acl_data.sc_conn_rate) %}
{% if acl_data.converter|default("") != "" %}
{% set converter_data = ',' ~ acl_data.converter %}
{% else %}
{% set converter_data = '' %}
{% endif %}
{% do acl_options.append('sc_conn_rate(' ~ acl_data.sc_number ~ table_data ~ ')' ~ converter_data ~ ' ' ~ acl_data.sc_conn_rate_comparison ~ ' ' ~ acl_data.sc_conn_rate) %}
{% else %}
{% set acl_enabled = '0' %}
# ERROR: missing parameters
@ -784,7 +799,12 @@
{% else %}
{% set table_data = '' %}
{% endif %}
{% do acl_options.append('sc_http_err_cnt(' ~ acl_data.sc_number ~ table_data ~ ') ' ~ acl_data.sc_http_err_cnt_comparison ~ ' ' ~ acl_data.sc_http_err_cnt) %}
{% if acl_data.converter|default("") != "" %}
{% set converter_data = ',' ~ acl_data.converter %}
{% else %}
{% set converter_data = '' %}
{% endif %}
{% do acl_options.append('sc_http_err_cnt(' ~ acl_data.sc_number ~ table_data ~ ')' ~ converter_data ~ ' ' ~ acl_data.sc_http_err_cnt_comparison ~ ' ' ~ acl_data.sc_http_err_cnt) %}
{% else %}
{% set acl_enabled = '0' %}
# ERROR: missing parameters
@ -796,7 +816,12 @@
{% else %}
{% set table_data = '' %}
{% endif %}
{% do acl_options.append('sc_http_err_rate(' ~ acl_data.sc_number ~ table_data ~ ') ' ~ acl_data.sc_http_err_rate_comparison ~ ' ' ~ acl_data.sc_http_err_rate) %}
{% if acl_data.converter|default("") != "" %}
{% set converter_data = ',' ~ acl_data.converter %}
{% else %}
{% set converter_data = '' %}
{% endif %}
{% do acl_options.append('sc_http_err_rate(' ~ acl_data.sc_number ~ table_data ~ ')' ~ converter_data ~ ' ' ~ acl_data.sc_http_err_rate_comparison ~ ' ' ~ acl_data.sc_http_err_rate) %}
{% else %}
{% set acl_enabled = '0' %}
# ERROR: missing parameters
@ -808,7 +833,12 @@
{% else %}
{% set table_data = '' %}
{% endif %}
{% do acl_options.append('sc_http_fail_cnt(' ~ acl_data.sc_number ~ table_data ~ ') ' ~ acl_data.sc_http_fail_cnt_comparison ~ ' ' ~ acl_data.sc_http_fail_cnt) %}
{% if acl_data.converter|default("") != "" %}
{% set converter_data = ',' ~ acl_data.converter %}
{% else %}
{% set converter_data = '' %}
{% endif %}
{% do acl_options.append('sc_http_fail_cnt(' ~ acl_data.sc_number ~ table_data ~ ')' ~ converter_data ~ ' ' ~ acl_data.sc_http_fail_cnt_comparison ~ ' ' ~ acl_data.sc_http_fail_cnt) %}
{% else %}
{% set acl_enabled = '0' %}
# ERROR: missing parameters
@ -820,7 +850,12 @@
{% else %}
{% set table_data = '' %}
{% endif %}
{% do acl_options.append('sc_http_fail_rate(' ~ acl_data.sc_number ~ table_data ~ ') ' ~ acl_data.sc_http_fail_rate_comparison ~ ' ' ~ acl_data.sc_http_fail_rate) %}
{% if acl_data.converter|default("") != "" %}
{% set converter_data = ',' ~ acl_data.converter %}
{% else %}
{% set converter_data = '' %}
{% endif %}
{% do acl_options.append('sc_http_fail_rate(' ~ acl_data.sc_number ~ table_data ~ ')' ~ converter_data ~ ' ' ~ acl_data.sc_http_fail_rate_comparison ~ ' ' ~ acl_data.sc_http_fail_rate) %}
{% else %}
{% set acl_enabled = '0' %}
# ERROR: missing parameters
@ -832,7 +867,12 @@
{% else %}
{% set table_data = '' %}
{% endif %}
{% do acl_options.append('sc_http_req_cnt(' ~ acl_data.sc_number ~ table_data ~ ') ' ~ acl_data.sc_http_req_cnt_comparison ~ ' ' ~ acl_data.sc_http_req_cnt) %}
{% if acl_data.converter|default("") != "" %}
{% set converter_data = ',' ~ acl_data.converter %}
{% else %}
{% set converter_data = '' %}
{% endif %}
{% do acl_options.append('sc_http_req_cnt(' ~ acl_data.sc_number ~ table_data ~ ')' ~ converter_data ~ ' ' ~ acl_data.sc_http_req_cnt_comparison ~ ' ' ~ acl_data.sc_http_req_cnt) %}
{% else %}
{% set acl_enabled = '0' %}
# ERROR: missing parameters
@ -844,7 +884,12 @@
{% else %}
{% set table_data = '' %}
{% endif %}
{% do acl_options.append('sc_http_req_rate(' ~ acl_data.sc_number ~ table_data ~ ') ' ~ acl_data.sc_http_req_rate_comparison ~ ' ' ~ acl_data.sc_http_req_rate) %}
{% if acl_data.converter|default("") != "" %}
{% set converter_data = ',' ~ acl_data.converter %}
{% else %}
{% set converter_data = '' %}
{% endif %}
{% do acl_options.append('sc_http_req_rate(' ~ acl_data.sc_number ~ table_data ~ ')' ~ converter_data ~ ' ' ~ acl_data.sc_http_req_rate_comparison ~ ' ' ~ acl_data.sc_http_req_rate) %}
{% else %}
{% set acl_enabled = '0' %}
# ERROR: missing parameters
@ -964,7 +1009,12 @@
{% else %}
{% set table_data = '' %}
{% endif %}
{% do acl_options.append('sc_sess_cnt(' ~ acl_data.sc_number ~ table_data ~ ') ' ~ acl_data.sc_sess_cnt_comparison ~ ' ' ~ acl_data.sc_sess_cnt) %}
{% if acl_data.converter|default("") != "" %}
{% set converter_data = ',' ~ acl_data.converter %}
{% else %}
{% set converter_data = '' %}
{% endif %}
{% do acl_options.append('sc_sess_cnt(' ~ acl_data.sc_number ~ table_data ~ ')' ~ converter_data ~ ' ' ~ acl_data.sc_sess_cnt_comparison ~ ' ' ~ acl_data.sc_sess_cnt) %}
{% else %}
{% set acl_enabled = '0' %}
# ERROR: missing parameters
@ -976,7 +1026,12 @@
{% else %}
{% set table_data = '' %}
{% endif %}
{% do acl_options.append('sc_sess_rate(' ~ acl_data.sc_number ~ table_data ~ ') ' ~ acl_data.sc_sess_rate_comparison ~ ' ' ~ acl_data.sc_sess_rate) %}
{% if acl_data.converter|default("") != "" %}
{% set converter_data = ',' ~ acl_data.converter %}
{% else %}
{% set converter_data = '' %}
{% endif %}
{% do acl_options.append('sc_sess_rate(' ~ acl_data.sc_number ~ table_data ~ ')' ~ converter_data ~ ' ' ~ acl_data.sc_sess_rate_comparison ~ ' ' ~ acl_data.sc_sess_rate) %}
{% else %}
{% set acl_enabled = '0' %}
# ERROR: missing parameters