Add drop_unauthorized parameter to proxy hosts

drop_unauthorized returns 444 when a client is not authorized as opposed
to 403. It can be used with Client Certificate authorization.
This commit is contained in:
Will Rouesnel
2023-05-29 14:43:11 +10:00
parent f601105776
commit 6cf91a2e70
11 changed files with 85 additions and 4 deletions

View File

@@ -82,6 +82,7 @@
"ssl_forced": 0,
"caching_enabled": 0,
"block_exploits": 0,
"drop_unauthorized": 0,
"advanced_config": "sdfsdfsdf",
"meta": {
"letsencrypt_agree": false,
@@ -124,6 +125,7 @@
"ssl_forced": 0,
"caching_enabled": 0,
"block_exploits": 0,
"drop_unauthorized": 0,
"advanced_config": "",
"meta": {
"letsencrypt_agree": false,
@@ -204,6 +206,7 @@
"ssl_forced": 0,
"caching_enabled": 0,
"block_exploits": 0,
"drop_unauthorized": 0,
"advanced_config": "",
"meta": {
"letsencrypt_agree": false,
@@ -1117,6 +1120,7 @@
"ssl_forced",
"caching_enabled",
"block_exploits",
"drop_unauthorized",
"advanced_config",
"meta",
"allow_websocket_upgrade",
@@ -1184,6 +1188,9 @@
"block_exploits": {
"type": "integer"
},
"drop_unauthorized": {
"type": "integer"
},
"advanced_config": {
"type": "string"
},

View File

@@ -153,7 +153,7 @@ const internalNginx = {
const locationRendering = async () => {
for (let i = 0; i < host.locations.length; i++) {
let locationCopy = Object.assign({}, {access_list_id: host.access_list_id}, {certificate_id: host.certificate_id},
{ssl_forced: host.ssl_forced}, {caching_enabled: host.caching_enabled}, {block_exploits: host.block_exploits},
{ssl_forced: host.ssl_forced}, {caching_enabled: host.caching_enabled}, {block_exploits: host.block_exploits}, {drop_unauthorized: host.drop_unauthorized},
{allow_websocket_upgrade: host.allow_websocket_upgrade}, {http2_support: host.http2_support},
{hsts_enabled: host.hsts_enabled}, {hsts_subdomains: host.hsts_subdomains}, {access_list: host.access_list},
{certificate: host.certificate}, host.locations[i]);
@@ -205,6 +205,12 @@ const internalNginx = {
let origLocations;
// Manipulate the data a bit before sending it to the template
if (typeof host.drop_unauthorized === 'undefined') {
// Only proxy-hosts can have drop_unauthorized, but all hosts share
// the templates.
host.drop_unauthorized = 0;
}
if (nice_host_type !== 'default') {
host.use_default_location = true;
if (typeof host.advanced_config !== 'undefined' && host.advanced_config) {

View File

@@ -0,0 +1,39 @@
const migrate_name = 'drop_unauthorized';
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('drop_unauthorized').notNull().unsigned().defaultTo(0);
}).then(() =>{
logger.info('[' + migrate_name + '] Migrating Up Complete');
});
};
/**
* Undo Migrate
*
* @param {Object} knex
* @param {Promise} Promise
* @returns {Promise}
*/
exports.down = function (knex/*, Promise*/) {
logger.info('[' + migrate_name + '] Migrating Down...');
return knex.schema.table('proxy_host', function(proxy_host) {
proxy_host.dropColumn('drop_unauthorized');
}).then(() =>{
logger.info('[' + migrate_name + '] Migrating Up Complete');
});
};

View File

@@ -231,6 +231,11 @@
"example": true,
"type": "boolean"
},
"drop_unauthorized": {
"description": "Close TCP connection with no response when authorization fails",
"example": true,
"type": "boolean"
},
"caching_enabled": {
"description": "Should we cache assets",
"example": true,

View File

@@ -50,6 +50,9 @@
"block_exploits": {
"$ref": "../definitions.json#/definitions/block_exploits"
},
"drop_unauthorized": {
"$ref": "../definitions.json#/definitions/drop_unauthorized"
},
"caching_enabled": {
"$ref": "../definitions.json#/definitions/caching_enabled"
},
@@ -149,6 +152,9 @@
"block_exploits": {
"$ref": "#/definitions/block_exploits"
},
"drop_unauthorized": {
"$ref": "#/definitions/drop_unauthorized"
},
"caching_enabled": {
"$ref": "#/definitions/caching_enabled"
},
@@ -239,6 +245,9 @@
"block_exploits": {
"$ref": "#/definitions/block_exploits"
},
"drop_unauthorized": {
"$ref": "#/definitions/drop_unauthorized"
},
"caching_enabled": {
"$ref": "#/definitions/caching_enabled"
},
@@ -312,6 +321,9 @@
"block_exploits": {
"$ref": "#/definitions/block_exploits"
},
"drop_unauthorized": {
"$ref": "#/definitions/drop_unauthorized"
},
"caching_enabled": {
"$ref": "#/definitions/caching_enabled"
},

View File

@@ -2,7 +2,7 @@
{% if access_list.clientcas.size > 0 %}
# TLS Client Certificate Authorization
if ($ssl_client_verify != "SUCCESS") {
return 403;
return {% if drop_unauthorized == 1 %}444{% else %}403{% endif %};
}
{% endif %}
{% if access_list.items.length > 0 %}

View File

@@ -72,7 +72,7 @@
</label>
</div>
</div>
<div class="col-sm-12 col-md-12">
<div class="col-sm-6 col-md-6">
<div class="form-group">
<label class="custom-switch">
<input type="checkbox" class="custom-switch-input" name="allow_websocket_upgrade" value="1"<%- allow_websocket_upgrade ? ' checked' : '' %>>
@@ -81,7 +81,15 @@
</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="drop_unauthorized" value="1"<%- drop_unauthorized ? ' checked' : '' %>>
<span class="custom-switch-indicator"></span>
<span class="custom-switch-description"><%- i18n('all-hosts', 'drop-unauthorized') %></span>
</label>
</div>
</div>
<div class="col-sm-12 col-md-12">
<div class="form-group">
<label class="form-label"><%- i18n('proxy-hosts', 'access-list') %></label>

View File

@@ -161,6 +161,7 @@ module.exports = Mn.View.extend({
// Manipulate
data.forward_port = parseInt(data.forward_port, 10);
data.block_exploits = !!data.block_exploits;
data.drop_unauthorized = !!data.drop_unauthorized;
data.caching_enabled = !!data.caching_enabled;
data.allow_websocket_upgrade = !!data.allow_websocket_upgrade;
data.http2_support = !!data.http2_support;

View File

@@ -75,6 +75,7 @@
"domain-names": "Domain Names",
"cert-provider": "Certificate Provider",
"block-exploits": "Block Common Exploits",
"drop-unauthorized": "Drop Unauthorized (444)",
"caching-enabled": "Cache Assets",
"ssl-certificate": "SSL Certificate",
"none": "None",

View File

@@ -20,6 +20,7 @@ const model = Backbone.Model.extend({
caching_enabled: false,
allow_websocket_upgrade: false,
block_exploits: false,
drop_unauthorized: false,
http2_support: false,
advanced_config: '',
enabled: true,

View File

@@ -27,6 +27,7 @@ describe('Hosts endpoints', () => {
advanced_config: '',
locations: [],
block_exploits: false,
drop_unauthorized: false,
caching_enabled: false,
allow_websocket_upgrade: false,
http2_support: false,