github.com/TeaOSLab/EdgeNode@v1.3.8/internal/nodes/node_tasks.go (about)

     1  // Copyright 2023 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
     2  
     3  package nodes
     4  
     5  import (
     6  	"encoding/json"
     7  	"errors"
     8  	"fmt"
     9  	"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
    10  	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
    11  	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
    12  	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ddosconfigs"
    13  	"github.com/TeaOSLab/EdgeNode/internal/configs"
    14  	"github.com/TeaOSLab/EdgeNode/internal/firewalls"
    15  	"github.com/TeaOSLab/EdgeNode/internal/goman"
    16  	"github.com/TeaOSLab/EdgeNode/internal/iplibrary"
    17  	"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
    18  	"github.com/TeaOSLab/EdgeNode/internal/rpc"
    19  	"github.com/TeaOSLab/EdgeNode/internal/trackers"
    20  	"github.com/TeaOSLab/EdgeNode/internal/utils"
    21  	"github.com/TeaOSLab/EdgeNode/internal/waf"
    22  	"github.com/iwind/TeaGo/Tea"
    23  	"github.com/iwind/TeaGo/maps"
    24  	"github.com/iwind/TeaGo/types"
    25  	"os"
    26  	"strings"
    27  	"time"
    28  )
    29  
    30  // 循环
    31  func (this *Node) loopTasks() error {
    32  	var tr = trackers.Begin("CHECK_NODE_CONFIG_CHANGES")
    33  	defer tr.End()
    34  
    35  	// 检查api_node.yaml是否存在
    36  	var apiConfigFile = Tea.ConfigFile(configs.ConfigFileName)
    37  	_, err := os.Stat(apiConfigFile)
    38  	if err != nil {
    39  		return nil
    40  	}
    41  
    42  	rpcClient, err := rpc.SharedRPC()
    43  	if err != nil {
    44  		return fmt.Errorf("create rpc client failed: %w", err)
    45  	}
    46  
    47  	tasksResp, err := rpcClient.NodeTaskRPC.FindNodeTasks(rpcClient.Context(), &pb.FindNodeTasksRequest{
    48  		Version: this.lastTaskVersion,
    49  	})
    50  	if err != nil {
    51  		if rpc.IsConnError(err) && !Tea.IsTesting() {
    52  			return nil
    53  		}
    54  		return fmt.Errorf("read node tasks failed: %w", err)
    55  	}
    56  	for _, task := range tasksResp.NodeTasks {
    57  		err := this.execTask(rpcClient, task)
    58  		if !this.finishTask(task.Id, task.Version, err) {
    59  			// 防止失败的任务无法重试
    60  			break
    61  		}
    62  	}
    63  
    64  	return nil
    65  }
    66  
    67  // 执行任务
    68  func (this *Node) execTask(rpcClient *rpc.RPCClient, task *pb.NodeTask) error {
    69  	var err error
    70  	switch task.Type {
    71  	case "ipItemChanged":
    72  		err = this.execIPItemChangedTask()
    73  	case "configChanged":
    74  		err = this.execConfigChangedTask(task)
    75  	case "nodeVersionChanged":
    76  		err = this.execNodeVersionChangedTask()
    77  	case "scriptsChanged":
    78  		err = this.execScriptsChangedTask()
    79  	case "nodeLevelChanged":
    80  		err = this.execNodeLevelChangedTask(rpcClient)
    81  	case "ddosProtectionChanged":
    82  		err = this.execDDoSProtectionChangedTask(rpcClient)
    83  	case "globalServerConfigChanged":
    84  		err = this.execGlobalServerConfigChangedTask(rpcClient)
    85  	case "userServersStateChanged":
    86  		err = this.execUserServersStateChangedTask(rpcClient, task)
    87  	case "uamPolicyChanged":
    88  		err = this.execUAMPolicyChangedTask(rpcClient)
    89  	case "httpCCPolicyChanged":
    90  		err = this.execHTTPCCPolicyChangedTask(rpcClient)
    91  	case "http3PolicyChanged":
    92  		err = this.execHTTP3PolicyChangedTask(rpcClient)
    93  	case "httpPagesPolicyChanged":
    94  		err = this.execHTTPPagesPolicyChangedTask(rpcClient)
    95  	case "updatingServers":
    96  		err = this.execUpdatingServersTask(rpcClient)
    97  	case "plusChanged":
    98  		err = this.notifyPlusChange()
    99  	case "toaChanged":
   100  		err = this.execTOAChangedTask()
   101  	case "networkSecurityPolicyChanged":
   102  		err = this.execNetworkSecurityPolicyChangedTask(rpcClient)
   103  	case "webPPolicyChanged":
   104  		err = this.execWebPPolicyChangedTask(rpcClient)
   105  	case "planChanged":
   106  		err = this.execPlanChangedTask(rpcClient)
   107  	default:
   108  		// 特殊任务
   109  		if strings.HasPrefix(task.Type, "ipListDeleted") { // 删除IP名单
   110  			err = this.execDeleteIPList(task.Type)
   111  		} else { // 未处理的任务
   112  			remotelogs.Error("NODE", "task '"+types.String(task.Id)+"', type '"+task.Type+"' has not been handled")
   113  		}
   114  	}
   115  
   116  	return err
   117  }
   118  
   119  // 更新IP条目变更
   120  func (this *Node) execIPItemChangedTask() error {
   121  	// 防止阻塞
   122  	select {
   123  	case iplibrary.IPListUpdateNotify <- true:
   124  	default:
   125  
   126  	}
   127  	return nil
   128  }
   129  
   130  // 更新节点配置变更
   131  func (this *Node) execConfigChangedTask(task *pb.NodeTask) error {
   132  	if task.ServerId > 0 {
   133  		return this.syncServerConfig(task.ServerId)
   134  	}
   135  	if !task.IsPrimary {
   136  		// 我们等等主节点配置准备完毕
   137  		time.Sleep(2 * time.Second)
   138  	}
   139  	return this.syncConfig(task.Version)
   140  }
   141  
   142  // 节点程序版本号变更
   143  func (this *Node) execNodeVersionChangedTask() error {
   144  	if !sharedUpgradeManager.IsInstalling() {
   145  		goman.New(func() {
   146  			sharedUpgradeManager.Start()
   147  		})
   148  	}
   149  	return nil
   150  }
   151  
   152  // 节点级别变更
   153  func (this *Node) execNodeLevelChangedTask(rpcClient *rpc.RPCClient) error {
   154  	levelInfoResp, err := rpcClient.NodeRPC.FindNodeLevelInfo(rpcClient.Context(), &pb.FindNodeLevelInfoRequest{})
   155  	if err != nil {
   156  		return err
   157  	}
   158  
   159  	if sharedNodeConfig != nil {
   160  		sharedNodeConfig.Level = levelInfoResp.Level
   161  	}
   162  
   163  	var parentNodes = map[int64][]*nodeconfigs.ParentNodeConfig{}
   164  	if len(levelInfoResp.ParentNodesMapJSON) > 0 {
   165  		err = json.Unmarshal(levelInfoResp.ParentNodesMapJSON, &parentNodes)
   166  		if err != nil {
   167  			return fmt.Errorf("decode level info failed: %w", err)
   168  		}
   169  	}
   170  
   171  	if sharedNodeConfig != nil {
   172  		sharedNodeConfig.ParentNodes = parentNodes
   173  	}
   174  
   175  	return nil
   176  }
   177  
   178  // DDoS配置变更
   179  func (this *Node) execDDoSProtectionChangedTask(rpcClient *rpc.RPCClient) error {
   180  	resp, err := rpcClient.NodeRPC.FindNodeDDoSProtection(rpcClient.Context(), &pb.FindNodeDDoSProtectionRequest{})
   181  	if err != nil {
   182  		return err
   183  	}
   184  	if len(resp.DdosProtectionJSON) == 0 {
   185  		if sharedNodeConfig != nil {
   186  			sharedNodeConfig.DDoSProtection = nil
   187  		}
   188  		return nil
   189  	}
   190  
   191  	var ddosProtectionConfig = &ddosconfigs.ProtectionConfig{}
   192  	err = json.Unmarshal(resp.DdosProtectionJSON, ddosProtectionConfig)
   193  	if err != nil {
   194  		return fmt.Errorf("decode DDoS protection config failed: %w", err)
   195  	}
   196  
   197  	if ddosProtectionConfig != nil && sharedNodeConfig != nil {
   198  		sharedNodeConfig.DDoSProtection = ddosProtectionConfig
   199  	}
   200  
   201  	go func() {
   202  		err = firewalls.SharedDDoSProtectionManager.Apply(ddosProtectionConfig)
   203  		if err != nil {
   204  			// 不阻塞
   205  			remotelogs.Warn("NODE", "apply DDoS protection failed: "+err.Error())
   206  		}
   207  	}()
   208  
   209  	return nil
   210  }
   211  
   212  // 服务全局配置变更
   213  func (this *Node) execGlobalServerConfigChangedTask(rpcClient *rpc.RPCClient) error {
   214  	resp, err := rpcClient.NodeRPC.FindNodeGlobalServerConfig(rpcClient.Context(), &pb.FindNodeGlobalServerConfigRequest{})
   215  	if err != nil {
   216  		return err
   217  	}
   218  	if len(resp.GlobalServerConfigJSON) > 0 {
   219  		var globalServerConfig = serverconfigs.NewGlobalServerConfig()
   220  		err = json.Unmarshal(resp.GlobalServerConfigJSON, globalServerConfig)
   221  		if err != nil {
   222  			return fmt.Errorf("decode global server config failed: %w", err)
   223  		}
   224  
   225  		if globalServerConfig != nil {
   226  			err = globalServerConfig.Init()
   227  			if err != nil {
   228  				return fmt.Errorf("validate global server config failed: %w", err)
   229  			}
   230  			if sharedNodeConfig != nil {
   231  				sharedNodeConfig.GlobalServerConfig = globalServerConfig
   232  			}
   233  		}
   234  	}
   235  	return nil
   236  }
   237  
   238  // 单个用户服务状态变更
   239  func (this *Node) execUserServersStateChangedTask(rpcClient *rpc.RPCClient, task *pb.NodeTask) error {
   240  	if task.UserId > 0 {
   241  		resp, err := rpcClient.UserRPC.CheckUserServersState(rpcClient.Context(), &pb.CheckUserServersStateRequest{UserId: task.UserId})
   242  		if err != nil {
   243  			return err
   244  		}
   245  
   246  		SharedUserManager.UpdateUserServersIsEnabled(task.UserId, resp.IsEnabled)
   247  
   248  		if resp.IsEnabled {
   249  			err = this.syncUserServersConfig(task.UserId)
   250  			if err != nil {
   251  				return err
   252  			}
   253  		}
   254  	}
   255  	return nil
   256  }
   257  
   258  // 更新一组服务列表
   259  func (this *Node) execUpdatingServersTask(rpcClient *rpc.RPCClient) error {
   260  	if this.lastUpdatingServerListId <= 0 {
   261  		this.lastUpdatingServerListId = sharedNodeConfig.UpdatingServerListId
   262  	}
   263  
   264  	resp, err := rpcClient.UpdatingServerListRPC.FindUpdatingServerLists(rpcClient.Context(), &pb.FindUpdatingServerListsRequest{LastId: this.lastUpdatingServerListId})
   265  	if err != nil {
   266  		return err
   267  	}
   268  
   269  	if resp.MaxId <= 0 || len(resp.ServersJSON) == 0 {
   270  		return nil
   271  	}
   272  
   273  	var serverConfigs = []*serverconfigs.ServerConfig{}
   274  	err = json.Unmarshal(resp.ServersJSON, &serverConfigs)
   275  	if err != nil {
   276  		return fmt.Errorf("decode server configs failed: %w", err)
   277  	}
   278  
   279  	if resp.MaxId > this.lastUpdatingServerListId {
   280  		this.lastUpdatingServerListId = resp.MaxId
   281  	}
   282  
   283  	if len(serverConfigs) == 0 {
   284  		return nil
   285  	}
   286  
   287  	this.locker.Lock()
   288  	defer this.locker.Unlock()
   289  	for _, serverConfig := range serverConfigs {
   290  		if serverConfig == nil {
   291  			continue
   292  		}
   293  
   294  		if serverConfig.IsOn {
   295  			this.updatingServerMap[serverConfig.Id] = serverConfig
   296  		} else {
   297  			this.updatingServerMap[serverConfig.Id] = nil
   298  		}
   299  	}
   300  
   301  	return nil
   302  }
   303  
   304  // 删除IP名单
   305  func (this *Node) execDeleteIPList(taskType string) error {
   306  	optionsString, ok := utils.CutPrefix(taskType, "ipListDeleted@")
   307  	if !ok {
   308  		return errors.New("invalid task type '" + taskType + "'")
   309  	}
   310  	var optionMap = maps.Map{}
   311  	err := json.Unmarshal([]byte(optionsString), &optionMap)
   312  	if err != nil {
   313  		return fmt.Errorf("decode options failed: %w, options: %s", err, optionsString)
   314  	}
   315  	var listId = optionMap.GetInt64("listId")
   316  	if listId <= 0 {
   317  		return nil
   318  	}
   319  
   320  	// 标记已被删除
   321  	waf.AddDeletedIPList(listId)
   322  
   323  	var list = iplibrary.SharedIPListManager.FindList(listId)
   324  
   325  	if list != nil {
   326  		list.SetDeleted()
   327  	}
   328  
   329  	return nil
   330  }
   331  
   332  // WebP策略变更
   333  func (this *Node) execWebPPolicyChangedTask(rpcClient *rpc.RPCClient) error {
   334  	remotelogs.Println("NODE", "updating webp policies ...")
   335  	resp, err := rpcClient.NodeRPC.FindNodeWebPPolicies(rpcClient.Context(), &pb.FindNodeWebPPoliciesRequest{})
   336  	if err != nil {
   337  		return err
   338  	}
   339  	var webPPolicyMap = map[int64]*nodeconfigs.WebPImagePolicy{}
   340  	for _, policy := range resp.WebPPolicies {
   341  		if len(policy.WebPPolicyJSON) > 0 {
   342  			var webPPolicy = nodeconfigs.NewWebPImagePolicy()
   343  			err = json.Unmarshal(policy.WebPPolicyJSON, webPPolicy)
   344  			if err != nil {
   345  				remotelogs.Error("NODE", "decode webp policy failed: "+err.Error())
   346  				continue
   347  			}
   348  			err = webPPolicy.Init()
   349  			if err != nil {
   350  				remotelogs.Error("NODE", "initialize webp policy failed: "+err.Error())
   351  				continue
   352  			}
   353  			webPPolicyMap[policy.NodeClusterId] = webPPolicy
   354  		}
   355  	}
   356  	sharedNodeConfig.UpdateWebPImagePolicies(webPPolicyMap)
   357  	return nil
   358  }
   359  
   360  // 标记任务完成
   361  func (this *Node) finishTask(taskId int64, taskVersion int64, taskErr error) (success bool) {
   362  	if taskId <= 0 {
   363  		return true
   364  	}
   365  
   366  	rpcClient, err := rpc.SharedRPC()
   367  	if err != nil {
   368  		remotelogs.Debug("NODE", "create rpc client failed: "+err.Error())
   369  		return false
   370  	}
   371  
   372  	var isOk = taskErr == nil
   373  	if isOk && taskVersion > this.lastTaskVersion {
   374  		this.lastTaskVersion = taskVersion
   375  	}
   376  
   377  	var errMsg = ""
   378  	if taskErr != nil {
   379  		errMsg = taskErr.Error()
   380  	}
   381  
   382  	_, err = rpcClient.NodeTaskRPC.ReportNodeTaskDone(rpcClient.Context(), &pb.ReportNodeTaskDoneRequest{
   383  		NodeTaskId: taskId,
   384  		IsOk:       isOk,
   385  		Error:      errMsg,
   386  	})
   387  	success = err == nil
   388  
   389  	if err != nil {
   390  		// 连接错误不需要上报到服务中心
   391  		if rpc.IsConnError(err) {
   392  			remotelogs.Debug("NODE", "report task done failed: "+err.Error())
   393  		} else {
   394  			remotelogs.Error("NODE", "report task done failed: "+err.Error())
   395  		}
   396  	}
   397  
   398  	return success
   399  }