diff --git a/cmd/verysimple/main.go b/cmd/verysimple/main.go index 1d47e1e..1c668f8 100644 --- a/cmd/verysimple/main.go +++ b/cmd/verysimple/main.go @@ -92,11 +92,15 @@ func cleanup() { } } - for _, tm := range tproxyList { - if tm != nil { - tm.Stop() + if len(tproxyList) > 0 { + log.Println("closing tproxies") + for _, tm := range tproxyList { + if tm != nil { + tm.Stop() + } } } + } func main() { @@ -393,18 +397,27 @@ func mainFunc() (result int) { } for _, thisConf := range tproxyConfs { - tm := vs.ListenTproxy(thisConf.GetAddrStrForListenOrDial(), defaultOutClient, routingEnv.RoutePolicy) + enableSniff := false + if thisConf.SniffConf != nil { + enableSniff = thisConf.SniffConf.Enable + } + lc := proxy.LesserConf{ + Addr: thisConf.GetAddrStrForListenOrDial(), + Tag: thisConf.Tag, + UseSniffing: enableSniff, + } + tm := vs.ListenTproxy(lc, defaultOutClient, routingEnv.RoutePolicy) if tm != nil { tproxyList = append(tproxyList, tm) } } - } + } //if len(tproxyConfs) > 0 { - } + } //if mode == proxy.SimpleMode { - } + } //if (defaultOutClient != nil) && (defaultInServer != nil || len(allServers) > 0 || len(tproxyConfs) > 0) { //没可用的listen/dial,而且还无法动态更改配置 if noFuture() { diff --git a/doc.go b/doc.go index 86e9225..88dcc2b 100644 --- a/doc.go +++ b/doc.go @@ -13,6 +13,12 @@ utils -> netLayer-> tlsLayer -> httpLayer -> advLayer -> proxy -> v2ray_simple - ListenSer函数用于主要 代理的转发,ListenTproxy函数用于转发透明代理。内置了 lazy的转发逻辑。 +Tproxy + +tproxy没有 TLS层 以及更上层的所有参数,只包含网络层和传输层的参数,网络层只包含 ip和端口这两个参数,传输层只包含 "是否开启sniffing" 这一个参数; 然后还有一个 tag参数,然后就没了。 + +所以tproxy不能算是一个完整的 proxy.Server. 所以要用单独的函数启动转发。 + Chain diff --git a/iics.go b/iics.go index a0502d4..dfce926 100644 --- a/iics.go +++ b/iics.go @@ -64,6 +64,9 @@ type incomingInserverConnState struct { inServer proxy.Server //可为 nil defaultClient proxy.Client + inTag string //在inServer为nil时,可用此项确定 inTag + useSniffing bool //在inServer为nil时,可用此项确定 是否使用sniffing + cachedRemoteAddr string inServerTlsConn *tlsLayer.Conn diff --git a/main.go b/main.go index 707ba76..b044d79 100644 --- a/main.go +++ b/main.go @@ -516,8 +516,8 @@ func handshakeInserver_and_passToOutClient(iics incomingInserverConnState) { } -//被 handshakeInserver_and_passToOutClient 和 handshakeInserver 的innerMux部分 调用。 iics.inServer可能为nil。 -// 本函数可能是本文件中 最长的函数。分别处理 回落,firstpayload,sniff,dns解析,分流,以及lazy。 +//被 handshakeInserver_and_passToOutClient 和 handshakeInserver 的innerMux部分 以及 tproxy 调用。 iics.inServer可能为nil。 +// 本函数可能是本文件中 最长的函数。分别处理 回落,firstpayload,sniff,dns解析,分流,以及lazy,最终转发到 某个 outClient。 // // 会调用 dialClient_andRelay. 若isfallback为true,传入的 wlc 和 udp_wlc 必须为nil,targetAddr必须为空值。 func passToOutClient(iics incomingInserverConnState, isfallback bool, wlc net.Conn, udp_wlc netLayer.MsgConn, targetAddr netLayer.Addr) { @@ -607,7 +607,7 @@ func passToOutClient(iics incomingInserverConnState, isfallback bool, wlc net.Co } if wlc == nil && udp_wlc == nil { - //无wlc证明 inServer 握手失败,且 没有任何回落可用, 直接退出。 + //证明 inServer 握手失败,且 没有任何回落可用, 直接退出。 if ce := iics.CanLogDebug("invalid request and no matched fallback, hung up"); ce != nil { ce.Write() } @@ -729,7 +729,13 @@ func passToOutClient(iics incomingInserverConnState, isfallback bool, wlc net.Co if len(iics.firstPayload) > 0 { - inserverMarkedSniffing := (inServer != nil && inServer.Sniffing()) + inserverMarkedSniffing := false + + if inServer == nil { + inserverMarkedSniffing = iics.useSniffing + } else { + inserverMarkedSniffing = inServer.Sniffing() + } dialIslazy := iics.defaultClient.IsLazyTls() @@ -793,6 +799,8 @@ func passToOutClient(iics incomingInserverConnState, isfallback bool, wlc net.Co } if inServer != nil { desc.InTag = inServer.GetTag() + } else { + desc.InTag = iics.inTag } if uc, ok := wlc.(utils.User); ok { desc.UserIdentityStr = uc.IdentityStr() diff --git a/netLayer/tproxy/common.go b/netLayer/tproxy/common.go index 4991e07..bef5b2d 100644 --- a/netLayer/tproxy/common.go +++ b/netLayer/tproxy/common.go @@ -105,7 +105,9 @@ http://ivo-wang.github.io/2018/02/24/ss-redir/ package tproxy import ( + "log" "net" + "time" "github.com/e1732a364fed/v2ray_simple/netLayer" ) @@ -120,10 +122,26 @@ type Machine struct { func (m *Machine) Stop() { if m.Listener != nil { - m.Listener.Close() + log.Println("closing tproxy listener") + //后来发现,不知为何,这个 Close调用会卡住 + + ch := make(chan int) + go func() { + m.Listener.Close() + close(ch) + }() + tCh := time.After(time.Second) + select { + case <-tCh: + log.Println("close tproxy listener timeout") + case <-ch: + break + } } if m.UDPConn != nil { + log.Println("closing tproxy udp conn") + m.UDPConn.Close() } diff --git a/proxy/config_proxy.go b/proxy/config_proxy.go index 4ca2d8a..493e988 100644 --- a/proxy/config_proxy.go +++ b/proxy/config_proxy.go @@ -8,6 +8,13 @@ import ( "github.com/e1732a364fed/v2ray_simple/utils" ) +//用于 tproxy 和 tun/tap 这种 只有 网络层 和传输层的情况 +type LesserConf struct { + Addr string + Tag string + UseSniffing bool +} + // CommonConf is the common part of ListenConf and DialConf. type CommonConf struct { Tag string `toml:"tag"` //可选 diff --git a/proxy/vmess/client.go b/proxy/vmess/client.go index 10255a4..346a815 100644 --- a/proxy/vmess/client.go +++ b/proxy/vmess/client.go @@ -61,16 +61,25 @@ func (ClientCreator) NewClient(dc *proxy.DialConf) (proxy.Client, error) { c.user = utils.V2rayUser(uuid) c.opt = OptChunkStream + hasSetSecurityByExtra := false + if len(dc.Extra) > 0 { if thing := dc.Extra["vmess_security"]; thing != nil { if str, ok := thing.(string); ok { - if err = c.specifySecurityByStr(str); err != nil { + + err = c.specifySecurityByStr(str) + + if err == nil { + hasSetSecurityByExtra = true + } else { return nil, err } } } - } else { + } + + if !hasSetSecurityByExtra { c.specifySecurityByStr("") } diff --git a/tproxy_linux.go b/tproxy_linux.go index 707bec8..e107246 100644 --- a/tproxy_linux.go +++ b/tproxy_linux.go @@ -11,15 +11,15 @@ import ( ) //非阻塞。监听透明代理 -func ListenTproxy(addr string, defaultOutClientForThis proxy.Client, routePolicy *netLayer.RoutePolicy) (tm *tproxy.Machine) { +func ListenTproxy(lc proxy.LesserConf, defaultOutClientForThis proxy.Client, routePolicy *netLayer.RoutePolicy) (tm *tproxy.Machine) { utils.Info("Start running Tproxy") - ad, err := netLayer.NewAddr(addr) + ad, err := netLayer.NewAddr(lc.Addr) if err != nil { panic(err) } //因为 tproxy比较特殊, 不属于 proxy.Server, 所以 需要 独立的 转发过程去处理. - lis, err := startLoopTCP(ad, defaultOutClientForThis, &proxy.RoutingEnv{ + lis, err := startLoopTCP(ad, lc, defaultOutClientForThis, &proxy.RoutingEnv{ RoutePolicy: routePolicy, }) if err != nil { @@ -28,7 +28,7 @@ func ListenTproxy(addr string, defaultOutClientForThis proxy.Client, routePolicy } return } - udpConn := startLoopUDP(ad, defaultOutClientForThis, &proxy.RoutingEnv{ + udpConn := startLoopUDP(ad, lc, defaultOutClientForThis, &proxy.RoutingEnv{ RoutePolicy: routePolicy, }) @@ -38,7 +38,7 @@ func ListenTproxy(addr string, defaultOutClientForThis proxy.Client, routePolicy } //非阻塞 -func startLoopTCP(ad netLayer.Addr, defaultOutClientForThis proxy.Client, env *proxy.RoutingEnv) (net.Listener, error) { +func startLoopTCP(ad netLayer.Addr, lc proxy.LesserConf, defaultOutClientForThis proxy.Client, env *proxy.RoutingEnv) (net.Listener, error) { return netLayer.ListenAndAccept("tcp", ad.String(), &netLayer.Sockopt{TProxy: true}, 0, func(conn net.Conn) { tcpconn := conn.(*net.TCPConn) targetAddr := tproxy.HandshakeTCP(tcpconn) @@ -48,6 +48,8 @@ func startLoopTCP(ad netLayer.Addr, defaultOutClientForThis proxy.Client, env *p } passToOutClient(incomingInserverConnState{ + inTag: lc.Tag, + useSniffing: lc.UseSniffing, wrappedConn: tcpconn, defaultClient: defaultOutClientForThis, routingEnv: env, @@ -57,7 +59,7 @@ func startLoopTCP(ad netLayer.Addr, defaultOutClientForThis proxy.Client, env *p } //非阻塞 -func startLoopUDP(ad netLayer.Addr, defaultOutClientForThis proxy.Client, env *proxy.RoutingEnv) *net.UDPConn { +func startLoopUDP(ad netLayer.Addr, lc proxy.LesserConf, defaultOutClientForThis proxy.Client, env *proxy.RoutingEnv) *net.UDPConn { ad.Network = "udp" conn, err := ad.ListenUDP_withOpt(&netLayer.Sockopt{TProxy: true}) if err != nil { @@ -83,6 +85,8 @@ func startLoopUDP(ad netLayer.Addr, defaultOutClientForThis proxy.Client, env *p } go passToOutClient(incomingInserverConnState{ + inTag: lc.Tag, + useSniffing: lc.UseSniffing, defaultClient: defaultOutClientForThis, routingEnv: env, }, false, nil, msgConn, raddr) diff --git a/tproxy_other.go b/tproxy_other.go index 093ab30..b8cdb0b 100644 --- a/tproxy_other.go +++ b/tproxy_other.go @@ -11,7 +11,7 @@ import ( ) //非阻塞。在非linux系统中无效。 -func ListenTproxy(string, proxy.Client, *netLayer.RoutePolicy) (_ *tproxy.Machine) { +func ListenTproxy(lc proxy.LesserConf, defaultClient proxy.Client, routePolicy *netLayer.RoutePolicy) (_ *tproxy.Machine) { utils.Error("Tproxy not possible on non-linux device") return }