diff --git a/README.md b/README.md index 9578dd1..1c39efa 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,29 @@ tls lazy encrypt 特性 运行时可以用 -lazy 参数打开(服务端客户 我只是在内网自己试试玩一玩,从来不会真正用于安全性要求高的用途。 -注意,因为技术实现不同,该功能不兼容xtls。 +关于splice的一个现有“降速”问题也要看看,我们这里也是会存在的 https://github.com/XTLS/Xray-core/discussions/59 + +**注意,因为技术实现不同,该功能不兼容xtls。**, 因为为了能够在tls包外进行过滤,我们需要做很多工作,所以技术实现与xtls是不一样的。 + +#### 总结 tls lazy encrypt 技术优点 + +解决了xtls一下痛点 + +1. 233 漏洞 +2. 只有单向splice +3. 无法与fullcone配合 +4. 无法与utls配合 + +原因: + +1. 我不使用循环进行tls过滤,而且不魔改tls包 +2. 我直接开启了双向splice;xtls只能优化客户端性能,我们两端都会优化 +3. 因为我的vless v1的fullcone是非mux的,分离信道,所以说是可以应用splice的(以后会添加支持,可能需要加一些代码,有待考察) +4. 因为我不魔改tls包,所以说可以套任何tls包的,比如utls + +而且alert根本不需要过滤,因为反正xtls本身过滤了还是有两个issue存在,是吧。 + +而且后面可以考虑,如果底层是使用的tls1.2,那么我们上层也可以用 tls1.2来握手。这个是可以做到的,因为底层的判断在客户端握手刚发生时就可以做到,而此时我们先判断,然后再发起对 服务端的连接,即可。 ### ws/grpc diff --git a/main.go b/main.go index 03599d8..009c861 100644 --- a/main.go +++ b/main.go @@ -392,7 +392,7 @@ func handleNewIncomeConnection(localServer proxy.Server, remoteClient proxy.Clie } -// tryRawCopy 尝试能否直接对拷,对拷 直接使用 原始 TCPConn +// tryRawCopy 尝试能否直接对拷,对拷 直接使用 原始 TCPConn,也就是裸奔转发 //和 xtls的splice 含义相同 // 我们内部先 使用 DetectConn进行过滤分析,然后再判断进化为splice 或者退化为普通拷贝 func tryRawCopy(wrc, wlc io.ReadWriter, localConn net.Conn, isclient bool, theRecorder *tlsLayer.Recorder) { @@ -403,7 +403,7 @@ func tryRawCopy(wrc, wlc io.ReadWriter, localConn net.Conn, isclient bool, theRe // 之所以可以对拷直连,是因为无论是 socks5 还是vless,只是在最开始的部分 加了目标头,后面的所有tcp连接都是直接传输的数据,就是说,一开始握手什么的是不能直接对拷的,等到后期就可以了 // 而且之所以能对拷,还有个原因就是,远程服务器 与 客户端 总是源源不断地 为 我们的 原始 TCP 连接 提供数据,我们只是一个中间商而已,左手倒右手 - // 如果开启了 half lazy 开关,则会在 Write的那一端 加强过滤,过滤一些alert,然后 只在Read端 进行splice + // 如果开启了 half lazy 开关,则会在 Write的那一端 加强过滤,过滤一些alert(目前还没做),然后 只在Read端 进行splice // // 如果是客户端,则 从 wlc 读取,写入 wrc ,这种情况是 Write, 然后对于 DetectConn 来说是 Read,即 从DetectConn读取,然后 写入到远程连接 // 如果是服务端,则 从 wrc 读取,写入 wlc, 这种情况是 Write @@ -425,6 +425,9 @@ func tryRawCopy(wrc, wlc io.ReadWriter, localConn net.Conn, isclient bool, theRe tlsConn := wrcVless.Conn.(*tlsLayer.Conn) rawWRC = tlsConn.GetRaw(tls_lazy_encrypt) + //不过仔细思考,我们根本不需要这么繁琐地获取啊?!因为我们的 原始连接我们本来就是有的! + //rawWRC = localConn.(*net.TCPConn) //然而我实测,竟然传输会得到错误的结果,怎么回事 + } else { rawWRC = wrc.(*net.TCPConn) //因为是direct } @@ -468,6 +471,7 @@ func tryRawCopy(wrc, wlc io.ReadWriter, localConn net.Conn, isclient bool, theRe break } //wrc.Write(p[:n]) + //在判断 “是TLS” 的瞬间,它会舍弃写入数据,而把写入的主动权交回我们,我们发送特殊命令后,通过直连写入数据 if wlcdc.R.IsTls && wlcdc.RawConn != nil { isgood = true diff --git a/tlsLayer/detect.go b/tlsLayer/detect.go index 03c968a..8c31ac6 100644 --- a/tlsLayer/detect.go +++ b/tlsLayer/detect.go @@ -421,6 +421,7 @@ func (dw *DetectWriter) SimpleWrite(p []byte) (n int, err error) { return } +//用于通知 “我们要开始tls数据部分啦” 的 “特殊指令”,该指令会被tls加密发送,因此不用担心暴露 var SpecialCommand = []byte{1, 2, 3, 4} //发现,数据基本就是 23 3 3, 22 3 3,22 3 1 , 20 3 3 diff --git a/tlsLayer/teeConn.go b/tlsLayer/teeConn.go index 7aecc98..c4c8939 100644 --- a/tlsLayer/teeConn.go +++ b/tlsLayer/teeConn.go @@ -35,6 +35,8 @@ func (wr *Recorder) StopRecord() { wr.stop = true } +// StartRecord后,Recorder就会开始记录数据。默认Recorder就是开启状态; +// 所以此方法仅用于之前 Stop过 func (wr *Recorder) StartRecord() { wr.stop = false } @@ -50,6 +52,7 @@ func (wr *Recorder) ReleaseBuffers() { } +// 打印内部所有包的前10字节 func (wr *Recorder) DigestAll() { tmp := wr.Buflist @@ -88,7 +91,7 @@ func (wr *Recorder) Write(p []byte) (n int, err error) { } // 实现net.Conn,专门用于 tls 检测步骤 -//每次 Read TeeConn, 都会从OldConn进行Read,然后把Read到的数据同时写入TargetWriter +//每次 Read TeeConn, 都会从OldConn进行Read,然后把Read到的数据同时写入 TargetWriter(NewTeeConn 的参数) // // 这个TeeConn设计时,专门用于 给 tls包一个 假的 net.Conn, 避免它 主动close我们的原Conn // @@ -110,6 +113,7 @@ func NewTeeConn(oldConn net.Conn, targetWriter io.Writer) *TeeConn { } +// 使用我们的Tee功能进行Read func (tc *TeeConn) Read(b []byte) (n int, err error) { n, err = tc.TargetReader.Read(b) @@ -117,19 +121,22 @@ func (tc *TeeConn) Read(b []byte) (n int, err error) { return } +// 直接使用原Conn发送 func (tc *TeeConn) Write(b []byte) (n int, err error) { return tc.OldConn.Write(b) } +//返回原Conn的地址 func (tc *TeeConn) LocalAddr() net.Addr { return tc.OldConn.LocalAddr() } +//返回原Conn的地址 func (tc *TeeConn) RemoteAddr() net.Addr { return tc.OldConn.RemoteAddr() } -// +//Close只会试图通知外界 Close调用过,并不真Close原Conn func (tc *TeeConn) Close() error { tc.closeCalled = true log.Println("TeeConn Close Called")