mirror of https://github.com/1Panel-dev/1Panel
feat: 节点证书验证启动
parent
865b6cba3f
commit
1e9494fa2b
|
@ -2,6 +2,8 @@ package migrations
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto/request"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/model"
|
||||
|
@ -9,6 +11,7 @@ import (
|
|||
"github.com/1Panel-dev/1Panel/agent/constant"
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/common"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/encrypt"
|
||||
|
||||
"github.com/go-gormigrate/gormigrate/v2"
|
||||
"gorm.io/gorm"
|
||||
|
@ -159,6 +162,24 @@ var InitSetting = &gormigrate.Migration{
|
|||
if err := tx.Create(&model.Setting{Key: "SnapshotIgnore", Value: "*.sock"}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := os.Stat(path.Join(global.CONF.System.DataDir, "ssl", "server.key")); err != nil {
|
||||
return err
|
||||
}
|
||||
serverKey, _ := os.ReadFile(path.Join(global.CONF.System.DataDir, "ssl", "server.key"))
|
||||
itemKey, _ := encrypt.StringEncrypt(string(serverKey))
|
||||
if err := tx.Create(&model.Setting{Key: "ServerKey", Value: itemKey}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := os.Stat(path.Join(global.CONF.System.DataDir, "ssl", "server.crt")); err != nil {
|
||||
return err
|
||||
}
|
||||
serverCrt, _ := os.ReadFile(path.Join(global.CONF.System.DataDir, "ssl", "server.crt"))
|
||||
itemCrt, _ := encrypt.StringEncrypt(string(serverCrt))
|
||||
if err := tx.Create(&model.Setting{Key: "ServerCert", Value: string(itemCrt)}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package router
|
|||
|
||||
import (
|
||||
"github.com/1Panel-dev/1Panel/agent/i18n"
|
||||
"github.com/1Panel-dev/1Panel/agent/middleware"
|
||||
rou "github.com/1Panel-dev/1Panel/agent/router"
|
||||
"github.com/gin-contrib/gzip"
|
||||
"github.com/gin-gonic/gin"
|
||||
|
@ -24,6 +25,7 @@ func Routers() *gin.Engine {
|
|||
PublicGroup.Static("/api/v1/images", "./uploads")
|
||||
}
|
||||
PrivateGroup := Router.Group("/api/v2")
|
||||
PrivateGroup.Use(middleware.Certificate())
|
||||
for _, router := range rou.RouterGroupApp {
|
||||
router.InitRouter(PrivateGroup)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package middleware
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/api/v1/helper"
|
||||
"github.com/1Panel-dev/1Panel/agent/constant"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func Certificate() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
if !c.Request.TLS.HandshakeComplete || len(c.Request.TLS.PeerCertificates) == 0 {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, errors.New("no such tls peer certificates"))
|
||||
return
|
||||
}
|
||||
cert := c.Request.TLS.PeerCertificates[0]
|
||||
if cert.Subject.CommonName != "panel_client" {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, fmt.Errorf("err certificate"))
|
||||
return
|
||||
}
|
||||
c.Next()
|
||||
}
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/repo"
|
||||
)
|
||||
|
||||
func LoadErrCode(errInfo string) int {
|
||||
settingRepo := repo.NewISettingRepo()
|
||||
codeVal, err := settingRepo.Get(settingRepo.WithByKey("NoAuthSetting"))
|
||||
if err != nil {
|
||||
return 500
|
||||
}
|
||||
|
||||
switch codeVal.Value {
|
||||
case "400":
|
||||
return http.StatusBadRequest
|
||||
case "401":
|
||||
return http.StatusUnauthorized
|
||||
case "403":
|
||||
return http.StatusForbidden
|
||||
case "404":
|
||||
return http.StatusNotFound
|
||||
case "408":
|
||||
return http.StatusRequestTimeout
|
||||
case "416":
|
||||
return http.StatusRequestedRangeNotSatisfiable
|
||||
default:
|
||||
return http.StatusOK
|
||||
}
|
||||
}
|
|
@ -1,10 +1,13 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/repo"
|
||||
"github.com/1Panel-dev/1Panel/agent/cron"
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
"github.com/1Panel-dev/1Panel/agent/i18n"
|
||||
|
@ -17,6 +20,7 @@ import (
|
|||
"github.com/1Panel-dev/1Panel/agent/init/router"
|
||||
"github.com/1Panel-dev/1Panel/agent/init/validator"
|
||||
"github.com/1Panel-dev/1Panel/agent/init/viper"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/encrypt"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
@ -40,7 +44,7 @@ func Start() {
|
|||
server := &http.Server{
|
||||
Handler: rootRouter,
|
||||
}
|
||||
if len(global.CurrentNode) == 0 || global.CurrentNode == "127.0.0.1" {
|
||||
if global.CurrentNode == "127.0.0.1" {
|
||||
_ = os.Remove("/tmp/agent.sock")
|
||||
listener, err := net.Listen("unix", "/tmp/agent.sock")
|
||||
if err != nil {
|
||||
|
@ -49,15 +53,28 @@ func Start() {
|
|||
_ = server.Serve(listener)
|
||||
} else {
|
||||
server.Addr = "0.0.0.0:9999"
|
||||
type tcpKeepAliveListener struct {
|
||||
*net.TCPListener
|
||||
}
|
||||
ln, err := net.Listen("tcp4", "0.0.0.0:9999")
|
||||
settingRepo := repo.NewISettingRepo()
|
||||
certItem, err := settingRepo.Get(settingRepo.WithByKey("ServerCert"))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
global.LOG.Info("listen at http://0.0.0.0:9999")
|
||||
if err := server.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)}); err != nil {
|
||||
cert, _ := encrypt.StringDecrypt(certItem.Value)
|
||||
keyItem, err := settingRepo.Get(settingRepo.WithByKey("ServerKey"))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
key, _ := encrypt.StringDecrypt(keyItem.Value)
|
||||
tlsCert, err := tls.X509KeyPair([]byte(cert), []byte(key))
|
||||
if err != nil {
|
||||
fmt.Printf("failed to load X.509 key pair: %s\n", err)
|
||||
return
|
||||
}
|
||||
server.TLSConfig = &tls.Config{
|
||||
Certificates: []tls.Certificate{tlsCert},
|
||||
ClientAuth: tls.RequireAnyClientCert,
|
||||
}
|
||||
global.LOG.Info("listen at https://0.0.0.0:9999")
|
||||
if err := server.ListenAndServeTLS("", ""); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ ErrTransform: "Type conversion failure: {{ .detail }}"
|
|||
ErrNotLogin: "User is not Login: {{ .detail }}"
|
||||
ErrPasswordExpired: "The current password has expired: {{ .detail }}"
|
||||
ErrNotSupportType: "The system does not support the current type: {{ .detail }}"
|
||||
ErrProxy: "Request error, please check the node status"
|
||||
ErrProxy: "Request error, please check the node status: {{ .detail }}"
|
||||
|
||||
#common
|
||||
ErrNameIsExist: "Name is already exist"
|
||||
|
|
|
@ -8,7 +8,7 @@ ErrTransform: "類型轉換失敗: {{ .detail }}"
|
|||
ErrNotLogin: "用戶未登入: {{ .detail }}"
|
||||
ErrPasswordExpired: "當前密碼已過期: {{ .detail }}"
|
||||
ErrNotSupportType: "系統暫不支持當前類型: {{ .detail }}"
|
||||
ErrProxy: "請求錯誤,請檢查該節點狀態"
|
||||
ErrProxy: "請求錯誤,請檢查該節點狀態: {{ .detail }}"
|
||||
|
||||
#common
|
||||
ErrNameIsExist: "名稱已存在"
|
||||
|
|
|
@ -8,7 +8,7 @@ ErrTransform: "类型转换失败: {{ .detail }}"
|
|||
ErrNotLogin: "用户未登录: {{ .detail }}"
|
||||
ErrPasswordExpired: "当前密码已过期: {{ .detail }}"
|
||||
ErrNotSupportType: "系统暂不支持当前类型: {{ .detail }}"
|
||||
ErrProxy: "请求错误,请检查该节点状态"
|
||||
ErrProxy: "请求错误,请检查该节点状态: {{ .detail }}"
|
||||
|
||||
#common
|
||||
ErrDemoEnvironment: "演示服务器,禁止此操作!"
|
||||
|
|
|
@ -6,12 +6,12 @@ import (
|
|||
"net"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/core/app/api/v1/helper"
|
||||
"github.com/1Panel-dev/1Panel/core/constant"
|
||||
"github.com/1Panel-dev/1Panel/core/xpack/utlis/proxy"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
|
@ -22,40 +22,35 @@ func Proxy() gin.HandlerFunc {
|
|||
return
|
||||
}
|
||||
currentNode := c.Request.Header.Get("CurrentNode")
|
||||
if currentNode == "127.0.0.1" {
|
||||
sockPath := "/tmp/agent.sock"
|
||||
if _, err := os.Stat(sockPath); err != nil {
|
||||
if len(currentNode) != 0 && currentNode != "127.0.0.1" {
|
||||
if err := proxy.Proxy(c, currentNode); err != nil {
|
||||
fmt.Println(err)
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrProxy, err)
|
||||
return
|
||||
}
|
||||
dialUnix := func() (conn net.Conn, err error) {
|
||||
return net.Dial("unix", sockPath)
|
||||
}
|
||||
transport := &http.Transport{
|
||||
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
return dialUnix()
|
||||
},
|
||||
}
|
||||
proxy := &httputil.ReverseProxy{
|
||||
Director: func(req *http.Request) {
|
||||
req.URL.Scheme = "http"
|
||||
req.URL.Host = "unix"
|
||||
},
|
||||
Transport: transport,
|
||||
}
|
||||
proxy.ServeHTTP(c.Writer, c.Request)
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
target, err := url.Parse(fmt.Sprintf("http://%s:9999", currentNode))
|
||||
if err != nil {
|
||||
sockPath := "/tmp/agent.sock"
|
||||
if _, err := os.Stat(sockPath); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrProxy, err)
|
||||
return
|
||||
}
|
||||
proxy := httputil.NewSingleHostReverseProxy(target)
|
||||
c.Request.Host = target.Host
|
||||
c.Request.URL.Scheme = target.Scheme
|
||||
c.Request.URL.Host = target.Host
|
||||
dialUnix := func() (conn net.Conn, err error) {
|
||||
return net.Dial("unix", sockPath)
|
||||
}
|
||||
transport := &http.Transport{
|
||||
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
return dialUnix()
|
||||
},
|
||||
}
|
||||
proxy := &httputil.ReverseProxy{
|
||||
Director: func(req *http.Request) {
|
||||
req.URL.Scheme = "http"
|
||||
req.URL.Host = "unix"
|
||||
},
|
||||
Transport: transport,
|
||||
}
|
||||
proxy.ServeHTTP(c.Writer, c.Request)
|
||||
c.Abort()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue