www/nginx: allow to generate the fingerprint database from config.xml (#1086)

* www/nginx: allow to generate the fingerprint database from config.xml
* www/nginx: add missing file
* www/nginx: run bmake style-fix
This commit is contained in:
Fabian Franz BSc
2018-12-22 14:06:04 +01:00
committed by GitHub
parent fd8bdec00f
commit d69f1a29f7
9 changed files with 133 additions and 1 deletions
@@ -374,6 +374,33 @@ class SettingsController extends ApiMutableModelControllerBase
return $this->setBase('limit_zone', 'limit_zone', $uuid);
}
// TLS fingerprints for MITM detection
public function searchtls_fingerprintAction()
{
return $this->searchBase('tls_fingerprint', array('description'));
}
public function gettls_fingerprintAction($uuid = null)
{
$this->sessionClose();
return $this->getBase('tls_fingerprint', 'tls_fingerprint', $uuid);
}
public function addtls_fingerprintAction()
{
return $this->addBase('tls_fingerprint', 'tls_fingerprint');
}
public function deltls_fingerprintAction($uuid)
{
return $this->delBase('tls_fingerprint', $uuid);
}
public function settls_fingerprintAction($uuid)
{
return $this->setBase('tls_fingerprint', 'tls_fingerprint', $uuid);
}
// limit_request_connection
public function searchlimit_request_connectionAction()
{
@@ -477,6 +504,7 @@ class SettingsController extends ApiMutableModelControllerBase
}
return [];
}
// IP / Network based ACLs
public function searchipaclAction()
{
@@ -60,6 +60,7 @@ class IndexController extends \OPNsense\Base\IndexController
$this->view->cache_path = $this->getForm("cache_path");
$this->view->sni_hostname_map = $this->getForm("sni_hostname_map");
$this->view->ipacl = $this->getForm("ipacl");
$this->view->tls_fingerprint = $this->getForm("tls_fingerprint");
$nginx = new Nginx();
$this->view->show_naxsi_download_button =
count($nginx->custom_policy->iterateItems()) == 0 && count($nginx->naxsi_rule->iterateItems()) == 0;
@@ -0,0 +1,31 @@
<form>
<field>
<id>tls_fingerprint.description</id>
<label>Description</label>
<type>text</type>
<help>Enter a useful description for your entry.</help>
</field>
<field>
<id>tls_fingerprint.trusted</id>
<label>Trusted</label>
<type>checkbox</type>
<help>If you check this box, this entry will be added to the configuration of trusted fingerprints.</help>
</field>
<field>
<id>tls_fingerprint.user_agent</id>
<label>User Agent</label>
<type>text</type>
</field>
<field>
<id>tls_fingerprint.ciphers</id>
<label>Cipher Suits</label>
<type>text</type>
<help>Enter a list of elliptic curves supported by the client in a standard configuration in OpenSSL syntax (cipher1:cipher2:0x0001).</help>
</field>
<field>
<id>tls_fingerprint.curves</id>
<label>Elliptic Curves</label>
<type>text</type>
<help>Enter a list of elliptic curves supported by the client in a standard configuration in OpenSSL syntax (curve1:curve2:0x0001).</help>
</field>
</form>
@@ -1274,6 +1274,29 @@
</rate>
</limit_zone>
<tls_fingerprint type="ArrayField">
<description type="TextField">
<Required>Y</Required>
</description>
<user_agent type="TextField">
<Required>Y</Required>
</user_agent>
<trusted type="BooleanField">
<default>0</default>
<Required>Y</Required>
</trusted>
<curves type="TextField">
<!-- OpenSSL curve list like the one used for configuring the supported ciphers by the web server -->
<Required>N</Required>
<mask>/^(0x[0-9a-fA-F]{4,4}|[a-zA-Z_\-0-9]+)(?::((0x[0-9a-fA-F]{4,4}|[a-zA-Z_\-0-9]+)))*$/</mask>
</curves>
<ciphers type="TextField">
<!-- OpenSSL cipher list like the one used for configuring the supported ciphers by the web server -->
<Required>Y</Required>
<mask>/^(0x[0-9a-fA-F]{4,4}|[a-zA-Z_\-0-9]+)(?::((0x[0-9a-fA-F]{4,4}|[a-zA-Z_\-0-9]+)))*$/</mask>
</ciphers>
</tls_fingerprint>
<limit_request_connection type="ArrayField">
<limit_zone type="ModelRelationField">
<Model>
@@ -124,6 +124,9 @@
<li>
<a data-toggle="tab" id="subtab_item_nginx-http-cache_path" href="#subtab_nginx-http-cache_path">{{ lang._('Cache Path')}}</a>
</li>
<li>
<a data-toggle="tab" id="subtab_item_nginx-http-tls-fingerprint" href="#subtab_nginx-http-tls-fingerprint">{{ lang._('TLS Fingerprint (Advanced)')}}</a>
</li>
</ul>
</li>
<li role="presentation" class="dropdown">
@@ -574,6 +577,27 @@
</tfoot>
</table>
</div>
<div id="subtab_nginx-http-tls-fingerprint" class="tab-pane fade">
<table id="grid-tls_fingerprint" class="table table-condensed table-hover table-striped table-responsive" data-editDialog="tls_fingerprint_dlg">
<thead>
<tr>
<th data-column-id="description" data-type="string" data-sortable="true" data-visible="true">{{ 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 data-action="add" type="button" class="btn btn-xs btn-default"><span class="fa fa-plus"></span></button>
<button type="button" class="btn btn-xs reload_btn btn-primary"><span class="fa fa-refresh reloadAct_progress"></span></button>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
@@ -593,3 +617,4 @@
{{ partial("layout_partials/base_dialog",['fields': cache_path,'id':'cache_pathdlg', 'label':lang._('Edit Cache Path')]) }}
{{ partial("layout_partials/base_dialog",['fields': sni_hostname_map,'id':'sni_hostname_mapdlg', 'label':lang._('Edit SNI Hostname Mapping')]) }}
{{ partial("layout_partials/base_dialog",['fields': ipacl,'id':'ipacl_dlg', 'label':lang._('Edit IP ACL')]) }}
{{ partial("layout_partials/base_dialog",['fields': tls_fingerprint,'id':'tls_fingerprint_dlg', 'label':lang._('Edit TLS Fingerprint')]) }}
@@ -241,3 +241,24 @@ foreach ($nginx->userlist->iterateItems() as $user_list) {
foreach ($nginx->cache_path->iterateItems() as $cache_path) {
@mkdir((string)$cache_path->path, 0755, true);
}
// export TLS fingerprint database for MitM detection
$tls_fingerprint_database = array();
foreach ($nginx->tls_fingerprint->iterateItems() as $tls_fingerprint) {
if ((string)$tls_fingerprint->trusted == '1') {
$ciphers = explode(':', (string)$tls_fingerprint->ciphers);
if (!empty((string)$tls_fingerprint->curves)) {
$curves = explode(':', (string)$tls_fingerprint->ciphers);
} else {
$curves = array();
}
$tls_fingerprint_database[(string)$tls_fingerprint->user_agent] =
array('ciphers' => $ciphers, 'curves' => $curves);
}
}
file_put_contents(
'/usr/local/etc/nginx/tls_fingerprints.json',
empty($tls_fingerprint_database) ? '{}' : json_encode($tls_fingerprint_database)
);
chmod('/usr/local/etc/nginx/tls_fingerprints.json', 0644);
@@ -6,6 +6,7 @@ include mime.types;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
log_format handshake '"$http_user_agent" "$ssl_ciphers" "$ssl_curves"';
log_format anonymized ':: - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
@@ -101,6 +102,7 @@ server {
charset {{ server.charset }};
{% endif %}
access_log /var/log/nginx/{{ server.servername }}.access.log {{ server.access_log_format }};
access_log /var/log/nginx/tls_handshake.log handshake;
error_log /var/log/nginx/{{ server.servername }}.error.log;
{% if server.root is defined and server.root != '' %}
root "{{server.root}}";
File diff suppressed because one or more lines are too long
@@ -68,6 +68,7 @@ function init_grids() {
'cache_path',
'limit_request_connection',
'snifwd',
'tls_fingerprint',
'naxsirule'].forEach(function (element) {
$("#grid-" + element).UIBootgrid(
{