diff --git a/backend/app/dto/request/website.go b/backend/app/dto/request/website.go
index faaa33a25..2cd425e01 100644
--- a/backend/app/dto/request/website.go
+++ b/backend/app/dto/request/website.go
@@ -123,6 +123,7 @@ type WebsiteHTTPSOp struct {
HttpConfig string `json:"httpConfig" validate:"oneof=HTTPSOnly HTTPAlso HTTPToHTTPS"`
SSLProtocol []string `json:"SSLProtocol"`
Algorithm string `json:"algorithm"`
+ Hsts bool `json:"hsts"`
}
type WebsiteNginxUpdate struct {
diff --git a/backend/app/dto/response/website.go b/backend/app/dto/response/website.go
index dd2fe1486..b80368224 100644
--- a/backend/app/dto/response/website.go
+++ b/backend/app/dto/response/website.go
@@ -37,6 +37,7 @@ type WebsiteHTTPS struct {
SSL model.WebsiteSSL `json:"SSL"`
SSLProtocol []string `json:"SSLProtocol"`
Algorithm string `json:"algorithm"`
+ Hsts bool `json:"hsts"`
}
type WebsiteLog struct {
diff --git a/backend/app/service/website.go b/backend/app/service/website.go
index 8d301d4b9..624e2dfe0 100644
--- a/backend/app/service/website.go
+++ b/backend/app/service/website.go
@@ -754,7 +754,7 @@ func (w WebsiteService) GetWebsiteHTTPS(websiteId uint) (response.WebsiteHTTPS,
} else {
res.HttpConfig = constant.HTTPToHTTPS
}
- params, err := getNginxParamsByKeys(constant.NginxScopeServer, []string{"ssl_protocols", "ssl_ciphers"}, &website)
+ params, err := getNginxParamsByKeys(constant.NginxScopeServer, []string{"ssl_protocols", "ssl_ciphers", "add_header"}, &website)
if err != nil {
return res, err
}
@@ -765,6 +765,9 @@ func (w WebsiteService) GetWebsiteHTTPS(websiteId uint) (response.WebsiteHTTPS,
if p.Name == "ssl_ciphers" {
res.Algorithm = p.Params[0]
}
+ if p.Name == "add_header" && len(p.Params) > 0 && p.Params[0] == "Strict-Transport-Security" {
+ res.Hsts = true
+ }
}
return res, nil
}
@@ -782,7 +785,7 @@ func (w WebsiteService) OpWebsiteHTTPS(ctx context.Context, req request.WebsiteH
if err != nil {
return nil, err
}
- if err = ChangeHSTSConfig(req.Enable, nginxInstall, website); err != nil {
+ if err = ChangeHSTSConfig(req.Hsts, nginxInstall, website); err != nil {
return nil, err
}
res.Enable = req.Enable
@@ -1616,9 +1619,6 @@ func (w WebsiteService) OperateProxy(req request.WebsiteProxyConfig) (err error)
}
location.UpdateDirective("proxy_pass", []string{req.ProxyPass})
location.UpdateDirective("proxy_set_header", []string{"Host", req.ProxyHost})
- if website.Protocol == constant.ProtocolHTTPS {
- location.UpdateDirective("add_header", []string{"Strict-Transport-Security", "\"max-age=31536000\""})
- }
location.ChangePath(req.Modifier, req.Match)
if req.Cache {
location.AddCache(req.CacheTime, req.CacheUnit)
diff --git a/backend/app/service/website_utils.go b/backend/app/service/website_utils.go
index 40ef2c20a..bdd76692c 100644
--- a/backend/app/service/website_utils.go
+++ b/backend/app/service/website_utils.go
@@ -609,6 +609,10 @@ func applySSL(website model.Website, websiteSSL model.WebsiteSSL, req request.We
}
}
+ if !req.Hsts {
+ server.RemoveDirective("add_header", []string{"Strict-Transport-Security", "\"max-age=31536000\""})
+ }
+
if err := nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
return err
}
@@ -630,6 +634,13 @@ func applySSL(website model.Website, websiteSSL model.WebsiteSSL, req request.We
nginxParams[i].Params = []string{req.Algorithm}
}
}
+ if req.Hsts {
+ nginxParams = append(nginxParams, dto.NginxParam{
+ Name: "add_header",
+ Params: []string{"Strict-Transport-Security", "\"max-age=31536000\""},
+ })
+ }
+
if err := updateNginxConfig(constant.NginxScopeServer, nginxParams, &website); err != nil {
return err
}
diff --git a/cmd/server/nginx_conf/ssl.conf b/cmd/server/nginx_conf/ssl.conf
index cc1786e91..d5c87bac6 100644
--- a/cmd/server/nginx_conf/ssl.conf
+++ b/cmd/server/nginx_conf/ssl.conf
@@ -5,7 +5,6 @@ ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDS
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
-add_header Strict-Transport-Security "max-age=31536000";
error_page 497 https://$host$request_uri;
proxy_set_header X-Forwarded-Proto https;
ssl_stapling on;
diff --git a/frontend/src/api/interface/website.ts b/frontend/src/api/interface/website.ts
index 25ed25f4e..a34070a10 100644
--- a/frontend/src/api/interface/website.ts
+++ b/frontend/src/api/interface/website.ts
@@ -263,6 +263,7 @@ export namespace Website {
httpConfig: string;
SSLProtocol: string[];
algorithm: string;
+ hsts: boolean;
}
export interface CheckReq {
diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts
index 952dd3435..fe4e6b702 100644
--- a/frontend/src/lang/modules/en.ts
+++ b/frontend/src/lang/modules/en.ts
@@ -2026,6 +2026,7 @@ const message = {
websiteBackupWarn:
'Only supports importing local backups, importing backups from other machines may cause recovery failure',
ipWebsiteWarn: 'Websites with IP as domain names need to be set as default sites to be accessed normally',
+ hstsHelper: 'Enabling HSTS can increase website security',
},
php: {
short_open_tag: 'Short tag support',
diff --git a/frontend/src/lang/modules/tw.ts b/frontend/src/lang/modules/tw.ts
index de9b5376e..54926ebf3 100644
--- a/frontend/src/lang/modules/tw.ts
+++ b/frontend/src/lang/modules/tw.ts
@@ -1887,6 +1887,7 @@ const message = {
rewriteHelper2: '從應用程式商店安裝的 WordPress 等應用,預設已經配置好偽靜態,重複配置可能會報錯',
websiteBackupWarn: '僅支援導入本機備份,導入其他機器備份可能會恢復失敗',
ipWebsiteWarn: 'IP 為網域名稱的網站,需要設定為預設網站才能正常存取',
+ hstsHelper: '開啟 HSTS 可以增加網站安全性',
},
php: {
short_open_tag: '短標簽支持',
diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts
index db3dad369..e217a6596 100644
--- a/frontend/src/lang/modules/zh.ts
+++ b/frontend/src/lang/modules/zh.ts
@@ -1888,6 +1888,7 @@ const message = {
rewriteHelper2: '从应用商店安装的 WordPress 等应用,默认已经配置好伪静态,重复配置可能会报错',
websiteBackupWarn: '仅支持导入本机备份,导入其他机器备份可能会恢复失败',
ipWebsiteWarn: 'IP 为域名的网站,需要设置为默认站点才能正常访问',
+ hstsHelper: '开启 HSTS 可以增加网站安全性',
},
php: {
short_open_tag: '短标签支持',
diff --git a/frontend/src/views/website/website/config/basic/https/index.vue b/frontend/src/views/website/website/config/basic/https/index.vue
index a1a8fba4c..316895e95 100644
--- a/frontend/src/views/website/website/config/basic/https/index.vue
+++ b/frontend/src/views/website/website/config/basic/https/index.vue
@@ -22,6 +22,10 @@
+
+ {{ $t('commons.button.start') }}
+ {{ $t('website.hstsHelper') }}
+
@@ -190,6 +194,7 @@ const form = reactive({
privateKeyPath: '',
certificatePath: '',
httpConfig: 'HTTPToHTTPS',
+ hsts: true,
algorithm:
'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:!aNULL:!eNULL:!EXPORT:!DSS:!DES:!RC4:!3DES:!MD5:!PSK:!KRB5:!SRP:!CAMELLIA:!SEED',
SSLProtocol: ['TLSv1.3', 'TLSv1.2', 'TLSv1.1', 'TLSv1'],
@@ -199,6 +204,7 @@ const ssls = ref();
const acmeAccounts = ref();
const websiteSSL = ref();
const rules = ref({
+ hsts: [Rules.requiredInput],
type: [Rules.requiredSelect],
privateKey: [Rules.requiredInput],
certificate: [Rules.requiredInput],
@@ -285,6 +291,7 @@ const get = () => {
websiteSSL.value = res.data.SSL;
form.acmeAccountID = res.data.SSL.acmeAccountId;
}
+ form.hsts = res.data.hsts;
}
listSSL();
listAcmeAccount();