diff --git a/core/app/dto/setting.go b/core/app/dto/setting.go index 6bc242f8a2e8..1b1ea449a0ea 100644 --- a/core/app/dto/setting.go +++ b/core/app/dto/setting.go @@ -64,7 +64,7 @@ type SettingUpdate struct { type SSLUpdate struct { SSLType string `json:"sslType" validate:"required,oneof=self select import import-paste import-local"` Domain string `json:"domain"` - SSL string `json:"ssl" validate:"required,oneof=Enable Disable"` + SSL string `json:"ssl" validate:"required,oneof=Enable Disable Mux"` Cert string `json:"cert"` Key string `json:"key"` SSLID uint `json:"sslID"` diff --git a/core/constant/status.go b/core/constant/status.go index b7d2755e93d6..b5ccc21df732 100644 --- a/core/constant/status.go +++ b/core/constant/status.go @@ -21,6 +21,7 @@ const ( StatusEnable = "Enable" StatusDisable = "Disable" + StatusMux = "Mux" StatusInstalling = "Installing" StatusNormal = "Normal" diff --git a/core/go.mod b/core/go.mod index 34196dc2f925..e05d5e0b2232 100644 --- a/core/go.mod +++ b/core/go.mod @@ -81,6 +81,7 @@ require ( github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/soheilhy/cmux v0.1.5 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect diff --git a/core/go.sum b/core/go.sum index c781495a5e7a..f12fe945cf42 100644 --- a/core/go.sum +++ b/core/go.sum @@ -250,6 +250,8 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0= github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M= +github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= +github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= @@ -342,6 +344,7 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -363,6 +366,7 @@ golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/core/server/server.go b/core/server/server.go index 4f673d826075..7c688db1dd7f 100644 --- a/core/server/server.go +++ b/core/server/server.go @@ -4,6 +4,11 @@ import ( "crypto/tls" "encoding/gob" "fmt" + "net" + "net/http" + "os" + "path" + "github.com/1Panel-dev/1Panel/core/init/auth" "github.com/1Panel-dev/1Panel/core/init/db" "github.com/1Panel-dev/1Panel/core/init/geo" @@ -12,10 +17,7 @@ import ( "github.com/1Panel-dev/1Panel/core/init/proxy" "github.com/1Panel-dev/1Panel/core/init/run" "github.com/gin-gonic/gin" - "net" - "net/http" - "os" - "path" + "github.com/soheilhy/cmux" "github.com/1Panel-dev/1Panel/core/constant" "github.com/1Panel-dev/1Panel/core/global" @@ -99,10 +101,64 @@ func Start() { if err := server.ServeTLS(tcpKeepAliveListener{ln.(*net.TCPListener)}, "", ""); err != nil { panic(err) } + return + } else if global.CONF.Conn.SSL == constant.StatusMux { + certPath := path.Join(global.CONF.Base.InstallDir, "1panel/secret/server.crt") + keyPath := path.Join(global.CONF.Base.InstallDir, "1panel/secret/server.key") + certificate, err := os.ReadFile(certPath) + if err != nil { + panic(err) + } + key, err := os.ReadFile(keyPath) + if err != nil { + panic(err) + } + cert, err := tls.X509KeyPair(certificate, key) + if err != nil { + panic(err) + } + constant.CertStore.Store(&cert) + + server.TLSConfig = &tls.Config{ + GetCertificate: func(info *tls.ClientHelloInfo) (*tls.Certificate, error) { + return constant.CertStore.Load().(*tls.Certificate), nil + }, + } + + global.LOG.Infof("listen at mux (http/https)://%s:%s [%s]", global.CONF.Conn.BindAddress, global.CONF.Conn.Port, tcpItem) + + m := cmux.New(ln) + + httpsL := m.Match(cmux.TLS()) + httpL := m.Match(cmux.Any()) + + go func() { + if err := server.Serve(tls.NewListener(httpsL, server.TLSConfig)); err != nil { + global.LOG.Errorf("HTTPS Serve Error: %v", err) + } + }() + + go func() { + redirectServer := &http.Server{ + Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + target := "https://" + r.Host + r.RequestURI + http.Redirect(w, r, target, http.StatusTemporaryRedirect) + }), + } + if err := redirectServer.Serve(httpL); err != nil { + global.LOG.Errorf("HTTP Redirect Serve Error: %v", err) + } + }() + + if err := m.Serve(); err != nil { + panic(err) + } + return } else { global.LOG.Infof("listen at http://%s:%s [%s]", global.CONF.Conn.BindAddress, global.CONF.Conn.Port, tcpItem) if err := server.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)}); err != nil { panic(err) } + return } } diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index b258a10bf259..7fd81e9bccf3 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -1995,7 +1995,7 @@ const message = { error444: 'Connection Closed', error500: 'Internal Server Error', - https: 'Setting up HTTPS protocol access for the panel can enhance the security of panel access.', + https: 'Setting up HTTPS for the panel improves access security.\nStrict mode blocks non-HTTPS traffic from reaching the panel.\nMux mode redirects HTTP to HTTPS, but may reduce security.', certType: 'Certificate type', selfSigned: 'Self signed', selfSignedHelper: `Browsers may not trust self-signed certificates and may display security warnings.`, diff --git a/frontend/src/lang/modules/es-es.ts b/frontend/src/lang/modules/es-es.ts index 1471d0b7cb2d..3a9fc56a14d7 100644 --- a/frontend/src/lang/modules/es-es.ts +++ b/frontend/src/lang/modules/es-es.ts @@ -2009,7 +2009,7 @@ const message = { error416: 'Rango no satisfactorio', error444: 'Conexión cerrada', error500: 'Error interno del servidor', - https: 'Configurar acceso al panel mediante protocolo HTTPS puede mejorar la seguridad del acceso.', + https: 'Configurar HTTPS en el panel mejora la seguridad de acceso.\nEn modo Strict, el tráfico sin HTTPS no puede conectarse al panel.\nEl modo Mux redirige HTTP a HTTPS, pero puede reducir la seguridad.', certType: 'Tipo de certificado', selfSigned: 'Autofirmado', selfSignedHelper: diff --git a/frontend/src/lang/modules/ja.ts b/frontend/src/lang/modules/ja.ts index 74d4b0a3a5e7..24c2cb399f0c 100644 --- a/frontend/src/lang/modules/ja.ts +++ b/frontend/src/lang/modules/ja.ts @@ -1921,7 +1921,7 @@ const message = { error444: '接続が閉じた', error500: 'サーバーエラー', - https: 'パネル用のHTTPSプロトコルアクセスをセットアップすると、パネルアクセスのセキュリティが強化されます。', + https: 'パネルに HTTPS を設定するとアクセスの安全性が向上します。\nStrict モードでは HTTPS 以外の通信はパネルに接続できません。\nMux モードは HTTP を HTTPS にリダイレクトしますが、安全性が低下する可能性があります。', certType: '証明書の種類', selfSigned: '自己署名', selfSignedHelper: `ブラウザは、自己署名の証明書を信頼していない場合があり、セキュリティ警告を表示する場合があります。`, diff --git a/frontend/src/lang/modules/ko.ts b/frontend/src/lang/modules/ko.ts index 3700609c8e6a..279c2a3be91e 100644 --- a/frontend/src/lang/modules/ko.ts +++ b/frontend/src/lang/modules/ko.ts @@ -1890,7 +1890,7 @@ const message = { error444: '연결 닫힘', error500: '서버 오류', - https: '패널의 HTTPS 프로토콜 접근 설정은 패널 접근 보안을 강화할 수 있습니다.', + https: '패널에 HTTPS를 설정하면 접근 보안이 향상됩니다.\nStrict 모드에서는 HTTPS가 아닌 트래픽이 패널에 연결할 수 없습니다.\nMux 모드는 HTTP를 HTTPS로 리다이렉트하지만 보안이 다소 낮아질 수 있습니다.', certType: '인증서 유형', selfSigned: '자가 서명', selfSignedHelper: '자가 서명 인증서는 브라우저에서 신뢰하지 않을 수 있으며 보안 경고가 표시될 수 있습니다.', diff --git a/frontend/src/lang/modules/ms.ts b/frontend/src/lang/modules/ms.ts index 4408bc2aaf94..4d5f4e675f7d 100644 --- a/frontend/src/lang/modules/ms.ts +++ b/frontend/src/lang/modules/ms.ts @@ -1977,7 +1977,7 @@ const message = { error444: 'Sambungan ditutup', error500: 'Ralat Pelayan', - https: 'Menetapkan protokol akses HTTPS untuk panel boleh meningkatkan keselamatan akses panel.', + https: 'Menetapkan HTTPS untuk panel meningkatkan keselamatan akses.\nDalam mod Strict, trafik bukan HTTPS tidak boleh menyambung ke panel.\nMod Mux mengalih hala HTTP ke HTTPS, tetapi mungkin mengurangkan keselamatan.', certType: 'Jenis sijil', selfSigned: 'Diterbitkan sendiri', selfSignedHelper: diff --git a/frontend/src/lang/modules/pt-br.ts b/frontend/src/lang/modules/pt-br.ts index fa57af207e32..81bded4184de 100644 --- a/frontend/src/lang/modules/pt-br.ts +++ b/frontend/src/lang/modules/pt-br.ts @@ -1965,7 +1965,7 @@ const message = { error444: 'Conexão fechada', error500: 'Erro no servidor', - https: 'Configurar o acesso via protocolo HTTPS para o painel pode melhorar a segurança do acesso ao painel.', + https: 'Configurar HTTPS no painel melhora a segurança de acesso.\nNo modo Strict, tráfego sem HTTPS não consegue se conectar ao painel.\nO modo Mux redireciona HTTP para HTTPS, mas pode reduzir a segurança.', certType: 'Tipo de certificado', selfSigned: 'Autoassinado', selfSignedHelper: diff --git a/frontend/src/lang/modules/ru.ts b/frontend/src/lang/modules/ru.ts index 9e93eda53c46..22bf7b0169ad 100644 --- a/frontend/src/lang/modules/ru.ts +++ b/frontend/src/lang/modules/ru.ts @@ -1963,7 +1963,7 @@ const message = { error444: 'Соединение закрыто', error500: 'Ошибка сервера', - https: 'Настройка доступа по протоколу HTTPS для панели может повысить безопасность доступа к панели.', + https: 'Настройка HTTPS для панели повышает безопасность доступа.\nВ режиме Strict трафик без HTTPS не может подключиться к панели.\nРежим Mux перенаправляет HTTP на HTTPS, но может снизить безопасность.', certType: 'Тип сертификата', selfSigned: 'Самоподписанный', selfSignedHelper: diff --git a/frontend/src/lang/modules/tr.ts b/frontend/src/lang/modules/tr.ts index 9d2ef4e5ab8e..829601003f9f 100644 --- a/frontend/src/lang/modules/tr.ts +++ b/frontend/src/lang/modules/tr.ts @@ -2018,7 +2018,7 @@ const message = { error416: 'Aralık Karşılanamadı', error444: 'Bağlantı Kapalı', error500: 'Dahili Sunucu Hatası', - https: 'Panel için HTTPS protokolü erişimini ayarlamak, panel erişiminin güvenliğini artırabilir.', + https: 'Panel için HTTPS ayarlamak erişim güvenliğini artırır.\nStrict modda HTTPS olmayan trafik panele bağlanamaz.\nMux modu HTTP\'yi HTTPS\'e yönlendirir, ancak güvenliği biraz azaltabilir.', certType: 'Sertifika türü', selfSigned: 'Kendi kendine imzalı', selfSignedHelper: diff --git a/frontend/src/lang/modules/zh-Hant.ts b/frontend/src/lang/modules/zh-Hant.ts index 05bae443c835..a71fb48bc057 100644 --- a/frontend/src/lang/modules/zh-Hant.ts +++ b/frontend/src/lang/modules/zh-Hant.ts @@ -1944,7 +1944,7 @@ const message = { error444: '連線已關閉', error500: '內部伺服器錯誤', - https: '為面板設定 https 協議訪問,提升面板訪問安全性', + https: '為面板設定 HTTPS 可提升訪問安全性 \nStrict 模式下非 HTTPS 流量無法連接面板\nMux 模式會將 HTTP 重新導向到 HTTPS,但可能會降低安全性', certType: '證書類型', selfSigned: '自簽名', selfSignedHelper: '自簽證書,不被瀏覽器信任,顯示不安全是正常現象', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index 03c4f72f6a8f..a73f72158b0f 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -1943,7 +1943,7 @@ const message = { error444: '连接被关闭', error500: '内部错误', - https: '为面板设置 https 协议访问,提升面板访问安全性', + https: '为面板设置HTTPS可提升访问安全性 \n Strict模式下非HTTPS流量无法连接面板\nMux模式会将 HTTP 重定向到 HTTPS ,但可能会降低安全性', certType: '证书类型', selfSigned: '自签名', selfSignedHelper: '自签证书,不被浏览器信任,显示不安全是正常现象', diff --git a/frontend/src/views/setting/safe/index.vue b/frontend/src/views/setting/safe/index.vue index a7b8c0d7b548..1b64b68a6f97 100644 --- a/frontend/src/views/setting/safe/index.vue +++ b/frontend/src/views/setting/safe/index.vue @@ -104,14 +104,13 @@ - + + {{ $t('setting.sslDisable') }} + {{ $t('commons.button.enable') }} (Strict) + {{ $t('commons.button.enable') }} (Mux) + {{ $t('setting.https') }} -
+
{{ $t('setting.domainOrIP') }} {{ sslInfo.domain }} {{ $t('setting.timeOut') }} {{ sslInfo.timeout }} @@ -210,6 +209,7 @@ const mfaRef = ref(); const responseRef = ref(); const sslRef = ref(); +const lastSSL = ref('Disable'); const sslInfo = ref(); const domainRef = ref(); const allowIPsRef = ref(); @@ -243,8 +243,9 @@ const search = async () => { form.ipv6 = res.data.ipv6; form.bindAddress = res.data.bindAddress; form.ssl = res.data.ssl; + lastSSL.value = form.ssl; form.sslType = res.data.sslType; - if (form.ssl === 'Enable') { + if (form.ssl !== 'Disable') { loadInfo(); } form.securityEntrance = res.data.securityEntrance; @@ -326,7 +327,7 @@ const onChangeAllowIPs = () => { allowIPsRef.value.acceptParams({ allowIPs: form.allowIPs }); }; const handleSSL = async () => { - if (form.ssl === 'Enable') { + if (form.ssl !== 'Disable') { let params = { ssl: form.ssl, sslType: form.sslType, @@ -343,6 +344,7 @@ const handleSSL = async () => { .then(async () => { await updateSSL({ ssl: 'Disable', domain: '', sslType: form.sslType, key: '', cert: '', sslID: 0 }); MsgSuccess(i18n.global.t('commons.msg.operationSuccess')); + lastSSL.value = 'Disable'; let href = window.location.href; globalStore.isLogin = false; let address = href.split('://')[1]; @@ -356,7 +358,7 @@ const handleSSL = async () => { }, 1000); }) .catch(() => { - form.ssl = 'Enable'; + form.ssl = lastSSL.value; }); }; diff --git a/frontend/src/views/setting/safe/ssl/index.vue b/frontend/src/views/setting/safe/ssl/index.vue index a12fb55f3e81..92ca7366c346 100644 --- a/frontend/src/views/setting/safe/ssl/index.vue +++ b/frontend/src/views/setting/safe/ssl/index.vue @@ -158,10 +158,12 @@ const sslList = ref(); const itemSSL = ref(); interface DialogProps { + ssl: string; sslType: string; sslInfo?: Setting.SSLInfo; } const acceptParams = async (params: DialogProps): Promise => { + form.ssl = params.ssl; if (params.sslType.indexOf('-') !== -1) { form.sslType = 'import'; form.itemSSLType = params.sslType.split('-')[1]; @@ -232,7 +234,7 @@ const onSaveSSL = async (formEl: FormInstance | undefined) => { itemType = form.itemSSLType === 'paste' ? 'import-paste' : 'import-local'; } let param = { - ssl: 'Enable', + ssl: form.ssl, sslType: itemType, domain: '', sslID: form.sslID,