Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add nginx HTTP/3 support #1285

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions actions/admin/settings/130.webserver.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,18 @@
],
'visible' => Settings::Get('system.use_ssl')
],
'system_http3_support' => [
'label' => lng('serversettings.http3_support'),
'settinggroup' => 'system',
'varname' => 'http3_support',
'type' => 'checkbox',
'default' => false,
'save_method' => 'storeSettingField',
'websrv_avail' => [
'nginx'
],
'visible' => Settings::Get('system.use_ssl')
],
'system_dhparams_file' => [
'label' => lng('serversettings.dhparams_file'),
'settinggroup' => 'system',
Expand Down
4 changes: 3 additions & 1 deletion install/froxlor.sql.php
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@
`hsts_preload` tinyint(1) NOT NULL default '0',
`ocsp_stapling` tinyint(1) DEFAULT '0',
`http2` tinyint(1) DEFAULT '0',
`http3` tinyint(1) DEFAULT '0',
`notryfiles` tinyint(1) DEFAULT '0',
`writeaccesslog` tinyint(1) DEFAULT '1',
`writeerrorlog` tinyint(1) DEFAULT '1',
Expand Down Expand Up @@ -599,6 +600,7 @@
('system', 'ssl_cipher_list', 'ECDH+AESGCM:ECDH+AES256:!aNULL:!MD5:!DSS:!DH:!AES128'),
('system', 'nginx_php_backend', '127.0.0.1:8888'),
('system', 'http2_support', '0'),
('system', 'http3_support', '0'),
('system', 'perl_server', 'unix:/var/run/nginx/cgiwrap-dispatch.sock'),
('system', 'phpreload_command', ''),
('system', 'apache24', '1'),
Expand Down Expand Up @@ -731,7 +733,7 @@
('panel', 'settings_mode', '0'),
('panel', 'menu_collapsed', '1'),
('panel', 'version', '2.2.4'),
('panel', 'db_version', '202409280');
('panel', 'db_version', '202410100');


DROP TABLE IF EXISTS `panel_tasks`;
Expand Down
13 changes: 13 additions & 0 deletions install/updates/froxlor/update_2.2.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -193,3 +193,16 @@
Update::showUpdateStep("Updating from 2.2.3 to 2.2.4", false);
Froxlor::updateToVersion('2.2.4');
}

