Files
tun2socks/internal/cmd/cmd.go
xjasonlyu e1e96c8cfb v2
2020-11-05 18:41:15 +08:00

101 lines
2.3 KiB
Go

package cmd
import (
"fmt"
"os"
"os/signal"
"runtime"
"syscall"
"time"
"github.com/urfave/cli/v2"
"github.com/xjasonlyu/clash/component/dialer"
"github.com/xjasonlyu/tun2socks/internal/api"
"github.com/xjasonlyu/tun2socks/internal/core"
"github.com/xjasonlyu/tun2socks/internal/dev"
"github.com/xjasonlyu/tun2socks/internal/dns"
"github.com/xjasonlyu/tun2socks/internal/proxy"
"github.com/xjasonlyu/tun2socks/internal/tunnel"
"github.com/xjasonlyu/tun2socks/pkg/log"
)
func bindToInterface(name string) {
dialer.DialHook = dialer.DialerWithInterface(name)
dialer.ListenPacketHook = dialer.ListenPacketWithInterface(name)
}
func printVersion(app *cli.App) {
fmt.Printf("%s %s\n%s/%s, %s, %s\n",
app.Name,
app.Version,
runtime.GOOS,
runtime.GOARCH,
runtime.Version(),
app.Compiled.Format(time.RFC3339),
)
}
func Main(c *cli.Context) error {
if c.Bool("version") {
printVersion(c.App)
return nil
}
level, err := log.ParseLevel(c.String("loglevel"))
if err != nil {
return err
}
log.SetLevel(level)
if c.IsSet("interface") {
name := c.String("interface")
bindToInterface(name)
log.Infof("[IFCE] bind to interface: %s", name)
}
if c.IsSet("api") { /* initiate API */
raw := c.String("api")
if err := api.Start(raw, c.App); err != nil {
return fmt.Errorf("start API server %s: %w", raw, err)
}
log.Infof("[API] listen and serve at: %s", raw)
}
if c.IsSet("dns") { /* initiate DNS */
raw := c.String("dns")
if err := dns.Start(raw, c.StringSlice("hosts")); err != nil {
return fmt.Errorf("start DNS server %s: %w", raw, err)
}
log.Infof("[DNS] listen and serve at: %s", raw)
}
deviceURL := c.String("device")
device, err := dev.Open(deviceURL)
if err != nil {
return fmt.Errorf("open device %s: %w", deviceURL, err)
}
defer func() {
err := device.Close()
if err != nil {
log.Errorf("close device %s error: %v", deviceURL, err)
}
}()
proxyURL := c.String("proxy")
if err := proxy.Register(proxyURL); err != nil {
return fmt.Errorf("register proxy %s: %w", proxyURL, err)
}
if _, err := core.NewDefaultStack(device, tunnel.Add, tunnel.AddPacket); err != nil {
return fmt.Errorf("initiate stack: %w", err)
}
log.Infof("[STACK] %s --> %s", device.String(), proxy.String())
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
<-sigCh
return nil
}