mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-03-16 18:54:43 +08:00
feat:网站 HTTPS 增加 HSTS 配置 (#5463)
Refs https://github.com/1Panel-dev/1Panel/issues/3906
This commit is contained in:
parent
b428d818e7
commit
b36e2c5676
@ -123,6 +123,7 @@ type WebsiteHTTPSOp struct {
|
|||||||
HttpConfig string `json:"httpConfig" validate:"oneof=HTTPSOnly HTTPAlso HTTPToHTTPS"`
|
HttpConfig string `json:"httpConfig" validate:"oneof=HTTPSOnly HTTPAlso HTTPToHTTPS"`
|
||||||
SSLProtocol []string `json:"SSLProtocol"`
|
SSLProtocol []string `json:"SSLProtocol"`
|
||||||
Algorithm string `json:"algorithm"`
|
Algorithm string `json:"algorithm"`
|
||||||
|
Hsts bool `json:"hsts"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type WebsiteNginxUpdate struct {
|
type WebsiteNginxUpdate struct {
|
||||||
|
@ -37,6 +37,7 @@ type WebsiteHTTPS struct {
|
|||||||
SSL model.WebsiteSSL `json:"SSL"`
|
SSL model.WebsiteSSL `json:"SSL"`
|
||||||
SSLProtocol []string `json:"SSLProtocol"`
|
SSLProtocol []string `json:"SSLProtocol"`
|
||||||
Algorithm string `json:"algorithm"`
|
Algorithm string `json:"algorithm"`
|
||||||
|
Hsts bool `json:"hsts"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type WebsiteLog struct {
|
type WebsiteLog struct {
|
||||||
|
@ -754,7 +754,7 @@ func (w WebsiteService) GetWebsiteHTTPS(websiteId uint) (response.WebsiteHTTPS,
|
|||||||
} else {
|
} else {
|
||||||
res.HttpConfig = constant.HTTPToHTTPS
|
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 {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
@ -765,6 +765,9 @@ func (w WebsiteService) GetWebsiteHTTPS(websiteId uint) (response.WebsiteHTTPS,
|
|||||||
if p.Name == "ssl_ciphers" {
|
if p.Name == "ssl_ciphers" {
|
||||||
res.Algorithm = p.Params[0]
|
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
|
return res, nil
|
||||||
}
|
}
|
||||||
@ -782,7 +785,7 @@ func (w WebsiteService) OpWebsiteHTTPS(ctx context.Context, req request.WebsiteH
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err = ChangeHSTSConfig(req.Enable, nginxInstall, website); err != nil {
|
if err = ChangeHSTSConfig(req.Hsts, nginxInstall, website); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
res.Enable = req.Enable
|
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_pass", []string{req.ProxyPass})
|
||||||
location.UpdateDirective("proxy_set_header", []string{"Host", req.ProxyHost})
|
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)
|
location.ChangePath(req.Modifier, req.Match)
|
||||||
if req.Cache {
|
if req.Cache {
|
||||||
location.AddCache(req.CacheTime, req.CacheUnit)
|
location.AddCache(req.CacheTime, req.CacheUnit)
|
||||||
|
@ -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 {
|
if err := nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -630,6 +634,13 @@ func applySSL(website model.Website, websiteSSL model.WebsiteSSL, req request.We
|
|||||||
nginxParams[i].Params = []string{req.Algorithm}
|
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 {
|
if err := updateNginxConfig(constant.NginxScopeServer, nginxParams, &website); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@ ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDS
|
|||||||
ssl_prefer_server_ciphers on;
|
ssl_prefer_server_ciphers on;
|
||||||
ssl_session_cache shared:SSL:10m;
|
ssl_session_cache shared:SSL:10m;
|
||||||
ssl_session_timeout 10m;
|
ssl_session_timeout 10m;
|
||||||
add_header Strict-Transport-Security "max-age=31536000";
|
|
||||||
error_page 497 https://$host$request_uri;
|
error_page 497 https://$host$request_uri;
|
||||||
proxy_set_header X-Forwarded-Proto https;
|
proxy_set_header X-Forwarded-Proto https;
|
||||||
ssl_stapling on;
|
ssl_stapling on;
|
||||||
|
@ -263,6 +263,7 @@ export namespace Website {
|
|||||||
httpConfig: string;
|
httpConfig: string;
|
||||||
SSLProtocol: string[];
|
SSLProtocol: string[];
|
||||||
algorithm: string;
|
algorithm: string;
|
||||||
|
hsts: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CheckReq {
|
export interface CheckReq {
|
||||||
|
@ -2026,6 +2026,7 @@ const message = {
|
|||||||
websiteBackupWarn:
|
websiteBackupWarn:
|
||||||
'Only supports importing local backups, importing backups from other machines may cause recovery failure',
|
'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',
|
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: {
|
php: {
|
||||||
short_open_tag: 'Short tag support',
|
short_open_tag: 'Short tag support',
|
||||||
|
@ -1887,6 +1887,7 @@ const message = {
|
|||||||
rewriteHelper2: '從應用程式商店安裝的 WordPress 等應用,預設已經配置好偽靜態,重複配置可能會報錯',
|
rewriteHelper2: '從應用程式商店安裝的 WordPress 等應用,預設已經配置好偽靜態,重複配置可能會報錯',
|
||||||
websiteBackupWarn: '僅支援導入本機備份,導入其他機器備份可能會恢復失敗',
|
websiteBackupWarn: '僅支援導入本機備份,導入其他機器備份可能會恢復失敗',
|
||||||
ipWebsiteWarn: 'IP 為網域名稱的網站,需要設定為預設網站才能正常存取',
|
ipWebsiteWarn: 'IP 為網域名稱的網站,需要設定為預設網站才能正常存取',
|
||||||
|
hstsHelper: '開啟 HSTS 可以增加網站安全性',
|
||||||
},
|
},
|
||||||
php: {
|
php: {
|
||||||
short_open_tag: '短標簽支持',
|
short_open_tag: '短標簽支持',
|
||||||
|
@ -1888,6 +1888,7 @@ const message = {
|
|||||||
rewriteHelper2: '从应用商店安装的 WordPress 等应用,默认已经配置好伪静态,重复配置可能会报错',
|
rewriteHelper2: '从应用商店安装的 WordPress 等应用,默认已经配置好伪静态,重复配置可能会报错',
|
||||||
websiteBackupWarn: '仅支持导入本机备份,导入其他机器备份可能会恢复失败',
|
websiteBackupWarn: '仅支持导入本机备份,导入其他机器备份可能会恢复失败',
|
||||||
ipWebsiteWarn: 'IP 为域名的网站,需要设置为默认站点才能正常访问',
|
ipWebsiteWarn: 'IP 为域名的网站,需要设置为默认站点才能正常访问',
|
||||||
|
hstsHelper: '开启 HSTS 可以增加网站安全性',
|
||||||
},
|
},
|
||||||
php: {
|
php: {
|
||||||
short_open_tag: '短标签支持',
|
short_open_tag: '短标签支持',
|
||||||
|
@ -22,6 +22,10 @@
|
|||||||
<el-option :label="$t('website.HTTPSOnly')" :value="'HTTPSOnly'"></el-option>
|
<el-option :label="$t('website.HTTPSOnly')" :value="'HTTPSOnly'"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item :label="'HSTS'" prop="hsts">
|
||||||
|
<el-checkbox v-model="form.hsts">{{ $t('commons.button.start') }}</el-checkbox>
|
||||||
|
<span class="input-help">{{ $t('website.hstsHelper') }}</span>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item :label="$t('website.sslConfig')" prop="type">
|
<el-form-item :label="$t('website.sslConfig')" prop="type">
|
||||||
<el-select v-model="form.type" @change="changeType(form.type)">
|
<el-select v-model="form.type" @change="changeType(form.type)">
|
||||||
<el-option :label="$t('website.oldSSL')" :value="'existed'"></el-option>
|
<el-option :label="$t('website.oldSSL')" :value="'existed'"></el-option>
|
||||||
@ -190,6 +194,7 @@ const form = reactive({
|
|||||||
privateKeyPath: '',
|
privateKeyPath: '',
|
||||||
certificatePath: '',
|
certificatePath: '',
|
||||||
httpConfig: 'HTTPToHTTPS',
|
httpConfig: 'HTTPToHTTPS',
|
||||||
|
hsts: true,
|
||||||
algorithm:
|
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',
|
'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'],
|
SSLProtocol: ['TLSv1.3', 'TLSv1.2', 'TLSv1.1', 'TLSv1'],
|
||||||
@ -199,6 +204,7 @@ const ssls = ref();
|
|||||||
const acmeAccounts = ref();
|
const acmeAccounts = ref();
|
||||||
const websiteSSL = ref();
|
const websiteSSL = ref();
|
||||||
const rules = ref({
|
const rules = ref({
|
||||||
|
hsts: [Rules.requiredInput],
|
||||||
type: [Rules.requiredSelect],
|
type: [Rules.requiredSelect],
|
||||||
privateKey: [Rules.requiredInput],
|
privateKey: [Rules.requiredInput],
|
||||||
certificate: [Rules.requiredInput],
|
certificate: [Rules.requiredInput],
|
||||||
@ -285,6 +291,7 @@ const get = () => {
|
|||||||
websiteSSL.value = res.data.SSL;
|
websiteSSL.value = res.data.SSL;
|
||||||
form.acmeAccountID = res.data.SSL.acmeAccountId;
|
form.acmeAccountID = res.data.SSL.acmeAccountId;
|
||||||
}
|
}
|
||||||
|
form.hsts = res.data.hsts;
|
||||||
}
|
}
|
||||||
listSSL();
|
listSSL();
|
||||||
listAcmeAccount();
|
listAcmeAccount();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user