Files
v2ray_simple/proxy/tun/tun.go
2022-12-16 09:17:20 +08:00

255 lines
5.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Package tun implements proxy.Server for tun device.
/*
tun Server使用 host 配置作为 tun device name
使用 ip 配置作为 gateway 的ip
使用 extra.tun_selfip 作为 tun向外拨号的ip
tun device name的默认值约定 mac utun5, windows vs_wintun
*/
package tun
import (
"io"
"net"
"net/url"
"runtime"
"github.com/e1732a364fed/v2ray_simple/netLayer"
"github.com/e1732a364fed/v2ray_simple/netLayer/tun"
"github.com/e1732a364fed/v2ray_simple/proxy"
"github.com/e1732a364fed/v2ray_simple/utils"
"go.uber.org/zap"
)
const name = "tun"
var AddManualRunCmdsListFunc func([]string)
var manualRoute bool
const manualPrompt = "Please try run these commands manually(Administrator):"
var rememberedRouterIP string
func promptManual(strs []string) {
utils.Warn(manualPrompt)
for _, s := range strs {
utils.Warn(s)
}
if AddManualRunCmdsListFunc != nil {
AddManualRunCmdsListFunc(strs)
}
}
func init() {
proxy.RegisterServer(name, &ServerCreator{})
}
type ServerCreator struct{ proxy.CreatorCommonStruct }
var (
autoRouteFunc func(tunDevName, tunGateway, tunIP string, directlist []string)
autoRouteDownFunc func(tunDevName, tunGateway, tunIP string, directlist []string)
)
func (ServerCreator) URLToListenConf(url *url.URL, lc *proxy.ListenConf, format int) (*proxy.ListenConf, error) {
if lc == nil {
return nil, utils.ErrNilParameter
}
return lc, nil
}
func (ServerCreator) NewServer(lc *proxy.ListenConf) (proxy.Server, error) {
s := &Server{}
s.devName = lc.Host
s.realIP = lc.IP
if len(lc.Extra) > 0 {
if thing := lc.Extra["tun_selfip"]; thing != nil {
if str, ok := thing.(string); ok {
s.selfip = str
}
}
if thing := lc.Extra["tun_auto_route"]; thing != nil {
if auto, autoOk := utils.AnyToBool(thing); autoOk && auto {
if thing := lc.Extra["tun_auto_route_direct_list"]; thing != nil {
if list, ok := thing.([]any); ok {
for _, v := range list {
if str, ok := v.(string); ok && str != "" {
s.autoRouteDirectList = append(s.autoRouteDirectList, str)
}
}
}
}
if len(s.autoRouteDirectList) == 0 {
utils.Warn("tun auto route set, but no direct list given. auto route will not run.")
} else {
s.autoRoute = true
}
if thing := lc.Extra["tun_auto_route_manual"]; thing != nil {
if manual, ok := utils.AnyToBool(thing); ok && manual {
manualRoute = true
}
}
}
}
}
return s, nil
}
func (ServerCreator) AfterCommonConfServer(ps proxy.Server) (err error) {
s := ps.(*Server)
const defaultSelfIP = "10.1.0.10"
const defaultRealIP = "10.1.0.20"
//const defaultMask = "255.255.255.0"
//上面两个默认ip取自water项目给出的示例
if s.realIP == "" {
s.realIP = defaultRealIP
}
if s.selfip == "" {
s.selfip = defaultSelfIP
}
return
}
type Server struct {
proxy.Base
stopped bool
infoChan chan<- netLayer.TCPRequestInfo
udpRequestChan chan<- netLayer.UDPRequestInfo
lwipCloser io.Closer
devName, realIP, selfip string
autoRoute bool
autoRouteDirectList []string
}
func (*Server) Name() string { return name }
func (s *Server) SelfListen() (is bool, tcp, udp int) {
switch n := s.Network(); n {
case "", netLayer.DualNetworkName:
tcp = 1
udp = 1
case "tcp":
tcp = 1
udp = -1
case "udp":
udp = 1
tcp = -1
}
is = true
return
}
func (s *Server) Close() error {
s.Stop()
return nil
}
func (s *Server) Stop() {
if !s.stopped {
s.stopped = true
if s.autoRoute && autoRouteDownFunc != nil {
utils.Info("tun running auto table down")
autoRouteDownFunc(s.devName, s.realIP, s.selfip, s.autoRouteDirectList)
}
close(s.infoChan)
close(s.udpRequestChan)
s.lwipCloser.Close()
}
}
func (s *Server) StartListen(tcpRequestChan chan<- netLayer.TCPRequestInfo, udpRequestChan chan<- netLayer.UDPRequestInfo) io.Closer {
s.stopped = false
if s.devName == "" {
switch runtime.GOOS {
case "darwin":
s.devName = "utun5"
case "windows":
s.devName = "vs_wintun"
}
}
tunDev, err := tun.Open(s.devName)
if err != nil {
if ce := utils.CanLogErr("tun open failed"); ce != nil {
ce.Write(zap.Error(err))
}
s.stopped = true
return nil
}
if s.autoRoute && autoRouteFunc != nil {
utils.Info("tun running auto table")
autoRouteFunc(s.devName, s.realIP, s.selfip, s.autoRouteDirectList)
}
s.infoChan = tcpRequestChan
s.udpRequestChan = udpRequestChan
newTchan, newUchan, closer, err := tun.Listen(tunDev)
if err != nil {
if ce := utils.CanLogErr("tun listen failed"); ce != nil {
ce.Write(zap.Error(err))
}
return nil
}
go func() {
for tr := range newTchan {
if s.stopped {
return
}
if ce := utils.CanLogInfo("tun got new tcp"); ce != nil {
ce.Write(zap.String("->", tr.Target.String()))
}
tcpRequestChan <- tr
}
}()
go func() {
for ur := range newUchan {
if s.stopped {
return
}
if ce := utils.CanLogInfo("tun got new udp"); ce != nil {
ce.Write(zap.String("->", ur.Target.String()))
}
udpRequestChan <- ur
}
}()
s.lwipCloser = closer
return s
}
func (s *Server) Handshake(underlay net.Conn) (net.Conn, netLayer.MsgConn, netLayer.Addr, error) {
return nil, nil, netLayer.Addr{}, utils.ErrUnImplemented
}