fix: fix issue with enable website ssl with ipv6 failed (#9255)

This commit is contained in:
CityFun 2025-06-24 13:44:17 +08:00 committed by GitHub
parent af4b23e0e0
commit 193ae2b7d6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 101 additions and 109 deletions

View file

@ -922,18 +922,12 @@ func (w WebsiteService) GetWebsiteHTTPS(websiteId uint) (response.WebsiteHTTPS,
res response.WebsiteHTTPS res response.WebsiteHTTPS
httpsPorts []string httpsPorts []string
) )
websiteDomains, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithWebsiteId(websiteId))
for _, domain := range websiteDomains { httpsPortsMap := getHttpsPort(websiteId)
if domain.SSL { for port := range httpsPortsMap {
httpsPorts = append(httpsPorts, strconv.Itoa(domain.Port)) httpsPorts = append(httpsPorts, strconv.Itoa(port))
} }
}
if len(httpsPorts) == 0 {
nginxInstall, _ := getAppInstallByKey(constant.AppOpenresty)
res.HttpsPort = strconv.Itoa(nginxInstall.HttpsPort)
} else {
res.HttpsPort = strings.Join(httpsPorts, ",") res.HttpsPort = strings.Join(httpsPorts, ",")
}
if website.WebsiteSSLID == 0 { if website.WebsiteSSLID == 0 {
res.Enable = false res.Enable = false
return res, nil return res, nil
@ -981,10 +975,6 @@ func (w WebsiteService) OpWebsiteHTTPS(ctx context.Context, req request.WebsiteH
res response.WebsiteHTTPS res response.WebsiteHTTPS
websiteSSL model.WebsiteSSL websiteSSL model.WebsiteSSL
) )
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
if err != nil {
return nil, err
}
if err = ChangeHSTSConfig(req.Hsts, req.Http3, website); err != nil { if err = ChangeHSTSConfig(req.Hsts, req.Http3, website); err != nil {
return nil, err return nil, err
} }
@ -995,24 +985,27 @@ func (w WebsiteService) OpWebsiteHTTPS(ctx context.Context, req request.WebsiteH
website.Protocol = constant.ProtocolHTTP website.Protocol = constant.ProtocolHTTP
website.WebsiteSSLID = 0 website.WebsiteSSLID = 0
httpsPorts, err := getHttpsPort(&website) websiteDomains, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithWebsiteId(website.ID))
ports := make(map[int]struct{})
for _, domain := range websiteDomains {
ports[domain.Port] = struct{}{}
}
for port := range ports {
if err = removeSSLListen(website, []string{strconv.Itoa(port)}); err != nil {
return nil, err
}
}
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if len(httpsPorts) == 1 && httpsPorts[0] == nginxInstall.HttpsPort { if _, ok := ports[nginxInstall.HttpsPort]; !ok {
httpsPortStr := strconv.Itoa(httpsPorts[0]) httpsPortStr := strconv.Itoa(nginxInstall.HttpsPort)
if err = deleteListenAndServerName(website, []string{httpsPortStr, "[::]:" + httpsPortStr}, []string{}); err != nil { if err = deleteListenAndServerName(website, []string{httpsPortStr, "[::]:" + httpsPortStr}, []string{}); err != nil {
return nil, err return nil, err
} }
} else {
for _, port := range httpsPorts {
httpsPortStr := strconv.Itoa(port)
if err = removeSSLListen(website, []string{httpsPortStr}); err != nil {
return nil, err
} }
}
}
nginxParams := getNginxParamsFromStaticFile(dto.SSL, nil) nginxParams := getNginxParamsFromStaticFile(dto.SSL, nil)
nginxParams = append(nginxParams, nginxParams = append(nginxParams,
dto.NginxParam{ dto.NginxParam{

View file

@ -651,22 +651,33 @@ func createPemFile(website model.Website, websiteSSL model.WebsiteSSL) error {
return nil return nil
} }
func getHttpsPort(website *model.Website) ([]int, error) { func getHttpsPort(websiteID uint) map[int]struct{} {
websiteDomains, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithWebsiteId(website.ID)) domains, err := websiteDomainRepo.GetBy(websiteDomainRepo.WithWebsiteId(websiteID))
var httpsPorts []int if err != nil {
for _, domain := range websiteDomains { return nil
if domain.SSL {
httpsPorts = append(httpsPorts, domain.Port)
} }
httpsPorts := make(map[int]struct{})
nginxInstall, _ := getAppInstallByKey(constant.AppOpenresty)
hasDefaultPort := false
for _, domain := range domains {
if domain.Port == nginxInstall.HttpPort {
hasDefaultPort = true
}
if domain.SSL {
httpsPorts[domain.Port] = struct{}{}
}
}
if hasDefaultPort {
httpsPorts[nginxInstall.HttpsPort] = struct{}{}
} }
if len(httpsPorts) == 0 { if len(httpsPorts) == 0 {
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty) for _, domain := range domains {
if err != nil { if !domain.SSL {
return nil, err httpsPorts[domain.Port] = struct{}{}
} }
httpsPorts = append(httpsPorts, nginxInstall.HttpsPort)
} }
return httpsPorts, nil }
return httpsPorts
} }
func applySSL(website *model.Website, websiteSSL model.WebsiteSSL, req request.WebsiteHTTPSOp) error { func applySSL(website *model.Website, websiteSSL model.WebsiteSSL, req request.WebsiteHTTPSOp) error {
@ -678,63 +689,71 @@ func applySSL(website *model.Website, websiteSSL model.WebsiteSSL, req request.W
if err != nil { if err != nil {
return nil return nil
} }
noDefaultPort := true
httpPorts := make(map[int]struct{}) httpPorts := make(map[int]struct{})
httpsPorts := make(map[int]struct{})
hasDefaultPort := false
for _, domain := range domains { for _, domain := range domains {
if domain.Port == 80 { if domain.Port == nginxFull.Install.HttpPort {
noDefaultPort = false hasDefaultPort = true
} }
if domain.Port != 80 && !domain.SSL { if domain.SSL {
httpsPorts[domain.Port] = struct{}{}
} else {
httpPorts[domain.Port] = struct{}{} httpPorts[domain.Port] = struct{}{}
} }
} }
if hasDefaultPort {
httpsPorts[nginxFull.Install.HttpsPort] = struct{}{}
}
if len(httpsPorts) == 0 {
for port := range httpPorts {
httpsPorts[port] = struct{}{}
}
}
config := nginxFull.SiteConfig.Config config := nginxFull.SiteConfig.Config
server := config.FindServers()[0] server := config.FindServers()[0]
httpPort := strconv.Itoa(nginxFull.Install.HttpPort) defaultHttpPort := strconv.Itoa(nginxFull.Install.HttpPort)
httpsPort, err := getHttpsPort(website) defaultHttpPortIPV6 := "[::]:" + defaultHttpPort
if err != nil {
return err
}
httpPortIPV6 := "[::]:" + httpPort
for _, port := range httpsPort { for port := range httpsPorts {
if _, ok := httpPorts[port]; !ok { portStr := strconv.Itoa(port)
server.DeleteListen(strconv.Itoa(port)) server.RemoveListenByBind(portStr)
} server.RemoveListenByBind("[::]:" + portStr)
setListen(server, strconv.Itoa(port), website.IPV6, req.Http3, website.DefaultServer, true) setListen(server, portStr, website.IPV6, req.Http3, website.DefaultServer, true)
} }
server.UpdateDirective("http2", []string{"on"}) server.UpdateDirective("http2", []string{"on"})
switch req.HttpConfig { switch req.HttpConfig {
case constant.HTTPSOnly: case constant.HTTPSOnly:
server.RemoveListenByBind(httpPort) server.RemoveListenByBind(defaultHttpPort)
server.RemoveListenByBind(httpPortIPV6) server.RemoveListenByBind(defaultHttpPortIPV6)
server.RemoveDirective("if", []string{"($scheme"}) server.RemoveDirective("if", []string{"($scheme"})
case constant.HTTPToHTTPS: case constant.HTTPToHTTPS:
if !noDefaultPort { if hasDefaultPort {
server.UpdateListen(httpPort, website.DefaultServer) server.UpdateListen(defaultHttpPort, website.DefaultServer)
}
if website.IPV6 { if website.IPV6 {
server.UpdateListen(httpPortIPV6, website.DefaultServer) server.UpdateListen(defaultHttpPortIPV6, website.DefaultServer)
}
} }
server.AddHTTP2HTTPS() server.AddHTTP2HTTPS()
case constant.HTTPAlso: case constant.HTTPAlso:
if !noDefaultPort { if hasDefaultPort {
server.UpdateListen(httpPort, website.DefaultServer) server.UpdateListen(defaultHttpPort, website.DefaultServer)
if website.IPV6 {
server.UpdateListen(defaultHttpPortIPV6, website.DefaultServer)
}
} }
server.RemoveDirective("if", []string{"($scheme"}) server.RemoveDirective("if", []string{"($scheme"})
if website.IPV6 {
server.UpdateListen(httpPortIPV6, website.DefaultServer)
}
} }
if !req.Hsts { 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\""})
} }
if !req.Http3 { if !req.Http3 {
for _, port := range httpsPort { for port := range httpsPorts {
server.RemoveListen(strconv.Itoa(port), "quic") server.RemoveListen(strconv.Itoa(port), "quic")
if website.IPV6 { if website.IPV6 {
httpsPortIPV6 := "[::]:" + strconv.Itoa(port) httpsPortIPV6 := "[::]:" + strconv.Itoa(port)

View file

@ -2416,8 +2416,6 @@ const message = {
enableSSLHelper: 'Failure to enable will not affect the creation of the website', enableSSLHelper: 'Failure to enable will not affect the creation of the website',
batchAdd: 'Batch Add Domains', batchAdd: 'Batch Add Domains',
generateDomain: 'Generate', generateDomain: 'Generate',
domainSSLHelper:
'Enabling SSL on a non-443 port will cause the 443 port to stop listening. If you need the 443 port to continue listening, please add the domain:443',
global: 'Global', global: 'Global',
subsite: 'Subsite', subsite: 'Subsite',
subsiteHelper: 'A subsite can select an existing PHP or static website directory as the main directory.', subsiteHelper: 'A subsite can select an existing PHP or static website directory as the main directory.',

View file

@ -2331,8 +2331,6 @@ const message = {
enableSSLHelper: 'SSLの有効化に失敗してもウェブサイトの作成には影響しません', enableSSLHelper: 'SSLの有効化に失敗してもウェブサイトの作成には影響しません',
batchAdd: 'ドメインを一括追加', batchAdd: 'ドメインを一括追加',
generateDomain: '生成', generateDomain: '生成',
domainSSLHelper:
'443以外のポートでSSLを有効にすると443ポートのリスナーが削除されます443ポートを引き続きリスニングするにはドメイン:443を追加してください',
global: 'グローバル', global: 'グローバル',
subsite: 'サブサイト', subsite: 'サブサイト',
subsiteHelper: subsiteHelper:

View file

@ -2291,8 +2291,6 @@ const message = {
enableSSLHelper: 'SSL 활성화 실패는 웹사이트 생성에 영향을 미치지 않습니다.', enableSSLHelper: 'SSL 활성화 실패는 웹사이트 생성에 영향을 미치지 않습니다.',
batchAdd: '도메인 일괄 추가', batchAdd: '도메인 일괄 추가',
generateDomain: '생성', generateDomain: '생성',
domainSSLHelper:
'443 아닌 포트에서 SSL을 활성화하면 443 포트 리스너가 제거됩니다. 443 포트를 계속 리스닝하려면 도메인:443 추가하세요.',
global: '글로벌', global: '글로벌',
subsite: '하위 사이트', subsite: '하위 사이트',
subsiteHelper: '하위 사이트는 기존 PHP 또는 정적 웹사이트의 디렉토리를 루트 디렉토리로 선택할 있습니다.', subsiteHelper: '하위 사이트는 기존 PHP 또는 정적 웹사이트의 디렉토리를 루트 디렉토리로 선택할 있습니다.',

View file

@ -2384,8 +2384,6 @@ const message = {
enableSSLHelper: 'Kegagalan mengaktifkan SSL tidak akan menjejaskan penciptaan laman web.', enableSSLHelper: 'Kegagalan mengaktifkan SSL tidak akan menjejaskan penciptaan laman web.',
batchAdd: 'Tambah Domain Secara Batch', batchAdd: 'Tambah Domain Secara Batch',
generateDomain: 'Hasilkan', generateDomain: 'Hasilkan',
domainSSLHelper:
'Mengaktifkan SSL pada port selain 443 akan menghapus pendengar port 443. Untuk terus mendengar port 443, sila tambah domain:443.',
global: 'Global', global: 'Global',
subsite: 'Sublaman', subsite: 'Sublaman',
subsiteHelper: subsiteHelper:

View file

@ -2381,8 +2381,6 @@ const message = {
enableSSLHelper: 'A falha ao ativar o SSL não afetará a criação do site.', enableSSLHelper: 'A falha ao ativar o SSL não afetará a criação do site.',
batchAdd: 'Adicionar Domínios em Lote', batchAdd: 'Adicionar Domínios em Lote',
generateDomain: 'Gerar', generateDomain: 'Gerar',
domainSSLHelper:
'Ativar o SSL em portas que não sejam a 443 removerá o ouvinte da porta 443. Para manter a porta 443 ouvindo, adicione o domínio:443.',
global: 'Global', global: 'Global',
subsite: 'Subsite', subsite: 'Subsite',
subsiteHelper: subsiteHelper:

View file

@ -2379,8 +2379,6 @@ const message = {
enableSSLHelper: 'Неудача при включении SSL не повлияет на создание сайта.', enableSSLHelper: 'Неудача при включении SSL не повлияет на создание сайта.',
batchAdd: 'Пакетное Добавление Доменов', batchAdd: 'Пакетное Добавление Доменов',
generateDomain: 'Сгенерировать', generateDomain: 'Сгенерировать',
domainSSLHelper:
'Включение SSL на портах, отличных от 443, удалит слушатель порта 443. Чтобы порт 443 продолжал прослушиваться, добавьте домен:443.',
global: 'Глобальный', global: 'Глобальный',
subsite: 'Подсайт', subsite: 'Подсайт',
subsiteHelper: subsiteHelper:

View file

@ -2255,7 +2255,6 @@ const message = {
enableSSLHelper: '開啟失敗不會影響網站創建', enableSSLHelper: '開啟失敗不會影響網站創建',
batchAdd: '批量添加域名', batchAdd: '批量添加域名',
generateDomain: '生成', generateDomain: '生成',
domainSSLHelper: ' 443 端口開啟 SSL 會導致 443 端口移除監聽如需 443 端口繼續監聽請添加域名:443',
global: '全局', global: '全局',
subsite: '子網站', subsite: '子網站',
subsiteHelper: '子網站可以選擇已存在的 PHP 和靜態網站的目錄作為主目錄', subsiteHelper: '子網站可以選擇已存在的 PHP 和靜態網站的目錄作為主目錄',

View file

@ -2243,7 +2243,6 @@ const message = {
enableSSLHelper: '开启失败不会影响网站创建', enableSSLHelper: '开启失败不会影响网站创建',
batchAdd: '批量添加域名', batchAdd: '批量添加域名',
generateDomain: '生成', generateDomain: '生成',
domainSSLHelper: ' 443 端口开启 SSL 会导致 443 端口去掉监听如需 443 端口继续监听请添加域名:443',
global: '全局', global: '全局',
subsite: '子网站', subsite: '子网站',
subsiteHelper: '子网站可以选择已存在的 PHP 和静态网站的目录作为主目录', subsiteHelper: '子网站可以选择已存在的 PHP 和静态网站的目录作为主目录',

View file

@ -2,7 +2,6 @@
<ComplexTable :data="data" @search="search" v-loading="loading" :heightDiff="400"> <ComplexTable :data="data" @search="search" v-loading="loading" :heightDiff="400">
<template #toolbar> <template #toolbar>
<el-button type="primary" plain @click="openCreate">{{ $t('website.addDomain') }}</el-button> <el-button type="primary" plain @click="openCreate">{{ $t('website.addDomain') }}</el-button>
<el-text type="info" class="!ml-2">{{ $t('website.domainSSLHelper') }}</el-text>
</template> </template>
<el-table-column width="30px"> <el-table-column width="30px">
<template #default="{ row }"> <template #default="{ row }">

View file

@ -55,6 +55,7 @@
label-width="125px" label-width="125px"
:rules="rules" :rules="rules"
:validate-on-rule-change="false" :validate-on-rule-change="false"
v-loading="loading"
> >
<el-form-item :label="$t('commons.table.group')" prop="webSiteGroupId"> <el-form-item :label="$t('commons.table.group')" prop="webSiteGroupId">
<el-select v-model="website.webSiteGroupId"> <el-select v-model="website.webSiteGroupId">
@ -888,7 +889,7 @@ const changeSSl = (sslid: number) => {
const submit = async (formEl: FormInstance | undefined) => { const submit = async (formEl: FormInstance | undefined) => {
if (!formEl) return; if (!formEl) return;
await formEl.validate((valid) => { await formEl.validate(async (valid) => {
if (!valid) { if (!valid) {
return; return;
} }
@ -897,10 +898,9 @@ const submit = async (formEl: FormInstance | undefined) => {
return; return;
} }
loading.value = true; loading.value = true;
preCheck({}) try {
.then((res) => { const res = await preCheck({});
if (res.data) { if (res.data) {
loading.value = false;
preCheckRef.value.acceptParams({ items: res.data }); preCheckRef.value.acceptParams({ items: res.data });
} else { } else {
if (website.value.type === 'proxy') { if (website.value.type === 'proxy') {
@ -912,20 +912,15 @@ const submit = async (formEl: FormInstance | undefined) => {
} }
const taskID = uuidv4(); const taskID = uuidv4();
website.value.taskID = taskID; website.value.taskID = taskID;
createWebsite(website.value) await createWebsite(website.value);
.then(() => {
MsgSuccess(i18n.global.t('commons.msg.createSuccess')); MsgSuccess(i18n.global.t('commons.msg.createSuccess'));
handleClose(); handleClose();
})
.finally(() => {
loading.value = false;
});
openTaskLog(taskID); openTaskLog(taskID);
} }
}) } catch (error) {
.catch(() => { } finally {
loading.value = false; loading.value = false;
}); }
}); });
}; };