Finalizes SSL Passthrough hosts

This commit is contained in:
chaptergy 2021-10-12 15:25:46 +02:00
parent ab026e5e18
commit 02d3093d88
13 changed files with 95 additions and 25 deletions

View File

@ -25,6 +25,7 @@ const internalNginx = {
*/
configure: (model, host_type, host) => {
let combined_meta = {};
const sslPassthroughEnabled = internalNginx.sslPassthroughEnabled();
return internalNginx.test()
.then(() => {
@ -33,7 +34,25 @@ const internalNginx = {
return internalNginx.deleteConfig(host_type, host); // Don't throw errors, as the file may not exist at all
})
.then(() => {
if(host_type === 'ssl_passthrough_host' && !sslPassthroughEnabled){
// ssl passthrough is disabled
const meta = {
nginx_online: false,
nginx_err: 'SSL passthrough is not enabled in environment'
};
return passthroughHostModel
.query()
.where('is_deleted', 0)
.andWhere('enabled', 1)
.patch({
meta
}).then(() => {
return internalNginx.deleteConfig('ssl_passthrough_host', host, false);
});
} else {
return internalNginx.generateConfig(host_type, host);
}
})
.then(() => {
// Test nginx again and update meta with result
@ -46,12 +65,18 @@ const internalNginx = {
});
if(host_type === 'ssl_passthrough_host'){
// If passthrough is disabled we have already marked the hosts as offline
if (sslPassthroughEnabled) {
return passthroughHostModel
.query()
.where('is_deleted', 0)
.andWhere('enabled', 1)
.patch({
meta: combined_meta
});
}
return Promise.resolve();
}
return model
.query()
@ -84,6 +109,18 @@ const internalNginx = {
nginx_err: valid_lines.join('\n')
});
if(host_type === 'ssl_passthrough_host'){
return passthroughHostModel
.query()
.where('is_deleted', 0)
.andWhere('enabled', 1)
.patch({
meta: combined_meta
}).then(() => {
return internalNginx.deleteConfig('ssl_passthrough_host', host, true);
});
}
return model
.query()
.where('id', host.id)
@ -241,7 +278,7 @@ const internalNginx = {
}),
}
} else {
internalNginx.deleteConfig(host_type, host)
internalNginx.deleteConfig(host_type, host, false)
}
} else if (host_type !== 'default') {
@ -470,7 +507,7 @@ const internalNginx = {
return (enabled === 'on' || enabled === 'true' || enabled === '1' || enabled === 'yes');
}
return true;
return false;
},
/**

View File

@ -230,7 +230,7 @@ const setupLogrotation = () => {
* @returns {Promise}
*/
const setupSslPassthrough = () => {
return internalNginx.configure(passthroughHostModel, 'ssl_passthrough_host', {}).then(() => internalNginx.reload());
return internalNginx.configure(passthroughHostModel, 'ssl_passthrough_host', {});
};
module.exports = function () {

View File

@ -85,7 +85,7 @@ http {
stream {
# Files generated by NPM
include /data/nginx/ssl_passthrough_host/hosts.conf;
include /data/nginx/ssl_passthrough_host/hosts[.]conf;
include /data/nginx/stream/*.conf;
# Custom

View File

@ -172,3 +172,28 @@ value by specifying it as a Docker environment variable. The default if not spec
X_FRAME_OPTIONS: "sameorigin"
...
```
## SSL Passthrough
SSL Passthrough will allow you to proxy a server without [SSL termination](https://en.wikipedia.org/wiki/TLS_termination_proxy). This means the SSL encryption of the server will be passed right through the proxy, retaining the original certificate.
Because of the SSL encryption the proxy does not know anything about the traffic and it just relies on an SSL feature called [Server Name Indication](https://en.wikipedia.org/wiki/Server_Name_Indication) to know where to send this network packet. This also means if the client does not provide this additional information, accessing the site through the proxy won't be possible. But most modern browsers include this information a HTTPS requests.
Due to nginx constraints using SSL Passthrough comes with **a performance penalty for other hosts**, since all hosts (including normal proxy hosts) now have to pass through this additional step and basically being proxied twice. If you want to retain the upstream SSL certificate but do not need your service to be available on port 443, it is recommended to use a stream host instead.
To enable SSL Passthrough on your npm instance you need to do two things: add the environment variable `ENABLE_SSL_PASSTHROUGH` with the value `"true"`, and expose port 444 instead of 443 to the outside as port 443.
```yml
version: '3'
services:
app:
...
ports:
- '80:80'
- '81:81'
- '443:444' # Expose internal port 444 instead of 443 as SSL port
environment:
...
ENABLE_SSL_PASSTHROUGH: "true" # Enable SSL Passthrough
...
```

View File

@ -253,7 +253,7 @@ module.exports = {
*
* @param model
*/
showNginxSslPassthroughConfirm: function (model) {
showNginxSslPassthroughDeleteConfirm: function (model) {
if (Cache.User.isAdmin() || Cache.User.canManage('ssl_passthrough_hosts')) {
require(['./main', './nginx/ssl-passthrough/delete'], function (App, View) {
App.UI.showModalDialog(new View({model: model}));

View File

@ -8,7 +8,7 @@
<div class="row">
<div class="col-sm-12 col-md-12">
<div class="form-group">
<label class="form-label"><%- i18n('all-hosts', 'domain-names') %> <span class="form-required">*</span></label>
<label class="form-label"><%- i18n('all-hosts', 'domain-name') %> <span class="form-required">*</span></label>
<input type="text" name="domain_name" class="form-control" id="input-domain" placeholder="example.com" value="<%- domain_name %>" required>
</div>
</div>

View File

@ -1,6 +1,6 @@
<thead>
<th width="30">&nbsp;</th>
<th><%- i18n('ssl-passthrough-hosts', 'domain-name') %></th>
<th><%- i18n('all-hosts', 'domain-name') %></th>
<th><%- i18n('str', 'destination') %></th>
<th><%- i18n('str', 'status') %></th>
<% if (canManage) { %>

View File

@ -1,17 +1,17 @@
<div class="card">
<div class="card-status bg-blue"></div>
<div class="card-status bg-dark"></div>
<div class="card-header">
<h3 class="card-title"><%- i18n('ssl-passthrough-hosts', 'title') %></h3>
<div class="card-options">
<a href="#" class="btn btn-outline-secondary btn-sm ml-2 help"><i class="fe fe-help-circle"></i></a>
<% if (showAddButton) { %>
<a href="#" class="btn btn-outline-blue btn-sm ml-2 add-item"><%- i18n('ssl-passthrough-hosts', 'add') %></a>
<a href="#" class="btn btn-outline-dark btn-sm ml-2 add-item"><%- i18n('ssl-passthrough-hosts', 'add') %></a>
<% } %>
</div>
</div>
<div class="card-body no-padding min-100">
<div id="ssl-passthrough-disabled-info">
Disabled
<div id="ssl-passthrough-disabled-info" class="alert alert-danger rounded-0 mb-0">
<%= i18n('ssl-passthrough-hosts', 'is-disabled-warning', {url: 'https://nginxproxymanager.com/advanced-config/#ssl-passthrough'}) %>
</div>
<div class="dimmer active">
<div class="loader"></div>

View File

@ -43,7 +43,6 @@ module.exports = Mn.View.extend({
view.ui.disabled_info.hide();
App.Api.Nginx.SslPassthroughHosts.getFeatureEnabled().then((response) => {
console.debug(response)
if (response.ssl_passthrough_enabled === false) {
view.ui.disabled_info.show();
} else {
@ -65,7 +64,7 @@ module.exports = Mn.View.extend({
title: App.i18n('ssl-passthrough-hosts', 'empty'),
subtitle: App.i18n('all-hosts', 'empty-subtitle', {manage: manage}),
link: manage ? App.i18n('ssl-passthrough-hosts', 'add') : null,
btn_color: 'blue',
btn_color: 'dark',
permission: 'ssl-passthrough-hosts',
action: function () {
App.Controller.showNginxSslPassthroughForm();

View File

@ -121,11 +121,11 @@
"empty": "There are no SSL Passthrough Hosts",
"add": "Add SSL Passthrough Hosts",
"form-title": "{id, select, undefined{New} other{Edit}} SSL Passthrough Host",
"domain-name": "Domain Name",
"forwarding-host": "Forward Host",
"forwarding-port": "Forward Port",
"delete": "Delete SSL Passthrough Host",
"delete-confirm": "Are you sure you want to delete this SSL Passthrough Host?",
"is-disabled-warning": "SSL Passthrough Hosts are not enabled in the environment. Please see <a href=\"{url}\" target=\"_blank\">the docs</a> for more information.",
"help-title": "What is an SSL Passthrough Host?",
"help-content": "An SSL Passthrough Host will allow you to proxy a server without SSL termination. This means the SSL encryption of the server will be passed right through the proxy, retaining the upstream certificate.\n Because of the SSL encryption the proxy does not know anything about the traffic, and it just relies on an SSL feature called Server Name Indication to know where to send this packet. This also means if the client does not provide this additional information, accessing the site through the proxy won't be possible. But most modern browsers include this information in HTTP requests.\n\nDue to nginx constraints using SSL Passthrough comes with a performance penalty for other hosts, since all hosts (including normal proxy hosts) now have to pass through this additional step and basically being proxied twice. If you want to retain the upstream SSL certificate but do not need your service to be available on port 443, it is recommended to use a stream host instead."
},

View File

@ -12,6 +12,15 @@ a:hover {
color: darken($primary-color, 10%);
}
.alert-danger a {
color: #6b1110;
text-decoration: underline;
}
a:hover {
color: darken(#6b1110, 10%);
}
.dropdown-header {
padding-left: 1rem;
}