if (Froxlor::isDatabaseVersion('202409280')) {

Update::showUpdateStep("Adding new settings");
Settings::AddNew("system.http3_support", "0");
Update::lastStepStatus(0);

Update::showUpdateStep("Adding http3 field to domain table");
Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` ADD `http3` tinyint(1) NOT NULL default '0' AFTER `http2`;");
Update::lastStepStatus(0);

Froxlor::updateToDbVersion('202410100');
}
15 changes: 15 additions & 0 deletions lib/Froxlor/Api/Commands/Domains.php
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,9 @@ public function listingCount()
* @param bool $http2
* optional, whether to enable http/2 for this domain (requires to be enabled in the settings), default
* 0 (false)
* @param bool $http3
* optional, whether to enable http/3 for this domain (requires to be enabled in the settings), default
* 0 (false)
* @param int $hsts_maxage
* optional max-age value for HSTS header
* @param bool $hsts_sub
Expand Down Expand Up @@ -322,6 +325,7 @@ public function add()
$dont_use_default_ssl_ipandport_if_empty = $this->getBoolParam('dont_use_default_ssl_ipandport_if_empty', true, 0);
$p_ssl_ipandports = $this->getParam('ssl_ipandport', true, $dont_use_default_ssl_ipandport_if_empty ? [] : explode(',', Settings::Get('system.defaultsslip')));
$http2 = $this->getBoolParam('http2', true, 0);
$http3 = $this->getBoolParam('http3', true, 0);
$hsts_maxage = $this->getParam('hsts_maxage', true, 0);
$hsts_sub = $this->getBoolParam('hsts_sub', true, 0);
$hsts_preload = $this->getBoolParam('hsts_preload', true, 0);
Expand Down Expand Up @@ -557,6 +561,7 @@ public function add()
$ssl_redirect = 0;
$letsencrypt = 0;
$http2 = 0;
$http3 = 0;
// we need this for the json_encode
// if ssl is disabled or no ssl-ip/port exists
$ssl_ipandports[] = -1;
Expand Down Expand Up @@ -726,6 +731,7 @@ public function add()
'mod_fcgid_maxrequests' => $mod_fcgid_maxrequests,
'letsencrypt' => $letsencrypt,
'http2' => $http2,
'http3' => $http3,
'hsts' => $hsts_maxage,
'hsts_sub' => $hsts_sub,
'hsts_preload' => $hsts_preload,
Expand Down Expand Up @@ -779,6 +785,7 @@ public function add()
`mod_fcgid_maxrequests` = :mod_fcgid_maxrequests,
`letsencrypt` = :letsencrypt,
`http2` = :http2,
`http3` = :http3,
`hsts` = :hsts,
`hsts_sub` = :hsts_sub,
`hsts_preload` = :hsts_preload,
Expand Down Expand Up @@ -1137,6 +1144,9 @@ private function getIpsFromIdArray(array $ids)
* @param bool $http2
* optional, whether to enable http/2 for this domain (requires to be enabled in the settings), default
* 0 (false)
* @param bool $http3
* optional, whether to enable http/3 for this domain (requires to be enabled in the settings), default
* 0 (false)
* @param int $hsts_maxage
* optional max-age value for HSTS header
* @param bool $hsts_sub
Expand Down Expand Up @@ -1224,6 +1234,7 @@ public function update()
] : null);
$sslenabled = $remove_ssl_ipandport ? false : $this->getBoolParam('sslenabled', true, $result['ssl_enabled']);
$http2 = $this->getBoolParam('http2', true, $result['http2']);
$http3 = $this->getBoolParam('http3', true, $result['http3']);
$hsts_maxage = $this->getParam('hsts_maxage', true, $result['hsts']);
$hsts_sub = $this->getBoolParam('hsts_sub', true, $result['hsts_sub']);
$hsts_preload = $this->getBoolParam('hsts_preload', true, $result['hsts_preload']);
Expand Down Expand Up @@ -1540,6 +1551,7 @@ public function update()
$ssl_redirect = 0;
$letsencrypt = 0;
$http2 = 0;
$http3 = 0;
// act like $remove_ssl_ipandport
$ssl_ipandports = [];

Expand Down Expand Up @@ -1674,6 +1686,7 @@ public function update()
|| ($speciallogfile != $result['speciallogfile'] && $speciallogverified == '1')
|| $letsencrypt != $result['letsencrypt']
|| $http2 != $result['http2']
|| $http3 != $result['http3']
|| $hsts_maxage != $result['hsts']
|| $hsts_sub != $result['hsts_sub']
|| $hsts_preload != $result['hsts_preload']
Expand Down Expand Up @@ -1847,6 +1860,7 @@ public function update()
$update_data['termination_date'] = $termination_date;
$update_data['letsencrypt'] = $letsencrypt;
$update_data['http2'] = $http2;
$update_data['http3'] = $http3;
$update_data['hsts'] = $hsts_maxage;
$update_data['hsts_sub'] = $hsts_sub;
$update_data['hsts_preload'] = $hsts_preload;
Expand Down Expand Up @@ -1895,6 +1909,7 @@ public function update()
`termination_date` = :termination_date,
`letsencrypt` = :letsencrypt,
`http2` = :http2,
`http3` = :http3,
`hsts` = :hsts,
`hsts_sub` = :hsts_sub,
`hsts_preload` = :hsts_preload,
Expand Down
15 changes: 15 additions & 0 deletions lib/Froxlor/Api/Commands/SubDomains.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ class SubDomains extends ApiCommand implements ResourceEntity
* @param bool $http2
* optional, whether to enable http/2 for this subdomain (requires to be enabled in the settings),
* default 0 (false)
* @param bool $http3
* optional, whether to enable http/3 for this subdomain (requires to be enabled in the settings),
* default 0 (false)
* @param int $hsts_maxage
* optional max-age value for HSTS header, default 0
* @param bool $hsts_sub
Expand Down Expand Up @@ -116,6 +119,7 @@ public function add()
$ssl_redirect = $this->getBoolParam('ssl_redirect', true, 0);
$letsencrypt = $this->getBoolParam('letsencrypt', true, 0);
$http2 = $this->getBoolParam('http2', true, 0);
$http3 = $this->getBoolParam('http3', true, 0);
$hsts_maxage = $this->getParam('hsts_maxage', true, 0);
$hsts_sub = $this->getBoolParam('hsts_sub', true, 0);
$hsts_preload = $this->getBoolParam('hsts_preload', true, 0);
Expand All @@ -124,6 +128,7 @@ public function add()
$ssl_redirect = 0;
$letsencrypt = 0;
$http2 = 0;
$http3 = 0;
$hsts_maxage = 0;
$hsts_sub = 0;
$hsts_preload = 0;
Expand Down Expand Up @@ -341,6 +346,7 @@ public function add()
`phpsettingid` = :phpsettingid,
`letsencrypt` = :letsencrypt,
`http2` = :http2,
`http3` = :http3,
`hsts` = :hsts,
`hsts_sub` = :hsts_sub,
`hsts_preload` = :hsts_preload,
Expand Down Expand Up @@ -373,6 +379,7 @@ public function add()
"phpsettingid" => $phpsid_result['phpsettingid'],
"letsencrypt" => $letsencrypt,
"http2" => $http2,
"http3" => $http3,
"hsts" => $hsts_maxage,
"hsts_sub" => $hsts_sub,
"hsts_preload" => $hsts_preload,
Expand Down Expand Up @@ -618,6 +625,9 @@ private function validateDomainDocumentRoot($path = null, $url = null, $customer
* @param bool $http2
* optional, whether to enable http/2 for this domain (requires to be enabled in the settings), default
* 0 (false)
* @param bool $http3
* optional, whether to enable http/3 for this domain (requires to be enabled in the settings), default
* 0 (false)
* @param int $hsts_maxage
* optional max-age value for HSTS header
* @param bool $hsts_sub
Expand Down Expand Up @@ -671,6 +681,7 @@ public function update()
$ssl_redirect = $this->getBoolParam('ssl_redirect', true, $result['ssl_redirect']);
$letsencrypt = $this->getBoolParam('letsencrypt', true, $result['letsencrypt']);
$http2 = $this->getBoolParam('http2', true, $result['http2']);
$http3 = $this->getBoolParam('http3', true, $result['http3']);
$hsts_maxage = $this->getParam('hsts_maxage', true, $result['hsts']);
$hsts_sub = $this->getBoolParam('hsts_sub', true, $result['hsts_sub']);
$hsts_preload = $this->getBoolParam('hsts_preload', true, $result['hsts_preload']);
Expand All @@ -679,6 +690,7 @@ public function update()
$ssl_redirect = 0;
$letsencrypt = 0;
$http2 = 0;
$http3 = 0;
$hsts_maxage = 0;
$hsts_sub = 0;
$hsts_preload = 0;
Expand Down Expand Up @@ -824,6 +836,7 @@ public function update()
|| $hsts_preload != $result['hsts_preload']
|| $phpsettingid != $result['phpsettingid']
|| $http2 != $result['http2']
|| $http3 != $result['http3']
|| ($speciallogfile != $result['speciallogfile'] && $speciallogverified == '1')
) {
$stmt = Database::prepare("
Expand All @@ -838,6 +851,7 @@ public function update()
`ssl_redirect` = :ssl_redirect,
`letsencrypt` = :letsencrypt,
`http2` = :http2,
`http3` = :http3,
`hsts` = :hsts,
`hsts_sub` = :hsts_sub,
`hsts_preload` = :hsts_preload,
Expand All @@ -856,6 +870,7 @@ public function update()
"ssl_redirect" => $ssl_redirect,
"letsencrypt" => $letsencrypt,
"http2" => $http2,
"http3" => $http3,
"hsts" => $hsts_maxage,
"hsts_sub" => $hsts_sub,
"hsts_preload" => $hsts_preload,
Expand Down
21 changes: 21 additions & 0 deletions lib/Froxlor/Cron/Http/Nginx.php
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ public function createIpPort()
}

$http2 = $ssl_vhost == true && Settings::Get('system.http2_support') == '1';
$http3 = $ssl_vhost == true && Settings::Get('system.http3_support') == '1';

/**
* this HAS to be set for the default host in nginx or else no vhost will work
Expand All @@ -177,6 +178,14 @@ public function createIpPort()
if ($http2 && $this->http2_on_directive) {
$this->nginx_data[$vhost_filename] .= "\t" . 'http2 on;' . "\n";
}
if ($http3) {
$this->nginx_data[$vhost_filename] .= "\t" . 'listen ' . $ip . ':' . $port . ' default_server quic reuseport;' . "\n";
$this->nginx_data[$vhost_filename] .= "\t" . 'http3 on;' . "\n";
$this->nginx_data[$vhost_filename] .= "\t" . 'http3_hq on;' . "\n";
$this->nginx_data[$vhost_filename] .= "\t" . 'quic_gso on;' . "\n";
$this->nginx_data[$vhost_filename] .= "\t" . 'quic_retry on;' . "\n";
$this->nginx_data[$vhost_filename] .= "\t" . 'add_header Alt-Svc \'h3=":' . $port . '"; ma=86400\';' . "\n";
}
$this->nginx_data[$vhost_filename] .= "\t" . '# Froxlor default vhost' . "\n";

$aliases = "";
Expand Down Expand Up @@ -515,6 +524,7 @@ protected function getVhostContent($domain, $ssl_vhost = false)
'domainid' => $domain['id']
]);

$http3 = $ssl_vhost == true && (isset($domain['http3']) && $domain['http3'] == '1' && Settings::Get('system.http3_support') == '1');
while ($ipandport = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
$domain['ip'] = $ipandport['ip'];
$domain['port'] = $ipandport['port'];
Expand Down Expand Up @@ -550,6 +560,17 @@ protected function getVhostContent($domain, $ssl_vhost = false)
$vhost_content .= "\t" . 'http2 on;' . "\n";
$has_http2_on = true;
}
if ($http3) {
$vhost_content .= "\t" . 'listen ' . $ipport . ' quic;' . "\n";
}
}

if ($http3) {
$vhost_content .= "\t" . 'add_header Alt-Svc \'h3=":' . $domain['port'] . '"; ma=86400\';' . "\n";
$vhost_content .= "\t" . 'http3 on;' . "\n";
$vhost_content .= "\t" . 'http3_hq on;' . "\n";
$vhost_content .= "\t" . 'quic_gso on;' . "\n";
$vhost_content .= "\t" . 'quic_retry on;' . "\n";
}

// get all server-names
Expand Down
2 changes: 1 addition & 1 deletion lib/Froxlor/Froxlor.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ final class Froxlor
const VERSION = '2.2.4';

// Database version (YYYYMMDDC where C is a daily counter)
const DBVERSION = '202409280';
const DBVERSION = '202410100';

// Distribution branding-tag (used for Debian etc.)
const BRANDING = '';
Expand Down
8 changes: 8 additions & 0 deletions lib/formfields/admin/domains/formfield.domains_add.php
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,14 @@
'value' => '1',
'checked' => false
],
'http3' => [
'visible' => !empty($ssl_ipsandports) && Settings::Get('system.webserver') == 'nginx' && Settings::Get('system.http3_support') == '1',
'label' => lng('admin.domain_http3.title'),
'desc' => lng('admin.domain_http3.description'),
'type' => 'checkbox',
'value' => '1',
'checked' => false
],
'override_tls' => [
'visible' => !empty($ssl_ipsandports) && $userinfo['change_serversettings'] == '1',
'label' => lng('admin.domain_override_tls'),
Expand Down
8 changes: 8 additions & 0 deletions lib/formfields/admin/domains/formfield.domains_edit.php
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,14 @@
'value' => '1',
'checked' => $result['http2']
],
'http3' => [
'visible' => !empty($ssl_ipsandports) && Settings::Get('system.webserver') == 'nginx' && Settings::Get('system.http3_support') == '1',
'label' => lng('admin.domain_http3.title'),
'desc' => lng('admin.domain_http3.description'),
'type' => 'checkbox',
'value' => '1',
'checked' => $result['http3']
],
'override_tls' => [
'visible' => !empty($ssl_ipsandports) && $userinfo['change_serversettings'] == '1',
'label' => lng('admin.domain_override_tls'),
Expand Down
8 changes: 8 additions & 0 deletions lib/formfields/customer/domains/formfield.domains_add.php
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,14 @@
'value' => '1',
'checked' => false
],
'http3' => [
'visible' => $ssl_ipsandports && Settings::Get('system.webserver') == 'nginx' && Settings::Get('system.http3_support') == '1',
'label' => lng('admin.domain_http3.title'),
'desc' => lng('admin.domain_http3.description'),
'type' => 'checkbox',
'value' => '1',
'checked' => false
],
'hsts_maxage' => [
'label' => lng('admin.domain_hsts_maxage.title'),
'desc' => lng('admin.domain_hsts_maxage.description'),
Expand Down
8 changes: 8 additions & 0 deletions lib/formfields/customer/domains/formfield.domains_edit.php
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,14 @@
'value' => '1',
'checked' => $result['http2']
],
'http3' => [
'visible' => $ssl_ipsandports && Settings::Get('system.webserver') == 'nginx' && Settings::Get('system.http3_support') == '1',
'label' => lng('admin.domain_http3.title'),
'desc' => lng('admin.domain_http3.description'),
'type' => 'checkbox',
'value' => '1',
'checked' => $result['http3']
],
'hsts_maxage' => [
'label' => lng('admin.domain_hsts_maxage.title'),
'desc' => lng('admin.domain_hsts_maxage.description'),
Expand Down
5 changes: 5 additions & 0 deletions lib/tablelisting/admin/tablelisting.domains.php
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,11 @@
'field' => 'http2',
'callback' => [Text::class, 'boolean'],
],
'd.http3' => [
'label' => lng('admin.domain_http3.title'),
'field' => 'http3',
'callback' => [Text::class, 'boolean'],
],
'd.letsencrypt' => [
'label' => lng('panel.letsencrypt'),
'field' => 'letsencrypt',
Expand Down
8 changes: 8 additions & 0 deletions lng/de.lng.php
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,10 @@
'title' => 'HTTP2 Unterstützung',
'description' => 'Siehe <a target="_blank" href="https://de.wikipedia.org/wiki/Hypertext_Transfer_Protocol#HTTP.2F2">Wikipedia</a> für eine ausführliche Beschreibung von HTTP2',
],
'domain_http3' => [
'title' => 'HTTP3 Unterstützung',
'description' => 'Siehe <a target="_blank" href="https://de.wikipedia.org/wiki/Hypertext_Transfer_Protocol#HTTP.2F3">Wikipedia</a> für eine ausführliche Beschreibung von HTTP3',
],
'testmail' => 'SMTP Test',
'phpsettingsforsubdomains' => 'PHP-Config für alle Subdomains übernehmen:',
'plans' => [
Expand Down Expand Up @@ -2005,6 +2009,10 @@
'title' => 'HTTP2 Unterstützung',
'description' => 'Aktiviere HTTP2 Unterstützung für SSL.<br><em class="text-danger">NUR AKTIVIEREN, WENN DER WEBSERVER DIESE FUNKTION UNTERSTÜTZT (nginx version 1.9.5+, apache2 version 2.4.17+)</em>',
],
'http3_support' => [
'title' => 'HTTP3 Unterstützung',
'description' => 'Aktiviere HTTP3 Unterstützung für SSL.<br><em class="text-danger">NUR AKTIVIEREN, WENN DER WEBSERVER DIESE FUNKTION UNTERSTÜTZT (nginx version 1.25.0+)</em>',
],
'nssextrausers' => [
'title' => 'Verwende libnss-extrausers anstatt libnss-mysql',
'description' => 'Lese Benutzer nicht direkt aus der Datenbank sondern über Dateien. Bitte nur aktivieren, wenn die entsprechende Konfiguration vorgenommen wurde (System -> libnss-extrausers).<br><strong class="text-danger">Nur für Debian/Ubuntu (oder wenn libnss-extrausers manuell kompiliert wurde!)</strong>',
Expand Down
Loading