diff --git a/commands.go b/commands.go index f469792..098f24f 100644 --- a/commands.go +++ b/commands.go @@ -12,10 +12,6 @@ import ( "github.com/hahahrfool/v2ray_simple/utils" ) -const ( - mmdbDownloadLink = "https://cdn.jsdelivr.net/gh/Loyalsoldier/geoip@release/Country.mmdb" -) - var ( cmdPrintSupportedProtocols bool cmdGenerateUUID bool @@ -39,7 +35,7 @@ func generateAndPrintUUID() { return } - log.Println("Your new randomly generated uuid is : ", utils.GenerateUUIDStr()) + log.Printf("Your new randomly generated uuid is : %s\n", utils.GenerateUUIDStr()) } func mayPrintSupportedProtocols() { @@ -55,33 +51,36 @@ func tryDownloadMMDB() { if utils.FileExist(utils.GetFilePath(netLayer.GeoipFileName)) { return } - log.Println("No GeoLite2-Country.mmdb found,start downloading from " + mmdbDownloadLink) + + const mmdbDownloadLink = "https://cdn.jsdelivr.net/gh/Loyalsoldier/geoip@release/Country.mmdb" + + log.Printf("No GeoLite2-Country.mmdb found,start downloading from%s\n", mmdbDownloadLink) resp, err := http.Get(mmdbDownloadLink) if err != nil { - log.Println("Download mmdb failed", err) + log.Printf("Download mmdb failed%s\n", err) return } defer resp.Body.Close() out, err := os.Create(netLayer.GeoipFileName) if err != nil { - log.Println("Download mmdb but Can't CreateFile,", err) + log.Printf("Download mmdb but Can't CreateFile,%s\n", err) return } defer out.Close() if resp.StatusCode != http.StatusOK { - log.Println("Download mmdb bad status:", resp.Status) + log.Printf("Download mmdb bad status:%s\n", resp.Status) return } _, err = io.Copy(out, resp.Body) if err != nil { - log.Println("Write downloaded mmdb to file err:", err) + log.Printf("Write downloaded mmdb to file err:%s\n", err) return } - log.Println("Download mmdb success!") + log.Printf("Download mmdb success!\n") } diff --git a/configs.go b/configs.go index 7e7e1f2..44d5c5c 100644 --- a/configs.go +++ b/configs.go @@ -33,7 +33,7 @@ func loadConfig() { standardConf, err = proxy.LoadTomlConfFile(fpath) if err != nil { - log.Fatalln("can not load standard config file: ", err) + log.Fatalf("can not load standard config file: %s\n", err) } //log.Println("standardConf.Fallbacks: ", len(standardConf.Fallbacks)) if len(standardConf.Fallbacks) != 0 { @@ -53,10 +53,11 @@ func loadConfig() { //默认认为所有其他后缀的都是json格式,因为有时我会用 server.json.vless 这种写法 // 默认所有json格式的文件都为 极简模式 - simpleConf, err = proxy.LoadSimpleConfigFile(fpath) - if err != nil { + var hasE bool + simpleConf, hasE, err = proxy.LoadSimpleConfigFile(fpath) + if hasE { - log.Fatalln("can not load simple config file: ", err) + log.Fatalf("can not load simple config file: %s\n", err) } if simpleConf.Fallbacks != nil { mainFallback = httpLayer.NewClassicFallbackFromConfList(simpleConf.Fallbacks) @@ -70,15 +71,15 @@ func loadConfig() { } } else { - log.Println("No Such Config File:", configFileName, ",will try using -L parameter ") + log.Printf("No Such Config File:%s,will try using -L parameter \n", configFileName) if listenURL != "" { _, err = url.Parse(listenURL) if err != nil { - log.Fatalln("listenURL given but invalid ", listenURL, err) + log.Fatalf("listenURL given but invalid %s %s\n", listenURL, err) } - simpleConf = &proxy.Simple{ + simpleConf = proxy.Simple{ Server_ThatListenPort_Url: listenURL, } @@ -86,7 +87,7 @@ func loadConfig() { _, err = url.Parse(dialURL) if err != nil { - log.Fatalln("dialURL given but invalid ", dialURL, err) + log.Fatalf("dialURL given but invalid %s %s\n", dialURL, err) } @@ -94,7 +95,7 @@ func loadConfig() { } } else { - log.Fatalln("no -L listen URL provided ") + log.Fatalf("no -L listen URL provided \n") } } diff --git a/grpc/conn.go b/grpc/conn.go index 401f4b5..3f97c90 100644 --- a/grpc/conn.go +++ b/grpc/conn.go @@ -32,7 +32,7 @@ func (c *Conn) Read(b []byte) (n int, err error) { if c.cacheReader == nil { h, err := c.stream.Recv() if err != nil { - return 0, utils.NewErr("unable to read from gun tunnel", err) + return 0, utils.ErrInErr{ErrDesc: "unable to read from gun tunnel", ErrDetail: err} } c.cacheReader = bytes.NewReader(h.Data) } @@ -47,7 +47,7 @@ func (c *Conn) Read(b []byte) (n int, err error) { func (c *Conn) Write(b []byte) (n int, err error) { err = c.stream.Send(&Hunk{Data: b}) if err != nil { - return 0, utils.NewErr("Unable to send data over stream service", err) + return 0, utils.ErrInErr{ErrDesc: "Unable to send data over stream service", ErrDetail: err} } return len(b), nil } diff --git a/httpLayer/fallback.go b/httpLayer/fallback.go index 5416ae9..2eaff6a 100644 --- a/httpLayer/fallback.go +++ b/httpLayer/fallback.go @@ -333,14 +333,14 @@ func NewClassicFallbackFromConfList(fcl []*FallbackConf) *ClassicFallback { return cfb } -func (cfb *ClassicFallback) InsertFallbackConditionSet(condition FallbackConditionSet, addr *netLayer.Addr) { +func (cfb *ClassicFallback) InsertFallbackConditionSet(condition FallbackConditionSet, addr netLayer.Addr) { theMap := cfb.Map ftype := condition.GetType() cfb.supportedTypeMask |= ftype - theMap[condition] = addr + theMap[condition] = &addr } func (cfb *ClassicFallback) FirstBuffer() *bytes.Buffer { diff --git a/main.go b/main.go index d7987c0..679a368 100644 --- a/main.go +++ b/main.go @@ -41,11 +41,11 @@ var ( uniqueTestDomain string //有时需要测试到单一网站的流量,此时为了避免其它干扰,需要在这里声明 一下 该域名,然后程序里会进行过滤 - confMode int = -1 //0: simple json, 1: standard toml, 2: v2ray compatible json - simpleConf *proxy.Simple - standardConf *proxy.Standard - directClient, _ = proxy.ClientFromURL("direct://") - default_uuid string + confMode int = -1 //0: simple json, 1: standard toml, 2: v2ray compatible json + simpleConf proxy.Simple + standardConf proxy.Standard + directClient, _, _ = proxy.ClientFromURL("direct://") + default_uuid string allServers = make([]proxy.Server, 0, 8) allClients = make([]proxy.Client, 0, 8) @@ -138,11 +138,9 @@ func main() { netLayer.UseReadv = usereadv_beforeLoadConfigFile } - fmt.Println("Log Level:", utils.LogLevel) - fmt.Println("UseReadv:", netLayer.UseReadv) - if utils.CanLogDebug() { - fmt.Println("MaxBufSize", utils.MaxBufLen) - } + //Printf不会发生 escapes to heap 现象,所以我们统一用 Printf + fmt.Printf("Log Level:%d\n", utils.LogLevel) + fmt.Printf("UseReadv:%t\n", netLayer.UseReadv) runPreCommands() @@ -153,9 +151,10 @@ func main() { //load server and routePolicy switch confMode { case simpleMode: - defaultInServer, err = proxy.ServerFromURL(simpleConf.Server_ThatListenPort_Url) - if err != nil { - log.Fatalln("can not create local server: ", err) + var hase bool + defaultInServer, hase, err = proxy.ServerFromURL(simpleConf.Server_ThatListenPort_Url) + if hase { + log.Fatalf("can not create local server: %s\n", err) } if !defaultInServer.CantRoute() && simpleConf.Route != nil { @@ -217,8 +216,9 @@ func main() { // load client switch confMode { case simpleMode: - defaultOutClient, err = proxy.ClientFromURL(simpleConf.Client_ThatDialRemote_Url) - if err != nil { + var hase bool + defaultOutClient, hase, err = proxy.ClientFromURL(simpleConf.Client_ThatDialRemote_Url) + if hase { log.Fatalln("can not create remote client: ", err) } case standardMode: @@ -274,14 +274,14 @@ func listenSer(inServer proxy.Server, defaultOutClientForThis proxy.Client) { handleFunc := inServer.HandleInitialLayersFunc() if handleFunc == nil { - log.Fatal("inServer.IsHandleInitialLayers but inServer.HandleInitialLayersFunc() returns nil") + log.Fatalf("inServer.IsHandleInitialLayers but inServer.HandleInitialLayersFunc() returns nil\n") } newConnChan, baseConn := handleFunc() if newConnChan == nil { //baseConn可以为nil,quic就是如此 if utils.CanLogErr() { - log.Println("StarthandleInitialLayers can't extablish baseConn") + log.Printf("StarthandleInitialLayers can't extablish baseConn\n") } return } @@ -291,7 +291,7 @@ func listenSer(inServer proxy.Server, defaultOutClientForThis proxy.Client) { newConn, ok := <-newConnChan if !ok { if utils.CanLogErr() { - log.Println("read from SuperProxy not ok") + log.Printf("read from SuperProxy not ok\n") } @@ -313,7 +313,7 @@ func listenSer(inServer proxy.Server, defaultOutClientForThis proxy.Client) { }() if utils.CanLogInfo() { - log.Println(proxy.GetFullName(inServer), "is listening ", inServer.Network(), "on", inServer.AddrStr()) + log.Printf("%s is listening %s on %s\n", proxy.GetFullName(inServer), inServer.Network(), inServer.AddrStr()) } return @@ -328,13 +328,13 @@ func listenSer(inServer proxy.Server, defaultOutClientForThis proxy.Client) { if err == nil { if utils.CanLogInfo() { - log.Println(proxy.GetFullName(inServer), "is listening ", network, "on", inServer.AddrStr()) + log.Printf("%s is listening %s on %s\n", proxy.GetFullName(inServer), network, inServer.AddrStr()) } } else { if err != nil { - log.Fatalln("can not listen inServer on", inServer.AddrStr(), err) + log.Fatalf("can not listen inServer on %s %s\n", inServer.AddrStr(), err) } } @@ -392,7 +392,7 @@ func handleNewIncomeConnection(inServer proxy.Server, defaultClientForThis proxy if utils.CanLogInfo() { str := wrappedConn.RemoteAddr().String() - log.Println("New Accepted Conn from", str, ", being handled by "+proxy.GetVSI_url(inServer)) + log.Printf("New Accepted Conn from %s , being handled by %s\n", str, proxy.GetVSI_url(inServer)) iics.cachedRemoteAddr = str } @@ -419,7 +419,7 @@ func handleNewIncomeConnection(inServer proxy.Server, defaultClientForThis proxy if err != nil { if utils.CanLogErr() { - log.Println("failed in inServer tls handshake ", inServer.AddrStr(), err) + log.Printf("failed in inServer tls handshake %s %s\n", inServer.AddrStr(), err) } wrappedConn.Close() @@ -450,7 +450,7 @@ func handleNewIncomeConnection(inServer proxy.Server, defaultClientForThis proxy // 我们直接循环监听然后分别用 新goroutine发向 handshakeInserver_and_passToOutClient if utils.CanLogDebug() { - log.Println("start upgrade grpc") + log.Printf("start upgrade grpc\n") } grpcs := inServer.GetGRPC_Server() //这个grpc server是在配置阶段初始化好的. @@ -464,7 +464,7 @@ func handleNewIncomeConnection(inServer proxy.Server, defaultClientForThis proxy newGConn, ok := <-grpcs.NewConnChan if !ok { if utils.CanLogWarn() { - log.Println("grpc getNewSubConn not ok") + log.Printf("grpc getNewSubConn not ok\n") } iics.baseLocalConn.Close() @@ -487,12 +487,12 @@ func handleNewIncomeConnection(inServer proxy.Server, defaultClientForThis proxy if re != nil { if re == httpLayer.ErrNotHTTP_Request { if utils.CanLogErr() { - log.Println("ws: got not http request ", inServer.AddrStr()) + log.Printf("ws: got not http request %s\n", inServer.AddrStr()) } } else { if utils.CanLogErr() { - log.Println("ws: handshake read error ", inServer.AddrStr()) + log.Printf("ws: handshake read error %s\n", inServer.AddrStr()) } } @@ -507,7 +507,7 @@ func handleNewIncomeConnection(inServer proxy.Server, defaultClientForThis proxy iics.theFallbackFirstBuffer = rp.WholeRequestBuf if utils.CanLogDebug() { - log.Println("ws path not match", rp.Method, rp.Path, "should be:", wss.Thepath) + log.Printf("ws path not match %s %s should be: %s\n", rp.Method, rp.Path, wss.Thepath) } @@ -520,7 +520,7 @@ func handleNewIncomeConnection(inServer proxy.Server, defaultClientForThis proxy wsConn, err := wss.Handshake(rp.WholeRequestBuf, wrappedConn) if err != nil { if utils.CanLogErr() { - log.Println("failed in inServer websocket handshake ", inServer.AddrStr(), err) + log.Printf("failed in inServer websocket handshake %s %s\n", inServer.AddrStr(), err) } @@ -550,7 +550,7 @@ func handshakeInserver_and_passToOutClient(iics incomingInserverConnState) { inServer := iics.inServer var wlc io.ReadWriteCloser - var targetAddr *netLayer.Addr + var targetAddr netLayer.Addr var err error if iics.shouldFallback { @@ -571,7 +571,7 @@ func handshakeInserver_and_passToOutClient(iics incomingInserverConnState) { wlc = nil if utils.CanLogWarn() { - log.Println("failed in inServer proxy handshake from", inServer.AddrStr(), err) + log.Printf("failed in inServer proxy handshake from %s %s\n", inServer.AddrStr(), err) } if !inServer.CanFallback() { @@ -591,7 +591,7 @@ func handshakeInserver_and_passToOutClient(iics incomingInserverConnState) { iics.theFallbackFirstBuffer = fe.First if iics.theFallbackFirstBuffer == nil { //不应该,至少能读到1字节的。 - log.Fatal("No FirstBuffer") + log.Fatalf("No FirstBuffer\n") } } @@ -602,7 +602,7 @@ checkFallback: if mainFallback != nil { if utils.CanLogDebug() { - log.Println("checkFallback") + log.Printf("checkFallback\n") } var thisFallbackType byte @@ -649,10 +649,10 @@ checkFallback: fbAddr := mainFallback.GetFallback(thisFallbackType, fallback_params...) if utils.CanLogDebug() { - log.Println("checkFallback ,matched fallback:", fbAddr) + log.Printf("checkFallback ,matched fallback: %s\n", fbAddr.String()) } if fbAddr != nil { - targetAddr = fbAddr + targetAddr = *fbAddr wlc = wrappedConn goto afterLocalServerHandshake } @@ -661,7 +661,7 @@ checkFallback: //默认回落, 每个listen配置 都可 有一个自己独享的默认回落 - if defaultFallbackAddr := inServer.GetFallback(); defaultFallbackAddr != nil { + if defaultFallbackAddr := inServer.GetFallback(); !defaultFallbackAddr.IsEmpty() { targetAddr = defaultFallbackAddr wlc = wrappedConn @@ -673,7 +673,7 @@ afterLocalServerHandshake: if wlc == nil { //无wlc证明 inServer 握手失败,且 没有任何回落可用, 直接return if utils.CanLogDebug() { - log.Println("invalid request and no matched fallback, hung up.") + log.Printf("invalid request and no matched fallback, hung up.\n") } wrappedConn.Close() return @@ -692,7 +692,7 @@ afterLocalServerHandshake: } if utils.CanLogDebug() { - log.Println("try routing", desc) + log.Printf("try routing %v\n", desc) } outtag := routePolicy.GetOutTag(desc) @@ -702,7 +702,7 @@ afterLocalServerHandshake: iics.routedToDirect = true if utils.CanLogInfo() { - log.Println("routed to direct", targetAddr.UrlString()) + log.Printf("routed to direct %s\n", targetAddr.UrlString()) } } else { //log.Println("outtag", outtag, clientsTagMap) @@ -710,7 +710,7 @@ afterLocalServerHandshake: if tagC, ok := clientsTagMap[outtag]; ok { client = tagC if utils.CanLogInfo() { - log.Println("routed to", outtag, proxy.GetFullName(client)) + log.Printf("routed to %s %s\n", outtag, proxy.GetFullName(client)) } } } @@ -743,7 +743,7 @@ afterLocalServerHandshake: if isTlsLazy_clientEnd || iics.isTlsLazyServerEnd { if tlsLayer.PDD { - log.Println("loading TLS SniffConn", isTlsLazy_clientEnd, iics.isTlsLazyServerEnd) + log.Printf("loading TLS SniffConn %t %t\n", isTlsLazy_clientEnd, iics.isTlsLazyServerEnd) } wlc = tlsLayer.NewSniffConn(iics.baseLocalConn, wlc, isTlsLazy_clientEnd, tls_lazy_secure) @@ -836,7 +836,7 @@ afterLocalServerHandshake: unknownRemoteAddrMsgWriter = theCRUMFURS - uniExtractor := netLayer.NewUniUDP_Extractor(targetAddr.ToUDPAddr(), wlc, unknownRemoteAddrMsgWriter) + uniExtractor := netLayer.NewUniUDP_Extractor(*targetAddr.ToUDPAddr(), wlc, unknownRemoteAddrMsgWriter) netLayer.RelayUDP_to_Direct(uniExtractor) //阻塞 @@ -847,7 +847,7 @@ afterLocalServerHandshake: // 此时socks5包已经帮我们dial好了一个udp连接,即wlc,但是还未读取到客户端想要访问的东西 udpConn := wlc.(*socks5.UDPConn) - dialFunc := func(targetAddr *netLayer.Addr) (io.ReadWriter, error) { + dialFunc := func(targetAddr netLayer.Addr) (io.ReadWriter, error) { return dialClient(incomingInserverConnState{}, targetAddr, client, false, nil, true) } @@ -871,7 +871,7 @@ afterLocalServerHandshake: } else { if utils.CanLogErr() { - log.Println("socks5 server -> client for udp, but client didn't implement netLayer.UDP_Putter", client.Name()) + log.Printf("socks5 server -> client for udp, but client didn't implement netLayer.UDP_Putter, %s\n", client.Name()) } } return @@ -892,7 +892,7 @@ afterLocalServerHandshake: //client为真实要拨号的client,可能会与iics里的defaultClient不同。以client为准。 // wlc为调用者所提供的 此请求的 来源 链接。wlc主要用于 Copy阶段. // noCopy是为了让其它调用者自行处理 转发 时使用。 -func dialClient(iics incomingInserverConnState, targetAddr *netLayer.Addr, client proxy.Client, isTlsLazy_clientEnd bool, wlc io.ReadWriteCloser, noCopy bool) (io.ReadWriter, error) { +func dialClient(iics incomingInserverConnState, targetAddr netLayer.Addr, client proxy.Client, isTlsLazy_clientEnd bool, wlc io.ReadWriteCloser, noCopy bool) (io.ReadWriter, error) { if iics.shouldCloseInSerBaseConnWhenFinish && !noCopy { if iics.baseLocalConn != nil { @@ -906,18 +906,18 @@ func dialClient(iics incomingInserverConnState, targetAddr *netLayer.Addr, clien //direct的话自己是没有目的地址的,直接使用 请求的地址 // 而其它代理的话, realTargetAddr会被设成实际配置的代理的地址 - var realTargetAddr *netLayer.Addr = targetAddr + var realTargetAddr netLayer.Addr = targetAddr if uniqueTestDomain != "" && uniqueTestDomain != targetAddr.Name { if utils.CanLogDebug() { - log.Println("request isn't the appointed domain", targetAddr, uniqueTestDomain) + log.Printf("request isn't the appointed domain, %s, %s\n", targetAddr.String(), uniqueTestDomain) } return nil, utils.NumErr{N: 1, Prefix: "dialClient err, "} } if utils.CanLogInfo() { - log.Println(iics.cachedRemoteAddr, " request ", targetAddr.UrlString(), "through", proxy.GetVSI_url(client)) + log.Printf("%s request %s through %s\n", iics.cachedRemoteAddr, targetAddr.UrlString(), proxy.GetVSI_url(client)) } @@ -926,7 +926,7 @@ func dialClient(iics incomingInserverConnState, targetAddr *netLayer.Addr, clien realTargetAddr, err = netLayer.NewAddr(client.AddrStr()) if err != nil { - log.Fatal("convert addr err:", err) + log.Fatalf("convert addr err:%s\n", err) } realTargetAddr.Network = client.Network() } @@ -943,7 +943,7 @@ func dialClient(iics incomingInserverConnState, targetAddr *netLayer.Addr, clien switch client.AdvancedLayer() { case "grpc": - grpcClientConn = grpc.GetEstablishedConnFor(realTargetAddr) + grpcClientConn = grpc.GetEstablishedConnFor(&realTargetAddr) if grpcClientConn != nil { //如果有已经建立好的连接,则跳过拨号阶段 @@ -951,7 +951,7 @@ func dialClient(iics incomingInserverConnState, targetAddr *netLayer.Addr, clien } case "quic": //quic这里并不是在tls层基础上进行dial,而是直接dial - dailedCommonConn = client.DialCommonInitialLayerConnFunc()(realTargetAddr) + dailedCommonConn = client.DialCommonInitialLayerConnFunc()(&realTargetAddr) if dailedCommonConn != nil { //如果有已经建立好的连接,则跳过拨号阶段 goto advLayerStep @@ -965,7 +965,7 @@ func dialClient(iics incomingInserverConnState, targetAddr *netLayer.Addr, clien clientConn, err = realTargetAddr.Dial() if err != nil { if utils.CanLogErr() { - log.Println("failed in dial", realTargetAddr.String(), ", Reason: ", err) + log.Printf("failed in dial %s , Reason: , %s\n", realTargetAddr.String(), err) } return nil, utils.NumErr{N: 2, Prefix: "dialClient err, "} @@ -986,7 +986,7 @@ func dialClient(iics incomingInserverConnState, targetAddr *netLayer.Addr, clien // 而且为了避免黑客攻击或探测,我们要使用uuid作为特殊指令,此时需要 UserServer和 UserClient if uc := client.(proxy.UserClient); uc != nil { - tryTlsLazyRawCopy(true, uc, nil, targetAddr, clientConn, wlc, nil, true, nil) + tryTlsLazyRawCopy(true, uc, nil, &targetAddr, clientConn, wlc, nil, true, nil) } @@ -1002,7 +1002,7 @@ func dialClient(iics incomingInserverConnState, targetAddr *netLayer.Addr, clien tlsConn, err := client.GetTLS_Client().Handshake(clientConn) if err != nil { - log.Println("failed in handshake outClient tls", targetAddr.String(), ", Reason: ", err) + log.Printf("failed in handshake outClient tls %s, Reason: %s\n", targetAddr.String(), err) return nil, utils.NumErr{N: 4, Prefix: "dialClient err, "} } @@ -1020,16 +1020,16 @@ advLayerStep: clientConn, err = client.DialSubConnFunc()(dailedCommonConn) if err != nil { if utils.CanLogErr() { - log.Println("DialSubConnFunc failed,", err) + log.Printf("DialSubConnFunc failed, %s\n", err) } return nil, utils.NumErr{N: 14, Prefix: "DialSubConnFunc err, "} } case "grpc": if grpcClientConn == nil { - grpcClientConn, err = grpc.ClientHandshake(clientConn, realTargetAddr) + grpcClientConn, err = grpc.ClientHandshake(clientConn, &realTargetAddr) if err != nil { if utils.CanLogErr() { - log.Println("grpc.ClientHandshake failed,", err) + log.Printf("grpc.ClientHandshake failed, %s\n", err) } if iics.baseLocalConn != nil { @@ -1041,10 +1041,10 @@ advLayerStep: } - clientConn, err = grpc.DialNewSubConn(client.Path(), grpcClientConn, realTargetAddr) + clientConn, err = grpc.DialNewSubConn(client.Path(), grpcClientConn, &realTargetAddr) if err != nil { if utils.CanLogErr() { - log.Println("grpc.DialNewSubConn failed,", err) + log.Printf("grpc.DialNewSubConn failed,%s\n", err) //如果底层tcp连接被关闭了的话,错误会是: // rpc error: code = Unavailable desc = connection error: desc = "transport: failed to write client preface: tls: use of closed connection" @@ -1068,7 +1068,7 @@ advLayerStep: n, e := wlc.Read(edBuf) if e != nil { if utils.CanLogErr() { - log.Println("err when reading ws early data", e) + log.Printf("err when reading ws early data %s\n", e) } return nil, utils.NumErr{N: 7, Prefix: "dialClient err, "} } @@ -1093,7 +1093,7 @@ advLayerStep: //wc, err := wsClient.Handshake(clientConn, ed) if err != nil { if utils.CanLogErr() { - log.Println("failed in handshake ws to", targetAddr.String(), ", Reason: ", err) + log.Printf("failed in handshake ws to %s , Reason: %s\n", targetAddr.String(), err) } return nil, utils.NumErr{N: 8, Prefix: "dialClient err, "} @@ -1105,10 +1105,10 @@ advLayerStep: ////////////////////////////// 代理层 握手阶段 ///////////////////////////////////// - wrc, err := client.Handshake(clientConn, targetAddr) + wrc, err := client.Handshake(clientConn, &targetAddr) if err != nil { if utils.CanLogErr() { - log.Println("failed in handshake to", targetAddr.String(), ", Reason: ", err) + log.Printf("failed in handshake to %s , Reason: %s\n", targetAddr.String(), err) } return nil, utils.NumErr{N: 9, Prefix: "dialClient err, "} @@ -1154,7 +1154,7 @@ advLayerStep: utils.PutBytes(iics.theFallbackFirstBuffer.Bytes()) //这个Buf不是从utils.GetBuf创建的,而是从一个 GetBytes的[]byte 包装 的,所以我们要PutBytes,而不是PutBuf } - netLayer.Relay(realTargetAddr, wlc, wrc) + netLayer.Relay(&realTargetAddr, wlc, wrc) return wrc, nil } diff --git a/netLayer/addr.go b/netLayer/addr.go index 4e5cace..47fbac7 100644 --- a/netLayer/addr.go +++ b/netLayer/addr.go @@ -48,8 +48,8 @@ func GetRandLocalAddr() string { return "0.0.0.0:" + RandPortStr() } -func NewAddrFromUDPAddr(addr *net.UDPAddr) *Addr { - return &Addr{ +func NewAddrFromUDPAddr(addr *net.UDPAddr) Addr { + return Addr{ IP: addr.IP, Port: addr.Port, Network: "udp", @@ -57,27 +57,27 @@ func NewAddrFromUDPAddr(addr *net.UDPAddr) *Addr { } //addrStr格式一般为 host:port ;如果不含冒号,将直接认为该字符串是域名或文件名 -func NewAddr(addrStr string) (*Addr, error) { +func NewAddr(addrStr string) (Addr, error) { if !strings.Contains(addrStr, ":") { //unix domain socket, 或者域名默认端口的情况 - return &Addr{Name: addrStr}, nil + return Addr{Name: addrStr}, nil } return NewAddrByHostPort(addrStr) } //hostPortStr格式 必须为 host:port,本函数不对此检查 -func NewAddrByHostPort(hostPortStr string) (*Addr, error) { +func NewAddrByHostPort(hostPortStr string) (Addr, error) { host, portStr, err := net.SplitHostPort(hostPortStr) if err != nil { - return nil, err + return Addr{}, err } if host == "" { host = "127.0.0.1" } port, err := strconv.Atoi(portStr) - a := &Addr{Port: port} + a := Addr{Port: port} if ip := net.ParseIP(host); ip != nil { a.IP = ip } else { @@ -88,27 +88,27 @@ func NewAddrByHostPort(hostPortStr string) (*Addr, error) { // 如 tcp://127.0.0.1:443 , tcp://google.com:443 ; // 不支持unix domain socket, 因为它是文件路径, / 还需要转义,太麻烦;不是我们代码麻烦, 而是怕用户嫌麻烦 -func NewAddrByURL(addrStr string) (*Addr, error) { +func NewAddrByURL(addrStr string) (Addr, error) { u, err := url.Parse(addrStr) if err != nil { - return nil, err + return Addr{}, err } if u.Scheme == "unix" { - return nil, errors.New("parse unix domain socket by url is not supported") + return Addr{}, errors.New("parse unix domain socket by url is not supported") } addrStr = u.Host host, portStr, err := net.SplitHostPort(addrStr) if err != nil { - return nil, err + return Addr{}, err } if host == "" { host = "127.0.0.1" } port, err := strconv.Atoi(portStr) - a := &Addr{Port: port} + a := Addr{Port: port} if ip := net.ParseIP(host); ip != nil { a.IP = ip } else { @@ -121,7 +121,7 @@ func NewAddrByURL(addrStr string) (*Addr, error) { } //会根据thing的类型 生成实际addr; 可以为数字端口,或者带冒号的字符串,或者一个 文件路径(unix domain socket) -func NewAddrFromAny(thing any) (addr *Addr, err error) { +func NewAddrFromAny(thing any) (addr Addr, err error) { var integer int var dest_type byte = 0 //0: port, 1: ip:port, 2: unix domain socket var dest_string string @@ -130,7 +130,7 @@ func NewAddrFromAny(thing any) (addr *Addr, err error) { case float64: //json 默认把数字转换成float64,就算是整数也一样 if value > 65535 || value < 1 { - err = utils.NewDataErr("int port not valid", nil, value) + err = utils.ErrInErr{ErrDesc: "int port not valid", Data: value} return } @@ -152,24 +152,24 @@ func NewAddrFromAny(thing any) (addr *Addr, err error) { } default: - err = utils.NewDataErr("Fallback dest config type err", nil, reflect.TypeOf(thing)) + err = utils.ErrInErr{ErrDesc: "Fallback dest config type err", Data: reflect.TypeOf(thing)} return } switch dest_type { case 0: - addr = &Addr{ + addr = Addr{ IP: net.IPv4(127, 0, 0, 1), Port: integer, } case 1: addr, err = NewAddrByHostPort(dest_string) if err != nil { - err = utils.NewDataErr("addr create with given string failed", err, dest_string) + err = utils.ErrInErr{ErrDesc: "addr create with given string failed", ErrDetail: err, Data: dest_string} return } case 2: - addr = &Addr{ + addr = Addr{ Network: "unix", Name: dest_string, } @@ -212,6 +212,10 @@ func (a *Addr) UrlString() string { } +func (a *Addr) IsEmpty() bool { + return a.Name == "" && len(a.IP) == 0 && a.Network == "" && a.Port == 0 +} + func (a *Addr) GetNetIPAddr() (na netip.Addr) { if len(a.IP) < 1 { return diff --git a/netLayer/listen.go b/netLayer/listen.go index 2baa76a..bc662b8 100644 --- a/netLayer/listen.go +++ b/netLayer/listen.go @@ -70,7 +70,7 @@ func ListenAndAccept(network, addr string, acceptFunc func(net.Conn)) error { } err := os.Remove(addr) if err != nil { - return utils.NewDataErr("Error when deleting previous unix socket file,", err, addr) + return utils.ErrInErr{ErrDesc: "Error when deleting previous unix socket file,", ErrDetail: err, Data: addr} } } diff --git a/netLayer/route.go b/netLayer/route.go index 9078985..e1efba2 100644 --- a/netLayer/route.go +++ b/netLayer/route.go @@ -10,7 +10,7 @@ import ( // TargetDescription 可以完整地描述一个网络层/传输层上的一个特定目标, // 一般来说,一个具体的监听配置就会分配一个tag type TargetDescription struct { - Addr *Addr + Addr Addr Tag string } @@ -72,7 +72,7 @@ func (sg *RouteSet) IsTransportProtocolAllowed(p uint16) bool { return sg.AllowedTransportLayerProtocols&p > 0 } -func (sg *RouteSet) IsAddrNetworkAllowed(a *Addr) bool { +func (sg *RouteSet) IsAddrNetworkAllowed(a Addr) bool { if a.Network == "" { return sg.IsTransportProtocolAllowed(TCP) @@ -91,7 +91,7 @@ func (sg *RouteSet) IsTCPAllowed() bool { return sg.IsTransportProtocolAllowed(TCP) } -func (sg *RouteSet) IsAddrIn(a *Addr) bool { +func (sg *RouteSet) IsAddrIn(a Addr) bool { //我们先过滤传输层,再过滤网络层 if !sg.IsAddrNetworkAllowed(a) { diff --git a/netLayer/udp_relay.go b/netLayer/udp_relay.go index 49cb303..bf96ed8 100644 --- a/netLayer/udp_relay.go +++ b/netLayer/udp_relay.go @@ -13,7 +13,7 @@ const ( //本文件内含 一些 转发 udp 数据的 接口与方法 // 阻塞. -func RelayUDP(putter UDP_Putter, extractor UDP_Extractor, dialFunc func(targetAddr *Addr) (io.ReadWriter, error)) { +func RelayUDP(putter UDP_Putter, extractor UDP_Extractor, dialFunc func(targetAddr Addr) (io.ReadWriter, error)) { go func() { for { @@ -43,11 +43,11 @@ func RelayUDP(putter UDP_Putter, extractor UDP_Extractor, dialFunc func(targetAd //////////////////// 接口 //////////////////// type UDPRequestReader interface { - GetNewUDPRequest() (*net.UDPAddr, []byte, error) + GetNewUDPRequest() (net.UDPAddr, []byte, error) } type UDPResponseWriter interface { - WriteUDPResponse(*net.UDPAddr, []byte) error + WriteUDPResponse(net.UDPAddr, []byte) error } // UDP_Extractor, 用于从一个虚拟的协议中提取出 udp请求 @@ -61,12 +61,12 @@ type UDP_Extractor interface { // 写入一个UDP请求; 可以包裹成任意协议。 // 因为有时该地址从来没申请过,所以此时就要用dialFunc创建一个新连接 type UDPRequestWriter interface { - WriteUDPRequest(target *net.UDPAddr, request []byte, dialFunc func(targetAddr *Addr) (io.ReadWriter, error)) error + WriteUDPRequest(target net.UDPAddr, request []byte, dialFunc func(targetAddr Addr) (io.ReadWriter, error)) error } //拉取一个新的 UDP 响应 type UDPResponseReader interface { - GetNewUDPResponse() (*net.UDPAddr, []byte, error) + GetNewUDPResponse() (net.UDPAddr, []byte, error) } // UDP_Putter, 用于把 udp请求转换成 虚拟的协议 @@ -85,14 +85,14 @@ type UDP_Putter interface { // 对于 vless v1来说, unknownRemoteAddrMsgWriter 要做的 就是 新建一个与服务端的 请求udp的连接, // 然后这个新连接就变成了新的 UniUDP_Putter type UniUDP_Putter struct { - targetAddr *net.UDPAddr + targetAddr net.UDPAddr io.ReadWriter unknownRemoteAddrMsgWriter UDPRequestWriter } // -func (e *UniUDP_Putter) GetNewUDPResponse() (*net.UDPAddr, []byte, error) { +func (e *UniUDP_Putter) GetNewUDPResponse() (net.UDPAddr, []byte, error) { bs := make([]byte, MaxUDP_packetLen) n, err := e.ReadWriter.Read(bs) if err != nil { @@ -101,7 +101,7 @@ func (e *UniUDP_Putter) GetNewUDPResponse() (*net.UDPAddr, []byte, error) { return e.targetAddr, bs[:n], nil } -func (e *UniUDP_Putter) WriteUDPRequest(addr *net.UDPAddr, bs []byte, dialFunc func(targetAddr *Addr) (io.ReadWriter, error)) (err error) { +func (e *UniUDP_Putter) WriteUDPRequest(addr net.UDPAddr, bs []byte, dialFunc func(targetAddr Addr) (io.ReadWriter, error)) (err error) { if addr.String() == e.targetAddr.String() { _, err = e.ReadWriter.Write(bs) @@ -122,14 +122,14 @@ func (e *UniUDP_Putter) WriteUDPRequest(addr *net.UDPAddr, bs []byte, dialFunc f // 收到的响应数据的来源 如果和 targetAddr 相同的话,直接写入传入的 ReadWriter // 收到的外界数据的来源 如果和 targetAddr 不同的话,那肯定就是使用了fullcone,那么要传入 unknownRemoteAddrMsgWriter; 如果New时传入unknownRemoteAddrMsgWriter的 是nil的话,那么意思就是不支持fullcone,将直接舍弃这一部分数据。 type UniUDP_Extractor struct { - targetAddr *net.UDPAddr + targetAddr net.UDPAddr io.ReadWriter unknownRemoteAddrMsgWriter UDPResponseWriter } // 新建,unknownRemoteAddrMsgWriter 用于写入 未知来源响应,rw 用于普通的客户请求的目标的响应 -func NewUniUDP_Extractor(addr *net.UDPAddr, rw io.ReadWriter, unknownRemoteAddrMsgWriter UDPResponseWriter) *UniUDP_Extractor { +func NewUniUDP_Extractor(addr net.UDPAddr, rw io.ReadWriter, unknownRemoteAddrMsgWriter UDPResponseWriter) *UniUDP_Extractor { return &UniUDP_Extractor{ targetAddr: addr, ReadWriter: rw, @@ -138,7 +138,7 @@ func NewUniUDP_Extractor(addr *net.UDPAddr, rw io.ReadWriter, unknownRemoteAddrM } // 从客户端连接中 提取出 它的 UDP请求,就是直接读取数据。然后搭配上之前设置好的地址 -func (e *UniUDP_Extractor) GetNewUDPRequest() (*net.UDPAddr, []byte, error) { +func (e *UniUDP_Extractor) GetNewUDPRequest() (net.UDPAddr, []byte, error) { bs := make([]byte, MaxUDP_packetLen) n, err := e.ReadWriter.Read(bs) if err != nil { @@ -150,7 +150,7 @@ func (e *UniUDP_Extractor) GetNewUDPRequest() (*net.UDPAddr, []byte, error) { // WriteUDPResponse 写入远程服务器的响应;要分情况讨论。 // 因为是单一目标extractor,所以正常情况下 传入的response 的源地址 也 应和 e.targetAddr 相同, // 如果地址不同的话,那肯定就是使用了fullcone,那么要传入 unknownRemoteAddrMsgWriter -func (e *UniUDP_Extractor) WriteUDPResponse(addr *net.UDPAddr, bs []byte) (err error) { +func (e *UniUDP_Extractor) WriteUDPResponse(addr net.UDPAddr, bs []byte) (err error) { if addr.String() == e.targetAddr.String() { _, err = e.ReadWriter.Write(bs) @@ -168,7 +168,7 @@ func (e *UniUDP_Extractor) WriteUDPResponse(addr *net.UDPAddr, bs []byte) (err e } type UDPAddrData struct { - Addr *net.UDPAddr + Addr net.UDPAddr Data []byte } @@ -183,20 +183,20 @@ func NewUDP_Pipe() *UDP_Pipe { responseChan: make(chan UDPAddrData, 10), } } -func (u *UDP_Pipe) GetNewUDPRequest() (*net.UDPAddr, []byte, error) { +func (u *UDP_Pipe) GetNewUDPRequest() (net.UDPAddr, []byte, error) { d := <-u.requestChan return d.Addr, d.Data, nil } -func (u *UDP_Pipe) GetNewUDPResponse() (*net.UDPAddr, []byte, error) { +func (u *UDP_Pipe) GetNewUDPResponse() (net.UDPAddr, []byte, error) { d := <-u.responseChan return d.Addr, d.Data, nil } // 会保存bs的副本,不必担心数据被改变的问题。 -func (u *UDP_Pipe) WriteUDPResponse(addr *net.UDPAddr, bs []byte) error { +func (u *UDP_Pipe) WriteUDPResponse(addr net.UDPAddr, bs []byte) error { bsCopy := make([]byte, len(bs)) copy(bsCopy, bs) @@ -208,7 +208,7 @@ func (u *UDP_Pipe) WriteUDPResponse(addr *net.UDPAddr, bs []byte) error { } // 会保存bs的副本,不必担心数据被改变的问题。 -func (u *UDP_Pipe) WriteUDPRequest(addr *net.UDPAddr, bs []byte, dialFunc func(targetAddr *Addr) (io.ReadWriter, error)) error { +func (u *UDP_Pipe) WriteUDPRequest(addr net.UDPAddr, bs []byte, dialFunc func(targetAddr Addr) (io.ReadWriter, error)) error { bsCopy := make([]byte, len(bs)) copy(bsCopy, bs) @@ -254,7 +254,7 @@ func RelayUDP_to_Direct(extractor UDP_Extractor) { } else { - newConn, err := net.DialUDP("udp", nil, addr) + newConn, err := net.DialUDP("udp", nil, &addr) if err != nil { break } @@ -269,7 +269,7 @@ func RelayUDP_to_Direct(extractor UDP_Extractor) { mutex.Unlock() //监听所有发往 newConn的 远程任意主机 发来的消息。 - go func(thisconn *net.UDPConn, supposedRemoteAddr *net.UDPAddr) { + go func(thisconn *net.UDPConn, supposedRemoteAddr net.UDPAddr) { bs := make([]byte, MaxUDP_packetLen) for { //log.Println("redirect udp, start read", supposedRemoteAddr) @@ -289,7 +289,7 @@ func RelayUDP_to_Direct(extractor UDP_Extractor) { //log.Println("redirect udp, will write to extractor", string(bs[:n])) - err = extractor.WriteUDPResponse(raddr, bs[:n]) + err = extractor.WriteUDPResponse(*raddr, bs[:n]) if err != nil { break } diff --git a/proxy/config_simple.go b/proxy/config_simple.go index ffd424e..4ef3ed2 100644 --- a/proxy/config_simple.go +++ b/proxy/config_simple.go @@ -18,27 +18,35 @@ type Simple struct { MyCountryISO_3166 string `toml:"mycountry" json:"mycountry"` } -func LoadSimpleConfigFile(fileNamePath string) (*Simple, error) { +func LoadSimpleConfigFile(fileNamePath string) (config Simple, hasError bool, E utils.ErrInErr) { if cf, err := os.Open(fileNamePath); err == nil { defer cf.Close() bs, _ := ioutil.ReadAll(cf) - config := &Simple{} - if err = json.Unmarshal(bs, config); err != nil { - return nil, utils.NewDataErr("can not parse config file ", err, fileNamePath) + if err = json.Unmarshal(bs, &config); err != nil { + hasError = true + E = utils.ErrInErr{ + ErrDesc: "can not parse config file ", + ErrDetail: err, + Data: fileNamePath, + } + } - return config, nil + return } else { - return nil, utils.NewErr("can't open config file", err) + hasError = true + E = utils.ErrInErr{ErrDesc: "can't open config file", ErrDetail: err} + return } } -func LoadSimpleConfigFromStr(str string) (*Simple, error) { - config := &Simple{} - if err := json.Unmarshal([]byte(str), config); err != nil { - return nil, utils.NewErr("can not parse config ", err) +func LoadSimpleConfigFromStr(str string) (config Simple, hasE bool, E utils.ErrInErr) { + + if err := json.Unmarshal([]byte(str), &config); err != nil { + E = utils.ErrInErr{ErrDesc: "can not parse config ", ErrDetail: err} + hasE = true } - return config, nil + return } diff --git a/proxy/config_standard.go b/proxy/config_standard.go index 2c65249..f2412a4 100644 --- a/proxy/config_standard.go +++ b/proxy/config_standard.go @@ -130,21 +130,20 @@ type Standard struct { App *AppConf `toml:"app"` } -func LoadTomlConfStr(str string) (c *Standard, err error) { - c = &Standard{} - _, err = toml.Decode(str, c) +func LoadTomlConfStr(str string) (c Standard, err error) { + _, err = toml.Decode(str, &c) return } -func LoadTomlConfFile(fileNamePath string) (*Standard, error) { +func LoadTomlConfFile(fileNamePath string) (Standard, error) { if cf, err := os.Open(fileNamePath); err == nil { defer cf.Close() bs, _ := ioutil.ReadAll(cf) return LoadTomlConfStr(string(bs)) } else { - return nil, utils.NewErr("can't open config file", err) + return Standard{}, utils.ErrInErr{ErrDesc: "can't open config file", ErrDetail: err} } } diff --git a/proxy/config_test.go b/proxy/config_test.go index 33b4c25..bf86a41 100644 --- a/proxy/config_test.go +++ b/proxy/config_test.go @@ -21,8 +21,8 @@ func TestClientSimpleConfig(t *testing.T) { ] }` - mc, err := proxy.LoadSimpleConfigFromStr(confstr1) - if err != nil { + mc, hasE, err := proxy.LoadSimpleConfigFromStr(confstr1) + if hasE { t.Log("loadConfigFromStr err", err) t.FailNow() } diff --git a/proxy/creator.go b/proxy/creator.go index 057790a..e7a3741 100644 --- a/proxy/creator.go +++ b/proxy/creator.go @@ -68,17 +68,17 @@ func NewClient(dc *DialConf) (Client, error) { } } - return nil, utils.NewDataErr("unknown client protocol '", nil, protocol) + return nil, utils.ErrInErr{ErrDesc: "unknown client protocol ", Data: protocol} } // ClientFromURL calls the registered creator to create client. // dialer is the default upstream dialer so cannot be nil, we can use Default when calling this function. -func ClientFromURL(s string) (Client, error) { +func ClientFromURL(s string) (Client, bool, utils.ErrInErr) { u, err := url.Parse(s) if err != nil { - return nil, utils.NewDataErr("can not parse client url", err, s) + return nil, true, utils.ErrInErr{ErrDesc: "can not parse client url", ErrDetail: err, Data: s} } schemeName := strings.ToLower(u.Scheme) @@ -87,10 +87,10 @@ func ClientFromURL(s string) (Client, error) { if ok { c, e := creator.NewClientFromURL(u) if e != nil { - return nil, e + return nil, true, utils.ErrInErr{ErrDesc: "creator.NewClientFromURL err", ErrDetail: e} } configCommonByURL(c, u) - return c, nil + return c, false, utils.ErrInErr{} } else { //尝试判断是否套tls, 比如vlesss实际上是vless+tls,https实际上是http+tls @@ -100,20 +100,20 @@ func ClientFromURL(s string) (Client, error) { if ok { c, err := creator.NewClientFromURL(u) if err != nil { - return c, err + return nil, true, utils.ErrInErr{ErrDesc: "creator.NewClientFromURL err", ErrDetail: err} } configCommonByURL(c, u) c.SetUseTLS() prepareTLS_forProxyCommon_withURL(u, true, c) - return c, err + return c, false, utils.ErrInErr{} } } - return nil, utils.NewDataErr("unknown client protocol '", nil, u.Scheme) + return nil, false, utils.ErrInErr{ErrDesc: "unknown client protocol ", Data: u.Scheme} } func NewServer(lc *ListenConf) (Server, error) { @@ -130,7 +130,7 @@ func NewServer(lc *ListenConf) (Server, error) { ser.SetUseTLS() err = prepareTLS_forServer(ser, lc) if err != nil { - log.Fatalln("prepareTLS error", err) + log.Fatalf("prepareTLS error %s\n", err) } return ser, nil } @@ -149,24 +149,28 @@ func NewServer(lc *ListenConf) (Server, error) { ser.SetUseTLS() err = prepareTLS_forServer(ser, lc) if err != nil { - log.Fatalln("prepareTLS error", err) + log.Fatalf("prepareTLS error %s\n", err) } return ser, nil } } - return nil, utils.NewDataErr("unknown server protocol '", nil, protocol) + return nil, utils.ErrInErr{ErrDesc: "unknown server protocol ", Data: protocol} } // ServerFromURL calls the registered creator to create proxy servers // dialer is the default upstream dialer so cannot be nil, we can use Default when calling this function // 所有的server都可有 "norule"参数,标明无需路由或者此server不可使用路由,在监听多个ip时是有用的; // 路由配置可以在json的其他配置里面设置,如 mycountry项 -func ServerFromURL(s string) (Server, error) { +func ServerFromURL(s string) (Server, bool, utils.ErrInErr) { u, err := url.Parse(s) if err != nil { - return nil, utils.NewDataErr("can not parse server url ", err, s) + return nil, true, utils.ErrInErr{ + ErrDesc: "can not parse server url ", + ErrDetail: err, + Data: s, + } } schemeName := strings.ToLower(u.Scheme) @@ -174,29 +178,35 @@ func ServerFromURL(s string) (Server, error) { if ok { ser, err := creator.NewServerFromURL(u) if err != nil { - return nil, err + return nil, true, utils.ErrInErr{ + ErrDesc: "creator.NewServerFromURL err ", + ErrDetail: err, + } } configCommonURLQueryForServer(ser, u) - return ser, nil + return ser, false, utils.ErrInErr{} } else { realScheme := strings.TrimSuffix(schemeName, "s") creator, ok = serverCreatorMap[realScheme] if ok { server, err := creator.NewServerFromURL(u) if err != nil { - return nil, err + return nil, true, utils.ErrInErr{ + ErrDesc: "creator.NewServerFromURL err ", + ErrDetail: err, + } } configCommonURLQueryForServer(server, u) server.SetUseTLS() prepareTLS_forProxyCommon_withURL(u, false, server) - return server, nil + return server, false, utils.ErrInErr{} } } - return nil, utils.NewDataErr("unknown server protocol '", nil, u.Scheme) + return nil, true, utils.ErrInErr{ErrDesc: "unknown server protocol ", Data: u.Scheme} } //setTag, setCantRoute, call configCommonByURL @@ -218,7 +228,7 @@ func configCommonURLQueryForServer(ser ProxyCommon, u *url.URL) { fa, err := netLayer.NewAddr(fallbackStr) if err != nil { - log.Fatalln("invalid fallback ", fallbackStr) + log.Fatalf("invalid fallback %s\n", fallbackStr) } ser.setFallback(fa) diff --git a/proxy/dokodemo/server.go b/proxy/dokodemo/server.go index e7b77b6..cbf6582 100644 --- a/proxy/dokodemo/server.go +++ b/proxy/dokodemo/server.go @@ -73,7 +73,7 @@ func (_ ServerCreator) NewServer(lc *proxy.ListenConf) (proxy.Server, error) { type Server struct { proxy.ProxyCommonStruct - targetAddr *netLayer.Addr + targetAddr netLayer.Addr } func NewServer() (proxy.Server, error) { @@ -82,6 +82,6 @@ func NewServer() (proxy.Server, error) { } func (d *Server) Name() string { return name } -func (s *Server) Handshake(underlay net.Conn) (io.ReadWriteCloser, *netLayer.Addr, error) { +func (s *Server) Handshake(underlay net.Conn) (io.ReadWriteCloser, netLayer.Addr, error) { return underlay, s.targetAddr, nil } diff --git a/proxy/http/server.go b/proxy/http/server.go index 1dc5ce8..60ab8dc 100644 --- a/proxy/http/server.go +++ b/proxy/http/server.go @@ -48,7 +48,7 @@ func (_ Server) Name() string { return name } -func (s *Server) Handshake(underlay net.Conn) (newconn io.ReadWriteCloser, targetAddr *netLayer.Addr, err error) { +func (s *Server) Handshake(underlay net.Conn) (newconn io.ReadWriteCloser, targetAddr netLayer.Addr, err error) { var b = utils.GetMTU() //一般要获取请求信息,不需要那么长; 就算是http,加了path,也不用太长 //因为要储存为 firstdata,所以也无法直接放回 @@ -67,7 +67,7 @@ func (s *Server) Handshake(underlay net.Conn) (newconn io.ReadWriteCloser, targe method, path, failreason := httpLayer.GetRequestMethod_and_PATH_from_Bytes(b[:n], true) if failreason != 0 { - err = utils.NewDataErr("get method/path failed, method:"+method+" ,reason:", nil, failreason) + err = utils.ErrInErr{ErrDesc: "get method/path failed, method:" + method + " ,reason:", Data: failreason} //一个正常的http代理如果遇到了 格式不符的情况的话是要返回 400 等错误代码的 // 但是,也不能说不返回400的就是异常服务器,因为这可能是服务器自己的策略,无视一切错误请求,比如防黑客时就常常会如此. diff --git a/proxy/proxy.go b/proxy/proxy.go index 32d6c23..20cc4c1 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -17,17 +17,19 @@ import ( ) func PrintAllServerNames() { - fmt.Println("===============================\nSupported Server protocols:") + fmt.Printf("===============================\nSupported Server protocols:\n") for v := range serverCreatorMap { - fmt.Println(v) + fmt.Print(v) + fmt.Print("\n") } } func PrintAllClientNames() { - fmt.Println("===============================\nSupported client protocols:") + fmt.Printf("===============================\nSupported client protocols:\n") for v := range clientCreatorMap { - fmt.Println(v) + fmt.Print(v) + fmt.Print("\n") } } @@ -50,7 +52,7 @@ type Client interface { type Server interface { ProxyCommon - Handshake(underlay net.Conn) (io.ReadWriteCloser, *netLayer.Addr, error) + Handshake(underlay net.Conn) (io.ReadWriteCloser, netLayer.Addr, error) } // FullName 可以完整表示 一个 代理的 VSI 层级. @@ -116,8 +118,8 @@ type ProxyCommon interface { /////////////////// http层 /////////////////// //默认回落地址. - GetFallback() *netLayer.Addr - setFallback(*netLayer.Addr) + GetFallback() netLayer.Addr + setFallback(netLayer.Addr) CanFallback() bool //如果能fallback,则handshake失败后,可能会专门返回 FallbackErr,如监测到返回了 FallbackErr, 则main函数会进行 回落处理. @@ -196,7 +198,7 @@ func prepareTLS_forClient(com ProxyCommon, dc *DialConf) error { if e != nil { log.Fatalln("prepareTLS_forClient,quic,netLayer.NewAddr err: ", e) } - return quic.DialCommonInitialLayer(na, &tls.Config{ + return quic.DialCommonInitialLayer(&na, tls.Config{ InsecureSkipVerify: dc.Insecure, ServerName: dc.Host, NextProtos: alpnList, @@ -275,10 +277,10 @@ func prepareTLS_forServer(com ProxyCommon, lc *ListenConf) error { certArray, err := tlsLayer.GetCertArrayFromFile(lc.TLSCert, lc.TLSKey) if err != nil { - log.Fatalln("can't create tls cert from file:", lc.TLSCert, lc.TLSKey, err) + log.Fatalf("can't create tls cert from file: %s, %s, %s\n", lc.TLSCert, lc.TLSKey, err) } - return quic.ListenInitialLayers(com.AddrStr(), &tls.Config{ + return quic.ListenInitialLayers(com.AddrStr(), tls.Config{ InsecureSkipVerify: lc.Insecure, ServerName: lc.Host, Certificates: certArray, @@ -368,7 +370,7 @@ type ProxyCommonStruct struct { ws_s *ws.Server grpc_s *grpc.Server - FallbackAddr *netLayer.Addr + FallbackAddr netLayer.Addr listenCommonConnFunc func() (newConnChan chan net.Conn, baseConn any) dialCommonConnFunc func(serverAddr *netLayer.Addr) any @@ -386,10 +388,10 @@ func (pcs *ProxyCommonStruct) setPath(a string) { pcs.PATH = a } -func (pcs *ProxyCommonStruct) GetFallback() *netLayer.Addr { +func (pcs *ProxyCommonStruct) GetFallback() netLayer.Addr { return pcs.FallbackAddr } -func (pcs *ProxyCommonStruct) setFallback(a *netLayer.Addr) { +func (pcs *ProxyCommonStruct) setFallback(a netLayer.Addr) { pcs.FallbackAddr = a } diff --git a/proxy/socks5/client.go b/proxy/socks5/client.go index df5f881..9565852 100644 --- a/proxy/socks5/client.go +++ b/proxy/socks5/client.go @@ -137,7 +137,7 @@ func Client_ReadUDPResponse(udpConn *net.UDPConn, supposedServerAddr *net.UDPAdd } if !(addr.IP.Equal(supposedServerAddr.IP) && addr.Port == supposedServerAddr.Port) { - e = utils.NewDataErr("socks5 Client_ReadUDPResponse , got data from unknown source", nil, addr) + e = utils.ErrInErr{ErrDesc: "socks5 Client_ReadUDPResponse , got data from unknown source", Data: addr} return } if buf[0] != 0 || buf[1] != 0 || buf[2] != 0 { diff --git a/proxy/socks5/server.go b/proxy/socks5/server.go index 3258d70..5798bd7 100644 --- a/proxy/socks5/server.go +++ b/proxy/socks5/server.go @@ -47,10 +47,11 @@ func (s *Server) Name() string { return Name } // 参考 https://studygolang.com/articles/31404 // 处理tcp收到的请求. 注意, udp associate后的 udp请求并不通过此函数处理, 而是由 UDPConn.StartReadRequest 处理 -func (s *Server) Handshake(underlay net.Conn) (io.ReadWriteCloser, *netLayer.Addr, error) { +func (s *Server) Handshake(underlay net.Conn) (result io.ReadWriteCloser, targetAddr netLayer.Addr, returnErr error) { // Set handshake timeout 4 seconds if err := underlay.SetReadDeadline(time.Now().Add(time.Second * 4)); err != nil { - return nil, nil, err + returnErr = err + return } defer underlay.SetReadDeadline(time.Time{}) @@ -61,24 +62,28 @@ func (s *Server) Handshake(underlay net.Conn) (io.ReadWriteCloser, *netLayer.Add // 一般握手包发来的是 [5 1 0] n, err := underlay.Read(buf) if err != nil || n == 0 { - return nil, nil, fmt.Errorf("failed to read hello: %w", err) + returnErr = fmt.Errorf("failed to read hello: %w", err) + return } version := buf[0] if version != Version5 { - return nil, nil, fmt.Errorf("unsupported socks version %v", version) + returnErr = fmt.Errorf("unsupported socks version %v", version) + return } // Write hello response, [5 0] // TODO: Support Auth _, err = underlay.Write([]byte{Version5, AuthNone}) if err != nil { - return nil, nil, fmt.Errorf("failed to write hello response: %w", err) + returnErr = fmt.Errorf("failed to write hello response: %w", err) + return } // Read command message, n, err = underlay.Read(buf) if err != nil || n < 7 { // Shortest length is 7 - return nil, nil, fmt.Errorf("read socks5 failed, msgTooShort: %w", err) + returnErr = fmt.Errorf("read socks5 failed, msgTooShort: %w", err) + return } // 一般可以为 5 1 0 3 n,3表示域名,n是域名长度,然后域名很可能是 119 119 119 46 开头,表示 www. @@ -86,7 +91,8 @@ func (s *Server) Handshake(underlay net.Conn) (io.ReadWriteCloser, *netLayer.Add cmd := buf[1] if cmd == CmdBind { - return nil, nil, fmt.Errorf("unsuppoted command %v", cmd) + returnErr = fmt.Errorf("unsuppoted command %v", cmd) + return } l := 2 @@ -104,11 +110,13 @@ func (s *Server) Handshake(underlay net.Conn) (io.ReadWriteCloser, *netLayer.Add l += int(buf[4]) off = 5 default: - return nil, nil, fmt.Errorf("unknown address type %v", buf[3]) + returnErr = fmt.Errorf("unknown address type %v", buf[3]) + return } if len(buf[off:]) < l { - return nil, nil, errors.New("short command request") + returnErr = errors.New("short command request") + return } var theName string @@ -145,7 +153,8 @@ func (s *Server) Handshake(underlay net.Conn) (io.ReadWriteCloser, *netLayer.Add udpRC, err := net.ListenUDP("udp", udpPreparedAddr) if err != nil { - return nil, nil, errors.New("UDPAssociate: unable to listen udp") + returnErr = errors.New("UDPAssociate: unable to listen udp") + return } //ver(5), rep(0,表示成功), rsv(0), atyp(1, 即ipv4), BND.ADDR(4字节的ipv4) , BND.PORT(2字节) @@ -154,10 +163,11 @@ func (s *Server) Handshake(underlay net.Conn) (io.ReadWriteCloser, *netLayer.Add // Write command response _, err = underlay.Write(reply) if err != nil { - return nil, nil, fmt.Errorf("failed to write command response: %w", err) + returnErr = fmt.Errorf("failed to write command response: %w", err) + return } - clientFutureAddr := &netLayer.Addr{ + clientFutureAddr := netLayer.Addr{ IP: theIP, Name: theName, Port: thePort, @@ -172,7 +182,7 @@ func (s *Server) Handshake(underlay net.Conn) (io.ReadWriteCloser, *netLayer.Add return uc, clientFutureAddr, nil } else { - addr := &netLayer.Addr{ + targetAddr = netLayer.Addr{ IP: theIP, Name: theName, Port: thePort, @@ -186,10 +196,11 @@ func (s *Server) Handshake(underlay net.Conn) (io.ReadWriteCloser, *netLayer.Add _, err = underlay.Write(reply) if err != nil { - return nil, nil, fmt.Errorf("failed to write command response: %w", err) + returnErr = fmt.Errorf("failed to write command response: %w", err) + return } - return underlay, addr, nil + return underlay, targetAddr, nil } } @@ -244,7 +255,7 @@ func (u *UDPConn) StartPushResponse(udpPutter netLayer.UDP_Putter) { // 然后将该请求 用 udpPutter.WriteUDPRequest 发送给 udpPutter // 至于fullcone与否它是不管的。 // 如果客户端一开始没有指明自己连接本服务端的ip和端口, 则将第一个发来的正确的socks5请求视为该客户端,并记录。 -func (u *UDPConn) StartReadRequest(udpPutter netLayer.UDP_Putter, dialFunc func(targetAddr *netLayer.Addr) (io.ReadWriter, error)) { +func (u *UDPConn) StartReadRequest(udpPutter netLayer.UDP_Putter, dialFunc func(targetAddr netLayer.Addr) (io.ReadWriter, error)) { var clientSupposedAddrIsNothing bool if len(u.clientSupposedAddr.IP) < 3 || u.clientSupposedAddr.IP.IsUnspecified() { @@ -341,7 +352,7 @@ func (u *UDPConn) StartReadRequest(udpPutter netLayer.UDP_Putter, dialFunc func( //log.Println("socks5 server,StartReadRequest, got msg", thisaddr, string(bs[newStart:n])) - udpPutter.WriteUDPRequest(requestAddr.ToUDPAddr(), bs[newStart:n], dialFunc) + udpPutter.WriteUDPRequest(*requestAddr.ToUDPAddr(), bs[newStart:n], dialFunc) } } diff --git a/proxy/socks5/udp_test.go b/proxy/socks5/udp_test.go index 3678150..a23c24d 100644 --- a/proxy/socks5/udp_test.go +++ b/proxy/socks5/udp_test.go @@ -54,7 +54,7 @@ func TestUDP(t *testing.T) { go udpConn.StartPushResponse(putter) - dialFunc := func(targetAddr *netLayer.Addr) (io.ReadWriter, error) { + dialFunc := func(targetAddr netLayer.Addr) (io.ReadWriter, error) { return targetAddr.Dial() } @@ -142,7 +142,7 @@ func TestUDP(t *testing.T) { t.Log("call Client_RequestUDP") - socks5.Client_RequestUDP(urc, raFake, []byte("hello")) + socks5.Client_RequestUDP(urc, &raFake, []byte("hello")) t.Log("call Client_ReadUDPResponse") diff --git a/proxy/vless/client.go b/proxy/vless/client.go index 044ce49..eec525e 100644 --- a/proxy/vless/client.go +++ b/proxy/vless/client.go @@ -3,7 +3,6 @@ package vless import ( "bufio" "bytes" - "encoding/binary" "io" "log" "net" @@ -17,14 +16,14 @@ import ( ) func init() { - proxy.RegisterClient(Name, &ClientCreator{}) + proxy.RegisterClient(Name, ClientCreator{}) } //实现 proxy.UserClient,以及 netLayer.UDP_Putter type Client struct { proxy.ProxyCommonStruct - udpResponseChan chan *netLayer.UDPAddrData + udpResponseChan chan netLayer.UDPAddrData version int @@ -52,12 +51,12 @@ func (_ ClientCreator) NewClient(dc *proxy.DialConf) (proxy.Client, error) { return nil, err } - c := &Client{ + c := Client{ user: id, } c.knownUDPDestinations = make(map[string]io.ReadWriter) - c.udpResponseChan = make(chan *netLayer.UDPAddrData, 20) + c.udpResponseChan = make(chan netLayer.UDPAddrData, 20) v := dc.Version if v >= 0 { @@ -68,7 +67,7 @@ func (_ ClientCreator) NewClient(dc *proxy.DialConf) (proxy.Client, error) { } - return c, nil + return &c, nil } func NewClientByURL(url *url.URL) (proxy.Client, error) { @@ -78,11 +77,11 @@ func NewClientByURL(url *url.URL) (proxy.Client, error) { return nil, err } - c := &Client{ + c := Client{ user: id, } c.knownUDPDestinations = make(map[string]io.ReadWriter) - c.udpResponseChan = make(chan *netLayer.UDPAddrData, 20) + c.udpResponseChan = make(chan netLayer.UDPAddrData, 20) vStr := url.Query().Get("version") if vStr != "" { @@ -94,7 +93,7 @@ func NewClientByURL(url *url.URL) (proxy.Client, error) { } } - return c, nil + return &c, nil } func (c *Client) Name() string { return Name } @@ -158,10 +157,10 @@ func (c *Client) Handshake(underlay net.Conn, target *netLayer.Addr) (io.ReadWri } buf := c.getBufWithCmd(cmd) - err = binary.Write(buf, binary.BigEndian, uint16(port)) // port - if err != nil { - return nil, err - } + + buf.WriteByte(byte(uint16(port) >> 8)) + buf.WriteByte(byte(uint16(port) << 8 >> 8)) + buf.WriteByte(atyp) buf.Write(addr) @@ -178,13 +177,13 @@ func (c *Client) Handshake(underlay net.Conn, target *netLayer.Addr) (io.ReadWri }, err } -func (c *Client) GetNewUDPResponse() (*net.UDPAddr, []byte, error) { +func (c *Client) GetNewUDPResponse() (net.UDPAddr, []byte, error) { x := <-c.udpResponseChan //v1的话,由 handle_CRUMFURS 以及 WriteUDPRequest 中的 goroutine 填充;v0的话,由 WriteUDPRequest 填充 return x.Addr, x.Data, nil } //一般由socks5或者透明代理等地方 获取到 udp请求后,被传入这里 -func (c *Client) WriteUDPRequest(a *net.UDPAddr, b []byte, dialFunc func(targetAddr *netLayer.Addr) (io.ReadWriter, error)) (err error) { +func (c *Client) WriteUDPRequest(a net.UDPAddr, b []byte, dialFunc func(targetAddr netLayer.Addr) (io.ReadWriter, error)) (err error) { astr := a.String() @@ -194,9 +193,9 @@ func (c *Client) WriteUDPRequest(a *net.UDPAddr, b []byte, dialFunc func(targetA if knownConn == nil { - knownConn, err = dialFunc(netLayer.NewAddrFromUDPAddr(a)) + knownConn, err = dialFunc(netLayer.NewAddrFromUDPAddr(&a)) if err != nil || knownConn == nil { - return utils.NewErr("vless WriteUDPRequest, err when creating an underlay", err) + return utils.ErrInErr{ErrDesc: "vless WriteUDPRequest, err when creating an underlay", ErrDetail: err} } //这里原来的代码是调用 c.Handshake,会自动帮我们拨号代理节点CmdUDP // 但是似乎有问题,因为不应该由client自己拨号vless,因为我们还有上层的tls; @@ -221,7 +220,7 @@ func (c *Client) WriteUDPRequest(a *net.UDPAddr, b []byte, dialFunc func(targetA msg := make([]byte, n) copy(msg, bs[:n]) - c.udpResponseChan <- &netLayer.UDPAddrData{ + c.udpResponseChan <- netLayer.UDPAddrData{ Addr: a, Data: msg, } @@ -283,8 +282,8 @@ func (c *Client) handle_CRUMFURS(UMFURS_conn net.Conn) { port := int16(msg[portIndex])<<8 + int16(msg[portIndex+1]) - c.udpResponseChan <- &netLayer.UDPAddrData{ - Addr: &net.UDPAddr{ + c.udpResponseChan <- netLayer.UDPAddrData{ + Addr: net.UDPAddr{ IP: theIP, Port: int(port), }, @@ -339,8 +338,8 @@ func (c *Client) handle_CRUMFURS(UMFURS_conn net.Conn) { break } - c.udpResponseChan <- &netLayer.UDPAddrData{ - Addr: &net.UDPAddr{ + c.udpResponseChan <- netLayer.UDPAddrData{ + Addr: net.UDPAddr{ IP: theIP, Port: port, }, diff --git a/proxy/vless/server.go b/proxy/vless/server.go index 33911b4..5b27bb1 100644 --- a/proxy/vless/server.go +++ b/proxy/vless/server.go @@ -133,10 +133,11 @@ func (s *Server) GetUserByStr(str string) proxy.User { func (s *Server) Name() string { return Name } // 返回的bytes.Buffer 是用于 回落使用的,内含了整个读取的数据;不回落时不要使用该Buffer -func (s *Server) Handshake(underlay net.Conn) (io.ReadWriteCloser, *netLayer.Addr, error) { +func (s *Server) Handshake(underlay net.Conn) (result io.ReadWriteCloser, targetAddr netLayer.Addr, returnErr error) { if err := underlay.SetReadDeadline(time.Now().Add(time.Second * 4)); err != nil { - return nil, nil, err + returnErr = err + return } defer underlay.SetReadDeadline(time.Time{}) @@ -149,30 +150,30 @@ func (s *Server) Handshake(underlay net.Conn) (io.ReadWriteCloser, *netLayer.Add //var auth [17]byte wholeReadLen, err := underlay.Read(readbs) if err != nil { - return nil, nil, utils.NewDataErr("read err", err, wholeReadLen) + returnErr = utils.ErrInErr{ErrDesc: "read err", ErrDetail: err, Data: wholeReadLen} + return } if wholeReadLen < 17 { //根据下面回答,HTTP的最小长度恰好是16字节,但是是0.9版本。1.0是18字节,1.1还要更长。总之我们可以直接不返回fallback地址 //https://stackoverflow.com/questions/25047905/http-request-minimum-size-in-bytes/25065089 - return nil, nil, utils.NewDataErr("fallback, msg too short", nil, wholeReadLen) - + returnErr = utils.ErrInErr{ErrDesc: "fallback, msg too short", Data: wholeReadLen} + return } readbuf := bytes.NewBuffer(readbs[:wholeReadLen]) - var returnErr error - goto realPart errorPart: //所返回的buffer必须包含所有数据,而Buffer不支持回退,所以只能重新New - return nil, nil, &utils.ErrFirstBuffer{ + returnErr = &utils.ErrFirstBuffer{ Err: returnErr, First: bytes.NewBuffer(readbs[:wholeReadLen]), } + return realPart: //这部分过程可以参照 v2ray的 proxy/vless/encoding/encoding.go DecodeRequestHeader 方法 @@ -183,7 +184,7 @@ realPart: version := auth[0] if version > 1 { - returnErr = utils.NewDataErr("Vless invalid version ", nil, version) + returnErr = utils.ErrInErr{ErrDesc: "Vless invalid version ", Data: version} goto errorPart } @@ -206,7 +207,8 @@ realPart: addonLenByte, err := readbuf.ReadByte() if err != nil { - return nil, nil, err //凡是和的层Read相关的错误,一律不再返回Fallback信息,因为连接已然不可用 + returnErr = err //凡是和的层Read相关的错误,一律不再返回Fallback信息,因为连接已然不可用 + return } if addonLenByte != 0 { //v2ray的vless中没有对应的任何处理。 @@ -223,7 +225,8 @@ realPart: utils.PutBytes(tmpBuf) */ if tmpbs := readbuf.Next(int(addonLenByte)); len(tmpbs) != int(addonLenByte) { - return nil, nil, errors.New("vless short read in addon") + returnErr = errors.New("vless short read in addon") + return } } } @@ -236,13 +239,11 @@ realPart: goto errorPart } - addr := &netLayer.Addr{} - switch commandByte { case CmdMux: //实际目前verysimple 暂时还未实现mux,先这么写 - addr.Port = 0 - addr.Name = "v1.mux.cool" + targetAddr.Port = 0 + targetAddr.Name = "v1.mux.cool" case Cmd_CRUMFURS: if version != 1 { @@ -255,11 +256,11 @@ realPart: _, err = underlay.Write([]byte{CRUMFURS_ESTABLISHED}) if err != nil { - returnErr = utils.NewErr("write to crumfurs err", err) + returnErr = utils.ErrInErr{ErrDesc: "write to crumfurs err", ErrDetail: err} goto errorPart } - addr.Name = CRUMFURS_Established_Str // 使用这个特殊的办法来告诉调用者,预留了 CRUMFURS 信道,防止其关闭上层连接导致 CRUMFURS 信道 被关闭。 + targetAddr.Name = CRUMFURS_Established_Str // 使用这个特殊的办法来告诉调用者,预留了 CRUMFURS 信道,防止其关闭上层连接导致 CRUMFURS 信道 被关闭。 theCRUMFURS := &CRUMFURS{ Conn: underlay, @@ -271,7 +272,7 @@ realPart: s.mux4Hashes.Unlock() - return nil, addr, nil + return case CmdTCP, CmdUDP: @@ -283,10 +284,10 @@ realPart: goto errorPart } - addr.Port = int(binary.BigEndian.Uint16(portbs)) + targetAddr.Port = int(binary.BigEndian.Uint16(portbs)) if commandByte == CmdUDP { - addr.Network = "udp" + targetAddr.Network = "udp" } var ip_or_domain_bytesLength byte = 0 @@ -303,7 +304,7 @@ realPart: case netLayer.AtypIP4: ip_or_domain_bytesLength = net.IPv4len - addr.IP = utils.GetBytes(net.IPv4len) + targetAddr.IP = utils.GetBytes(net.IPv4len) case netLayer.AtypDomain: // 解码域名的长度 @@ -320,7 +321,7 @@ realPart: case netLayer.AtypIP6: ip_or_domain_bytesLength = net.IPv6len - addr.IP = utils.GetBytes(net.IPv6len) + targetAddr.IP = utils.GetBytes(net.IPv6len) default: returnErr = fmt.Errorf("unknown address type %v", addrTypeByte) @@ -332,13 +333,14 @@ realPart: _, err = readbuf.Read(ip_or_domain) if err != nil { - return nil, nil, errors.New("fallback, reason 6") + returnErr = errors.New("fallback, reason 6") + return } - if addr.IP != nil { - copy(addr.IP, ip_or_domain) + if targetAddr.IP != nil { + copy(targetAddr.IP, ip_or_domain) } else { - addr.Name = string(ip_or_domain) + targetAddr.Name = string(ip_or_domain) } utils.PutBytes(ip_or_domain) @@ -355,10 +357,10 @@ realPart: remainFirstBufLen: readbuf.Len(), uuid: thisUUIDBytes, version: int(version), - isUDP: addr.IsUDP(), + isUDP: targetAddr.IsUDP(), underlayIsBasic: netLayer.IsBasicConn(underlay), isServerEnd: true, - }, addr, nil + }, targetAddr, nil } @@ -375,7 +377,7 @@ type CRUMFURS struct { hasAdvancedLayer bool //在用ws或grpc时,这个开关保持打开 } -func (c *CRUMFURS) WriteUDPResponse(a *net.UDPAddr, b []byte) (err error) { +func (c *CRUMFURS) WriteUDPResponse(a net.UDPAddr, b []byte) (err error) { atype := netLayer.AtypIP4 if len(a.IP) > 4 { atype = netLayer.AtypIP6 diff --git a/proxy/vless/vless_test.go b/proxy/vless/vless_test.go index 6dfae6e..3379ac9 100644 --- a/proxy/vless/vless_test.go +++ b/proxy/vless/vless_test.go @@ -24,13 +24,13 @@ func TestVLess1(t *testing.T) { func testVLess(version int, port string, t *testing.T) { url := "vless://a684455c-b14f-11ea-bf0d-42010aaa0003@127.0.0.1:" + port + "?version=" + strconv.Itoa(version) - server, err := proxy.ServerFromURL(url) - if err != nil { + server, hase, _ := proxy.ServerFromURL(url) + if hase { t.FailNow() } defer server.Stop() - client, err := proxy.ClientFromURL(url) - if err != nil { + client, hase, _ := proxy.ClientFromURL(url) + if hase { t.FailNow() } @@ -127,15 +127,15 @@ func TestVLess0_udp(t *testing.T) { // 不过实测,这个test暂时只能使用v0版本,因为 v1版本具有 独特信道,不能直接使用下面代码。 func testVLessUDP(version int, port string, t *testing.T) { url := "vless://a684455c-b14f-11ea-bf0d-42010aaa0003@127.0.0.1:" + port + "?version=" + strconv.Itoa(version) - fakeServerEndLocalServer, err := proxy.ServerFromURL(url) - if err != nil { - t.Log("fakeClientEndLocalServer parse err", err) + fakeServerEndLocalServer, hase, errx := proxy.ServerFromURL(url) + if hase { + t.Log("fakeClientEndLocalServer parse err", errx) t.FailNow() } defer fakeServerEndLocalServer.Stop() - fakeClientEndRemoteClient, err := proxy.ClientFromURL(url) - if err != nil { - t.Log("fakeClientEndRemoteClient parse err", err) + fakeClientEndRemoteClient, hase, errx := proxy.ClientFromURL(url) + if hase { + t.Log("fakeClientEndRemoteClient parse err", errx) t.FailNow() } diff --git a/quic/quic.go b/quic/quic.go index 76640b7..ac423f6 100644 --- a/quic/quic.go +++ b/quic/quic.go @@ -76,9 +76,9 @@ var ( } ) -func ListenInitialLayers(addr string, tlsConf *tls.Config, useHysteria bool, hysteriaMaxByteCount int) (newConnChan chan net.Conn, baseConn any) { +func ListenInitialLayers(addr string, tlsConf tls.Config, useHysteria bool, hysteriaMaxByteCount int) (newConnChan chan net.Conn, baseConn any) { - listener, err := quic.ListenAddr(addr, tlsConf, &our_ListenConfig) + listener, err := quic.ListenAddr(addr, &tlsConf, &our_ListenConfig) if err != nil { if utils.CanLogErr() { log.Println(err) @@ -140,8 +140,8 @@ func ListenInitialLayers(addr string, tlsConf *tls.Config, useHysteria bool, hys return } -func DialCommonInitialLayer(serverAddr *netLayer.Addr, tlsConf *tls.Config, useHysteria bool, hysteriaMaxByteCount int) any { - session, err := quic.DialAddr(serverAddr.String(), tlsConf, &our_DialConfig) +func DialCommonInitialLayer(serverAddr *netLayer.Addr, tlsConf tls.Config, useHysteria bool, hysteriaMaxByteCount int) any { + session, err := quic.DialAddr(serverAddr.String(), &tlsConf, &our_DialConfig) if err != nil { if utils.CanLogErr() { log.Println(err) diff --git a/tlsLayer/server.go b/tlsLayer/server.go index b1d7a60..aa2bb99 100644 --- a/tlsLayer/server.go +++ b/tlsLayer/server.go @@ -37,7 +37,7 @@ func (s *Server) Handshake(underlay net.Conn) (tlsConn *Conn, err error) { rawTlsConn := tls.Server(underlay, s.tlsConfig) err = rawTlsConn.Handshake() if err != nil { - err = utils.NewErr("tlsLayer: tls握手失败", err) + err = utils.ErrInErr{ErrDesc: "tlsLayer: tls握手失败", ErrDetail: err} return } diff --git a/tlsLayer/tls_test.go b/tlsLayer/tls_test.go index cd557d0..561a22c 100644 --- a/tlsLayer/tls_test.go +++ b/tlsLayer/tls_test.go @@ -27,15 +27,15 @@ func testTls(protocol string, port string, t *testing.T) { } url := protocol + "://a684455c-b14f-11ea-bf0d-42010aaa0003@localhost:" + port + "?alterID=4&cert=../cert.pem&key=../cert.key&insecure=1" - server, err := proxy.ServerFromURL(url) - if err != nil { - t.Log("fail1", err) + server, hase, errx := proxy.ServerFromURL(url) + if hase { + t.Log("fail1", errx) t.FailNow() } defer server.Stop() - client, err := proxy.ClientFromURL(url) - if err != nil { - t.Log("fail2", err) + client, hase, errx := proxy.ClientFromURL(url) + if hase { + t.Log("fail2", errx) t.FailNow() } diff --git a/utils/buffers.go b/utils/buffers.go index a0e21ad..5ec054f 100644 --- a/utils/buffers.go +++ b/utils/buffers.go @@ -136,6 +136,8 @@ func MergeBuffers(bs [][]byte) (result []byte, duplicate bool) { } else { result = make([]byte, allLen) //实际目前的readv实现也很难出现这种情况 + // 一定要尽量避免这种情况,如果 MaxBufLen小于readv buf总长度,会导致严重的内存泄漏问题, + // 见github issue #24 } cursor := 0 diff --git a/utils/error.go b/utils/error.go index 80fd17f..2c597a8 100644 --- a/utils/error.go +++ b/utils/error.go @@ -34,7 +34,8 @@ func (ef ErrFirstBuffer) Error() string { } // 返回结构体,而不是指针, 这样可以避免内存逃逸到堆 -func NewErr(desc string, e error) ErrInErr { +// 发现只要是函数就会逃逸到堆,自己初始化就没事。那就不提供初始化函数了。 +/*func NewErr(desc string, e error) ErrInErr { return ErrInErr{ ErrDesc: desc, ErrDetail: e, @@ -42,6 +43,7 @@ func NewErr(desc string, e error) ErrInErr { } // 返回结构体,而不是指针, 这样可以避免内存逃逸到堆 + func NewDataErr(desc string, e error, data interface{}) ErrInErr { return ErrInErr{ ErrDesc: desc, @@ -49,6 +51,7 @@ func NewDataErr(desc string, e error, data interface{}) ErrInErr { Data: data, } } +*/ // ErrInErr 很适合一个err包含另一个err,并且提供附带数据的情况. type ErrInErr struct { diff --git a/version.go b/version.go index 036aa47..2ce1d56 100644 --- a/version.go +++ b/version.go @@ -50,10 +50,10 @@ var Version string //版本号由 Makefile 里的 BUILD_VERSION 指定 func printVersion() { const desc = "verysimple, a very simple implementation of V2Ray with some innovation" - fmt.Printf("===============================\nverysimple %v (%v), %v %v %v\n", Version, desc, runtime.Version(), runtime.GOOS, runtime.GOARCH) - fmt.Println("Support tls and websocket for all protocols.") + fmt.Printf("===============================\nverysimple %s (%s), %s %s %s\n", Version, desc, runtime.Version(), runtime.GOOS, runtime.GOARCH) + fmt.Printf("Support tls and websocket for all protocols.\n") if netLayer.HasEmbedGeoip() { - fmt.Println("Contains embeded Geoip file") + fmt.Printf("Contains embeded Geoip file\n") } } diff --git a/ws/client.go b/ws/client.go index a6026cf..7099ea6 100644 --- a/ws/client.go +++ b/ws/client.go @@ -137,7 +137,7 @@ func (edc *EarlyDataConn) Write(p []byte) (int, error) { _, encerr := io.Copy(encoder, multiReader) if encerr != nil { close(edc.firstHandshakeOkChan) - return 0, utils.NewErr("encode early data err", encerr) + return 0, utils.ErrInErr{ErrDesc: "encode early data err", ErrDetail: encerr} } encoder.Close() diff --git a/ws/conn.go b/ws/conn.go index b317377..5246cba 100644 --- a/ws/conn.go +++ b/ws/conn.go @@ -89,7 +89,7 @@ func (c *Conn) Read(p []byte) (int, error) { */ //log.Println("OpCode not Binary", h.OpCode) - return 0, utils.NewDataErr("ws OpCode not Binary", nil, h.OpCode) + return 0, utils.ErrInErr{ErrDesc: "ws OpCode not Binary", Data: h.OpCode} } //log.Println("Read next frame header ok,", h.Length, c.r.State.Fragmented(), "givenbuf len", len(p))