mirror of
https://github.com/netbirdio/plugins.git
synced 2026-05-22 18:44:07 -07:00
www/caddy: Add Layer4 openvpn, winbox and quic matcher (#4325)
* www/caddy: Add CRUD for Layer4 OpenVPN matcher with mode and static key support. * www/caddy: Export static keys to the filesystem as uuid.key * www/caddy: Remove validation that checks for multiple keys, help text is enough. * www/caddy: Expand layer4 template for all supported OpenVPN modes. * www/caddy: Prevent multiple static keys for modes other than crypt2_client. Fix helptexts. * www/caddy: Add unique constraint to description of openvpn static key * www/caddy: Changelog and version bump * www/caddy: Make static key optional when choosing the tls mode in openvpn matcher * www/caddy: Prepare new Layer7 Matcher Tab for more customizable matchers in the future. * www/caddy: Add Layer4 QUIC matcher. * www/caddy: Rename matcherTab * www/caddy: Revert a4ea0cb3 since its non operational and will not be needed for a while anyway * www/caddy: Changelog
This commit is contained in:
+1
-1
@@ -1,5 +1,5 @@
|
||||
PLUGIN_NAME= caddy
|
||||
PLUGIN_VERSION= 1.7.3
|
||||
PLUGIN_VERSION= 1.7.4
|
||||
PLUGIN_DEPENDS= caddy-custom
|
||||
PLUGIN_COMMENT= Modern Reverse Proxy with Automatic HTTPS, Dynamic DNS and Layer4 Routing
|
||||
PLUGIN_MAINTAINER= cedrik@pischem.com
|
||||
|
||||
@@ -13,6 +13,18 @@ DOC: https://docs.opnsense.org/manual/how-tos/caddy.html
|
||||
Plugin Changelog
|
||||
================
|
||||
|
||||
1.7.4
|
||||
|
||||
* Add: Layer4 OpenVPN matcher with mode, digest and static key support
|
||||
* Add: Layer4 Winbox matcher
|
||||
* Add: Layer4 QUIC matcher
|
||||
* Build: Update dependency to lang/go123
|
||||
* Build: Update caddy-l4 and caddy-dynamicdns module
|
||||
* Build: Fix that caddy-l4 does not stop when ssh is proxied
|
||||
* Build: DNS Providers: Update porkbun, dnsmadeeasy
|
||||
* Cleanup: Layer4 default route in listener_wrappers has been removed (obsolete)
|
||||
* Fix: Error when same Access List is set to wildcard and subdomain
|
||||
|
||||
1.7.3
|
||||
|
||||
* Add: Clear All button to Filter by Domain selectpicker
|
||||
|
||||
+66
-34
@@ -209,40 +209,6 @@ class ReverseProxyController extends ApiMutableModelControllerBase
|
||||
return $this->toggleBase("reverseproxy.handle", $uuid, $enabled);
|
||||
}
|
||||
|
||||
|
||||
// Layer4 Section
|
||||
|
||||
public function searchLayer4Action()
|
||||
{
|
||||
return $this->searchBase("reverseproxy.layer4", null, 'description');
|
||||
}
|
||||
|
||||
public function setLayer4Action($uuid)
|
||||
{
|
||||
return $this->setBase("layer4", "reverseproxy.layer4", $uuid);
|
||||
}
|
||||
|
||||
public function addLayer4Action()
|
||||
{
|
||||
return $this->addBase("layer4", "reverseproxy.layer4");
|
||||
}
|
||||
|
||||
public function getLayer4Action($uuid = null)
|
||||
{
|
||||
return $this->getBase("layer4", "reverseproxy.layer4", $uuid);
|
||||
}
|
||||
|
||||
public function delLayer4Action($uuid)
|
||||
{
|
||||
return $this->delBase("reverseproxy.layer4", $uuid);
|
||||
}
|
||||
|
||||
public function toggleLayer4Action($uuid, $enabled = null)
|
||||
{
|
||||
return $this->toggleBase("reverseproxy.layer4", $uuid, $enabled);
|
||||
}
|
||||
|
||||
|
||||
// AccessList Section
|
||||
|
||||
public function searchAccessListAction()
|
||||
@@ -349,4 +315,70 @@ class ReverseProxyController extends ApiMutableModelControllerBase
|
||||
{
|
||||
return $this->delBase("reverseproxy.header", $uuid);
|
||||
}
|
||||
|
||||
|
||||
// Layer4 Proxy Section
|
||||
|
||||
public function searchLayer4Action()
|
||||
{
|
||||
return $this->searchBase("reverseproxy.layer4", null, 'description');
|
||||
}
|
||||
|
||||
public function setLayer4Action($uuid)
|
||||
{
|
||||
return $this->setBase("layer4", "reverseproxy.layer4", $uuid);
|
||||
}
|
||||
|
||||
public function addLayer4Action()
|
||||
{
|
||||
return $this->addBase("layer4", "reverseproxy.layer4");
|
||||
}
|
||||
|
||||
public function getLayer4Action($uuid = null)
|
||||
{
|
||||
return $this->getBase("layer4", "reverseproxy.layer4", $uuid);
|
||||
}
|
||||
|
||||
public function delLayer4Action($uuid)
|
||||
{
|
||||
return $this->delBase("reverseproxy.layer4", $uuid);
|
||||
}
|
||||
|
||||
public function toggleLayer4Action($uuid, $enabled = null)
|
||||
{
|
||||
return $this->toggleBase("reverseproxy.layer4", $uuid, $enabled);
|
||||
}
|
||||
|
||||
|
||||
// Layer4 OpenVPN Section
|
||||
|
||||
public function searchLayer4OpenvpnAction()
|
||||
{
|
||||
return $this->searchBase("reverseproxy.layer4openvpn", null, 'description');
|
||||
}
|
||||
|
||||
public function setLayer4OpenvpnAction($uuid)
|
||||
{
|
||||
return $this->setBase("layer4openvpn", "reverseproxy.layer4openvpn", $uuid);
|
||||
}
|
||||
|
||||
public function addLayer4OpenvpnAction()
|
||||
{
|
||||
return $this->addBase("layer4openvpn", "reverseproxy.layer4openvpn");
|
||||
}
|
||||
|
||||
public function getLayer4OpenvpnAction($uuid = null)
|
||||
{
|
||||
return $this->getBase("layer4openvpn", "reverseproxy.layer4openvpn", $uuid);
|
||||
}
|
||||
|
||||
public function delLayer4OpenvpnAction($uuid)
|
||||
{
|
||||
return $this->delBase("reverseproxy.layer4openvpn", $uuid);
|
||||
}
|
||||
|
||||
public function toggleLayer4OpenvpnAction($uuid, $enabled = null)
|
||||
{
|
||||
return $this->toggleBase("reverseproxy.layer4openvpn", $uuid, $enabled);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,5 +38,6 @@ class Layer4Controller extends IndexController
|
||||
{
|
||||
$this->view->pick('OPNsense/Caddy/layer4');
|
||||
$this->view->formDialogLayer4 = $this->getForm("dialogLayer4");
|
||||
$this->view->formDialogLayer4Openvpn = $this->getForm("dialogLayer4Openvpn");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,10 +62,26 @@
|
||||
<id>layer4.FromDomain</id>
|
||||
<label>Domain</label>
|
||||
<type>select_multiple</type>
|
||||
<style>style_matchers tokenize</style>
|
||||
<style>style_matchers tokenize matchers_domain</style>
|
||||
<allownew>true</allownew>
|
||||
<help><![CDATA[Enter one or multiple domains to route via SNI or Host Header. Wildcard domains and host wildcards are allowed, e.g. "*.example.com" and "*".]]></help>
|
||||
</field>
|
||||
<field>
|
||||
<id>layer4.FromOpenvpnModes</id>
|
||||
<label>OpenVPN Mode</label>
|
||||
<type>dropdown</type>
|
||||
<style>style_matchers matchers_openvpn</style>
|
||||
<help><![CDATA[Select the mode matching the OpenVPN Server or Client.]]></help>
|
||||
</field>
|
||||
<field>
|
||||
<id>layer4.FromOpenvpnStaticKey</id>
|
||||
<label>OpenVPN Static Key</label>
|
||||
<type>select_multiple</type>
|
||||
<style>style_matchers selectpicker matchers_openvpn</style>
|
||||
<hint>Any</hint>
|
||||
<size>5</size>
|
||||
<help><![CDATA[Select a Static Key to match. Multiple Static Keys are only supported for tls-crypt2_client mode.]]></help>
|
||||
</field>
|
||||
<field>
|
||||
<id>layer4.InvertMatchers</id>
|
||||
<label>Invert Matchers</label>
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
<fields>
|
||||
<field>
|
||||
<id>layer4openvpn.description</id>
|
||||
<label>Description</label>
|
||||
<type>text</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>layer4openvpn.StaticKey</id>
|
||||
<label>Static Key</label>
|
||||
<type>textbox</type>
|
||||
<help>Paste an OpenVPN Static key.</help>
|
||||
</field>
|
||||
</fields>
|
||||
@@ -180,7 +180,7 @@ class Caddy extends BaseModel
|
||||
foreach ($this->reverseproxy->layer4->iterateItems() as $item) {
|
||||
if ($item->isFieldChanged()) {
|
||||
$key = $item->__reference;
|
||||
if (in_array((string)$item->Matchers, ['httphost', 'tlssni']) && empty((string)$item->FromDomain)) {
|
||||
if (in_array((string)$item->Matchers, ['httphost', 'tlssni', 'quicsni']) && empty((string)$item->FromDomain)) {
|
||||
$messages->appendMessage(new Message(
|
||||
sprintf(
|
||||
gettext(
|
||||
@@ -191,7 +191,7 @@ class Caddy extends BaseModel
|
||||
$key . ".FromDomain"
|
||||
));
|
||||
} elseif (
|
||||
!in_array((string)$item->Matchers, ['httphost', 'tlssni']) &&
|
||||
!in_array((string)$item->Matchers, ['httphost', 'tlssni', 'quicsni']) &&
|
||||
(
|
||||
!empty((string)$item->FromDomain) &&
|
||||
(string)$item->FromDomain != '*'
|
||||
@@ -208,6 +208,30 @@ class Caddy extends BaseModel
|
||||
));
|
||||
}
|
||||
|
||||
if ((string)$item->Matchers !== 'openvpn' && !empty((string)$item->FromOpenvpnModes)) {
|
||||
$messages->appendMessage(new Message(
|
||||
sprintf(
|
||||
gettext(
|
||||
'When "%s" matcher is selected, field must be empty.'
|
||||
),
|
||||
$item->Matchers
|
||||
),
|
||||
$key . ".FromOpenvpnModes"
|
||||
));
|
||||
}
|
||||
|
||||
if ((string)$item->Matchers !== 'openvpn' && !empty((string)$item->FromOpenvpnStaticKey)) {
|
||||
$messages->appendMessage(new Message(
|
||||
sprintf(
|
||||
gettext(
|
||||
'When "%s" matcher is selected, field must be empty.'
|
||||
),
|
||||
$item->Matchers
|
||||
),
|
||||
$key . ".FromOpenvpnStaticKey"
|
||||
));
|
||||
}
|
||||
|
||||
if ((string)$item->Type === 'global' && empty((string)$item->FromPort)) {
|
||||
$messages->appendMessage(new Message(
|
||||
sprintf(
|
||||
@@ -246,13 +270,14 @@ class Caddy extends BaseModel
|
||||
(string)$item->Type !== 'global' &&
|
||||
(
|
||||
(string)$item->Matchers == 'tls' ||
|
||||
(string)$item->Matchers == 'http'
|
||||
(string)$item->Matchers == 'http' ||
|
||||
(string)$item->Matchers == 'quic'
|
||||
)
|
||||
) {
|
||||
$messages->appendMessage(new Message(
|
||||
sprintf(
|
||||
gettext(
|
||||
'When routing type is "%s", matchers "HTTP" or "TLS" cannot be chosen.'
|
||||
'When routing type is "%s", matchers "HTTP", "TLS" or "QUIC" cannot be chosen.'
|
||||
),
|
||||
$item->Type
|
||||
),
|
||||
|
||||
@@ -489,6 +489,29 @@
|
||||
<AsList>Y</AsList>
|
||||
<ValidationMessage>Please enter one or multiple hostnames or FQDNs.</ValidationMessage>
|
||||
</FromDomain>
|
||||
<FromOpenvpnModes type="OptionField">
|
||||
<BlankDesc>Any</BlankDesc>
|
||||
<OptionValues>
|
||||
<auth_sha256_normal>tls-auth_sha256_normal</auth_sha256_normal>
|
||||
<auth_sha256_inverse>tls-auth_sha256_inverse</auth_sha256_inverse>
|
||||
<auth_sha512_normal>tls-auth_sha512_normal</auth_sha512_normal>
|
||||
<auth_sha512_inverse>tls-auth_sha512_inverse</auth_sha512_inverse>
|
||||
<crypt>tls-crypt</crypt>
|
||||
<crypt2_client>tls-crypt2_client</crypt2_client>
|
||||
<crypt2_server>tls-crypt2_server</crypt2_server>
|
||||
</OptionValues>
|
||||
</FromOpenvpnModes>
|
||||
<FromOpenvpnStaticKey type="ModelRelationField">
|
||||
<Model>
|
||||
<reverseproxy>
|
||||
<source>OPNsense.Caddy.Caddy</source>
|
||||
<items>reverseproxy.layer4openvpn</items>
|
||||
<display>description</display>
|
||||
<display_format>%s</display_format>
|
||||
</reverseproxy>
|
||||
</Model>
|
||||
<Multiple>Y</Multiple>
|
||||
</FromOpenvpnStaticKey>
|
||||
<Matchers type="OptionField">
|
||||
<Required>Y</Required>
|
||||
<Default>tlssni</Default>
|
||||
@@ -497,14 +520,18 @@
|
||||
<dns>DNS</dns>
|
||||
<http>HTTP</http>
|
||||
<httphost>HTTP (Host Header)</httphost>
|
||||
<openvpn>OpenVPN</openvpn>
|
||||
<postgres>Postgres</postgres>
|
||||
<proxy_protocol>Proxy Protocol</proxy_protocol>
|
||||
<quic>QUIC</quic>
|
||||
<quicsni>QUIC (SNI Client Hello)</quicsni>
|
||||
<rdp>RDP</rdp>
|
||||
<socks4>SOCKSv4</socks4>
|
||||
<socks5>SOCKSv5</socks5>
|
||||
<ssh>SSH</ssh>
|
||||
<tls>TLS</tls>
|
||||
<tlssni>TLS (SNI Client Hello)</tlssni>
|
||||
<winbox>Winbox</winbox>
|
||||
<wireguard>Wireguard</wireguard>
|
||||
<xmpp>XMPP</xmpp>
|
||||
</OptionValues>
|
||||
@@ -539,6 +566,20 @@
|
||||
</RemoteIp>
|
||||
<description type="DescriptionField"/>
|
||||
</layer4>
|
||||
<layer4openvpn type="ArrayField">
|
||||
<StaticKey type="TextField">
|
||||
<Required>Y</Required>
|
||||
</StaticKey>
|
||||
<description type="DescriptionField">
|
||||
<Required>Y</Required>
|
||||
<Constraints>
|
||||
<check001>
|
||||
<ValidationMessage>Description must be unique.</ValidationMessage>
|
||||
<type>UniqueConstraint</type>
|
||||
</check001>
|
||||
</Constraints>
|
||||
</description>
|
||||
</layer4openvpn>
|
||||
</reverseproxy>
|
||||
</items>
|
||||
</model>
|
||||
|
||||
@@ -36,6 +36,15 @@
|
||||
toggle:'/api/caddy/ReverseProxy/toggleLayer4/',
|
||||
});
|
||||
|
||||
$("#Layer4OpenvpnGrid").UIBootgrid({
|
||||
search:'/api/caddy/ReverseProxy/searchLayer4Openvpn/',
|
||||
get:'/api/caddy/ReverseProxy/getLayer4Openvpn/',
|
||||
set:'/api/caddy/ReverseProxy/setLayer4Openvpn/',
|
||||
add:'/api/caddy/ReverseProxy/addLayer4Openvpn/',
|
||||
del:'/api/caddy/ReverseProxy/delLayer4Openvpn/',
|
||||
toggle:'/api/caddy/ReverseProxy/toggleLayer4Openvpn/',
|
||||
});
|
||||
|
||||
/**
|
||||
* Displays an alert message to the user.
|
||||
*
|
||||
@@ -86,11 +95,17 @@
|
||||
}
|
||||
});
|
||||
|
||||
// Hide all elements with style_matchers initially
|
||||
$(".style_matchers").closest('tr').hide();
|
||||
|
||||
$("#layer4\\.Matchers").change(function() {
|
||||
if ($(this).val() !== "tlssni" && $(this).val() !== "httphost") {
|
||||
$(".style_matchers").closest('tr').hide();
|
||||
} else {
|
||||
$(".style_matchers").closest('tr').show();
|
||||
$(".style_matchers").closest('tr').hide();
|
||||
const selectedVal = $(this).val();
|
||||
|
||||
if (selectedVal === "tlssni" || selectedVal === "httphost" || selectedVal === "quicsni") {
|
||||
$(".matchers_domain").closest('tr').show();
|
||||
} else if (selectedVal === "openvpn") {
|
||||
$(".matchers_openvpn").closest('tr').show();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -108,6 +123,7 @@
|
||||
|
||||
<ul class="nav nav-tabs" data-tabs="tabs" id="maintabs">
|
||||
<li id="tab-layer4" class="active"><a data-toggle="tab" href="#layer4Tab">{{ lang._('Layer4 Routes') }}</a></li>
|
||||
<li id="tab-matcher"><a data-toggle="tab" href="#matcherTab">{{ lang._('Layer7 Matcher Settings') }}</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="tab-content content-box">
|
||||
@@ -115,7 +131,7 @@
|
||||
<div id="layer4Tab" class="tab-pane fade active in">
|
||||
<div style="padding-left: 16px;">
|
||||
<h1 class="custom-header">{{ lang._('Layer4 Routes') }}</h1>
|
||||
<div style="display: block;"> <!-- Common container -->
|
||||
<div style="display: block;">
|
||||
<table id="Layer4Grid" class="table table-condensed table-hover table-striped" data-editDialog="DialogLayer4" data-editAlert="ConfigurationChangeMessage">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -125,9 +141,11 @@
|
||||
<th data-column-id="Type" data-type="string" data-visible="false">{{ lang._('Routing Type') }}</th>
|
||||
<th data-column-id="Protocol" data-type="string">{{ lang._('Protocol') }}</th>
|
||||
<th data-column-id="FromPort" data-type="string" data-visible="false">{{ lang._('Local Port') }}</th>
|
||||
<th data-column-id="FromDomain" data-type="string">{{ lang._('Domain') }}</th>
|
||||
<th data-column-id="Matchers" data-type="string">{{ lang._('Matchers') }}</th>
|
||||
<th data-column-id="InvertMatchers" data-type="boolean" data-formatter="boolean" data-visible="false">{{ lang._('Invert Matchers') }}</th>
|
||||
<th data-column-id="FromDomain" data-type="string">{{ lang._('Domain') }}</th>
|
||||
<th data-column-id="FromOpenvpnModes" data-type="string" data-visible="false">{{ lang._('OpenVPN Modes') }}</th>
|
||||
<th data-column-id="FromOpenvpnStaticKey" data-type="string" data-visible="false">{{ lang._('OpenVPN Static Key') }}</th>
|
||||
<th data-column-id="ToDomain" data-type="string">{{ lang._('Upstream Domain') }}</th>
|
||||
<th data-column-id="ToPort" data-type="string">{{ lang._('Upstream Port') }}</th>
|
||||
<th data-column-id="RemoteIp" data-type="string" data-visible="false">{{ lang._('Remote IP') }}</th>
|
||||
@@ -152,8 +170,39 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Layer7 Tab -->
|
||||
<div id="matcherTab" class="tab-pane fade">
|
||||
<div style="padding-left: 16px;">
|
||||
<!-- OpenVPN Matcher -->
|
||||
<h1 class="custom-header">{{ lang._('OpenVPN Static Keys') }}</h1>
|
||||
<div style="display: block;">
|
||||
<table id="Layer4OpenvpnGrid" class="table table-condensed table-hover table-striped" data-editDialog="DialogLayer4Openvpn" data-editAlert="ConfigurationChangeMessage">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="uuid" data-type="string" data-identifier="true" data-visible="false">{{ lang._('ID') }}</th>
|
||||
<th data-column-id="description" data-type="string">{{ lang._('Description') }}</th>
|
||||
<th data-column-id="commands" data-width="7em" data-formatter="commands" data-sortable="false">{{ lang._('Commands') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>
|
||||
<button id="addLayer4OpenvpnBtn" data-action="add" type="button" class="btn btn-xs btn-primary"><span class="fa fa-plus"></span></button>
|
||||
<button data-action="deleteSelected" type="button" class="btn btn-xs btn-default"><span class="fa fa-trash-o"></span></button>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Reconfigure Button -->
|
||||
<section class="page-content-main">
|
||||
<div class="content-box">
|
||||
@@ -177,3 +226,4 @@
|
||||
</section>
|
||||
|
||||
{{ partial("layout_partials/base_dialog",['fields':formDialogLayer4,'id':'DialogLayer4','label':lang._('Edit Layer4 Route')])}}
|
||||
{{ partial("layout_partials/base_dialog",['fields':formDialogLayer4Openvpn,'id':'DialogLayer4Openvpn','label':lang._('Edit OpenVPN Static Key')])}}
|
||||
|
||||
@@ -36,22 +36,22 @@ $temp_dir = '/var/db/caddy/data/caddy/certificates/temp/';
|
||||
|
||||
// Traverse through certificates
|
||||
foreach ($configObj->cert as $cert) {
|
||||
$cert_refid = (string) $cert->refid;
|
||||
$cert_content = base64_decode((string) $cert->crt);
|
||||
$key_content = base64_decode((string) $cert->prv);
|
||||
$cert_refid = (string)$cert->refid;
|
||||
$cert_content = base64_decode((string)$cert->crt);
|
||||
$key_content = base64_decode((string)$cert->prv);
|
||||
$cert_chain = $cert_content;
|
||||
|
||||
// Handle CA and possible intermediate CA to create a certificate bundle
|
||||
if (!empty($cert->caref)) {
|
||||
foreach ($configObj->ca as $ca) {
|
||||
if ((string) $cert->caref === (string) $ca->refid) {
|
||||
$ca_content = base64_decode((string) $ca->crt);
|
||||
if ((string)$cert->caref === (string)$ca->refid) {
|
||||
$ca_content = base64_decode((string)$ca->crt);
|
||||
$cert_chain .= "\n" . $ca_content;
|
||||
|
||||
if (!empty($ca->caref)) {
|
||||
foreach ($configObj->ca as $parent_ca) {
|
||||
if ((string) $ca->caref === (string) $parent_ca->refid) {
|
||||
$parent_ca_content = base64_decode((string) $parent_ca->crt);
|
||||
if ((string)$ca->caref === (string)$parent_ca->refid) {
|
||||
$parent_ca_content = base64_decode((string)$parent_ca->crt);
|
||||
$cert_chain .= "\n" . $parent_ca_content;
|
||||
break;
|
||||
}
|
||||
@@ -68,9 +68,20 @@ foreach ($configObj->cert as $cert) {
|
||||
|
||||
// Traverse through CA certificates and save them
|
||||
foreach ($configObj->ca as $ca) {
|
||||
$ca_refid = (string) $ca->refid;
|
||||
$ca_content = base64_decode((string) $ca->crt);
|
||||
$ca_refid = (string)$ca->refid;
|
||||
$ca_content = base64_decode((string)$ca->crt);
|
||||
|
||||
// Save the CA certificate
|
||||
file_put_contents($temp_dir . $ca_refid . '.pem', $ca_content);
|
||||
}
|
||||
|
||||
// Traverse through layer4 OpenVPN static keys and save them as files
|
||||
if (isset($configObj->Pischem->caddy->reverseproxy->layer4openvpn)) {
|
||||
foreach ($configObj->Pischem->caddy->reverseproxy->layer4openvpn as $openvpn) {
|
||||
$uuid = (string) $openvpn['uuid'];
|
||||
$static_key = (string) $openvpn->StaticKey;
|
||||
|
||||
// Save the static key
|
||||
file_put_contents($temp_dir . $uuid . '.key', $static_key);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,6 +70,66 @@
|
||||
{{ invert_prefix }}http host {{ layer4.FromDomain.replace(',', ' ') }}
|
||||
{% elif layer4.Matchers == 'tlssni' %}
|
||||
{{ invert_prefix }}tls sni {{ layer4.FromDomain.replace(',', ' ') }}
|
||||
{% elif layer4.Matchers == 'quicsni' %}
|
||||
{{ invert_prefix }}quic sni {{ layer4.FromDomain.replace(',', ' ') }}
|
||||
{% elif layer4.Matchers == 'openvpn' and layer4.FromOpenvpnModes %}
|
||||
{% for mode in layer4.FromOpenvpnModes.split(',') %}
|
||||
{% set mode_clean = mode.strip() %}
|
||||
{% if layer4.FromOpenvpnStaticKey %}
|
||||
{% set key_list = layer4.FromOpenvpnStaticKey.split(',') %}
|
||||
{% endif %}
|
||||
{% if mode_clean.startswith('auth') %}
|
||||
{% if key_list|length > 1 %}
|
||||
{% set key_list = key_list[:1] %}
|
||||
{% endif %}
|
||||
{% set digest = 'sha256' if 'sha256' in mode_clean else 'sha512' %}
|
||||
{% set direction = 'normal' if 'normal' in mode_clean else 'inverse' %}
|
||||
{{ invert_prefix }}openvpn {
|
||||
modes auth
|
||||
auth_digest {{ digest }}
|
||||
{% if layer4.FromOpenvpnStaticKey %}
|
||||
group_key_direction {{ direction }}
|
||||
{% for key_uuid in key_list %}
|
||||
group_key_file /var/db/caddy/data/caddy/certificates/temp/{{ key_uuid.strip() }}.key
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
}
|
||||
{% elif mode_clean == 'crypt' %}
|
||||
{% if key_list|length > 1 %}
|
||||
{% set key_list = key_list[:1] %}
|
||||
{% endif %}
|
||||
{{ invert_prefix }}openvpn {
|
||||
modes crypt
|
||||
{% if layer4.FromOpenvpnStaticKey %}
|
||||
{% for key_uuid in key_list %}
|
||||
group_key_file /var/db/caddy/data/caddy/certificates/temp/{{ key_uuid.strip() }}.key
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
}
|
||||
{% elif mode_clean == 'crypt2_client' %}
|
||||
{# Multiple keys are allowed for crypt2_client #}
|
||||
{{ invert_prefix }}openvpn {
|
||||
modes crypt2
|
||||
{% if layer4.FromOpenvpnStaticKey %}
|
||||
{% for key_uuid in key_list %}
|
||||
client_key_file /var/db/caddy/data/caddy/certificates/temp/{{ key_uuid.strip() }}.key
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
}
|
||||
{% elif mode_clean == 'crypt2_server' %}
|
||||
{% if key_list|length > 1 %}
|
||||
{% set key_list = key_list[:1] %}
|
||||
{% endif %}
|
||||
{{ invert_prefix }}openvpn {
|
||||
modes crypt2
|
||||
{% if layer4.FromOpenvpnStaticKey %}
|
||||
{% for key_uuid in key_list %}
|
||||
server_key_file /var/db/caddy/data/caddy/certificates/temp/{{ key_uuid.strip() }}.key
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{{ invert_prefix }}{{ layer4.Matchers }}
|
||||
{% endif %}
|
||||
|
||||
Reference in New Issue
Block a user