diff --git a/agent/app/dto/request/website.go b/agent/app/dto/request/website.go
index 3a623ff85e0e..15c86276f955 100644
--- a/agent/app/dto/request/website.go
+++ b/agent/app/dto/request/website.go
@@ -165,6 +165,7 @@ type WebsiteHTTPSOp struct {
SSLProtocol []string `json:"SSLProtocol"`
Algorithm string `json:"algorithm"`
Hsts bool `json:"hsts"`
+ HstsIncludeSubDomains bool `json:"hstsIncludeSubDomains"`
HttpsPorts []int `json:"httpsPorts"`
Http3 bool `json:"http3"`
}
diff --git a/agent/app/dto/response/website.go b/agent/app/dto/response/website.go
index ed0ad4cdb0b3..3f4570e1a82d 100644
--- a/agent/app/dto/response/website.go
+++ b/agent/app/dto/response/website.go
@@ -65,6 +65,7 @@ type WebsiteHTTPS struct {
SSLProtocol []string `json:"SSLProtocol"`
Algorithm string `json:"algorithm"`
Hsts bool `json:"hsts"`
+ HstsIncludeSubDomains bool `json:"hstsIncludeSubDomains"`
HttpsPorts []int `json:"httpsPorts"`
HttpsPort string `json:"httpsPort"`
Http3 bool `json:"http3"`
diff --git a/agent/app/service/website.go b/agent/app/service/website.go
index 24b9ec5439d9..4b4841ebf81c 100644
--- a/agent/app/service/website.go
+++ b/agent/app/service/website.go
@@ -474,6 +474,7 @@ func (w WebsiteService) CreateWebsite(create request.WebsiteCreate) (err error)
SSLProtocol: []string{"TLSv1.3", "TLSv1.2"},
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",
Hsts: true,
+ HstsIncludeSubDomains: true,
}
if err = applySSL(website, *websiteModel, appSSLReq); err != nil {
return err
@@ -959,6 +960,13 @@ func (w WebsiteService) GetWebsiteHTTPS(websiteId uint) (response.WebsiteHTTPS,
if p.Name == "add_header" && len(p.Params) > 0 {
if p.Params[0] == "Strict-Transport-Security" {
res.Hsts = true
+ //增加HSTS下子域名检查逻辑
+ if len(p.Params) > 1 {
+ hstsValue := p.Params[1]
+ if strings.Contains(hstsValue, "includeSubDomains") {
+ res.HstsIncludeSubDomains = true
+ }
+ }
}
if p.Params[0] == "Alt-Svc" {
res.Http3 = true
@@ -977,12 +985,13 @@ func (w WebsiteService) OpWebsiteHTTPS(ctx context.Context, req request.WebsiteH
res response.WebsiteHTTPS
websiteSSL model.WebsiteSSL
)
- if err = ChangeHSTSConfig(req.Hsts, req.Http3, website); err != nil {
+ if err = ChangeHSTSConfig(req.Hsts, req.HstsIncludeSubDomains, req.Http3, website); err != nil {
return nil, err
}
res.Enable = req.Enable
res.SSLProtocol = req.SSLProtocol
res.Algorithm = req.Algorithm
+ res.HstsIncludeSubDomains = req.HstsIncludeSubDomains
if !req.Enable {
website.Protocol = constant.ProtocolHTTP
website.WebsiteSSLID = 0
diff --git a/agent/app/service/website_utils.go b/agent/app/service/website_utils.go
index 5298cce9ae3e..1fa887b8f898 100644
--- a/agent/app/service/website_utils.go
+++ b/agent/app/service/website_utils.go
@@ -753,6 +753,7 @@ func applySSL(website *model.Website, websiteSSL model.WebsiteSSL, req request.W
if !req.Hsts {
server.RemoveDirective("add_header", []string{"Strict-Transport-Security", "\"max-age=31536000\""})
+ server.RemoveDirective("add_header", []string{"Strict-Transport-Security", "\"max-age=31536000; includeSubDomains\""})
}
if !req.Http3 {
for port := range httpsPorts {
@@ -793,9 +794,15 @@ func applySSL(website *model.Website, websiteSSL model.WebsiteSSL, req request.W
}
}
if req.Hsts {
+ var hstsValue string
+ if req.HstsIncludeSubDomains {
+ hstsValue = "\"max-age=31536000; includeSubDomains\""
+ } else {
+ hstsValue = "\"max-age=31536000\""
+ }
nginxParams = append(nginxParams, dto.NginxParam{
Name: "add_header",
- Params: []string{"Strict-Transport-Security", "\"max-age=31536000\""},
+ Params: []string{"Strict-Transport-Security", hstsValue},
})
}
if req.Http3 {
@@ -1182,7 +1189,7 @@ func UpdateSSLConfig(websiteSSL model.WebsiteSSL) error {
return nil
}
-func ChangeHSTSConfig(enable bool, http3Enable bool, website model.Website) error {
+func ChangeHSTSConfig(enable bool, includeSubDomains bool, http3Enable bool, website model.Website) error {
includeDir := GetSitePath(website, SiteProxyDir)
fileOp := files.NewFileOp()
if !fileOp.Stat(includeDir) {
@@ -1208,11 +1215,19 @@ func ChangeHSTSConfig(enable bool, http3Enable bool, website model.Website) erro
if !ok {
return nil
}
+ //前置移除HSTS配置
+ location.RemoveDirective("add_header", []string{"Strict-Transport-Security", "\"max-age=31536000\""})
+ location.RemoveDirective("add_header", []string{"Strict-Transport-Security", "\"max-age=31536000; includeSubDomains\""})
if enable {
- location.UpdateDirective("add_header", []string{"Strict-Transport-Security", "\"max-age=31536000\""})
- } else {
- location.RemoveDirective("add_header", []string{"Strict-Transport-Security", "\"max-age=31536000\""})
+ var hstsValue string
+ if includeSubDomains {
+ hstsValue = "\"max-age=31536000; includeSubDomains\""
+ } else {
+ hstsValue = "\"max-age=31536000\""
+ }
+ location.UpdateDirective("add_header", []string{"Strict-Transport-Security", hstsValue})
}
+
if http3Enable {
location.UpdateDirective("add_header", []string{"Alt-Svc", "'h3=\":443\"; ma=2592000'"})
} else {
diff --git a/core/cmd/server/docs/docs.go b/core/cmd/server/docs/docs.go
index a345f8c1bb22..e8abcfd5ab47 100644
--- a/core/cmd/server/docs/docs.go
+++ b/core/cmd/server/docs/docs.go
@@ -26932,6 +26932,9 @@ const docTemplate = `{
"hsts": {
"type": "boolean"
},
+ "hstsIncludeSubDomains": {
+ "type": "boolean"
+ },
"http3": {
"type": "boolean"
},
@@ -28911,6 +28914,9 @@ const docTemplate = `{
"hsts": {
"type": "boolean"
},
+ "hstsIncludeSubDomains": {
+ "type": "boolean"
+ },
"http3": {
"type": "boolean"
},
diff --git a/core/cmd/server/docs/swagger.json b/core/cmd/server/docs/swagger.json
index 8590c011e14c..ed649e530e55 100644
--- a/core/cmd/server/docs/swagger.json
+++ b/core/cmd/server/docs/swagger.json
@@ -26928,6 +26928,9 @@
"hsts": {
"type": "boolean"
},
+ "hstsIncludeSubDomains": {
+ "type": "boolean"
+ },
"http3": {
"type": "boolean"
},
@@ -28907,6 +28910,9 @@
"hsts": {
"type": "boolean"
},
+ "hstsIncludeSubDomains": {
+ "type": "boolean"
+ },
"http3": {
"type": "boolean"
},
diff --git a/frontend/src/api/interface/website.ts b/frontend/src/api/interface/website.ts
index bef6ff6aa872..4e79f75acb62 100644
--- a/frontend/src/api/interface/website.ts
+++ b/frontend/src/api/interface/website.ts
@@ -318,6 +318,7 @@ export namespace Website {
SSLProtocol: string[];
algorithm: string;
hsts: boolean;
+ hstsIncludeSubDomains: boolean;
httpsPort?: string;
http3: boolean;
}
diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts
index 7df1dd4d378d..6e578a54ef3a 100644
--- a/frontend/src/lang/modules/en.ts
+++ b/frontend/src/lang/modules/en.ts
@@ -2435,6 +2435,9 @@ const message = {
'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 site to be accessed normally.',
hstsHelper: 'Enabling HSTS can increase website security',
+ includeSubDomains: 'SubDomains',
+ hstsIncludeSubDomainsHelper:
+ 'Once enabled, the HSTS policy will apply to all subdomains of the current domain.',
defaultHtml: 'Set default page',
website404: 'Website 404 error page',
domain404: 'Website page does not exist',
diff --git a/frontend/src/lang/modules/ja.ts b/frontend/src/lang/modules/ja.ts
index 667642e6c728..939a1c0ab18f 100644
--- a/frontend/src/lang/modules/ja.ts
+++ b/frontend/src/lang/modules/ja.ts
@@ -2350,6 +2350,8 @@ const message = {
ipWebsiteWarn:
'ドメイン名としてIPを持つWebサイトは、正常にアクセスするデフォルトサイトとして設定する必要があります。',
hstsHelper: 'HSTを有効にすると、Webサイトのセキュリティが向上する可能性があります',
+ includeSubDomains: 'サブドメイン',
+ hstsIncludeSubDomainsHelper: '有効化すると、HSTSポリシーが現在のドメインのすべてのサブドメインに適用されます。',
defaultHtml: 'デフォルトページ',
website404: 'ウェブサイト404エラーページ',
domain404: 'ウェブサイトドメインは存在しません',
diff --git a/frontend/src/lang/modules/ko.ts b/frontend/src/lang/modules/ko.ts
index 94fe1a46fbb2..f6ee68aaf73c 100644
--- a/frontend/src/lang/modules/ko.ts
+++ b/frontend/src/lang/modules/ko.ts
@@ -2310,6 +2310,8 @@ const message = {
ipWebsiteWarn:
'IP를 도메인 이름으로 사용하는 웹사이트는 정상적으로 접속되기 위해 기본 사이트로 설정해야 합니다.',
hstsHelper: 'HSTS 를 활성화하면 웹사이트 보안을 강화할 수 있습니다.',
+ includeSubDomains: '서브도메인',
+ hstsIncludeSubDomainsHelper: '활성화하면 HSTS 정책이 현재 도메인의 모든 서브도메인에 적용됩니다.',
defaultHtml: '기본 페이지',
website404: '웹사이트 404 오류 페이지',
domain404: '웹사이트 도메인이 존재하지 않습니다.',
diff --git a/frontend/src/lang/modules/ms.ts b/frontend/src/lang/modules/ms.ts
index ab5a7375510c..d17580ffadd1 100644
--- a/frontend/src/lang/modules/ms.ts
+++ b/frontend/src/lang/modules/ms.ts
@@ -2405,6 +2405,9 @@ const message = {
ipWebsiteWarn:
'Laman web dengan IP sebagai nama domain perlu disetkan sebagai laman web lalai untuk diakses secara normal.',
hstsHelper: 'Mengaktifkan HSTS boleh meningkatkan keselamatan laman web',
+ includeSubDomains: 'SubDomains',
+ hstsIncludeSubDomainsHelper:
+ 'Apabila diaktifkan, dasar HSTS akan digunakan pada semua subdomain bagi domain semasa.',
defaultHtml: 'Halaman lalai',
website404: 'Halaman ralat 404 laman web',
domain404: 'Domain laman web tidak wujud',
diff --git a/frontend/src/lang/modules/pt-br.ts b/frontend/src/lang/modules/pt-br.ts
index 25a4d48f6285..510107d04d3f 100644
--- a/frontend/src/lang/modules/pt-br.ts
+++ b/frontend/src/lang/modules/pt-br.ts
@@ -2405,6 +2405,9 @@ const message = {
ipWebsiteWarn:
'Sites com IP como nomes de domínio precisam ser configurados como site padrão para serem acessados normalmente',
hstsHelper: 'Ativar HSTS pode aumentar a segurança do site',
+ includeSubDomains: 'SubDomains',
+ hstsIncludeSubDomainsHelper:
+ 'Quando ativado, a política HSTS será aplicada a todos os subdomínios do domínio atual.',
defaultHtml: 'Página padrão',
website404: 'Página de erro 404 do site',
domain404: 'O domínio do site não existe',
diff --git a/frontend/src/lang/modules/ru.ts b/frontend/src/lang/modules/ru.ts
index 27bb17c812c9..f618ee6ffe9a 100644
--- a/frontend/src/lang/modules/ru.ts
+++ b/frontend/src/lang/modules/ru.ts
@@ -2401,6 +2401,9 @@ const message = {
ipWebsiteWarn:
'Веб-сайты с IP в качестве домена должны быть установлены как сайт по умолчанию для нормального доступа.',
hstsHelper: 'Включение HSTS может повысить безопасность веб-сайта',
+ includeSubDomains: 'Поддомены',
+ hstsIncludeSubDomainsHelper:
+ 'После включения политика HSTS будет применяться ко всем поддоменам текущего домена.',
defaultHtml: 'Страница по умолчанию',
website404: 'Страница ошибки 404 веб-сайта',
domain404: 'Домен веб-сайта не существует',
diff --git a/frontend/src/lang/modules/tr.ts b/frontend/src/lang/modules/tr.ts
index 38a7361d5fac..cab52856c09b 100644
--- a/frontend/src/lang/modules/tr.ts
+++ b/frontend/src/lang/modules/tr.ts
@@ -2464,6 +2464,9 @@ const message = {
ipWebsiteWarn:
'IP alan adlarına sahip web sitelerinin normal şekilde erişilebilmesi için varsayılan site olarak ayarlanması gerekir.',
hstsHelper: 'HSTS’nin etkinleştirilmesi web sitesi güvenliğini artırabilir',
+ includeSubDomains: 'Alt Alan Adları',
+ hstsIncludeSubDomainsHelper:
+ 'Etkinleştirildiğinde, HSTS politikası geçerli etki alanının tüm alt alan adlarına uygulanacaktır.',
defaultHtml: 'Varsayılan sayfayı ayarla',
website404: 'Web sitesi 404 hata sayfası',
domain404: 'Web sitesi sayfası mevcut değil',
diff --git a/frontend/src/lang/modules/zh-Hant.ts b/frontend/src/lang/modules/zh-Hant.ts
index 87a329400906..a86c4014d338 100644
--- a/frontend/src/lang/modules/zh-Hant.ts
+++ b/frontend/src/lang/modules/zh-Hant.ts
@@ -2273,6 +2273,8 @@ const message = {
websiteBackupWarn: '僅支援導入本機備份,導入其他機器備份可能會恢復失敗',
ipWebsiteWarn: 'IP 為網域名稱的網站,需要設定為預設網站才能正常存取',
hstsHelper: '開啟 HSTS 可以增加網站安全性',
+ includeSubDomains: '子域',
+ hstsIncludeSubDomainsHelper: '啟用後,HSTS策略將應用於目前域名的所有子域名',
defaultHtml: '預設頁面',
website404: '網站 404 錯誤頁',
domain404: '網站不存在頁面',
diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts
index 36d5b48ae618..8da66746f96b 100644
--- a/frontend/src/lang/modules/zh.ts
+++ b/frontend/src/lang/modules/zh.ts
@@ -2262,6 +2262,8 @@ const message = {
websiteBackupWarn: '仅支持导入本机备份,导入其他机器备份可能会恢复失败',
ipWebsiteWarn: 'IP 为域名的网站,需要设置为默认站点才能正常访问',
hstsHelper: '开启 HSTS 可以增加网站安全性',
+ includeSubDomains: '子域',
+ hstsIncludeSubDomainsHelper: '启用后,HSTS策略将应用于当前域名的所有子域名',
defaultHtml: '默认页面',
website404: '网站 404 错误页',
domain404: '网站不存在页',
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 446d6f197889..c8d228070636 100644
--- a/frontend/src/views/website/website/config/basic/https/index.vue
+++ b/frontend/src/views/website/website/config/basic/https/index.vue
@@ -29,6 +29,18 @@
{{ $t('commons.button.enable') }}
{{ $t('website.hstsHelper') }}
+
+
+ {{ $t('commons.button.enable') }}
+
+
+ {{ $t('website.hstsIncludeSubDomainsHelper') }}
+
+
{{ $t('commons.button.enable') }}
{{ $t('website.http3Helper') }}
@@ -205,6 +217,7 @@ const form = reactive({
certificatePath: '',
httpConfig: 'HTTPToHTTPS',
hsts: true,
+ hstsIncludeSubDomains: false,
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'],
@@ -314,6 +327,7 @@ const get = () => {
form.acmeAccountID = data.SSL.acmeAccountId;
}
form.hsts = data.hsts;
+ form.hstsIncludeSubDomains = data.hstsIncludeSubDomains || false;
form.http3 = data.http3;
form.httpsPort = data.httpsPort;
}
@@ -344,6 +358,8 @@ const changeEnable = (enable: boolean) => {
if (enable) {
listSSLs();
form.hsts = true;
+ } else {
+ form.hstsIncludeSubDomains = false;
}
if (resData.value.enable && !enable) {
ElMessageBox.confirm(i18n.global.t('website.disableHTTPSHelper'), i18n.global.t('website.disableHTTPS'), {