fix attempt1. (failed)issue: -lazy在fallback下闪退问题

This commit is contained in:
hahahrfool
2022-03-17 22:43:25 +08:00
parent 3fdeded6cf
commit b533b34e5f
2 changed files with 38 additions and 18 deletions

46
main.go
View File

@@ -8,6 +8,7 @@ import (
"net" "net"
"os" "os"
"os/signal" "os/signal"
"runtime"
"strings" "strings"
"syscall" "syscall"
"time" "time"
@@ -42,6 +43,8 @@ var (
listenURL string listenURL string
dialURL string dialURL string
isServerEnd bool
) )
func init() { func init() {
@@ -104,6 +107,7 @@ func main() {
log.Println("can not create remote client: ", err) log.Println("can not create remote client: ", err)
os.Exit(-1) os.Exit(-1)
} }
isServerEnd = outClient.Name() == "direct"
listener, err := net.Listen("tcp", inServer.AddrStr()) listener, err := net.Listen("tcp", inServer.AddrStr())
if err != nil { if err != nil {
@@ -230,6 +234,8 @@ afterLocalServerHandshake:
var client proxy.Client = outClient var client proxy.Client = outClient
var routedToDirect bool
//如果可以route //如果可以route
if !inServer.CantRoute() && routePolicy != nil { if !inServer.CantRoute() && routePolicy != nil {
@@ -244,6 +250,7 @@ afterLocalServerHandshake:
}) })
if outtag == "direct" { if outtag == "direct" {
client = directClient client = directClient
routedToDirect = true
if utils.CanLogInfo() { if utils.CanLogInfo() {
log.Println("routed to direct", targetAddr.UrlString()) log.Println("routed to direct", targetAddr.UrlString())
@@ -251,14 +258,18 @@ afterLocalServerHandshake:
} }
} }
// 我们在客户端 lazy_encrypt 探测时读取socks5 传来的信息,因为这个要发送到tls的信息是一模一样的所以就不需要等包上vless、tls后再判断了, 直接解包 socks5进行判断 // 我们在客户端 lazy_encrypt 探测时读取socks5 传来的信息,因为这个 就是要发送到 outClient 的信息所以就不需要等包上vless、tls后再判断了, 直接解包 socks5 对 tls 进行判断
// //
// 而在服务端探测时,因为 客户端传来的连接 包了 tls所以要在tls解包后, vless 解包后,再进行判断; // 而在服务端探测时,因为 客户端传来的连接 包了 tls所以要在tls解包后, vless 解包后,再进行判断;
// 所以总之都是要在 inServer 判断 wlc; 总之,含义就是,去检索“用户承载数据”的来源 // 所以总之都是要在 inServer 判断 wlc; 总之,含义就是,去检索“用户承载数据”的来源
if tls_lazy_encrypt { if tls_lazy_encrypt && !(!isServerEnd && routedToDirect) {
wlc = tlsLayer.NewSniffConn(baseLocalConn, wlc, client.IsUseTLS(), tls_lazy_secure) if tlsLayer.PDD {
log.Println("loading TLS SniffConn", !isServerEnd)
}
wlc = tlsLayer.NewSniffConn(baseLocalConn, wlc, !isServerEnd, tls_lazy_secure)
//clientConn = cc //clientConn = cc
} }
@@ -445,22 +456,25 @@ afterLocalServerHandshake:
return return
} }
if tls_lazy_encrypt { if !routedToDirect && client.Name() != "direct" && tls_lazy_encrypt {
isclient := client.IsUseTLS()
if isclient {
//必须是 UserClient // 这里的错误是,我们加了回落之后,就无法确定 “未使用tls的outClient 一定是在服务端” 了
if userClient := client.(proxy.UserClient); userClient != nil { if !isServerEnd {
tryRawCopy(false, userClient, nil, nil, wrc, wlc, baseLocalConn, true, clientEndRemoteClientTlsRawReadRecorder)
return if client.IsUseTLS() {
//必须是 UserClient
if userClient := client.(proxy.UserClient); userClient != nil {
tryRawCopy(false, userClient, nil, nil, wrc, wlc, baseLocalConn, true, clientEndRemoteClientTlsRawReadRecorder)
return
}
} }
} else { } else {
// 最新代码已经确认使用uuid 作为 “特殊指令”所以要求Server必须是一个 proxy.UserServer // 最新代码已经确认使用uuid 作为 “特殊指令”所以要求Server必须是一个 proxy.UserServer
// 否则将无法开启splice功能。这是为了防止0-rtt 探测 // 否则将无法开启splice功能。这是为了防止0-rtt 探测;
if userServer := inServer.(proxy.UserServer); userServer != nil { if userServer, ok := inServer.(proxy.UserServer); ok {
tryRawCopy(false, nil, userServer, nil, wrc, wlc, baseLocalConn, false, serverEndLocalServerTlsRawReadRecorder) tryRawCopy(false, nil, userServer, nil, wrc, wlc, baseLocalConn, false, serverEndLocalServerTlsRawReadRecorder)
return return
} }
@@ -488,7 +502,6 @@ afterLocalServerHandshake:
go io.Copy(wrc, wlc) go io.Copy(wrc, wlc)
io.Copy(wlc, wrc) io.Copy(wlc, wrc)
} }
// tryRawCopy 尝试能否直接对拷,对拷 直接使用 原始 TCPConn也就是裸奔转发 // tryRawCopy 尝试能否直接对拷,对拷 直接使用 原始 TCPConn也就是裸奔转发
@@ -744,6 +757,9 @@ func tryRawCopy(useSecureMethod bool, proxy_client proxy.UserClient, proxy_serve
} }
if isgood { if isgood {
if runtime.GOOS == "linux" {
//runtime.Gosched() //详情请阅读我的 xray_splice- 文章,了解为什么这个调用是必要的
}
if tlsLayer.PDD { if tlsLayer.PDD {
log.Println("成功SpliceRead R方向") log.Println("成功SpliceRead R方向")
@@ -852,6 +868,10 @@ func tryRawCopy(useSecureMethod bool, proxy_client proxy.UserClient, proxy_serve
log.Println("成功SpliceRead W方向,准备 直连对拷") log.Println("成功SpliceRead W方向,准备 直连对拷")
} }
if runtime.GOOS == "linux" {
//runtime.Gosched() //详情请阅读我的 xray_splice- 文章,了解为什么这个调用是必要的
}
if tlsLayer.PDD { if tlsLayer.PDD {
num, e2 := wlccc_raw.ReadFrom(rawWRC) //看起来是ReadFrom实际上是向 wlccc_raw进行Write即箭头向左 num, e2 := wlccc_raw.ReadFrom(rawWRC) //看起来是ReadFrom实际上是向 wlccc_raw进行Write即箭头向左

View File

@@ -130,7 +130,7 @@ func (c *ComSniff) GetFailReason() int {
} }
// 总之,如果读写都用同样的判断代码的话,客户端和服务端应该就能同步进行 相同的TLS判断 // 总之,如果读写都用同样的判断代码的话,客户端和服务端应该就能同步进行 相同的TLS判断
func (cd *ComSniff) utilsDetect(p []byte, isRead bool) { func (cd *ComSniff) commonDetect(p []byte, isRead bool) {
/* /*
我们把tls的细节放在这个注释里便于参考 我们把tls的细节放在这个注释里便于参考
@@ -506,7 +506,7 @@ func (cd *ComSniff) utilsDetect(p []byte, isRead bool) {
} }
func utilsFilterStep(err error, cd *ComSniff, p []byte, isRead bool) { func commonFilterStep(err error, cd *ComSniff, p []byte, isRead bool) {
if !OnlyTest && (cd.DefinitelyNotTLS || cd.IsTls) { //确定了是TLS 或者肯定不是 tls了的话就直接return掉 if !OnlyTest && (cd.DefinitelyNotTLS || cd.IsTls) { //确定了是TLS 或者肯定不是 tls了的话就直接return掉
return return
} }
@@ -524,7 +524,7 @@ func utilsFilterStep(err error, cd *ComSniff, p []byte, isRead bool) {
} }
if len(p) > 3 { if len(p) > 3 {
cd.utilsDetect(p, isRead) cd.commonDetect(p, isRead)
} }
} }
@@ -542,7 +542,7 @@ type DetectReader struct {
func (dr *DetectReader) Read(p []byte) (n int, err error) { func (dr *DetectReader) Read(p []byte) (n int, err error) {
n, err = dr.Reader.Read(p) n, err = dr.Reader.Read(p)
utilsFilterStep(err, &dr.ComSniff, p[:n], true) commonFilterStep(err, &dr.ComSniff, p[:n], true)
if PDD { if PDD {
if dr.DefinitelyNotTLS { if dr.DefinitelyNotTLS {
@@ -616,7 +616,7 @@ func (dw *DetectWriter) Write(p []byte) (n int, err error) {
return return
} }
utilsFilterStep(nil, &dw.ComSniff, p, false) commonFilterStep(nil, &dw.ComSniff, p, false)
// 经过判断之后,确认是 tls了则我们缓存这个记录 然后通过tls发送特殊指令 // 经过判断之后,确认是 tls了则我们缓存这个记录 然后通过tls发送特殊指令
if dw.IsTls { if dw.IsTls {