mirror of
https://github.com/xiaoxinpro/nginx-proxy-manager-zh.git
synced 2025-01-22 12:58:13 -05:00
Fixes #68 - HSTS is now part of the UI
This commit is contained in:
parent
4d754275ab
commit
2a3d792591
@ -7,6 +7,3 @@ ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA
|
||||
ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AE
|
||||
S128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
|
||||
ssl_prefer_server_ciphers on;
|
||||
|
||||
# HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
|
||||
add_header Strict-Transport-Security max-age=15768000;
|
||||
|
@ -47,6 +47,7 @@ const internalDeadHost = {
|
||||
.then(() => {
|
||||
// At this point the domains should have been checked
|
||||
data.owner_user_id = access.token.getUserId(1);
|
||||
data = internalHost.cleanSslHstsData(data);
|
||||
|
||||
return deadHostModel
|
||||
.query()
|
||||
@ -89,11 +90,11 @@ const internalDeadHost = {
|
||||
|
||||
// Add to audit log
|
||||
return internalAuditLog.add(access, {
|
||||
action: 'created',
|
||||
object_type: 'dead-host',
|
||||
object_id: row.id,
|
||||
meta: data
|
||||
})
|
||||
action: 'created',
|
||||
object_type: 'dead-host',
|
||||
object_id: row.id,
|
||||
meta: data
|
||||
})
|
||||
.then(() => {
|
||||
return row;
|
||||
});
|
||||
@ -144,9 +145,9 @@ const internalDeadHost = {
|
||||
|
||||
if (create_certificate) {
|
||||
return internalCertificate.createQuickCertificate(access, {
|
||||
domain_names: data.domain_names || row.domain_names,
|
||||
meta: _.assign({}, row.meta, data.meta)
|
||||
})
|
||||
domain_names: data.domain_names || row.domain_names,
|
||||
meta: _.assign({}, row.meta, data.meta)
|
||||
})
|
||||
.then(cert => {
|
||||
// update host with cert id
|
||||
data.certificate_id = cert.id;
|
||||
@ -162,7 +163,9 @@ const internalDeadHost = {
|
||||
// Add domain_names to the data in case it isn't there, so that the audit log renders correctly. The order is important here.
|
||||
data = _.assign({}, {
|
||||
domain_names: row.domain_names
|
||||
},data);
|
||||
}, data);
|
||||
|
||||
data = internalHost.cleanSslHstsData(data, row);
|
||||
|
||||
return deadHostModel
|
||||
.query()
|
||||
@ -171,11 +174,11 @@ const internalDeadHost = {
|
||||
.then(saved_row => {
|
||||
// Add to audit log
|
||||
return internalAuditLog.add(access, {
|
||||
action: 'updated',
|
||||
object_type: 'dead-host',
|
||||
object_id: row.id,
|
||||
meta: data
|
||||
})
|
||||
action: 'updated',
|
||||
object_type: 'dead-host',
|
||||
object_id: row.id,
|
||||
meta: data
|
||||
})
|
||||
.then(() => {
|
||||
return _.omit(saved_row, omissions());
|
||||
});
|
||||
@ -183,15 +186,15 @@ const internalDeadHost = {
|
||||
})
|
||||
.then(() => {
|
||||
return internalDeadHost.get(access, {
|
||||
id: data.id,
|
||||
expand: ['owner', 'certificate']
|
||||
})
|
||||
id: data.id,
|
||||
expand: ['owner', 'certificate']
|
||||
})
|
||||
.then(row => {
|
||||
// Configure nginx
|
||||
return internalNginx.configure(deadHostModel, 'dead_host', row)
|
||||
.then(new_meta => {
|
||||
row.meta = new_meta;
|
||||
row = internalHost.cleanRowCertificateMeta(row);
|
||||
row = internalHost.cleanRowCertificateMeta(row);
|
||||
return _.omit(row, omissions());
|
||||
});
|
||||
});
|
||||
|
@ -1,11 +1,40 @@
|
||||
'use strict';
|
||||
|
||||
const _ = require('lodash');
|
||||
const proxyHostModel = require('../models/proxy_host');
|
||||
const redirectionHostModel = require('../models/redirection_host');
|
||||
const deadHostModel = require('../models/dead_host');
|
||||
|
||||
const internalHost = {
|
||||
|
||||
/**
|
||||
* Makes sure that the ssl_* and hsts_* fields play nicely together.
|
||||
* ie: if there is no cert, then force_ssl is off.
|
||||
* if force_ssl is off, then hsts_enabled is definitely off.
|
||||
*
|
||||
* @param {object} data
|
||||
* @param {object} [existing_data]
|
||||
* @returns {object}
|
||||
*/
|
||||
cleanSslHstsData: function (data, existing_data) {
|
||||
existing_data = existing_data === undefined ? {} : existing_data;
|
||||
|
||||
let combined_data = _.assign({}, existing_data, data);
|
||||
|
||||
if (!combined_data.certificate_id) {
|
||||
combined_data.ssl_forced = false;
|
||||
combined_data.http2_support = false;
|
||||
}
|
||||
|
||||
if (!combined_data.ssl_forced) {
|
||||
combined_data.hsts_enabled = false;
|
||||
}
|
||||
|
||||
if (!combined_data.hsts_enabled) {
|
||||
combined_data.hsts_subdomains = false;
|
||||
}
|
||||
|
||||
return combined_data;
|
||||
},
|
||||
|
||||
/**
|
||||
* used by the getAll functions of hosts, this removes the certificate meta if present
|
||||
*
|
||||
|
@ -1,5 +1,3 @@
|
||||
'use strict';
|
||||
|
||||
const _ = require('lodash');
|
||||
const error = require('../lib/error');
|
||||
const proxyHostModel = require('../models/proxy_host');
|
||||
@ -47,6 +45,7 @@ const internalProxyHost = {
|
||||
.then(() => {
|
||||
// At this point the domains should have been checked
|
||||
data.owner_user_id = access.token.getUserId(1);
|
||||
data = internalHost.cleanSslHstsData(data);
|
||||
|
||||
return proxyHostModel
|
||||
.query()
|
||||
@ -90,11 +89,11 @@ const internalProxyHost = {
|
||||
|
||||
// Add to audit log
|
||||
return internalAuditLog.add(access, {
|
||||
action: 'created',
|
||||
object_type: 'proxy-host',
|
||||
object_id: row.id,
|
||||
meta: data
|
||||
})
|
||||
action: 'created',
|
||||
object_type: 'proxy-host',
|
||||
object_id: row.id,
|
||||
meta: data
|
||||
})
|
||||
.then(() => {
|
||||
return row;
|
||||
});
|
||||
@ -109,7 +108,7 @@ const internalProxyHost = {
|
||||
*/
|
||||
update: (access, data) => {
|
||||
let create_certificate = data.certificate_id === 'new';
|
||||
|
||||
console.log('PH UPDATE:', data);
|
||||
if (create_certificate) {
|
||||
delete data.certificate_id;
|
||||
}
|
||||
@ -145,9 +144,9 @@ const internalProxyHost = {
|
||||
|
||||
if (create_certificate) {
|
||||
return internalCertificate.createQuickCertificate(access, {
|
||||
domain_names: data.domain_names || row.domain_names,
|
||||
meta: _.assign({}, row.meta, data.meta)
|
||||
})
|
||||
domain_names: data.domain_names || row.domain_names,
|
||||
meta: _.assign({}, row.meta, data.meta)
|
||||
})
|
||||
.then(cert => {
|
||||
// update host with cert id
|
||||
data.certificate_id = cert.id;
|
||||
@ -165,6 +164,8 @@ const internalProxyHost = {
|
||||
domain_names: row.domain_names
|
||||
}, data);
|
||||
|
||||
data = internalHost.cleanSslHstsData(data, row);
|
||||
|
||||
return proxyHostModel
|
||||
.query()
|
||||
.where({id: data.id})
|
||||
@ -172,11 +173,11 @@ const internalProxyHost = {
|
||||
.then(saved_row => {
|
||||
// Add to audit log
|
||||
return internalAuditLog.add(access, {
|
||||
action: 'updated',
|
||||
object_type: 'proxy-host',
|
||||
object_id: row.id,
|
||||
meta: data
|
||||
})
|
||||
action: 'updated',
|
||||
object_type: 'proxy-host',
|
||||
object_id: row.id,
|
||||
meta: data
|
||||
})
|
||||
.then(() => {
|
||||
return _.omit(saved_row, omissions());
|
||||
});
|
||||
@ -184,9 +185,9 @@ const internalProxyHost = {
|
||||
})
|
||||
.then(() => {
|
||||
return internalProxyHost.get(access, {
|
||||
id: data.id,
|
||||
expand: ['owner', 'certificate', 'access_list']
|
||||
})
|
||||
id: data.id,
|
||||
expand: ['owner', 'certificate', 'access_list']
|
||||
})
|
||||
.then(row => {
|
||||
// Configure nginx
|
||||
return internalNginx.configure(proxyHostModel, 'proxy_host', row)
|
||||
|
@ -47,6 +47,7 @@ const internalRedirectionHost = {
|
||||
.then(() => {
|
||||
// At this point the domains should have been checked
|
||||
data.owner_user_id = access.token.getUserId(1);
|
||||
data = internalHost.cleanSslHstsData(data);
|
||||
|
||||
return redirectionHostModel
|
||||
.query()
|
||||
@ -89,11 +90,11 @@ const internalRedirectionHost = {
|
||||
|
||||
// Add to audit log
|
||||
return internalAuditLog.add(access, {
|
||||
action: 'created',
|
||||
object_type: 'redirection-host',
|
||||
object_id: row.id,
|
||||
meta: data
|
||||
})
|
||||
action: 'created',
|
||||
object_type: 'redirection-host',
|
||||
object_id: row.id,
|
||||
meta: data
|
||||
})
|
||||
.then(() => {
|
||||
return row;
|
||||
});
|
||||
@ -144,9 +145,9 @@ const internalRedirectionHost = {
|
||||
|
||||
if (create_certificate) {
|
||||
return internalCertificate.createQuickCertificate(access, {
|
||||
domain_names: data.domain_names || row.domain_names,
|
||||
meta: _.assign({}, row.meta, data.meta)
|
||||
})
|
||||
domain_names: data.domain_names || row.domain_names,
|
||||
meta: _.assign({}, row.meta, data.meta)
|
||||
})
|
||||
.then(cert => {
|
||||
// update host with cert id
|
||||
data.certificate_id = cert.id;
|
||||
@ -162,7 +163,9 @@ const internalRedirectionHost = {
|
||||
// Add domain_names to the data in case it isn't there, so that the audit log renders correctly. The order is important here.
|
||||
data = _.assign({}, {
|
||||
domain_names: row.domain_names
|
||||
},data);
|
||||
}, data);
|
||||
|
||||
data = internalHost.cleanSslHstsData(data, row);
|
||||
|
||||
return redirectionHostModel
|
||||
.query()
|
||||
@ -171,11 +174,11 @@ const internalRedirectionHost = {
|
||||
.then(saved_row => {
|
||||
// Add to audit log
|
||||
return internalAuditLog.add(access, {
|
||||
action: 'updated',
|
||||
object_type: 'redirection-host',
|
||||
object_id: row.id,
|
||||
meta: data
|
||||
})
|
||||
action: 'updated',
|
||||
object_type: 'redirection-host',
|
||||
object_id: row.id,
|
||||
meta: data
|
||||
})
|
||||
.then(() => {
|
||||
return _.omit(saved_row, omissions());
|
||||
});
|
||||
@ -183,15 +186,15 @@ const internalRedirectionHost = {
|
||||
})
|
||||
.then(() => {
|
||||
return internalRedirectionHost.get(access, {
|
||||
id: data.id,
|
||||
expand: ['owner', 'certificate']
|
||||
})
|
||||
id: data.id,
|
||||
expand: ['owner', 'certificate']
|
||||
})
|
||||
.then(row => {
|
||||
// Configure nginx
|
||||
return internalNginx.configure(redirectionHostModel, 'redirection_host', row)
|
||||
.then(new_meta => {
|
||||
row.meta = new_meta;
|
||||
row = internalHost.cleanRowCertificateMeta(row);
|
||||
row = internalHost.cleanRowCertificateMeta(row);
|
||||
return _.omit(row, omissions());
|
||||
});
|
||||
});
|
||||
|
53
src/backend/migrations/20190218060101_hsts.js
Normal file
53
src/backend/migrations/20190218060101_hsts.js
Normal file
@ -0,0 +1,53 @@
|
||||
'use strict';
|
||||
|
||||
const migrate_name = 'hsts';
|
||||
const logger = require('../logger').migrate;
|
||||
|
||||
/**
|
||||
* Migrate
|
||||
*
|
||||
* @see http://knexjs.org/#Schema
|
||||
*
|
||||
* @param {Object} knex
|
||||
* @param {Promise} Promise
|
||||
* @returns {Promise}
|
||||
*/
|
||||
exports.up = function (knex/*, Promise*/) {
|
||||
logger.info('[' + migrate_name + '] Migrating Up...');
|
||||
|
||||
return knex.schema.table('proxy_host', function (proxy_host) {
|
||||
proxy_host.integer('hsts_enabled').notNull().unsigned().defaultTo(0);
|
||||
proxy_host.integer('hsts_subdomains').notNull().unsigned().defaultTo(0);
|
||||
})
|
||||
.then(() => {
|
||||
logger.info('[' + migrate_name + '] proxy_host Table altered');
|
||||
|
||||
return knex.schema.table('redirection_host', function (redirection_host) {
|
||||
redirection_host.integer('hsts_enabled').notNull().unsigned().defaultTo(0);
|
||||
redirection_host.integer('hsts_subdomains').notNull().unsigned().defaultTo(0);
|
||||
});
|
||||
})
|
||||
.then(() => {
|
||||
logger.info('[' + migrate_name + '] redirection_host Table altered');
|
||||
|
||||
return knex.schema.table('dead_host', function (dead_host) {
|
||||
dead_host.integer('hsts_enabled').notNull().unsigned().defaultTo(0);
|
||||
dead_host.integer('hsts_subdomains').notNull().unsigned().defaultTo(0);
|
||||
});
|
||||
})
|
||||
.then(() => {
|
||||
logger.info('[' + migrate_name + '] dead_host Table altered');
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Undo Migrate
|
||||
*
|
||||
* @param {Object} knex
|
||||
* @param {Promise} Promise
|
||||
* @returns {Promise}
|
||||
*/
|
||||
exports.down = function (knex, Promise) {
|
||||
logger.warn('[' + migrate_name + '] You can\'t migrate down this one.');
|
||||
return Promise.resolve(true);
|
||||
};
|
@ -187,6 +187,16 @@
|
||||
"example": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"hsts_enabled": {
|
||||
"description": "Is HSTS Enabled",
|
||||
"example": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"hsts_subdomains": {
|
||||
"description": "Is HSTS applicable to all subdomains",
|
||||
"example": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"ssl_provider": {
|
||||
"type": "string",
|
||||
"pattern": "^(letsencrypt|other)$"
|
||||
|
@ -24,6 +24,12 @@
|
||||
"ssl_forced": {
|
||||
"$ref": "../definitions.json#/definitions/ssl_forced"
|
||||
},
|
||||
"hsts_enabled": {
|
||||
"$ref": "../definitions.json#/definitions/hsts_enabled"
|
||||
},
|
||||
"hsts_subdomains": {
|
||||
"$ref": "../definitions.json#/definitions/hsts_subdomains"
|
||||
},
|
||||
"http2_support": {
|
||||
"$ref": "../definitions.json#/definitions/http2_support"
|
||||
},
|
||||
@ -56,6 +62,12 @@
|
||||
"ssl_forced": {
|
||||
"$ref": "#/definitions/ssl_forced"
|
||||
},
|
||||
"hsts_enabled": {
|
||||
"$ref": "#/definitions/hsts_enabled"
|
||||
},
|
||||
"hsts_subdomains": {
|
||||
"$ref": "#/definitions/hsts_subdomains"
|
||||
},
|
||||
"http2_support": {
|
||||
"$ref": "#/definitions/http2_support"
|
||||
},
|
||||
@ -113,6 +125,12 @@
|
||||
"ssl_forced": {
|
||||
"$ref": "#/definitions/ssl_forced"
|
||||
},
|
||||
"hsts_enabled": {
|
||||
"$ref": "#/definitions/hsts_enabled"
|
||||
},
|
||||
"hsts_subdomains": {
|
||||
"$ref": "#/definitions/hsts_enabled"
|
||||
},
|
||||
"http2_support": {
|
||||
"$ref": "#/definitions/http2_support"
|
||||
},
|
||||
@ -153,6 +171,12 @@
|
||||
"ssl_forced": {
|
||||
"$ref": "#/definitions/ssl_forced"
|
||||
},
|
||||
"hsts_enabled": {
|
||||
"$ref": "#/definitions/hsts_enabled"
|
||||
},
|
||||
"hsts_subdomains": {
|
||||
"$ref": "#/definitions/hsts_enabled"
|
||||
},
|
||||
"http2_support": {
|
||||
"$ref": "#/definitions/http2_support"
|
||||
},
|
||||
|
@ -38,6 +38,12 @@
|
||||
"ssl_forced": {
|
||||
"$ref": "../definitions.json#/definitions/ssl_forced"
|
||||
},
|
||||
"hsts_enabled": {
|
||||
"$ref": "../definitions.json#/definitions/hsts_enabled"
|
||||
},
|
||||
"hsts_subdomains": {
|
||||
"$ref": "../definitions.json#/definitions/hsts_subdomains"
|
||||
},
|
||||
"http2_support": {
|
||||
"$ref": "../definitions.json#/definitions/http2_support"
|
||||
},
|
||||
@ -93,6 +99,12 @@
|
||||
"ssl_forced": {
|
||||
"$ref": "#/definitions/ssl_forced"
|
||||
},
|
||||
"hsts_enabled": {
|
||||
"$ref": "#/definitions/hsts_enabled"
|
||||
},
|
||||
"hsts_subdomains": {
|
||||
"$ref": "#/definitions/hsts_subdomains"
|
||||
},
|
||||
"http2_support": {
|
||||
"$ref": "#/definitions/http2_support"
|
||||
},
|
||||
@ -174,6 +186,12 @@
|
||||
"ssl_forced": {
|
||||
"$ref": "#/definitions/ssl_forced"
|
||||
},
|
||||
"hsts_enabled": {
|
||||
"$ref": "#/definitions/hsts_enabled"
|
||||
},
|
||||
"hsts_subdomains": {
|
||||
"$ref": "#/definitions/hsts_enabled"
|
||||
},
|
||||
"http2_support": {
|
||||
"$ref": "#/definitions/http2_support"
|
||||
},
|
||||
@ -238,6 +256,12 @@
|
||||
"ssl_forced": {
|
||||
"$ref": "#/definitions/ssl_forced"
|
||||
},
|
||||
"hsts_enabled": {
|
||||
"$ref": "#/definitions/hsts_enabled"
|
||||
},
|
||||
"hsts_subdomains": {
|
||||
"$ref": "#/definitions/hsts_enabled"
|
||||
},
|
||||
"http2_support": {
|
||||
"$ref": "#/definitions/http2_support"
|
||||
},
|
||||
|
@ -32,6 +32,12 @@
|
||||
"ssl_forced": {
|
||||
"$ref": "../definitions.json#/definitions/ssl_forced"
|
||||
},
|
||||
"hsts_enabled": {
|
||||
"$ref": "../definitions.json#/definitions/hsts_enabled"
|
||||
},
|
||||
"hsts_subdomains": {
|
||||
"$ref": "../definitions.json#/definitions/hsts_subdomains"
|
||||
},
|
||||
"http2_support": {
|
||||
"$ref": "../definitions.json#/definitions/http2_support"
|
||||
},
|
||||
@ -73,6 +79,12 @@
|
||||
"ssl_forced": {
|
||||
"$ref": "#/definitions/ssl_forced"
|
||||
},
|
||||
"hsts_enabled": {
|
||||
"$ref": "#/definitions/hsts_enabled"
|
||||
},
|
||||
"hsts_subdomains": {
|
||||
"$ref": "#/definitions/hsts_subdomains"
|
||||
},
|
||||
"http2_support": {
|
||||
"$ref": "#/definitions/http2_support"
|
||||
},
|
||||
@ -140,6 +152,12 @@
|
||||
"ssl_forced": {
|
||||
"$ref": "#/definitions/ssl_forced"
|
||||
},
|
||||
"hsts_enabled": {
|
||||
"$ref": "#/definitions/hsts_enabled"
|
||||
},
|
||||
"hsts_subdomains": {
|
||||
"$ref": "#/definitions/hsts_enabled"
|
||||
},
|
||||
"http2_support": {
|
||||
"$ref": "#/definitions/http2_support"
|
||||
},
|
||||
@ -189,6 +207,12 @@
|
||||
"ssl_forced": {
|
||||
"$ref": "#/definitions/ssl_forced"
|
||||
},
|
||||
"hsts_enabled": {
|
||||
"$ref": "#/definitions/hsts_enabled"
|
||||
},
|
||||
"hsts_subdomains": {
|
||||
"$ref": "#/definitions/hsts_enabled"
|
||||
},
|
||||
"http2_support": {
|
||||
"$ref": "#/definitions/http2_support"
|
||||
},
|
||||
|
8
src/backend/templates/_hsts.conf
Normal file
8
src/backend/templates/_hsts.conf
Normal file
@ -0,0 +1,8 @@
|
||||
{% if certificate and certificate_id > 0 -%}
|
||||
{% if ssl_forced == 1 or ssl_forced == true %}
|
||||
{% if hsts_enabled == 1 or hsts_enabled == true %}
|
||||
# HSTS (ngx_http_headers_module is required) (31536000 seconds = 1 year)
|
||||
add_header Strict-Transport-Security "max-age=31536000;{% if hsts_subdomains == 1 or hsts_subdomains == true -%} includeSubDomains;{% endif %} preload" always;
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
@ -4,11 +4,16 @@
|
||||
server {
|
||||
{% include "_listen.conf" %}
|
||||
{% include "_certificates.conf" %}
|
||||
{% include "_hsts.conf" %}
|
||||
|
||||
access_log /data/logs/dead_host-{{ id }}.log standard;
|
||||
|
||||
{{ advanced_config }}
|
||||
|
||||
return 404;
|
||||
location / {
|
||||
{% include "_forced_ssl.conf" %}
|
||||
{% include "_hsts.conf" %}
|
||||
return 404;
|
||||
}
|
||||
}
|
||||
{% endif %}
|
||||
|
@ -10,6 +10,7 @@ server {
|
||||
{% include "_certificates.conf" %}
|
||||
{% include "_assets.conf" %}
|
||||
{% include "_exploits.conf" %}
|
||||
{% include "_hsts.conf" %}
|
||||
|
||||
access_log /data/logs/proxy_host-{{ id }}.log proxy;
|
||||
|
||||
@ -23,6 +24,7 @@ server {
|
||||
{%- endif %}
|
||||
|
||||
{% include "_forced_ssl.conf" %}
|
||||
{% include "_hsts.conf" %}
|
||||
|
||||
{% if allow_websocket_upgrade == 1 or allow_websocket_upgrade == true %}
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
|
@ -6,15 +6,15 @@ server {
|
||||
{% include "_certificates.conf" %}
|
||||
{% include "_assets.conf" %}
|
||||
{% include "_exploits.conf" %}
|
||||
{% include "_hsts.conf" %}
|
||||
|
||||
access_log /data/logs/redirection_host-{{ id }}.log standard;
|
||||
|
||||
{{ advanced_config }}
|
||||
|
||||
# TODO: Preserve Path Option
|
||||
|
||||
location / {
|
||||
{% include "_forced_ssl.conf" %}
|
||||
{% include "_hsts.conf" %}
|
||||
|
||||
{% if preserve_path == 1 or preserve_path == true %}
|
||||
return 301 $scheme://{{ forward_domain_name }}$request_uri;
|
||||
|
@ -54,6 +54,24 @@
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 col-md-6">
|
||||
<div class="form-group">
|
||||
<label class="custom-switch">
|
||||
<input type="checkbox" class="custom-switch-input" name="hsts_enabled" value="1"<%- hsts_enabled ? ' checked' : '' %><%- certificate_id && ssl_forced ? '' : ' disabled' %>>
|
||||
<span class="custom-switch-indicator"></span>
|
||||
<span class="custom-switch-description"><%- i18n('all-hosts', 'hsts-enabled') %> <a href="https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security" target="_blank"><i class="fe fe-help-circle"></i></a></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 col-md-6">
|
||||
<div class="form-group">
|
||||
<label class="custom-switch">
|
||||
<input type="checkbox" class="custom-switch-input" name="hsts_subdomains" value="1"<%- hsts_subdomains ? ' checked' : '' %><%- certificate_id && ssl_forced && hsts_enabled ? '' : ' disabled' %>>
|
||||
<span class="custom-switch-indicator"></span>
|
||||
<span class="custom-switch-description"><%- i18n('all-hosts', 'hsts-subdomains') %></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Lets encrypt -->
|
||||
<div class="col-sm-12 col-md-12 letsencrypt">
|
||||
|
@ -22,6 +22,8 @@ module.exports = Mn.View.extend({
|
||||
save: 'button.save',
|
||||
certificate_select: 'select[name="certificate_id"]',
|
||||
ssl_forced: 'input[name="ssl_forced"]',
|
||||
hsts_enabled: 'input[name="hsts_enabled"]',
|
||||
hsts_subdomains: 'input[name="hsts_subdomains"]',
|
||||
http2_support: 'input[name="http2_support"]',
|
||||
letsencrypt: '.letsencrypt'
|
||||
},
|
||||
@ -36,11 +38,44 @@ module.exports = Mn.View.extend({
|
||||
}
|
||||
|
||||
let enabled = id === 'new' || parseInt(id, 10) > 0;
|
||||
this.ui.ssl_forced.add(this.ui.http2_support)
|
||||
|
||||
let inputs = this.ui.ssl_forced.add(this.ui.http2_support);
|
||||
inputs
|
||||
.prop('disabled', !enabled)
|
||||
.parents('.form-group')
|
||||
.css('opacity', enabled ? 1 : 0.5);
|
||||
this.ui.http2_support.prop('disabled', !enabled);
|
||||
|
||||
if (!enabled) {
|
||||
inputs.prop('checked', false);
|
||||
}
|
||||
|
||||
inputs.trigger('change');
|
||||
},
|
||||
|
||||
'change @ui.ssl_forced': function () {
|
||||
let checked = this.ui.ssl_forced.prop('checked');
|
||||
this.ui.hsts_enabled
|
||||
.prop('disabled', !checked)
|
||||
.parents('.form-group')
|
||||
.css('opacity', checked ? 1 : 0.5);
|
||||
|
||||
if (!checked) {
|
||||
this.ui.hsts_enabled.prop('checked', false);
|
||||
}
|
||||
|
||||
this.ui.hsts_enabled.trigger('change');
|
||||
},
|
||||
|
||||
'change @ui.hsts_enabled': function () {
|
||||
let checked = this.ui.hsts_enabled.prop('checked');
|
||||
this.ui.hsts_subdomains
|
||||
.prop('disabled', !checked)
|
||||
.parents('.form-group')
|
||||
.css('opacity', checked ? 1 : 0.5);
|
||||
|
||||
if (!checked) {
|
||||
this.ui.hsts_subdomains.prop('checked', false);
|
||||
}
|
||||
},
|
||||
|
||||
'click @ui.save': function (e) {
|
||||
@ -55,13 +90,10 @@ module.exports = Mn.View.extend({
|
||||
let data = this.ui.form.serializeJSON();
|
||||
|
||||
// Manipulate
|
||||
if (typeof data.ssl_forced !== 'undefined' && data.ssl_forced === '1') {
|
||||
data.ssl_forced = true;
|
||||
}
|
||||
|
||||
if (typeof data.http2_support !== 'undefined') {
|
||||
data.http2_support = !!data.http2_support;
|
||||
}
|
||||
data.hsts_enabled = !!data.hsts_enabled;
|
||||
data.hsts_subdomains = !!data.hsts_subdomains;
|
||||
data.http2_support = !!data.http2_support;
|
||||
data.ssl_forced = !!data.ssl_forced;
|
||||
|
||||
if (typeof data.domain_names === 'string' && data.domain_names) {
|
||||
data.domain_names = data.domain_names.split(',');
|
||||
|
@ -110,6 +110,24 @@
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 col-md-6">
|
||||
<div class="form-group">
|
||||
<label class="custom-switch">
|
||||
<input type="checkbox" class="custom-switch-input" name="hsts_enabled" value="1"<%- hsts_enabled ? ' checked' : '' %><%- certificate_id && ssl_forced ? '' : ' disabled' %>>
|
||||
<span class="custom-switch-indicator"></span>
|
||||
<span class="custom-switch-description"><%- i18n('all-hosts', 'hsts-enabled') %> <a href="https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security" target="_blank"><i class="fe fe-help-circle"></i></a></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 col-md-6">
|
||||
<div class="form-group">
|
||||
<label class="custom-switch">
|
||||
<input type="checkbox" class="custom-switch-input" name="hsts_subdomains" value="1"<%- hsts_subdomains ? ' checked' : '' %><%- certificate_id && ssl_forced && hsts_enabled ? '' : ' disabled' %>>
|
||||
<span class="custom-switch-indicator"></span>
|
||||
<span class="custom-switch-description"><%- i18n('all-hosts', 'hsts-subdomains') %></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Lets encrypt -->
|
||||
<div class="col-sm-12 col-md-12 letsencrypt">
|
||||
|
@ -25,6 +25,8 @@ module.exports = Mn.View.extend({
|
||||
certificate_select: 'select[name="certificate_id"]',
|
||||
access_list_select: 'select[name="access_list_id"]',
|
||||
ssl_forced: 'input[name="ssl_forced"]',
|
||||
hsts_enabled: 'input[name="hsts_enabled"]',
|
||||
hsts_subdomains: 'input[name="hsts_subdomains"]',
|
||||
http2_support: 'input[name="http2_support"]',
|
||||
forward_scheme: 'select[name="forward_scheme"]',
|
||||
letsencrypt: '.letsencrypt'
|
||||
@ -40,10 +42,44 @@ module.exports = Mn.View.extend({
|
||||
}
|
||||
|
||||
let enabled = id === 'new' || parseInt(id, 10) > 0;
|
||||
this.ui.ssl_forced.add(this.ui.http2_support)
|
||||
|
||||
let inputs = this.ui.ssl_forced.add(this.ui.http2_support);
|
||||
inputs
|
||||
.prop('disabled', !enabled)
|
||||
.parents('.form-group')
|
||||
.css('opacity', enabled ? 1 : 0.5);
|
||||
|
||||
if (!enabled) {
|
||||
inputs.prop('checked', false);
|
||||
}
|
||||
|
||||
inputs.trigger('change');
|
||||
},
|
||||
|
||||
'change @ui.ssl_forced': function () {
|
||||
let checked = this.ui.ssl_forced.prop('checked');
|
||||
this.ui.hsts_enabled
|
||||
.prop('disabled', !checked)
|
||||
.parents('.form-group')
|
||||
.css('opacity', checked ? 1 : 0.5);
|
||||
|
||||
if (!checked) {
|
||||
this.ui.hsts_enabled.prop('checked', false);
|
||||
}
|
||||
|
||||
this.ui.hsts_enabled.trigger('change');
|
||||
},
|
||||
|
||||
'change @ui.hsts_enabled': function () {
|
||||
let checked = this.ui.hsts_enabled.prop('checked');
|
||||
this.ui.hsts_subdomains
|
||||
.prop('disabled', !checked)
|
||||
.parents('.form-group')
|
||||
.css('opacity', checked ? 1 : 0.5);
|
||||
|
||||
if (!checked) {
|
||||
this.ui.hsts_subdomains.prop('checked', false);
|
||||
}
|
||||
},
|
||||
|
||||
'click @ui.save': function (e) {
|
||||
@ -63,14 +99,9 @@ module.exports = Mn.View.extend({
|
||||
data.caching_enabled = !!data.caching_enabled;
|
||||
data.allow_websocket_upgrade = !!data.allow_websocket_upgrade;
|
||||
data.http2_support = !!data.http2_support;
|
||||
|
||||
if (typeof data.ssl_forced !== 'undefined' && data.ssl_forced === '1') {
|
||||
data.ssl_forced = true;
|
||||
}
|
||||
|
||||
if (typeof data.http2_support !== 'undefined') {
|
||||
data.http2_support = !!data.http2_support;
|
||||
}
|
||||
data.hsts_enabled = !!data.hsts_enabled;
|
||||
data.hsts_subdomains = !!data.hsts_subdomains;
|
||||
data.ssl_forced = !!data.ssl_forced;
|
||||
|
||||
if (typeof data.domain_names === 'string' && data.domain_names) {
|
||||
data.domain_names = data.domain_names.split(',');
|
||||
@ -132,6 +163,9 @@ module.exports = Mn.View.extend({
|
||||
onRender: function () {
|
||||
let view = this;
|
||||
|
||||
this.ui.ssl_forced.trigger('change');
|
||||
this.ui.hsts_enabled.trigger('change');
|
||||
|
||||
// Domain names
|
||||
this.ui.domain_names.selectize({
|
||||
delimiter: ',',
|
||||
|
@ -78,6 +78,24 @@
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 col-md-6">
|
||||
<div class="form-group">
|
||||
<label class="custom-switch">
|
||||
<input type="checkbox" class="custom-switch-input" name="hsts_enabled" value="1"<%- hsts_enabled ? ' checked' : '' %><%- certificate_id && ssl_forced ? '' : ' disabled' %>>
|
||||
<span class="custom-switch-indicator"></span>
|
||||
<span class="custom-switch-description"><%- i18n('all-hosts', 'hsts-enabled') %> <a href="https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security" target="_blank"><i class="fe fe-help-circle"></i></a></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 col-md-6">
|
||||
<div class="form-group">
|
||||
<label class="custom-switch">
|
||||
<input type="checkbox" class="custom-switch-input" name="hsts_subdomains" value="1"<%- hsts_subdomains ? ' checked' : '' %><%- certificate_id && ssl_forced && hsts_enabled ? '' : ' disabled' %>>
|
||||
<span class="custom-switch-indicator"></span>
|
||||
<span class="custom-switch-description"><%- i18n('all-hosts', 'hsts-subdomains') %></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Lets encrypt -->
|
||||
<div class="col-sm-12 col-md-12 letsencrypt">
|
||||
|
@ -22,6 +22,8 @@ module.exports = Mn.View.extend({
|
||||
save: 'button.save',
|
||||
certificate_select: 'select[name="certificate_id"]',
|
||||
ssl_forced: 'input[name="ssl_forced"]',
|
||||
hsts_enabled: 'input[name="hsts_enabled"]',
|
||||
hsts_subdomains: 'input[name="hsts_subdomains"]',
|
||||
http2_support: 'input[name="http2_support"]',
|
||||
letsencrypt: '.letsencrypt'
|
||||
},
|
||||
@ -36,11 +38,44 @@ module.exports = Mn.View.extend({
|
||||
}
|
||||
|
||||
let enabled = id === 'new' || parseInt(id, 10) > 0;
|
||||
this.ui.ssl_forced.add(this.ui.http2_support)
|
||||
|
||||
let inputs = this.ui.ssl_forced.add(this.ui.http2_support);
|
||||
inputs
|
||||
.prop('disabled', !enabled)
|
||||
.parents('.form-group')
|
||||
.css('opacity', enabled ? 1 : 0.5);
|
||||
this.ui.http2_support.prop('disabled', !enabled);
|
||||
|
||||
if (!enabled) {
|
||||
inputs.prop('checked', false);
|
||||
}
|
||||
|
||||
inputs.trigger('change');
|
||||
},
|
||||
|
||||
'change @ui.ssl_forced': function () {
|
||||
let checked = this.ui.ssl_forced.prop('checked');
|
||||
this.ui.hsts_enabled
|
||||
.prop('disabled', !checked)
|
||||
.parents('.form-group')
|
||||
.css('opacity', checked ? 1 : 0.5);
|
||||
|
||||
if (!checked) {
|
||||
this.ui.hsts_enabled.prop('checked', false);
|
||||
}
|
||||
|
||||
this.ui.hsts_enabled.trigger('change');
|
||||
},
|
||||
|
||||
'change @ui.hsts_enabled': function () {
|
||||
let checked = this.ui.hsts_enabled.prop('checked');
|
||||
this.ui.hsts_subdomains
|
||||
.prop('disabled', !checked)
|
||||
.parents('.form-group')
|
||||
.css('opacity', checked ? 1 : 0.5);
|
||||
|
||||
if (!checked) {
|
||||
this.ui.hsts_subdomains.prop('checked', false);
|
||||
}
|
||||
},
|
||||
|
||||
'click @ui.save': function (e) {
|
||||
@ -55,16 +90,12 @@ module.exports = Mn.View.extend({
|
||||
let data = this.ui.form.serializeJSON();
|
||||
|
||||
// Manipulate
|
||||
data.block_exploits = !!data.block_exploits;
|
||||
data.preserve_path = !!data.preserve_path;
|
||||
|
||||
if (typeof data.ssl_forced !== 'undefined' && data.ssl_forced === '1') {
|
||||
data.ssl_forced = true;
|
||||
}
|
||||
|
||||
if (typeof data.http2_support !== 'undefined') {
|
||||
data.http2_support = !!data.http2_support;
|
||||
}
|
||||
data.block_exploits = !!data.block_exploits;
|
||||
data.preserve_path = !!data.preserve_path;
|
||||
data.http2_support = !!data.http2_support;
|
||||
data.hsts_enabled = !!data.hsts_enabled;
|
||||
data.hsts_subdomains = !!data.hsts_subdomains;
|
||||
data.ssl_forced = !!data.ssl_forced;
|
||||
|
||||
if (typeof data.domain_names === 'string' && data.domain_names) {
|
||||
data.domain_names = data.domain_names.split(',');
|
||||
|
@ -79,7 +79,9 @@
|
||||
"no-ssl": "This host will not use HTTPS",
|
||||
"advanced": "Advanced",
|
||||
"advanced-warning": "Enter your custom Nginx configuration here at your own risk!",
|
||||
"advanced-config": "Custom Nginx Configuration"
|
||||
"advanced-config": "Custom Nginx Configuration",
|
||||
"hsts-enabled": "HSTS Enabled",
|
||||
"hsts-subdomains": "HSTS Subdomains"
|
||||
},
|
||||
"ssl": {
|
||||
"letsencrypt": "Let's Encrypt",
|
||||
|
@ -14,6 +14,8 @@ const model = Backbone.Model.extend({
|
||||
certificate_id: 0,
|
||||
ssl_forced: false,
|
||||
http2_support: false,
|
||||
hsts_enabled: false,
|
||||
hsts_subdomains: false,
|
||||
enabled: true,
|
||||
meta: {},
|
||||
advanced_config: '',
|
||||
|
@ -17,6 +17,8 @@ const model = Backbone.Model.extend({
|
||||
access_list_id: 0,
|
||||
certificate_id: 0,
|
||||
ssl_forced: false,
|
||||
hsts_enabled: false,
|
||||
hsts_subdomains: false,
|
||||
caching_enabled: false,
|
||||
allow_websocket_upgrade: false,
|
||||
block_exploits: false,
|
||||
|
@ -15,6 +15,8 @@ const model = Backbone.Model.extend({
|
||||
preserve_path: true,
|
||||
certificate_id: 0,
|
||||
ssl_forced: false,
|
||||
hsts_enabled: false,
|
||||
hsts_subdomains: false,
|
||||
block_exploits: false,
|
||||
http2_support: false,
|
||||
advanced_config: '',
|
||||
|
Loading…
Reference in New Issue
Block a user