Launch
This commit is contained in:
96
internal/tun/tun2socks.go
Normal file
96
internal/tun/tun2socks.go
Normal file
@@ -0,0 +1,96 @@
|
||||
package tun
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/xjasonlyu/tun2socks/v2/engine"
|
||||
"socksrevivepc/internal/config"
|
||||
"socksrevivepc/internal/platformtun"
|
||||
)
|
||||
|
||||
type Logger interface {
|
||||
Add(level, format string, args ...any)
|
||||
}
|
||||
|
||||
type Runner struct {
|
||||
active bool
|
||||
logger Logger
|
||||
cleanup func()
|
||||
}
|
||||
|
||||
func NewRunner(logger Logger) *Runner { return &Runner{logger: logger} }
|
||||
|
||||
func (r *Runner) Start(p *config.Profile, socksAddr string) error {
|
||||
if p == nil || !p.Tun.Enabled {
|
||||
return nil
|
||||
}
|
||||
if r.active {
|
||||
return fmt.Errorf("tun is already active")
|
||||
}
|
||||
if err := waitForProxyPort(socksAddr, 2500*time.Millisecond); err != nil {
|
||||
return fmt.Errorf("cannot start TUN because upstream SOCKS is not reachable at %s: %w", socksAddr, err)
|
||||
}
|
||||
device, iface, cleanup, err := platformtun.Prepare(p.Tun.Device, p.Tun.InterfaceName, p.Tun.MTU, r.logger)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.Tun.Device = device
|
||||
p.Tun.InterfaceName = iface
|
||||
r.cleanup = cleanup
|
||||
key := &engine.Key{
|
||||
MTU: p.Tun.MTU,
|
||||
Device: p.Tun.Device,
|
||||
Proxy: "socks5://" + socksAddr,
|
||||
LogLevel: "error",
|
||||
}
|
||||
if p.Tun.InterfaceName != "" && runtime.GOOS != "windows" {
|
||||
key.Interface = p.Tun.InterfaceName
|
||||
}
|
||||
if runtime.GOOS == "windows" && r.logger != nil {
|
||||
r.logger.Add("info", "Windows TUN: leaving tun2socks interface binding empty; the TUN adapter name is %s", p.Tun.InterfaceName)
|
||||
}
|
||||
engine.Insert(key)
|
||||
// tun2socks/v2 engine.Start() initializes the default netstack and then
|
||||
// returns; it does not block for the lifetime of the tunnel. The stack stays
|
||||
// alive globally until engine.Stop() is called. Older builds treated this
|
||||
// normal return as "engine exited immediately", which made TUN mode fail even
|
||||
// after the stack was correctly created.
|
||||
engine.Start()
|
||||
r.active = true
|
||||
r.logger.Add("info", "tun2socks started: device=%s interface=%s proxy=socks5://%s", p.Tun.Device, p.Tun.InterfaceName, socksAddr)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Runner) Stop() {
|
||||
if !r.active {
|
||||
return
|
||||
}
|
||||
engine.Stop()
|
||||
if r.cleanup != nil {
|
||||
r.cleanup()
|
||||
r.cleanup = nil
|
||||
}
|
||||
r.active = false
|
||||
r.logger.Add("info", "tun2socks stopped")
|
||||
}
|
||||
|
||||
func waitForProxyPort(addr string, timeout time.Duration) error {
|
||||
deadline := time.Now().Add(timeout)
|
||||
var lastErr error
|
||||
for time.Now().Before(deadline) {
|
||||
c, err := net.DialTimeout("tcp", addr, 350*time.Millisecond)
|
||||
if err == nil {
|
||||
_ = c.Close()
|
||||
return nil
|
||||
}
|
||||
lastErr = err
|
||||
time.Sleep(150 * time.Millisecond)
|
||||
}
|
||||
if lastErr != nil {
|
||||
return lastErr
|
||||
}
|
||||
return fmt.Errorf("timeout waiting for %s", addr)
|
||||
}
|
||||
Reference in New Issue
Block a user