2023-01-28 00:50:21 +07:00
|
|
|
package cmd
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"github.com/sirupsen/logrus"
|
|
|
|
"github.com/spf13/cobra"
|
2023-01-28 12:27:54 +07:00
|
|
|
"github.com/v2rayA/dae/cmd/internal"
|
2023-01-28 00:50:21 +07:00
|
|
|
"github.com/v2rayA/dae/component/control"
|
|
|
|
"github.com/v2rayA/dae/config"
|
|
|
|
"github.com/v2rayA/dae/pkg/config_parser"
|
|
|
|
"github.com/v2rayA/dae/pkg/logger"
|
|
|
|
"os"
|
|
|
|
"os/signal"
|
|
|
|
"syscall"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2023-02-04 21:02:37 +07:00
|
|
|
cfgFile string
|
|
|
|
disableTimestamp bool
|
2023-01-28 00:50:21 +07:00
|
|
|
|
|
|
|
runCmd = &cobra.Command{
|
|
|
|
Use: "run",
|
|
|
|
Short: "Run dae in the foreground",
|
|
|
|
Run: func(cmd *cobra.Command, args []string) {
|
2023-02-01 10:10:41 +07:00
|
|
|
if cfgFile == "" {
|
|
|
|
logrus.Fatalln("Argument \"--config\" or \"-c\" is required but not provided.")
|
|
|
|
}
|
2023-02-04 21:02:37 +07:00
|
|
|
logrus.SetLevel(logrus.DebugLevel)
|
|
|
|
log := logger.NewLogger(2, disableTimestamp)
|
|
|
|
if err := Run(log); err != nil {
|
2023-01-28 00:50:21 +07:00
|
|
|
logrus.Fatalln(err)
|
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
func init() {
|
2023-02-01 10:10:41 +07:00
|
|
|
runCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "", "config file")
|
2023-02-04 21:02:37 +07:00
|
|
|
runCmd.PersistentFlags().BoolVarP(&disableTimestamp, "disable-timestamp", "", false, "disable timestamp")
|
2023-01-28 00:50:21 +07:00
|
|
|
}
|
|
|
|
|
2023-02-04 21:02:37 +07:00
|
|
|
func Run(log *logrus.Logger) (err error) {
|
2023-01-28 00:50:21 +07:00
|
|
|
|
2023-02-04 14:02:44 +07:00
|
|
|
// Require "sudo" if necessary.
|
|
|
|
internal.AutoSu()
|
|
|
|
|
2023-01-28 00:50:21 +07:00
|
|
|
// Read config from --config cfgFile.
|
2023-02-04 21:21:27 +07:00
|
|
|
param, err := readConfig(cfgFile)
|
2023-01-28 00:50:21 +07:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("readConfig: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Resolve subscriptions to nodes.
|
|
|
|
nodeList := make([]string, len(param.Node))
|
|
|
|
copy(nodeList, param.Node)
|
|
|
|
for _, sub := range param.Subscription {
|
2023-01-28 12:27:54 +07:00
|
|
|
nodes, err := internal.ResolveSubscription(log, sub)
|
2023-01-28 00:50:21 +07:00
|
|
|
if err != nil {
|
|
|
|
log.Warnf(`failed to resolve subscription "%v": %v`, sub, err)
|
|
|
|
}
|
|
|
|
nodeList = append(nodeList, nodes...)
|
|
|
|
}
|
2023-02-04 21:02:37 +07:00
|
|
|
if len(nodeList) == 0 {
|
|
|
|
return fmt.Errorf("no node found, which could because all subscription resolving failed")
|
|
|
|
}
|
2023-01-28 00:50:21 +07:00
|
|
|
|
2023-02-01 11:30:26 +07:00
|
|
|
if len(param.Global.LanInterface) == 0 && len(param.Global.WanInterface) == 0 {
|
2023-02-01 09:59:57 +07:00
|
|
|
return fmt.Errorf("LanInterface and WanInterface cannot both be empty")
|
|
|
|
}
|
|
|
|
|
2023-01-28 00:50:21 +07:00
|
|
|
// New ControlPlane.
|
|
|
|
t, err := control.NewControlPlane(
|
|
|
|
log,
|
|
|
|
nodeList,
|
|
|
|
param.Group,
|
|
|
|
¶m.Routing,
|
|
|
|
param.Global.DnsUpstream,
|
|
|
|
param.Global.CheckUrl,
|
2023-01-28 14:47:43 +07:00
|
|
|
param.Global.CheckInterval,
|
2023-02-02 20:22:18 +07:00
|
|
|
param.Global.LanInterface,
|
|
|
|
param.Global.WanInterface,
|
2023-01-28 00:50:21 +07:00
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Serve tproxy TCP/UDP server util signals.
|
|
|
|
sigs := make(chan os.Signal, 1)
|
|
|
|
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGKILL, syscall.SIGILL)
|
|
|
|
go func() {
|
|
|
|
if err := t.ListenAndServe(param.Global.TproxyPort); err != nil {
|
|
|
|
log.Errorln("ListenAndServe:", err)
|
|
|
|
sigs <- nil
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
<-sigs
|
|
|
|
if e := t.Close(); e != nil {
|
|
|
|
return fmt.Errorf("close control plane: %w", e)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2023-02-04 21:21:27 +07:00
|
|
|
func readConfig(cfgFile string) (params *config.Params, err error) {
|
2023-01-28 00:50:21 +07:00
|
|
|
b, err := os.ReadFile(cfgFile)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
sections, err := config_parser.Parse(string(b))
|
|
|
|
if err != nil {
|
2023-01-28 17:51:21 +07:00
|
|
|
return nil, fmt.Errorf("\n%w", err)
|
2023-01-28 00:50:21 +07:00
|
|
|
}
|
|
|
|
if params, err = config.New(sections); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return params, nil
|
|
|
|
}
|