diff --git a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogBackend.xml b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogBackend.xml
index 155592a74..0af01e120 100644
--- a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogBackend.xml
+++ b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogBackend.xml
@@ -105,6 +105,32 @@
true
+
+
+ header
+
+
+
+ backend.http2Enabled
+
+ checkbox
+
+
+
+ backend.http2Enabled_nontls
+
+ checkbox
+
+
+
+ backend.ba_advertised_protocols
+
+ select_multiple
+
+ true
+ true
+
+
header
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 336c7938e..3aa40fb28 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
@@ -270,11 +270,26 @@
- frontend.ssl_http2Enabled
+ frontend.http2Enabled
checkbox
+
+ frontend.http2Enabled_nontls
+
+ checkbox
+
+
+
+ frontend.advertised_protocols
+
+ select_multiple
+
+ true
+ true
+
+
frontend.forwardFor
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 eebc03b2f..bb080b736 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
@@ -443,10 +443,6 @@
ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
N
-
- 0
- N
-
1
Y
@@ -667,6 +663,25 @@
Should be a number between 1 and 8 characters, optionally followed by either "d", "h", "m", "s", "ms" or "us".
N
+
+ 0
+ N
+
+
+ 0
+ N
+
+
+ N
+ http2,http11
+ Y
+ Y
+
+ HTTP/2
+ HTTP/1.1
+ HTTP/1.0
+
+
0
Y
@@ -817,6 +832,25 @@
Please specify a value between 1 and 100.
N
+
+ 0
+ N
+
+
+ 0
+ N
+
+
+ N
+ http2,http11
+ Y
+ Y
+
+ HTTP/2
+ HTTP/1.1
+ HTTP/1.0
+
+
N
sticktable
diff --git a/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/index.volt b/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/index.volt
index 5471daace..6cc446097 100644
--- a/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/index.volt
+++ b/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/index.volt
@@ -222,6 +222,13 @@ POSSIBILITY OF SUCH DAMAGE.
// hook into on-show event for dialog to extend layout.
$('#DialogBackend').on('shown.bs.modal', function (e) {
+ $("#backend\\.mode").change(function(){
+ var service_id = 'table_' + $(this).val();
+ $(".mode_table").hide();
+ $("."+service_id).show();
+ });
+ $("#backend\\.mode").change();
+
$("#backend\\.healthCheckEnabled").change(function(){
var service_id = 'table_healthcheck_' + $(this).is(':checked');
$(".healthcheck_table").hide();
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 0bd3cef3e..b6401e74d 100644
--- a/net/haproxy/src/opnsense/service/templates/OPNsense/HAProxy/haproxy.conf
+++ b/net/haproxy/src/opnsense/service/templates/OPNsense/HAProxy/haproxy.conf
@@ -985,6 +985,7 @@ userlist stats_auth
frontend {{frontend.name}}
{% set ssl_certs = [] %}
{% set ssl_options = [] %}
+{% set adv_options = [] %}
{% if frontend.ssl_enabled == '1' %}
{# # check if ssl certs are configured #}
{% if frontend.ssl_certificates|default("") != "" or frontend.ssl_default_certificate|default("") != "" %}
@@ -1006,8 +1007,10 @@ frontend {{frontend.name}}
{% do ssl_options.append('ciphers ' ~ frontend.ssl_cipherList) %}
{% endif %}
{# # HTTP/2 #}
-{% if frontend.ssl_http2Enabled|default("") == '1' and frontend.mode == 'http' %}
-{% do ssl_options.append('alpn h2,http/1.1') %}
+{% if frontend.http2Enabled|default("") == '1' and frontend.advertised_protocols|default("") != "" %}
+{# # convert protocols to HAProxy-compatible format #}
+{% set alpn_options = frontend.advertised_protocols|replace('http10', 'http/1.0')|replace('http11', 'http/1.1') %}
+{% do ssl_options.append('alpn ' ~ alpn_options) %}
{% endif %}
{# # HSTS #}
{% if frontend.ssl_hstsEnabled|default("") == '1' and frontend.mode == 'http' %}
@@ -1039,10 +1042,12 @@ frontend {{frontend.name}}
{% endif %}
{% endif %}
{% endif %}
+{# # HTTP/2 without TLS #}
+{% elif frontend.http2Enabled|default("") == '1' and frontend.http2Enabled_nontls|default("") == '1' %}
+{% do adv_options.append('proto h2') %}
{% endif %}
{# # CPU affinity configuration #}
{% set bind_process = [] %}
-{% set process_thread = [] %}
{% if frontend.linkedCpuAffinityRules|default('') != '' %}
{% for cpu_map in frontend.linkedCpuAffinityRules.split(',') %}
{% set cpu_map_data = helpers.getUUID(cpu_map) %}
@@ -1050,7 +1055,7 @@ frontend {{frontend.name}}
{# # Limit visibility to a certain set of processes #}
{% do bind_process.append(cpu_map_data.process_id|replace('x', '')) %}
{# # Restrict the list of processes/threads on which this listener is allowed to run #}
-{% do process_thread.append('process ' ~ cpu_map_data.process_id|replace('x', '') ~ '/' ~ cpu_map_data.thread_id|replace('x', '')) %}
+{% do adv_options.append('process ' ~ cpu_map_data.process_id|replace('x', '') ~ '/' ~ cpu_map_data.thread_id|replace('x', '')) %}
{% endif %}
{% endfor %}
{% if bind_process|length > 0 %}
@@ -1060,7 +1065,7 @@ frontend {{frontend.name}}
{# # bind/listen configuration #}
{% if frontend.bind|default("") != "" %}
{% for bind in frontend.bind.split(",") %}
- bind {{bind}} name {{bind}} {% if frontend.bindOptions|default("") != "" %}{{ frontend.bindOptions }} {% endif %}{% if frontend.ssl_enabled == '1' and ssl_certs|default("") != "" %}ssl {{ ssl_options|join(' ') }} {{ ssl_certs|join(' ') }} {% endif %}{% if process_thread|length > 0 %} {{ process_thread|join(' ') }} {% endif %}
+ bind {{bind}} name {{bind}} {% if frontend.bindOptions|default("") != "" %}{{ frontend.bindOptions }} {% endif %}{% if frontend.ssl_enabled == '1' and ssl_certs|default("") != "" %}ssl {{ ssl_options|join(' ') }} {{ ssl_certs|join(' ') }} {% endif %}{% if adv_options|length > 0 %} {{ adv_options|join(' ') }} {% endif %}
{% endfor %}
{% endif %}
@@ -1259,10 +1264,10 @@ backend {{backend.name}}
# health checking is DISABLED
{% set healthcheck_enabled = '0' %}
{% endif %}
-{# # XXX: Usually the frontend and the backend are in the same mode, #}
-{# # but we have no way to know what frontend uses this backend. #}
-{# # Hence we can't automatically set the mode and thus need a #}
-{# # (redundant) GUI option for this. #}
+{# # NOTE: Usually the frontend and the backend are in the same mode, #}
+{# # but we have no way to know what frontend uses this backend. #}
+{# # Hence we can't automatically set the mode and thus need a #}
+{# # (redundant) GUI option for this. #}
mode {{backend.mode}}
balance {{backend.algorithm}}
{# # call macro to evaluate stickiness config #}
@@ -1400,6 +1405,15 @@ backend {{backend.name}}
{% else %}
{% do server_options.append('verify none') %}
{% endif %}
+{# # HTTP/2 #}
+{% if backend.http2Enabled|default("") == '1' and backend.ba_advertised_protocols|default("") != "" %}
+{# # convert protocols to HAProxy-compatible format #}
+{% set alpn_options = backend.ba_advertised_protocols|replace('http10', 'http/1.0')|replace('http11', 'http/1.1') %}
+{% do server_options.append('alpn ' ~ alpn_options) %}
+{% endif %}
+{# # HTTP/2 without TLS #}
+{% elif backend.http2Enabled|default("") == '1' and backend.http2Enabled_nontls|default("") == '1' %}
+{% do server_options.append('proto h2') %}
{% endif %}
{# # source address #}
{% if backend.source|default("") != "" %}