diff --git a/net/haproxy/Makefile b/net/haproxy/Makefile
index 653211941..f9625a6b5 100644
--- a/net/haproxy/Makefile
+++ b/net/haproxy/Makefile
@@ -1,5 +1,5 @@
PLUGIN_NAME= haproxy
-PLUGIN_VERSION= 2.9
+PLUGIN_VERSION= 2.10
PLUGIN_COMMENT= Reliable, high performance TCP/HTTP load balancer
PLUGIN_DEPENDS= haproxy
PLUGIN_MAINTAINER= opnsense@moov.de
diff --git a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogFrontend.xml b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogFrontend.xml
index da3c7d2a0..af4f53a11 100644
--- a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogFrontend.xml
+++ b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogFrontend.xml
@@ -128,6 +128,39 @@
text
+
+
+ header
+
+
+
+ frontend.ssl_clientAuthEnabled
+
+ checkbox
+
+
+
+ frontend.ssl_clientAuthVerify
+
+ dropdown
+
+
+
+ frontend.ssl_clientAuthCAs
+
+ select_multiple
+ true
+ To import additional CAs, go to CA Manager.]]>
+ Type CA name or choose from list.
+
+
+ frontend.ssl_clientAuthCRLs
+
+ select_multiple
+ true
+ To import additional CRLs, go to CRL Manager.]]>
+ Type CRL name or choose from list.
+
header
diff --git a/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/HAProxy.xml b/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/HAProxy.xml
index 566a97e6c..3ada067d2 100644
--- a/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/HAProxy.xml
+++ b/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/HAProxy.xml
@@ -1,9 +1,7 @@
//OPNsense/HAProxy
- 2.4.0
-
- the HAProxy load balancer
-
+ 2.5.0
+ the HAProxy load balancer
@@ -406,6 +404,31 @@
Please specify a value between 1 and 1000000000.
Y
+
+ 0
+ N
+
+
+ N
+ required
+
+ none
+ optional
+ required
+
+
+
+ N
+ ca
+ Y
+ Please select a valid CA from the list.
+
+
+ N
+ crl
+ Y
+ Please select a valid CA from the list.
+
1
500000
diff --git a/net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/exportCerts.php b/net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/exportCerts.php
index ca577f177..41965bb2d 100755
--- a/net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/exportCerts.php
+++ b/net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/exportCerts.php
@@ -2,7 +2,7 @@
['ssl_certificates'],
+ 'frontends' => ['ssl_certificates', 'ssl_clientAuthCAs', 'ssl_clientAuthCRLs'],
'servers' => ['sslCA', 'sslCRL', 'sslClientCertificate'],
];
$certTypes = ['cert', 'ca', 'crl'];
@@ -51,19 +52,20 @@ foreach ($configNodes as $key => $value) {
// lookup all config nodes
if (isset($configObj->OPNsense->HAProxy->$key)) {
foreach ($configObj->OPNsense->HAProxy->$key->children() as $child) {
- // generate a crt-list for every child node
- $crtlist = array();
- $crtlist_filename = "/var/etc/haproxy/ssl/" . (string)$child->id . ".crtlist";
// search in all matching child elements for ssl data
foreach ($configNodes[$key] as $sslchild) {
if (isset($child->$sslchild)) {
- // multiple comma-separated values are possible
- $certs = explode(',', $child->$sslchild);
- foreach ($certs as $cert_refid) {
- // if the element has a cert attached, search for its contents
- if ($cert_refid != "") {
- // check all known cert types
- foreach ($certTypes as $type) {
+ // generate a list for every known cert type
+ foreach ($certTypes as $type) {
+ // every child node needs its own set of lists
+ $crtlist = array();
+ $crtlist_filename = $export_path . (string)$child->id . "." . $type . "list";
+
+ // multiple comma-separated values are possible
+ $certs = explode(',', $child->$sslchild);
+ foreach ($certs as $cert_refid) {
+ // if the element has a cert attached, search for its contents
+ if ($cert_refid != "") {
// search for cert (type) in config
foreach ($configObj->$type as $cert) {
if ($cert_refid == (string)$cert->refid) {
@@ -83,37 +85,44 @@ foreach ($configNodes as $key => $value) {
$pem_content .= "\n" . $ca;
}
}
- // generate pem file
- $output_pem_filename = "/var/etc/haproxy/ssl/" . $cert_refid . ".pem";
- file_put_contents($output_pem_filename, $pem_content);
- chmod($output_pem_filename, 0600);
- echo "exported $type to " . $output_pem_filename . "\n";
- // add pem file to crt-list
- $crtlist[] = $output_pem_filename;
+ // generate pem file for individual certs
+ // (only supported for type "cert")
+ if ($type == cert) {
+ $output_pem_filename = $export_path . $cert_refid . ".pem";
+ file_put_contents($output_pem_filename, $pem_content);
+ chmod($output_pem_filename, 0600);
+ echo "exported $type to " . $output_pem_filename . "\n";
+ // add pem file to crt-list
+ $crtlist[] = $output_pem_filename;
+ } else {
+ // All other types do not support list files.
+ // Add cert content directly to the list file.
+ $crtlist[] = $pem_content;
+ }
}
}
}
}
- }
- // generate crt-list file
- // (this makes only sense for frontends)
- if ($key == 'frontends') {
- // ignore if crt-list is empty
- if (empty($crtlist)) {
- continue;
+ // generate list file
+ // (only supported for frontends)
+ if ($key == 'frontends') {
+ // ignore if list is empty
+ if (empty($crtlist)) {
+ continue;
+ }
+ // check if a default certificate is configured
+ if (($type == cert) and isset($child->ssl_default_certificate) and (string)$child->ssl_default_certificate != "") {
+ $default_cert = (string)$child->ssl_default_certificate;
+ $default_cert_filename = $export_path . $default_cert . ".pem";
+ // ensure default certificate is the first entry on the list
+ unset($crtlist[$default_cert]);
+ array_unshift($crtlist, $default_cert_filename);
+ }
+ $crtlist_content = implode("\n", $crtlist) . "\n";
+ file_put_contents($crtlist_filename, $crtlist_content);
+ chmod($crtlist_filename, 0600);
+ echo "exported $type list to " . $crtlist_filename . "\n";
}
- // check if a default certificate is configured
- if (isset($child->ssl_default_certificate) and (string)$child->ssl_default_certificate != "") {
- $default_cert = (string)$child->ssl_default_certificate;
- $default_cert_filename = "/var/etc/haproxy/ssl/" . $default_cert . ".pem";
- // ensure default certificate is the first entry on the list
- unset($crtlist[$default_cert]);
- array_unshift($crtlist, $default_cert_filename);
- }
- $crtlist_content = implode("\n", $crtlist) . "\n";
- file_put_contents($crtlist_filename, $crtlist_content);
- chmod($crtlist_filename, 0600);
- echo "exported crt-list to " . $crtlist_filename . "\n";
}
}
}
diff --git a/net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/exportErrorFiles.php b/net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/exportErrorFiles.php
index 48c843c8b..48fcc023c 100755
--- a/net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/exportErrorFiles.php
+++ b/net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/exportErrorFiles.php
@@ -37,6 +37,7 @@ require_once("legacy_bindings.inc");
use OPNsense\Core\Config;
global $config;
+$export_path = '/tmp/haproxy/errorfiles/';
// traverse HAProxy error files
$configObj = Config::getInstance()->object();
@@ -46,7 +47,7 @@ if (isset($configObj->OPNsense->HAProxy->errorfiles)) {
$ef_id = (string)$errorfile->id;
if ($ef_id != "") {
$ef_content = htmlspecialchars_decode(str_replace("\r", "", (string)$errorfile->content));
- $ef_filename = "/var/etc/haproxy/errorfiles/" . $ef_id . ".txt";
+ $ef_filename = $export_path . $ef_id . ".txt";
file_put_contents($ef_filename, $ef_content);
chmod($ef_filename, 0600);
echo "error file exported to " . $ef_filename . "\n";
diff --git a/net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/exportLuaScripts.php b/net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/exportLuaScripts.php
index b4bc1ebc4..2e77053e3 100755
--- a/net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/exportLuaScripts.php
+++ b/net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/exportLuaScripts.php
@@ -37,6 +37,7 @@ require_once("legacy_bindings.inc");
use OPNsense\Core\Config;
global $config;
+$export_path = '/tmp/haproxy/lua/';
// traverse HAProxy Lua scripts
$configObj = Config::getInstance()->object();
@@ -49,7 +50,7 @@ if (isset($configObj->OPNsense->HAProxy->luas)) {
$lua_id = (string)$lua->id;
if ($lua_id != "") {
$lua_content = htmlspecialchars_decode(str_replace("\r", "", (string)$lua->content));
- $lua_filename = "/var/etc/haproxy/lua/" . $lua_id . ".lua";
+ $lua_filename = $export_path . $lua_id . ".lua";
file_put_contents($lua_filename, $lua_content);
chmod($lua_filename, 0600);
echo "lua script exported to " . $lua_filename . "\n";
diff --git a/net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/exportMapFiles.php b/net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/exportMapFiles.php
index e0836d7f0..938e1d67d 100755
--- a/net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/exportMapFiles.php
+++ b/net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/exportMapFiles.php
@@ -37,6 +37,7 @@ require_once("legacy_bindings.inc");
use OPNsense\Core\Config;
global $config;
+$export_path = '/tmp/haproxy/mapfiles/';
// traverse HAProxy map files
$configObj = Config::getInstance()->object();
@@ -46,7 +47,7 @@ if (isset($configObj->OPNsense->HAProxy->mapfiles)) {
$mf_id = (string)$mapfile->id;
if ($mf_id != "") {
$mf_content = htmlspecialchars_decode(str_replace("\r", "", (string)$mapfile->content));
- $mf_filename = "/var/etc/haproxy/mapfiles/" . $mf_id . ".txt";
+ $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";
diff --git a/net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/setup.sh b/net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/setup.sh
index 8af5efe23..cb88ee64d 100755
--- a/net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/setup.sh
+++ b/net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/setup.sh
@@ -1,7 +1,7 @@
#!/bin/sh
# NOTE: Keep /var/haproxy on this list, see GH issue opnsense/plugins #39.
-HAPROXY_DIRS="/var/haproxy /var/haproxy/var/run /var/etc/haproxy/ssl /var/etc/haproxy/lua /var/etc/haproxy/errorfiles /var/etc/haproxy/mapfiles"
+HAPROXY_DIRS="/var/haproxy /var/haproxy/var/run /tmp/haproxy /tmp/haproxy/ssl /tmp/haproxy/lua /tmp/haproxy/errorfiles /tmp/haproxy/mapfiles"
for directory in ${HAPROXY_DIRS}; do
mkdir -p ${directory}
diff --git a/net/haproxy/src/opnsense/service/templates/OPNsense/HAProxy/haproxy.conf b/net/haproxy/src/opnsense/service/templates/OPNsense/HAProxy/haproxy.conf
index 5ed67d2c2..9565bd8a2 100644
--- a/net/haproxy/src/opnsense/service/templates/OPNsense/HAProxy/haproxy.conf
+++ b/net/haproxy/src/opnsense/service/templates/OPNsense/HAProxy/haproxy.conf
@@ -29,7 +29,7 @@
{% else %}
{% do http_codes_seen.append(errorfile_data.code) %}
# ERROR FILE: {{errorfile_data.name}}
- errorfile {{errorfile_data.code|replace("x", "")}} /var/etc/haproxy/errorfiles/{{errorfile_data.id}}.txt
+ errorfile {{errorfile_data.code|replace("x", "")}} /tmp/haproxy/errorfiles/{{errorfile_data.id}}.txt
{% endif %}
{% endfor %}
{% else %}
@@ -310,7 +310,7 @@
{# # First get the map file path #}
{% if action_data.map_use_backend_file|default("") != "" %}
{% set mapfile_data = helpers.getUUID(action_data.map_use_backend_file) %}
-{% set mapfile_path = '/var/etc/haproxy/mapfiles/' ~ mapfile_data.id ~ '.txt' %}
+{% set mapfile_path = '/tmp/haproxy/mapfiles/' ~ mapfile_data.id ~ '.txt' %}
{# # Check if a default backend is specified #}
{% if action_data.map_use_backend_default|default("") != "" %}
{% set defaultbackend_data = helpers.getUUID(action_data.map_use_backend_default) %}
@@ -373,7 +373,7 @@
{% endif %}
{% elif action_data.type == 'http-request_del-header' %}
{% if action_data.http_request_del_header_name|default("") != "" %}
-{% do action_options.append('http-request del-header' ~ action_data.http_request_del_header_name) %}
+{% do action_options.append('http-request del-header ' ~ action_data.http_request_del_header_name) %}
{% else %}
{% set action_enabled = '0' %}
# ERROR: missing parameters
@@ -426,7 +426,7 @@
{% endif %}
{% elif action_data.type == 'http-response_del-header' %}
{% if action_data.http_response_del_header_name|default("") != "" %}
-{% do action_options.append('http-response del-header' ~ action_data.http_response_del_header_name) %}
+{% do action_options.append('http-response del-header ' ~ action_data.http_response_del_header_name) %}
{% else %}
{% set action_enabled = '0' %}
# ERROR: missing parameters
@@ -686,7 +686,7 @@ global
{% for lua in helpers.toList('OPNsense.HAProxy.luas.lua') %}
{% if lua.enabled == '1' %}
# lua script: {{lua.name}}
- lua-load /var/etc/haproxy/lua/{{lua.id}}.lua
+ lua-load /tmp/haproxy/lua/{{lua.id}}.lua
{% endif %}
{% endfor %}
{% endif %}
@@ -762,7 +762,7 @@ frontend {{frontend.name}}
{# # check if ssl certs are configured #}
{% if frontend.ssl_certificates|default("") != "" %}
{# # NOTE: Cert lists are generated by exportCerts.php #}
-{% do ssl_certs.append('crt-list /var/etc/haproxy/ssl/' ~ frontend.id ~ '.crtlist') %}
+{% do ssl_certs.append('crt-list /tmp/haproxy/ssl/' ~ frontend.id ~ '.certlist') %}
{% endif %}
{# # advanced ssl parameters (pass-through) #}
{% if frontend.ssl_customOptions|default("") != "" %}
@@ -791,6 +791,23 @@ frontend {{frontend.name}}
http-response set-header Strict-Transport-Security "{{ hsts_options|join('') }}"
{% endif %}
{% endif %}
+{# # configure client certificate authentication #}
+{% if frontend.ssl_clientAuthEnabled == '1' %}
+{# # check for CAs (required) #}
+{% if frontend.ssl_clientAuthCAs|default("") != "" %}
+{# # NOTE: CA lists are generated by exportCerts.php #}
+{% do ssl_options.append('ca-file /tmp/haproxy/ssl/' ~ frontend.id ~ '.calist') %}
+{# # check for verification mode #}
+{% if frontend.ssl_clientAuthVerify|default("") != "" %}
+{% do ssl_options.append('verify ' ~ frontend.ssl_clientAuthVerify) %}
+{% endif %}
+{# # check for CRL #}
+{% if frontend.ssl_clientAuthCRLs|default("") != "" %}
+{# # NOTE: CRL lists are generated by exportCerts.php #}
+{% do ssl_options.append('crl-file /tmp/haproxy/ssl/' ~ frontend.id ~ '.crllist') %}
+{% endif %}
+{% endif %}
+{% endif %}
{% endif %}
{# # bind/listen configuration #}
{% if frontend.bind|default("") != "" %}
@@ -1105,15 +1122,15 @@ backend {{backend.name}}
{% do server_options.append('verify required') %}
{# # check for SSL CA #}
{% if server_data.sslCA|default("") != "" %}
-{% do server_options.append('ca-file /var/etc/haproxy/ssl/' ~ server_data.sslCA ~ '.pem') %}
+{% do server_options.append('ca-file /tmp/haproxy/ssl/' ~ server_data.sslCA ~ '.pem') %}
{% endif %}
{# # check for SSL CRL #}
{% if server_data.sslCRL|default("") != "" %}
-{% do server_options.append('crl-file /var/etc/haproxy/ssl/' ~ server_data.sslCRL ~ '.pem') %}
+{% do server_options.append('crl-file /tmp/haproxy/ssl/' ~ server_data.sslCRL ~ '.pem') %}
{% endif %}
{# # check for SSL client cert #}
{% if server_data.sslClientCertificate|default("") != "" %}
-{% do server_options.append('crt /var/etc/haproxy/ssl/' ~ server_data.sslClientCertificate ~ '.pem') %}
+{% do server_options.append('crt /tmp/haproxy/ssl/' ~ server_data.sslClientCertificate ~ '.pem') %}
{% endif %}
{% else %}
{% do server_options.append('verify none') %}