diff --git a/www/caddy/pkg-descr b/www/caddy/pkg-descr
index 378f12b86..023352a4a 100644
--- a/www/caddy/pkg-descr
+++ b/www/caddy/pkg-descr
@@ -15,6 +15,7 @@ Plugin Changelog
1.7.5
+* Add: Load Balancing options to Layer 4 Proxy and HTTP Handle
* Add: Layer4 TLS Termination
* Add: h2c protocol to HTTP Handler
* Cleanup: Caddy Certificate widget hides unused automatic certificates
diff --git a/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/forms/dialogHandle.xml b/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/forms/dialogHandle.xml
index 68714b31c..3ada90d0b 100644
--- a/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/forms/dialogHandle.xml
+++ b/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/forms/dialogHandle.xml
@@ -136,14 +136,6 @@
true
-
- handle.PassiveHealthFailDuration
-
- text
-
-
- true
-
handle.HttpTlsInsecureSkipVerify
@@ -172,4 +164,89 @@
+
+ header
+
+ true
+
+
+ handle.lb_policy
+
+ dropdown
+
+
+ true
+
+
+ handle.lb_retries
+
+ text
+
+ off
+
+ true
+
+
+ handle.lb_try_duration
+
+ text
+
+ 0
+
+ true
+
+
+ handle.lb_try_interval
+
+ text
+
+ 250
+
+ true
+
+
+ handle.PassiveHealthFailDuration
+
+ text
+
+ off
+
+ true
+
+
+ handle.PassiveHealthMaxFails
+
+ text
+
+ 1
+
+ true
+
+
+ handle.PassiveHealthUnhealthyStatus
+
+ text
+
+ off
+
+ true
+
+
+ handle.PassiveHealthUnhealthyLatency
+
+ text
+
+ off
+
+ true
+
+
+ handle.PassiveHealthUnhealthyRequestCount
+
+ text
+
+ off
+
+ true
+
diff --git a/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/forms/dialogLayer4.xml b/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/forms/dialogLayer4.xml
index a3ebb43f9..8fa4fdcae 100644
--- a/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/forms/dialogLayer4.xml
+++ b/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/forms/dialogLayer4.xml
@@ -107,13 +107,6 @@
text
-
- layer4.PassiveHealthFailDuration
-
- text
-
- true
-
layer4.ProxyProtocol
@@ -121,6 +114,37 @@
true
+
+ header
+
+ true
+
+
+ layer4.lb_policy
+
+ dropdown
+
+
+ true
+
+
+ layer4.PassiveHealthFailDuration
+
+ text
+
+ off
+
+ true
+
+
+ layer4.PassiveHealthMaxFails
+
+ text
+
+ 1
+
+ true
+
header
diff --git a/www/caddy/src/opnsense/mvc/app/models/OPNsense/Caddy/Caddy.xml b/www/caddy/src/opnsense/mvc/app/models/OPNsense/Caddy/Caddy.xml
index dc0f8de5e..f7da86b03 100644
--- a/www/caddy/src/opnsense/mvc/app/models/OPNsense/Caddy/Caddy.xml
+++ b/www/caddy/src/opnsense/mvc/app/models/OPNsense/Caddy/Caddy.xml
@@ -344,11 +344,6 @@
/^(\/.*)?$/u
Please enter a valid Path that starts with '/'.
-
- 1
- 100
- Please enter a value between 1 to 100.
-
Y
@@ -392,6 +387,46 @@
ca
+
+ random
+
+ first
+ round_robin
+ least_conn
+ ip_hash
+ client_ip_hash
+ uri_hash
+
+
+
+ 1
+ Please enter a minimum value of 1 or leave empty for defaults.
+
+
+ 1
+ Please enter a minimum value of 1 or leave empty for defaults.
+
+
+
+ 1
+ Please enter a minimum value of 1 or leave empty for defaults.
+
+
+ 2
+ Please enter a minimum value of 2 or leave empty for defaults.
+
+
+ /^(100|[1-5][0-9]{2}|[1-5]xx)$/u
+ Please enter a valid HTTP response code like 404 a status code class like 4xx.
+
+
+ 1
+ Please enter a minimum value of 1 or leave empty for defaults.
+
+
+ 1
+ Please enter a minimum value of 1 or leave empty for defaults.
+
@@ -548,11 +583,6 @@
Y
-
- 1
- 100
- Please enter a value between 1 to 100.
-
Off (default)
@@ -560,6 +590,25 @@
v2
+
+ random
+
+ first
+ round_robin
+ least_conn
+ ip_hash
+ client_ip_hash
+ uri_hash
+
+
+
+ 1
+ Please enter a minimum value of 1 or leave empty for defaults.
+
+
+ 2
+ Please enter a minimum value of 2 or leave empty for defaults.
+
,
Y
diff --git a/www/caddy/src/opnsense/mvc/app/views/OPNsense/Caddy/layer4.volt b/www/caddy/src/opnsense/mvc/app/views/OPNsense/Caddy/layer4.volt
index 7e41ee417..f1c57229c 100644
--- a/www/caddy/src/opnsense/mvc/app/views/OPNsense/Caddy/layer4.volt
+++ b/www/caddy/src/opnsense/mvc/app/views/OPNsense/Caddy/layer4.volt
@@ -148,13 +148,16 @@
| {{ lang._('Local Port') }} |
{{ lang._('Matchers') }} |
{{ lang._('Invert Matchers') }} |
+ {{ lang._('Terminate TLS') }} |
{{ lang._('Domain') }} |
{{ lang._('OpenVPN Modes') }} |
{{ lang._('OpenVPN Static Key') }} |
{{ lang._('Upstream Domain') }} |
{{ lang._('Upstream Port') }} |
{{ lang._('Remote IP') }} |
- {{ lang._('Fail Duration') }} |
+ {{ lang._('Load Balance Policy') }} |
+ {{ lang._('Passive Health Fail Duration') }} |
+ {{ lang._('Passive Health Max Fails') }} |
{{ lang._('Proxy Protocol') }} |
{{ lang._('Description') }} |
{{ lang._('Commands') }} |
diff --git a/www/caddy/src/opnsense/mvc/app/views/OPNsense/Caddy/reverse_proxy.volt b/www/caddy/src/opnsense/mvc/app/views/OPNsense/Caddy/reverse_proxy.volt
index 2840c9b83..42036d604 100644
--- a/www/caddy/src/opnsense/mvc/app/views/OPNsense/Caddy/reverse_proxy.volt
+++ b/www/caddy/src/opnsense/mvc/app/views/OPNsense/Caddy/reverse_proxy.volt
@@ -435,7 +435,6 @@
{{ lang._('Upstream Domain') }} |
{{ lang._('Upstream Port') }} |
{{ lang._('Upstream Path') }} |
- {{ lang._('Upstream Fail Duration') }} |
{{ lang._('Forward Auth') }} |
{{ lang._('Access List') }} |
{{ lang._('HTTP Version') }} |
@@ -444,6 +443,15 @@
{{ lang._('TLS Server Name') }} |
{{ lang._('NTLM') }} |
{{ lang._('TLS Insecure Skip Verify') }} |
+ {{ lang._('Load Balance Policy') }} |
+ {{ lang._('Load Balance Retries') }} |
+ {{ lang._('Load Balance Try Duration') }} |
+ {{ lang._('Load Balance Try Interval') }} |
+ {{ lang._('Passive Health Fail Duration') }} |
+ {{ lang._('Passive Health Max Fails') }} |
+ {{ lang._('Passive Health Unhealthy Status') }} |
+ {{ lang._('Passive Health Unhealthy Latency') }} |
+ {{ lang._('Passive Health Unhealthy Request Count') }} |
{{ lang._('Description') }} |
{{ lang._('Commands') }} |
diff --git a/www/caddy/src/opnsense/service/templates/OPNsense/Caddy/Caddyfile b/www/caddy/src/opnsense/service/templates/OPNsense/Caddy/Caddyfile
index ba29d7e26..90543e2fd 100644
--- a/www/caddy/src/opnsense/service/templates/OPNsense/Caddy/Caddyfile
+++ b/www/caddy/src/opnsense/service/templates/OPNsense/Caddy/Caddyfile
@@ -412,9 +412,33 @@ http://{{ domain }} {
{% if handle.HandleDirective == "reverse_proxy" %}
{{ handle.HandleDirective }} {{ formatted_domains | join(' ') }} {
{{ header_manipulation(handle) }}
+ {% if handle.lb_policy|default("") %}
+ lb_policy {{ handle.lb_policy }}
+ {% endif %}
+ {% if handle.lb_retries|default("") %}
+ lb_retries {{ handle.lb_retries }}
+ {% endif %}
+ {% if handle.lb_try_duration|default("") %}
+ lb_try_duration {{ handle.lb_try_duration }}s
+ {% endif %}
+ {% if handle.lb_try_interval|default("") %}
+ lb_try_interval {{ handle.lb_try_interval }}ms
+ {% endif %}
{% if handle.PassiveHealthFailDuration|default("") %}
fail_duration {{ handle.PassiveHealthFailDuration }}s
{% endif %}
+ {% if handle.PassiveHealthMaxFails|default("") %}
+ max_fails {{ handle.PassiveHealthMaxFails }}
+ {% endif %}
+ {% if handle.PassiveHealthUnhealthyStatus|default("") %}
+ unhealthy_status {{ handle.PassiveHealthUnhealthyStatus }}
+ {% endif %}
+ {% if handle.PassiveHealthUnhealthyLatency|default("") %}
+ unhealthy_latency {{ handle.PassiveHealthUnhealthyLatency }}ms
+ {% endif %}
+ {% if handle.PassiveHealthUnhealthyRequestCount|default("") %}
+ unhealthy_request_count {{ handle.PassiveHealthUnhealthyRequestCount }}
+ {% endif %}
{% set has_transport_options =
handle.HttpVersion or
handle.HttpKeepalive or
diff --git a/www/caddy/src/opnsense/service/templates/OPNsense/Caddy/includeLayer4 b/www/caddy/src/opnsense/service/templates/OPNsense/Caddy/includeLayer4
index 0029c1ba6..92d638759 100644
--- a/www/caddy/src/opnsense/service/templates/OPNsense/Caddy/includeLayer4
+++ b/www/caddy/src/opnsense/service/templates/OPNsense/Caddy/includeLayer4
@@ -22,35 +22,41 @@
{# Sort the configurations based on 'Sequence' #}
{% set layer4_configs = unsorted_layer4_configs | sort(attribute='Sequence') %}
-{% macro define_proxy(layer4, to_domains, to_port, fail_duration, proxy_protocol) %}
+{% macro define_proxy(layer4) %}
{% if layer4.TerminateTls|default("0") == "1" %}
tls
{% endif %}
- proxy {% for domain in to_domains.split(',') %}
+ proxy {% for domain in layer4.ToDomain.split(',') %}
{% set is_ipv6 = (':' in domain) %}
- {{ layer4.Protocol }}/{{ '[' if is_ipv6 }}{{ domain }}{{ ']' if is_ipv6 }}:{{ to_port }}{% if not loop.last %} {% endif %}
+ {{ layer4.Protocol }}/{{ '[' if is_ipv6 }}{{ domain }}{{ ']' if is_ipv6 }}:{{ layer4.ToPort }}{% if not loop.last %} {% endif %}
{% endfor %} {
- {% if fail_duration %}
- fail_duration {{ fail_duration }}s
+ {% if layer4.lb_policy|default("") %}
+ lb_policy {{ layer4.lb_policy }}
{% endif %}
- {% if proxy_protocol %}
- proxy_protocol {{ proxy_protocol }}
+ {% if layer4.PassiveHealthFailDuration|default("") %}
+ fail_duration {{ layer4.PassiveHealthFailDuration }}s
+ {% endif %}
+ {% if layer4.PassiveHealthMaxFails|default("") %}
+ max_fails {{ layer4.PassiveHealthMaxFails }}
+ {% endif %}
+ {% if layer4.ProxyProtocol %}
+ proxy_protocol {{ layer4.ProxyProtocol }}
{% endif %}
}
{% endmacro %}
-{% macro configure_proxy(layer4, to_domains, to_port, remote_ips, fail_duration, proxy_protocol) %}
+{% macro configure_proxy(layer4) %}
{% set content %}
- {% if remote_ips %}
- {% set ip_list = remote_ips.split(',') %}
+ {% if layer4.RemoteIp %}
+ {% set ip_list = layer4.RemoteIp.split(',') %}
subroute {
@allowed_ips remote_ip {{ ip_list|join(' ') }}
route @allowed_ips {
- {{ define_proxy(layer4, to_domains, to_port, fail_duration, proxy_protocol) }}
+ {{ define_proxy(layer4) }}
}
}
{% else %}
- {{ define_proxy(layer4, to_domains, to_port, fail_duration, proxy_protocol) }}
+ {{ define_proxy(layer4) }}
{% endif %}
{% endset %}
{{ content|trim }}
@@ -144,7 +150,7 @@
{% if layer4.Matchers != 'any' %}
@{{ layer4['@uuid'] }} {{ handle_special_matchers(layer4) }}
route @{{ layer4['@uuid'] }} {
- {{ configure_proxy(layer4, layer4.ToDomain, layer4.ToPort, layer4.RemoteIp, layer4.PassiveHealthFailDuration, layer4.ProxyProtocol) }}
+ {{ configure_proxy(layer4) }}
}
{% endif %}
{% endif %}
@@ -157,11 +163,11 @@
{% if layer4.Matchers != 'any' %}
@{{ layer4['@uuid'] }} {{ handle_special_matchers(layer4) }}
route @{{ layer4['@uuid'] }} {
- {{ configure_proxy(layer4, layer4.ToDomain, layer4.ToPort, layer4.RemoteIp, layer4.PassiveHealthFailDuration, layer4.ProxyProtocol) }}
+ {{ configure_proxy(layer4) }}
}
{% else %}
route {
- {{ configure_proxy(layer4, layer4.ToDomain, layer4.ToPort, layer4.RemoteIp, layer4.PassiveHealthFailDuration, layer4.ProxyProtocol) }}
+ {{ configure_proxy(layer4) }}
}
{% endif %}
{% endif %}