From d68a0b076bbedfbecd6e16e0778db589540d9281 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=98=AD?= <81747598+lan-yonghui@users.noreply.github.com> Date: Tue, 17 Jun 2025 11:56:53 +0800 Subject: [PATCH] feat: transfer some code (#9124) refs #9067 --- agent/app/api/v2/host_tool.go | 16 +- agent/app/api/v2/ssh.go | 16 +- agent/app/service/firewall.go | 19 +- agent/app/service/ftp.go | 24 +-- agent/app/service/image_repo.go | 5 +- agent/app/service/snapshot_recover.go | 4 +- agent/app/service/website_ca.go | 6 +- agent/utils/cloud_storage/client/cos.go | 14 +- agent/utils/firewall/client/info.go | 9 + agent/utils/firewall/client/iptables.go | 172 +++++++++++++++--- agent/utils/firewall/client/ufw.go | 36 ++-- core/utils/cloud_storage/client/cos.go | 14 +- frontend/src/components/task-list/index.vue | 2 +- .../views/cronjob/cronjob/operate/index.vue | 2 +- frontend/src/views/cronjob/library/index.vue | 2 +- frontend/src/views/home/index.vue | 14 +- .../src/views/host/file-management/index.vue | 4 +- frontend/src/views/host/ssh/log/log.vue | 2 +- frontend/src/views/log/login/index.vue | 2 +- frontend/src/views/log/operation/index.vue | 2 +- frontend/src/views/log/task/index.vue | 2 +- .../src/views/toolbox/supervisor/index.vue | 2 +- .../website/runtime/php/supervisor/index.vue | 2 +- 23 files changed, 265 insertions(+), 106 deletions(-) diff --git a/agent/app/api/v2/host_tool.go b/agent/app/api/v2/host_tool.go index 5e0891f26..7132163ef 100644 --- a/agent/app/api/v2/host_tool.go +++ b/agent/app/api/v2/host_tool.go @@ -13,7 +13,7 @@ import ( // @Success 200 {object} response.HostToolRes // @Security ApiKeyAuth // @Security Timestamp -// @Router /host/tool [post] +// @Router /hosts/tool [post] func (b *BaseApi) GetToolStatus(c *gin.Context) { var req request.HostToolReq if err := helper.CheckBindAndValidate(&req, c); err != nil { @@ -35,7 +35,7 @@ func (b *BaseApi) GetToolStatus(c *gin.Context) { // @Success 200 // @Security ApiKeyAuth // @Security Timestamp -// @Router /host/tool/create [post] +// @Router /hosts/tool/create [post] // @x-panel-log {"bodyKeys":["type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建 [type] 配置","formatEN":"create [type] config"} func (b *BaseApi) InitToolConfig(c *gin.Context) { var req request.HostToolCreate @@ -57,7 +57,7 @@ func (b *BaseApi) InitToolConfig(c *gin.Context) { // @Success 200 // @Security ApiKeyAuth // @Security Timestamp -// @Router /host/tool/operate [post] +// @Router /hosts/tool/operate [post] // @x-panel-log {"bodyKeys":["operate","type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"[operate] [type] ","formatEN":"[operate] [type]"} func (b *BaseApi) OperateTool(c *gin.Context) { var req request.HostToolReq @@ -79,7 +79,7 @@ func (b *BaseApi) OperateTool(c *gin.Context) { // @Success 200 {object} response.HostToolConfig // @Security ApiKeyAuth // @Security Timestamp -// @Router /host/tool/config [post] +// @Router /hosts/tool/config [post] // @x-panel-log {"bodyKeys":["operate"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"[operate] 主机工具配置文件 ","formatEN":"[operate] tool config"} func (b *BaseApi) OperateToolConfig(c *gin.Context) { var req request.HostToolConfig @@ -102,7 +102,7 @@ func (b *BaseApi) OperateToolConfig(c *gin.Context) { // @Success 200 {string} logContent // @Security ApiKeyAuth // @Security Timestamp -// @Router /host/tool/log [post] +// @Router /hosts/tool/log [post] func (b *BaseApi) GetToolLog(c *gin.Context) { var req request.HostToolLogReq if err := helper.CheckBindAndValidate(&req, c); err != nil { @@ -124,7 +124,7 @@ func (b *BaseApi) GetToolLog(c *gin.Context) { // @Success 200 // @Security ApiKeyAuth // @Security Timestamp -// @Router /host/tool/supervisor/process [post] +// @Router /hosts/tool/supervisor/process [post] // @x-panel-log {"bodyKeys":["operate"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"[operate] 守护进程 ","formatEN":"[operate] process"} func (b *BaseApi) OperateProcess(c *gin.Context) { var req request.SupervisorProcessConfig @@ -146,7 +146,7 @@ func (b *BaseApi) OperateProcess(c *gin.Context) { // @Success 200 {object} response.SupervisorProcessConfig // @Security ApiKeyAuth // @Security Timestamp -// @Router /host/tool/supervisor/process [get] +// @Router /hosts/tool/supervisor/process [get] func (b *BaseApi) GetProcess(c *gin.Context) { configs, err := hostToolService.GetSupervisorProcessConfig() if err != nil { @@ -163,7 +163,7 @@ func (b *BaseApi) GetProcess(c *gin.Context) { // @Success 200 {string} content // @Security ApiKeyAuth // @Security Timestamp -// @Router /host/tool/supervisor/process/file [post] +// @Router /hosts/tool/supervisor/process/file [post] // @x-panel-log {"bodyKeys":["operate"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"[operate] Supervisor 进程文件 ","formatEN":"[operate] Supervisor Process Config file"} func (b *BaseApi) GetProcessFile(c *gin.Context) { var req request.SupervisorProcessFileReq diff --git a/agent/app/api/v2/ssh.go b/agent/app/api/v2/ssh.go index 1a35324b2..9215d960c 100644 --- a/agent/app/api/v2/ssh.go +++ b/agent/app/api/v2/ssh.go @@ -11,7 +11,7 @@ import ( // @Success 200 {object} dto.SSHInfo // @Security ApiKeyAuth // @Security Timestamp -// @Router /host/ssh/search [post] +// @Router /hosts/ssh/search [post] func (b *BaseApi) GetSSHInfo(c *gin.Context) { info, err := sshService.GetSSHInfo() if err != nil { @@ -28,7 +28,7 @@ func (b *BaseApi) GetSSHInfo(c *gin.Context) { // @Success 200 // @Security ApiKeyAuth // @Security Timestamp -// @Router /host/ssh/operate [post] +// @Router /hosts/ssh/operate [post] // @x-panel-log {"bodyKeys":["operation"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"[operation] SSH ","formatEN":"[operation] SSH"} func (b *BaseApi) OperateSSH(c *gin.Context) { var req dto.Operate @@ -50,7 +50,7 @@ func (b *BaseApi) OperateSSH(c *gin.Context) { // @Success 200 // @Security ApiKeyAuth // @Security Timestamp -// @Router /host/ssh/update [post] +// @Router /hosts/ssh/update [post] // @x-panel-log {"bodyKeys":["key","value"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改 SSH 配置 [key] => [value]","formatEN":"update SSH setting [key] => [value]"} func (b *BaseApi) UpdateSSH(c *gin.Context) { var req dto.SSHUpdate @@ -72,7 +72,7 @@ func (b *BaseApi) UpdateSSH(c *gin.Context) { // @Success 200 // @Security ApiKeyAuth // @Security Timestamp -// @Router /host/conffile/update [post] +// @Router /hosts/conffile/update [post] // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改 SSH 配置文件","formatEN":"update SSH conf"} func (b *BaseApi) UpdateSSHByfile(c *gin.Context) { var req dto.SSHConf @@ -94,7 +94,7 @@ func (b *BaseApi) UpdateSSHByfile(c *gin.Context) { // @Success 200 // @Security ApiKeyAuth // @Security Timestamp -// @Router /host/ssh/generate [post] +// @Router /hosts/ssh/generate [post] // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"生成 SSH 密钥 ","formatEN":"generate SSH secret"} func (b *BaseApi) GenerateSSH(c *gin.Context) { var req dto.GenerateSSH @@ -116,7 +116,7 @@ func (b *BaseApi) GenerateSSH(c *gin.Context) { // @Success 200 {string} secret // @Security ApiKeyAuth // @Security Timestamp -// @Router /host/ssh/secret [post] +// @Router /hosts/ssh/secret [post] func (b *BaseApi) LoadSSHSecret(c *gin.Context) { var req dto.GenerateLoad if err := helper.CheckBindAndValidate(&req, c); err != nil { @@ -138,7 +138,7 @@ func (b *BaseApi) LoadSSHSecret(c *gin.Context) { // @Success 200 {object} dto.SSHLog // @Security ApiKeyAuth // @Security Timestamp -// @Router /host/ssh/log [post] +// @Router /hosts/ssh/log [post] func (b *BaseApi) LoadSSHLogs(c *gin.Context) { var req dto.SearchSSHLog if err := helper.CheckBindAndValidate(&req, c); err != nil { @@ -158,7 +158,7 @@ func (b *BaseApi) LoadSSHLogs(c *gin.Context) { // @Success 200 {string} conf // @Security ApiKeyAuth // @Security Timestamp -// @Router /host/ssh/conf [get] +// @Router /hosts/ssh/conf [get] func (b *BaseApi) LoadSSHConf(c *gin.Context) { data, err := sshService.LoadSSHConf() if err != nil { diff --git a/agent/app/service/firewall.go b/agent/app/service/firewall.go index 3be87a426..eb32139ae 100644 --- a/agent/app/service/firewall.go +++ b/agent/app/service/firewall.go @@ -182,6 +182,7 @@ func (u *FirewallService) OperateFirewall(operation string) error { if err != nil { return err } + needRestartDocker := false switch operation { case "start": if err := client.Start(); err != nil { @@ -191,26 +192,30 @@ func (u *FirewallService) OperateFirewall(operation string) error { _ = client.Stop() return err } - _, _ = cmd.RunDefaultWithStdoutBashC("systemctl restart docker") - return nil + needRestartDocker = true case "stop": if err := client.Stop(); err != nil { return err } - _, _ = cmd.RunDefaultWithStdoutBashC("systemctl restart docker") - return nil + needRestartDocker = true case "restart": if err := client.Restart(); err != nil { return err } - _, _ = cmd.RunDefaultWithStdoutBashC("systemctl restart docker") - return nil + needRestartDocker = true case "disablePing": return u.updatePingStatus("0") case "enablePing": return u.updatePingStatus("1") + default: + return fmt.Errorf("not supported operation: %s", operation) } - return fmt.Errorf("not support such operation: %s", operation) + if needRestartDocker { + if err := restartDocker(); err != nil { + return err + } + } + return nil } func (u *FirewallService) OperatePortRule(req dto.PortRuleOperate, reload bool) error { diff --git a/agent/app/service/ftp.go b/agent/app/service/ftp.go index b213fff18..368cd4f3b 100644 --- a/agent/app/service/ftp.go +++ b/agent/app/service/ftp.go @@ -105,21 +105,23 @@ func (f *FtpService) Sync() error { if err != nil { return err } + currentData := make(map[string]model.Ftp) + for _, item := range listsInDB { + currentData[item.User] = item + } sameData := make(map[string]struct{}) for _, item := range lists { - for _, itemInDB := range listsInDB { - if item.User == itemInDB.User { - sameData[item.User] = struct{}{} - if item.Path != itemInDB.Path || item.Status != itemInDB.Status { - _ = ftpRepo.Update(itemInDB.ID, map[string]interface{}{"path": item.Path, "status": item.Status}) + if itemInDB, ok := currentData[item.User]; ok { + sameData[item.User] = struct{}{} + if item.Path != itemInDB.Path || item.Status != itemInDB.Status { + if err := ftpRepo.Update(itemInDB.ID, map[string]interface{}{"path": item.Path, "status": item.Status}); err != nil { + return err } - break } - } - } - for _, item := range lists { - if _, ok := sameData[item.User]; !ok { - _ = ftpRepo.Create(&model.Ftp{User: item.User, Path: item.Path, Status: item.Status}) + } else { + if err := ftpRepo.Create(&model.Ftp{User: item.User, Path: item.Path, Status: item.Status}); err != nil { + return err + } } } for _, item := range listsInDB { diff --git a/agent/app/service/image_repo.go b/agent/app/service/image_repo.go index 434012422..7486af997 100644 --- a/agent/app/service/image_repo.go +++ b/agent/app/service/image_repo.go @@ -91,9 +91,8 @@ func (u *ImageRepoService) Create(req dto.ImageRepoCreate) error { if err := u.handleRegistries(req.DownloadUrl, "", "create"); err != nil { return fmt.Errorf("create registry %s failed, err: %v", req.DownloadUrl, err) } - stdout, err := cmd.RunDefaultWithStdoutBashC("systemctl restart docker") - if err != nil { - return errors.New(string(stdout)) + if err := restartDocker(); err != nil { + return err } ticker := time.NewTicker(3 * time.Second) defer ticker.Stop() diff --git a/agent/app/service/snapshot_recover.go b/agent/app/service/snapshot_recover.go index 878c7b641..87642f54c 100644 --- a/agent/app/service/snapshot_recover.go +++ b/agent/app/service/snapshot_recover.go @@ -371,7 +371,9 @@ func recoverBaseData(src string, itemHelper *snapRecoverHelper) error { } } - _, _ = cmd.RunDefaultWithStdoutBashC("systemctl restart docker") + if err := restartDocker(); err != nil { + return err + } return nil } diff --git a/agent/app/service/website_ca.go b/agent/app/service/website_ca.go index 34768ba75..e5e765cd7 100644 --- a/agent/app/service/website_ca.go +++ b/agent/app/service/website_ca.go @@ -436,14 +436,14 @@ func (w WebsiteCAService) DownloadFile(id uint) (*os.File, error) { if err = fileOp.CreateDir(dir, constant.DirPerm); err != nil { return nil, err } - if err = fileOp.WriteFile(path.Join(dir, "ca.csr"), strings.NewReader(ca.CSR), constant.DirPerm); err != nil { + if err = fileOp.WriteFile(path.Join(dir, "ca.crt"), strings.NewReader(ca.CSR), constant.DirPerm); err != nil { return nil, err } - if err = fileOp.WriteFile(path.Join(dir, "private.key"), strings.NewReader(ca.PrivateKey), constant.DirPerm); err != nil { + if err = fileOp.WriteFile(path.Join(dir, "ca.key"), strings.NewReader(ca.PrivateKey), constant.DirPerm); err != nil { return nil, err } fileName := ca.Name + ".zip" - if err = fileOp.Compress([]string{path.Join(dir, "ca.csr"), path.Join(dir, "private.key")}, dir, fileName, files.SdkZip, ""); err != nil { + if err = fileOp.Compress([]string{path.Join(dir, "ca.crt"), path.Join(dir, "ca.key")}, dir, fileName, files.SdkZip, ""); err != nil { return nil, err } return os.Open(path.Join(dir, fileName)) diff --git a/agent/utils/cloud_storage/client/cos.go b/agent/utils/cloud_storage/client/cos.go index 0184c8ed4..7a4f996e7 100644 --- a/agent/utils/cloud_storage/client/cos.go +++ b/agent/utils/cloud_storage/client/cos.go @@ -6,6 +6,7 @@ import ( "net/http" "net/url" "os" + "regexp" cosSDK "github.com/tencentyun/cos-go-sdk-v5" ) @@ -18,6 +19,7 @@ type cosClient struct { func NewCosClient(vars map[string]interface{}) (*cosClient, error) { region := loadParamFromVars("region", vars) + endpoint := loadParamFromVars("endpoint", vars) accessKey := loadParamFromVars("accessKey", vars) secretKey := loadParamFromVars("secretKey", vars) bucket := loadParamFromVars("bucket", vars) @@ -26,7 +28,15 @@ func NewCosClient(vars map[string]interface{}) (*cosClient, error) { scType = "Standard" } - u, _ := url.Parse(fmt.Sprintf("https://cos.%s.myqcloud.com", region)) + endpointType := "cos" + if len(endpoint) != 0 { + re := regexp.MustCompile(`.*cos-dualstack\..*`) + if re.MatchString(endpoint) { + endpointType = "cos-dualstack" + } + } + + u, _ := url.Parse(fmt.Sprintf("https://%s.%s.myqcloud.com", endpointType, region)) b := &cosSDK.BaseURL{BucketURL: u} client := cosSDK.NewClient(b, &http.Client{ Transport: &cosSDK.AuthorizationTransport{ @@ -36,7 +46,7 @@ func NewCosClient(vars map[string]interface{}) (*cosClient, error) { }) if len(bucket) != 0 { - u2, _ := url.Parse(fmt.Sprintf("https://%s.cos.%s.myqcloud.com", bucket, region)) + u2, _ := url.Parse(fmt.Sprintf("https://%s.%s.%s.myqcloud.com", bucket, endpointType, region)) b2 := &cosSDK.BaseURL{BucketURL: u2} clientWithBucket := cosSDK.NewClient(b2, &http.Client{ Transport: &cosSDK.AuthorizationTransport{ diff --git a/agent/utils/firewall/client/info.go b/agent/utils/firewall/client/info.go index 3503c25ed..f88bd155b 100644 --- a/agent/utils/firewall/client/info.go +++ b/agent/utils/firewall/client/info.go @@ -33,3 +33,12 @@ type IptablesNatInfo struct { SrcPort string `json:"srcPort"` DestPort string `json:"destPort"` } + +type IptablesFilterInfo struct { + Num string `json:"num"` + Target string `json:"target"` + Protocol string `json:"protocol"` + Opt string `json:"opt"` + Source string `json:"source"` + Destination string `json:"destination"` +} diff --git a/agent/utils/firewall/client/iptables.go b/agent/utils/firewall/client/iptables.go index 16b3b4e1f..7faa06104 100644 --- a/agent/utils/firewall/client/iptables.go +++ b/agent/utils/firewall/client/iptables.go @@ -10,9 +10,22 @@ import ( "github.com/1Panel-dev/1Panel/agent/utils/cmd" ) +const ( + PreRoutingChain = "1PANEL_PREROUTING" + PostRoutingChain = "1PANEL_POSTROUTING" + ForwardChain = "1PANEL_FORWARD" +) + +const ( + FilterTab = "filter" + NatTab = "nat" +) + const NatChain = "1PANEL" -var NatListRegex = regexp.MustCompile(`^(\d+)\s+(.+?)\s+(.+?)\s+(.+?)\s+(.+?)\s+(.+?)(?:\s+(.+?) .+?:(\d{1,5}(?::\d+)?).+?[ :](.+-.+|(?:.+:)?\d{1,5}(?:-\d{1,5})?))?$`) +var ( + natListRegex = regexp.MustCompile(`^(\d+)\s+(.+?)\s+(.+?)\s+(.+?)\s+(.+?)\s+(.+?)(?:\s+(.+?) .+?:(\d{1,5}(?::\d+)?).+?[ :](.+-.+|(?:.+:)?\d{1,5}(?:-\d{1,5})?))?$`) +) type Iptables struct { CmdStr string @@ -37,8 +50,24 @@ func (iptables *Iptables) run(rule string) error { return nil } -func (iptables *Iptables) runf(rule string, a ...any) error { - return iptables.run(fmt.Sprintf(rule, a...)) +func (iptables *Iptables) outf(tab, rule string, a ...any) (stdout string, err error) { + stdout, err = cmd.RunDefaultWithStdoutBashCf("%s iptables -t %s %s", iptables.CmdStr, tab, fmt.Sprintf(rule, a...)) + if err != nil && stdout != "" { + global.LOG.Errorf("iptables failed, err: %s", stdout) + } + return +} + +func (iptables *Iptables) runf(tab, rule string, a ...any) error { + stdout, err := iptables.outf(tab, rule, a...) + if err != nil { + return fmt.Errorf("%s, %s", err, stdout) + } + if stdout != "" { + return fmt.Errorf("iptables error: %s", stdout) + } + + return nil } func (iptables *Iptables) Check() error { @@ -47,26 +76,30 @@ func (iptables *Iptables) Check() error { return fmt.Errorf("%s, %s", err, stdout) } if stdout == "0" { - return fmt.Errorf("disable") + return fmt.Errorf("ipv4 forward disable") + } + + chain, _ := iptables.outf(NatTab, "-L -n | grep 'Chain %s'", PreRoutingChain) + if len(strings.ReplaceAll(chain, "\n", "")) != 0 { + return fmt.Errorf("chain enabled") } return nil } -func (iptables *Iptables) NatNewChain() error { - return iptables.runf("-N %s", NatChain) +func (iptables *Iptables) NewChain(tab, chain string) error { + return iptables.runf(tab, "-N %s", chain) } -func (iptables *Iptables) NatAppendChain() error { - return iptables.runf("-A PREROUTING -j %s", NatChain) +func (iptables *Iptables) AppendChain(tab string, chain, chain1 string) error { + return iptables.runf(tab, "-A %s -j %s", chain, chain1) } func (iptables *Iptables) NatList(chain ...string) ([]IptablesNatInfo, error) { - rule := fmt.Sprintf("%s iptables -t nat -nL %s --line", iptables.CmdStr, NatChain) - if len(chain) == 1 { - rule = fmt.Sprintf("%s iptables -t nat -nL %s --line", iptables.CmdStr, chain[0]) + if len(chain) == 0 { + chain = append(chain, PreRoutingChain) } - stdout, err := cmd.RunDefaultWithStdoutBashC(rule) + stdout, err := iptables.outf(NatTab, "-nL %s --line", chain[0]) if err != nil { return nil, err } @@ -76,8 +109,8 @@ func (iptables *Iptables) NatList(chain ...string) ([]IptablesNatInfo, error) { line = strings.TrimFunc(line, func(r rune) bool { return r <= 32 }) - if NatListRegex.MatchString(line) { - match := NatListRegex.FindStringSubmatch(line) + if natListRegex.MatchString(line) { + match := natListRegex.FindStringSubmatch(line) if !strings.Contains(match[9], ":") { match[9] = fmt.Sprintf(":%s", match[9]) } @@ -97,43 +130,126 @@ func (iptables *Iptables) NatList(chain ...string) ([]IptablesNatInfo, error) { return forwardList, nil } -func (iptables *Iptables) NatAdd(protocol, src, destIp, destPort string, save bool) error { - rule := fmt.Sprintf("-A %s -p %s --dport %s -j REDIRECT --to-port %s", NatChain, protocol, src, destPort) - if destIp != "" && destIp != "127.0.0.1" && destIp != "localhost" { - rule = fmt.Sprintf("-A %s -p %s --dport %s -j DNAT --to-destination %s:%s", NatChain, protocol, src, destIp, destPort) - } - if err := iptables.run(rule); err != nil { - return err +func (iptables *Iptables) NatAdd(protocol, srcPort, dest, destPort string, save bool) error { + if dest != "" && dest != "127.0.0.1" && dest != "localhost" { + if err := iptables.runf(NatTab, fmt.Sprintf( + "-A %s -p %s --dport %s -j DNAT --to-destination %s:%s", + PreRoutingChain, + protocol, + srcPort, + dest, + destPort, + )); err != nil { + return err + } + + if err := iptables.runf(NatTab, fmt.Sprintf( + "-A %s -d %s -p %s --dport %s -j MASQUERADE", + PostRoutingChain, + dest, + protocol, + destPort, + )); err != nil { + return err + } + + if err := iptables.runf(FilterTab, fmt.Sprintf( + "-A %s -d %s -p %s --dport %s -j ACCEPT", + ForwardChain, + dest, + protocol, + destPort, + )); err != nil { + return err + } + + if err := iptables.runf(FilterTab, fmt.Sprintf( + "-A %s -s %s -p %s --sport %s -j ACCEPT", + ForwardChain, + dest, + protocol, + destPort, + )); err != nil { + return err + } + } else { + if err := iptables.runf(NatTab, fmt.Sprintf( + "-A %s -p %s --dport %s -j REDIRECT --to-port %s", + PreRoutingChain, + protocol, + srcPort, + destPort, + )); err != nil { + return err + } } if save { return global.DB.Save(&model.Forward{ Protocol: protocol, - Port: src, - TargetIP: destIp, + Port: srcPort, + TargetIP: dest, TargetPort: destPort, }).Error } return nil } -func (iptables *Iptables) NatRemove(num string, protocol, src, destIp, destPort string) error { - if err := iptables.runf("-D %s %s", NatChain, num); err != nil { +func (iptables *Iptables) NatRemove(num string, protocol, srcPort, dest, destPort string) error { + if err := iptables.runf(NatTab, "-D %s %s", PreRoutingChain, num); err != nil { return err } + if dest != "" && dest != "127.0.0.1" && dest != "localhost" { + if err := iptables.runf(NatTab, fmt.Sprintf( + "-D %s -d %s -p %s --dport %s -j MASQUERADE", + PostRoutingChain, + dest, + protocol, + destPort, + )); err != nil { + return err + } + + if err := iptables.runf(FilterTab, fmt.Sprintf( + "-D %s -d %s -p %s --dport %s -j ACCEPT", + ForwardChain, + dest, + protocol, + destPort, + )); err != nil { + return err + } + + if err := iptables.runf(FilterTab, fmt.Sprintf( + "-D %s -s %s -p %s --sport %s -j ACCEPT", + ForwardChain, + dest, + protocol, + destPort, + )); err != nil { + return err + } + } + global.DB.Where( "protocol = ? AND port = ? AND target_ip = ? AND target_port = ?", protocol, - src, - destIp, + srcPort, + dest, destPort, ).Delete(&model.Forward{}) return nil } func (iptables *Iptables) Reload() error { - if err := iptables.runf("-F %s", NatChain); err != nil { + if err := iptables.runf(NatTab, "-F %s", PreRoutingChain); err != nil { + return err + } + if err := iptables.runf(NatTab, "-F %s", PostRoutingChain); err != nil { + return err + } + if err := iptables.runf(FilterTab, "-F %s", ForwardChain); err != nil { return err } diff --git a/agent/utils/firewall/client/ufw.go b/agent/utils/firewall/client/ufw.go index f394ee40a..d609f1ea4 100644 --- a/agent/utils/firewall/client/ufw.go +++ b/agent/utils/firewall/client/ufw.go @@ -5,7 +5,6 @@ import ( "strings" "github.com/1Panel-dev/1Panel/agent/buserr" - "github.com/1Panel-dev/1Panel/agent/global" "github.com/1Panel-dev/1Panel/agent/utils/cmd" ) @@ -100,16 +99,11 @@ func (f *Ufw) ListPort() ([]FireInfo, error) { } func (f *Ufw) ListForward() ([]FireInfo, error) { + _ = f.EnableForward() iptables, err := NewIptables() if err != nil { return nil, err } - panelChian, _ := cmd.RunDefaultWithStdoutBashCf("%s iptables -t nat -L -n | grep 'Chain 1PANEL'", iptables.CmdStr) - if len(strings.ReplaceAll(panelChian, "\n", "")) == 0 { - if err := f.EnableForward(); err != nil { - global.LOG.Errorf("init port forward failed, err: %v", err) - } - } rules, err := iptables.NatList() if err != nil { return nil, err @@ -304,21 +298,33 @@ func (f *Ufw) EnableForward() error { if err != nil { return err } - _ = iptables.NatNewChain() + if err = iptables.Check(); err != nil { + return err + } + _ = iptables.NewChain(NatTab, PreRoutingChain) + _ = iptables.NewChain(NatTab, PostRoutingChain) + _ = iptables.NewChain(FilterTab, ForwardChain) + + if err = f.enableChain(iptables); err != nil { + return err + } + return iptables.Reload() +} + +func (f *Ufw) enableChain(iptables *Iptables) error { rules, err := iptables.NatList("PREROUTING") if err != nil { return err } for _, rule := range rules { - if rule.Target == NatChain { - goto reload + if rule.Target == PreRoutingChain { + return nil } } - if err = iptables.NatAppendChain(); err != nil { - return err - } -reload: - return iptables.Reload() + _ = iptables.AppendChain(NatTab, "PREROUTING", PreRoutingChain) + _ = iptables.AppendChain(NatTab, "POSTROUTING", PostRoutingChain) + _ = iptables.AppendChain(FilterTab, "FORWARD", ForwardChain) + return nil } diff --git a/core/utils/cloud_storage/client/cos.go b/core/utils/cloud_storage/client/cos.go index ede0e9c7e..d0225a997 100644 --- a/core/utils/cloud_storage/client/cos.go +++ b/core/utils/cloud_storage/client/cos.go @@ -6,6 +6,7 @@ import ( "net/http" "net/url" "os" + "regexp" cosSDK "github.com/tencentyun/cos-go-sdk-v5" ) @@ -18,6 +19,7 @@ type cosClient struct { func NewCosClient(vars map[string]interface{}) (*cosClient, error) { region := loadParamFromVars("region", vars) + endpoint := loadParamFromVars("endpoint", vars) accessKey := loadParamFromVars("accessKey", vars) secretKey := loadParamFromVars("secretKey", vars) bucket := loadParamFromVars("bucket", vars) @@ -26,7 +28,15 @@ func NewCosClient(vars map[string]interface{}) (*cosClient, error) { scType = "Standard" } - u, _ := url.Parse(fmt.Sprintf("https://cos.%s.myqcloud.com", region)) + endpointType := "cos" + if len(endpoint) != 0 { + re := regexp.MustCompile(`.*cos-dualstack\..*`) + if re.MatchString(endpoint) { + endpointType = "cos-dualstack" + } + } + + u, _ := url.Parse(fmt.Sprintf("https://%s.%s.myqcloud.com", endpointType, region)) b := &cosSDK.BaseURL{BucketURL: u} client := cosSDK.NewClient(b, &http.Client{ Transport: &cosSDK.AuthorizationTransport{ @@ -36,7 +46,7 @@ func NewCosClient(vars map[string]interface{}) (*cosClient, error) { }) if len(bucket) != 0 { - u2, _ := url.Parse(fmt.Sprintf("https://%s.cos.%s.myqcloud.com", bucket, region)) + u2, _ := url.Parse(fmt.Sprintf("https://%s.%s.%s.myqcloud.com", bucket, endpointType, region)) b2 := &cosSDK.BaseURL{BucketURL: u2} clientWithBucket := cosSDK.NewClient(b2, &http.Client{ Transport: &cosSDK.AuthorizationTransport{ diff --git a/frontend/src/components/task-list/index.vue b/frontend/src/components/task-list/index.vue index 2e6d552e0..d436ef521 100644 --- a/frontend/src/components/task-list/index.vue +++ b/frontend/src/components/task-list/index.vue @@ -52,7 +52,7 @@