mirror of
https://github.com/e1732a364fed/v2ray_simple.git
synced 2025-12-24 13:27:56 +08:00
update tls lazy encrypt code.
目前该特性尚不稳定,会导致一些网页无法访问(不是速度慢,是有些tls连接因为检测tls措施不够好的问题, 给搞丢了,导致加载不出来,需要进一步调试;实测一般刷新一下页面就能加载出来,也不知道什么情况)
This commit is contained in:
13
README.md
13
README.md
@@ -10,6 +10,10 @@ verysimple项目大大简化了 转发机制,能提高运行速度。
|
||||
|
||||
在本项目里 制定 并实现了 vless v1标准。
|
||||
|
||||
在最新代码里,我还实现了 双向 tls lazy encrypt, 即另一种 xtls的 splice的实现。因为是双向的,而xtls的splice是单向,所以 理论上 tls lazy encrypt 比xtls 还快。
|
||||
|
||||
目前该特性尚不稳定,会导致一些网页无法访问(不是速度慢,是有些tls连接因为检测tls措施不够好的问题, 给搞丢了,导致加载不出来,需要进一步调试;实测一般刷新一下页面就能加载出来,也不知道什么情况),运行时可以用 -lazy 参数打开(服务端客户端都要打开),然后可以用 -pdd 参数 打印 tls 探测输出
|
||||
|
||||
|
||||
安装方式:
|
||||
|
||||
@@ -101,15 +105,6 @@ verysimple 继承 v2simple的一个优点,就是服务端的配置也可以用
|
||||
对于功能的golang test,请使用 `go test ./...` 命令。如果要详细的打印出test的过程,可以添加 -v 参数
|
||||
|
||||
|
||||
## 腾讯视频问题
|
||||
如果用此代理打开腾讯视频网页的话,会发现视频加载不出来。bilibili是没问题的。而且按理说和udp没关系因为websocket还是基于tcp的。
|
||||
|
||||
经过我测试, verysimple 返回的错误是:
|
||||
```
|
||||
failed to dail 'apd-9d8f8b192cbf63303ebad8d58b51293f.v.sm:443': dial tcp: lookup apd-9d8f8b192cbf63303ebad8d58b51293f.v.sm: no such host
|
||||
```
|
||||
|
||||
此问题有待考证解决。也不知道是不是只有我自己有这个问题。。
|
||||
|
||||
## 交叉编译
|
||||
|
||||
|
||||
79
main.go
79
main.go
@@ -33,13 +33,13 @@ var (
|
||||
conf *Config
|
||||
directClient proxy.Client
|
||||
|
||||
tls_lazy_encryptPtr = flag.Bool("lazy", false, "tls lazy encrypt (splice)")
|
||||
tls_lazy_encrypt bool
|
||||
tls_lazy_encrypt bool
|
||||
)
|
||||
|
||||
func init() {
|
||||
directClient, _ = proxy.ClientFromURL("direct://")
|
||||
|
||||
flag.BoolVar(&tls_lazy_encrypt, "lazy", false, "tls lazy encrypt (splice)")
|
||||
}
|
||||
|
||||
func printVersion() {
|
||||
@@ -78,7 +78,6 @@ func main() {
|
||||
printVersion()
|
||||
|
||||
flag.Parse()
|
||||
tls_lazy_encrypt = *tls_lazy_encryptPtr
|
||||
|
||||
var err error
|
||||
|
||||
@@ -109,7 +108,7 @@ func main() {
|
||||
log.Println(localServer.Name(), "is listening TCP on ", localServer.AddrStr())
|
||||
|
||||
// 后台运行主代码,而main函数只监听中断信号
|
||||
// TODO: 未来main函数可以推出 交互模式,未来推出动态增删用户、查询流量等功能时就有用
|
||||
// TODO: 未来main函数可以推出 交互模式,等未来推出动态增删用户、查询流量等功能时就有用
|
||||
go func() {
|
||||
for {
|
||||
lc, err := listener.Accept()
|
||||
@@ -142,7 +141,7 @@ func handleNewIncomeConnection(localServer proxy.Server, remoteClient proxy.Clie
|
||||
|
||||
baseLocalConn := thisLocalConnectionInstance
|
||||
|
||||
log.Println("got new", thisLocalConnectionInstance.RemoteAddr().String())
|
||||
//log.Println("got new", thisLocalConnectionInstance.RemoteAddr().String())
|
||||
|
||||
var err error
|
||||
|
||||
@@ -166,26 +165,24 @@ func handleNewIncomeConnection(localServer proxy.Server, remoteClient proxy.Clie
|
||||
|
||||
wlc, targetAddr, err := localServer.Handshake(thisLocalConnectionInstance)
|
||||
if err != nil {
|
||||
log.Printf("failed in handshake from %v: %v", localServer.AddrStr(), err)
|
||||
log.Println("failed in handshake from", localServer.AddrStr(), err)
|
||||
thisLocalConnectionInstance.Close()
|
||||
return
|
||||
}
|
||||
|
||||
// 我们在客户端 lazy_encrypt 探测时,读取socks5 传来的信息,因为这个和要发送到tls的信息时一模一样的,所以就不需要等包上vless、tls后再判断了, 直接解包 socks5进行判断
|
||||
// 我们在客户端 lazy_encrypt 探测时,读取socks5 传来的信息,因为这个和要发送到tls的信息是一模一样的,所以就不需要等包上vless、tls后再判断了, 直接解包 socks5进行判断
|
||||
//
|
||||
// 而在服务端探测时,因为包了 tls,所以要在tls解包后, vless 解包后,再进行判断;
|
||||
// 所以总之都是要在 localServer判断 wlc,只不过理由不一样
|
||||
|
||||
var thecc *tlsLayer.CopyConn
|
||||
// 而在服务端探测时,因为 客户端传来的连接 包了 tls,所以要在tls解包后, vless 解包后,再进行判断;
|
||||
// 所以总之都是要在 localServer判断 wlc;总之,含义就是,去检索“用户承载数据”的来源
|
||||
|
||||
if tls_lazy_encrypt {
|
||||
|
||||
thecc = tlsLayer.NewDetectConn(baseLocalConn, wlc)
|
||||
wlc = tlsLayer.NewDetectConn(baseLocalConn, wlc, tlsLayer.OnlyTest)
|
||||
|
||||
wlc = thecc
|
||||
//clientConn = cc
|
||||
}
|
||||
|
||||
//如果目标是udp则要分情况讨论
|
||||
if targetAddr.IsUDP {
|
||||
|
||||
switch localServer.Name() {
|
||||
@@ -250,9 +247,9 @@ func handleNewIncomeConnection(localServer proxy.Server, remoteClient proxy.Clie
|
||||
|
||||
var client proxy.Client
|
||||
|
||||
client = remoteClient
|
||||
client = remoteClient //如果加了白名单等过滤方式,则client可能会等于direct等,再说
|
||||
|
||||
log.Printf("%s want to dial %s", client.Name(), targetAddr.UrlString())
|
||||
log.Println(client.Name(), " want to dial ", targetAddr.UrlString())
|
||||
|
||||
// 如果目标是udp 则我们单独处理。这里为了简便,不考虑多级串联的关系,直接只考虑 直接转发到direct
|
||||
// 根据 vless_v1的讨论,vless_v1 的udp转发的 通信方式 也是与tcp连接类似的分离信道方式
|
||||
@@ -338,7 +335,7 @@ func handleNewIncomeConnection(localServer proxy.Server, remoteClient proxy.Clie
|
||||
*/
|
||||
|
||||
if tls_lazy_encrypt {
|
||||
tryRaw(wrc, wlc, client.IsUseTLS())
|
||||
tryRawCopy(wrc, wlc, client.IsUseTLS())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -347,15 +344,17 @@ func handleNewIncomeConnection(localServer proxy.Server, remoteClient proxy.Clie
|
||||
|
||||
}
|
||||
|
||||
// tryRawCopy 尝试能否直接对拷,对拷 直接使用 原始 TCPConn
|
||||
//和 xtls的splice 含义相同
|
||||
func tryRaw(wrc, wlc io.ReadWriter, isclient bool) {
|
||||
func tryRawCopy(wrc, wlc io.ReadWriter, isclient bool) {
|
||||
|
||||
//如果用了 lazy_encrypt, 则不直接利用Copy,因为有两个阶段:判断阶段和直连阶段
|
||||
// 在判断阶段,因为还没确定是否是 tls,所以是要继续用tls加密的,
|
||||
// 而直连阶段,只要能让 Copy使用 ReadFrom, 就能一步一步最终使用splice了
|
||||
// 而直连阶段,只要能让 Copy使用 net.TCPConn的 ReadFrom, 就不用管了, golang最终就会使用splice
|
||||
// 之所以可以对拷直连,是因为无论是 socks5 还是vless,只是在最开始的部分 加了目标头,后面的所有tcp连接都是直接传输的数据,就是说,一开始握手什么的是不能直接对拷的,等到后期就可以了
|
||||
// 而且之所以能对拷,还有个原因就是,远程服务器 与 客户端 总是源源不断地 为 我们的 原始 TCP 连接 提供数据,我们只是一个中间商而已,左手倒右手
|
||||
|
||||
//首先判断我们的wlc(*tlsLayer.CopyConn) 是否得出来 IsTLS
|
||||
wlccc := wlc.(*tlsLayer.CopyConn)
|
||||
wlccc := wlc.(*tlsLayer.DetectConn)
|
||||
wlccc_raw := wlccc.RawConn
|
||||
|
||||
var rawWRC *net.TCPConn
|
||||
@@ -363,21 +362,23 @@ func tryRaw(wrc, wlc io.ReadWriter, isclient bool) {
|
||||
//wrc 有两种情况,如果客户端那就是tls,服务端那就是direct。我们不讨论服务端 处于中间层的情况
|
||||
|
||||
if isclient {
|
||||
// 不过实际上 wrc 是 vless的 UserConn, 而UserConn的底层连接才是TLS
|
||||
// 不过实际上客户端 wrc 是 vless的 UserConn, 而UserConn的底层连接才是TLS
|
||||
// 很明显,目前我们只支持vless所以才这么操作,以后再说。
|
||||
|
||||
wrcVless := wrc.(*vless.UserConn)
|
||||
|
||||
tlsConn := wrcVless.Conn.(*tlsLayer.Conn)
|
||||
|
||||
rawWRC = tlsConn.GetRaw()
|
||||
|
||||
} else {
|
||||
rawWRC = wrc.(*net.TCPConn)
|
||||
rawWRC = wrc.(*net.TCPConn) //因为是direct
|
||||
}
|
||||
|
||||
if rawWRC == nil {
|
||||
log.Println("splice fail reason 3 ")
|
||||
io.Copy(wrc, wlc)
|
||||
log.Println("splice fail reason 1 ")
|
||||
|
||||
//退化回原始状态
|
||||
go io.Copy(wrc, wlc)
|
||||
io.Copy(wlc, wrc)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -385,6 +386,7 @@ func tryRaw(wrc, wlc io.ReadWriter, isclient bool) {
|
||||
//从 wlccc 读取,向 wrc 写入
|
||||
// 此时如果ReadFrom,那就是 wrc.ReadFrom(wlccc)
|
||||
//wrc 要实现 ReaderFrom才行, 或者把最底层TCPConn暴露,然后 wlccc 也要把最底层 TCPConn暴露出来
|
||||
// 这里就直接采取底层方式
|
||||
|
||||
p := common.GetPacket()
|
||||
isgood := false
|
||||
@@ -396,20 +398,24 @@ func tryRaw(wrc, wlc io.ReadWriter, isclient bool) {
|
||||
|
||||
n, err := wlccc.Read(p)
|
||||
if err != nil {
|
||||
|
||||
break
|
||||
}
|
||||
wrc.Write(p[:n])
|
||||
|
||||
if wlccc.R.IsTls && wlccc.RawConn != nil {
|
||||
isgood = true
|
||||
|
||||
}
|
||||
}
|
||||
common.PutPacket(p)
|
||||
if isgood {
|
||||
|
||||
log.Println("成功SpliceRead 方向1")
|
||||
rawWRC.ReadFrom(wlccc_raw)
|
||||
if tlsLayer.PDD {
|
||||
log.Println("成功SpliceRead 方向1")
|
||||
num, _ := rawWRC.ReadFrom(wlccc_raw)
|
||||
log.Println("SpliceRead 方向1 读完,", num)
|
||||
} else {
|
||||
rawWRC.ReadFrom(wlccc_raw)
|
||||
}
|
||||
|
||||
}
|
||||
}()
|
||||
@@ -424,17 +430,22 @@ func tryRaw(wrc, wlc io.ReadWriter, isclient bool) {
|
||||
}
|
||||
n, err := wrc.Read(p)
|
||||
if err != nil {
|
||||
|
||||
break
|
||||
}
|
||||
wlccc.Write(p[:n])
|
||||
if wlccc.W.IsTls && wlccc.RawConn != nil {
|
||||
isgood2 = true
|
||||
|
||||
}
|
||||
}
|
||||
common.PutPacket(p)
|
||||
if isgood2 {
|
||||
log.Println("成功SpliceRead 方向2")
|
||||
wlccc_raw.ReadFrom(rawWRC)
|
||||
if tlsLayer.PDD {
|
||||
log.Println("成功SpliceRead 方向2")
|
||||
num, _ := wlccc_raw.ReadFrom(rawWRC)
|
||||
log.Println("SpliceRead 方向2 读完,", num)
|
||||
} else {
|
||||
wlccc_raw.ReadFrom(rawWRC)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package tlsLayer
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"log"
|
||||
"net"
|
||||
"unsafe"
|
||||
)
|
||||
@@ -21,7 +20,7 @@ func (c *Conn) GetRaw() *net.TCPConn {
|
||||
rc := (*faketlsconn)(unsafe.Pointer(uintptr(unsafe.Pointer(c.Conn))))
|
||||
if rc != nil {
|
||||
if rc.conn != nil {
|
||||
log.Println("成功获取到 *net.TCPConn!", rc.conn.(*net.TCPConn))
|
||||
//log.Println("成功获取到 *net.TCPConn!", rc.conn.(*net.TCPConn)) //经测试,是毫无问题的
|
||||
return rc.conn.(*net.TCPConn)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package tlsLayer
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
@@ -8,40 +9,55 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
type CopyConn struct {
|
||||
net.Conn //这个 Conn本包中不会用到,只是为了能让CopyConn支持 net.Conn
|
||||
io.ReadWriter
|
||||
W *DetectWriter
|
||||
R *DetectReader
|
||||
var PDD bool //print tls detect detail
|
||||
var OnlyTest bool
|
||||
|
||||
func init() {
|
||||
log.SetOutput(os.Stdout) //主要是日志太多,如果都能直接用管道放到文件中就好了,默认不是Stdout所以优点尴尬,操作麻烦点
|
||||
|
||||
flag.BoolVar(&PDD, "pdd", false, "print tls detect detail")
|
||||
flag.BoolVar(&OnlyTest, "ot", false, "only detect tls, doesn't actually mark tls")
|
||||
|
||||
RawConn *net.TCPConn // 这个是为了让外界能够直接拿到底层的连接
|
||||
}
|
||||
|
||||
func (cc *CopyConn) Read(p []byte) (int, error) {
|
||||
// 用于 探测 承载数据是否使用了tls
|
||||
// 可以参考 https://www.baeldung.com/linux/tcpdump-capture-ssl-handshake
|
||||
type DetectConn struct {
|
||||
net.Conn //这个 Conn本DetectConn 中不会用到,只是为了能让CopyConn支持 net.Conn
|
||||
W *DetectWriter
|
||||
R *DetectReader
|
||||
|
||||
RawConn *net.TCPConn // 这个是为了让外界能够直接拿到底层的连接
|
||||
|
||||
onlyTest bool //如果此开关打开,则不会去真实修改IsTLS,而只是去过滤所有的包。
|
||||
}
|
||||
|
||||
func (cc *DetectConn) Read(p []byte) (int, error) {
|
||||
return cc.R.Read(p)
|
||||
}
|
||||
|
||||
func (cc *CopyConn) Write(p []byte) (int, error) {
|
||||
func (cc *DetectConn) Write(p []byte) (int, error) {
|
||||
return cc.W.Write(p)
|
||||
}
|
||||
|
||||
func (cc *CopyConn) ReadFrom(r io.Reader) (int64, error) {
|
||||
//这个暂时没用到,先留着
|
||||
func (cc *DetectConn) ReadFrom(r io.Reader) (int64, error) {
|
||||
if cc.RawConn != nil {
|
||||
return cc.RawConn.ReadFrom(r)
|
||||
}
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
func NewDetectConn(oldConn net.Conn, rw io.ReadWriter) *CopyConn {
|
||||
//可选两个参数传入,优先使用rw ,为nil的话 再使用oldConn,作为 底层Read 和Write的 主体
|
||||
func NewDetectConn(oldConn net.Conn, rw io.ReadWriter, onlyTest bool) *DetectConn {
|
||||
|
||||
var validOne io.ReadWriter = rw
|
||||
if rw == nil {
|
||||
validOne = oldConn
|
||||
}
|
||||
|
||||
cc := &CopyConn{
|
||||
Conn: oldConn,
|
||||
ReadWriter: rw,
|
||||
cc := &DetectConn{
|
||||
Conn: oldConn,
|
||||
W: &DetectWriter{
|
||||
Writer: validOne,
|
||||
},
|
||||
@@ -50,6 +66,9 @@ func NewDetectConn(oldConn net.Conn, rw io.ReadWriter) *CopyConn {
|
||||
},
|
||||
}
|
||||
|
||||
cc.W.onlyTest = onlyTest
|
||||
cc.R.onlyTest = onlyTest
|
||||
|
||||
if netConn := oldConn.(*net.TCPConn); netConn != nil {
|
||||
//log.Println("get netConn!") // 如果是客户端的socks5,网页浏览的话这里一定能转成 TCPConn
|
||||
cc.RawConn = netConn
|
||||
@@ -58,81 +77,107 @@ func NewDetectConn(oldConn net.Conn, rw io.ReadWriter) *CopyConn {
|
||||
return cc
|
||||
}
|
||||
|
||||
// DetectReader 对每个Read的数据进行分析,判断是否是tls流量
|
||||
type DetectReader struct {
|
||||
io.Reader
|
||||
IsTls bool
|
||||
type ComDetectStruct struct {
|
||||
IsTls bool
|
||||
onlyTest bool
|
||||
|
||||
packetCount int
|
||||
}
|
||||
|
||||
func init() {
|
||||
log.SetOutput(os.Stdout)
|
||||
// DetectReader 对每个Read的数据进行分析,判断是否是tls流量
|
||||
type DetectReader struct {
|
||||
io.Reader
|
||||
|
||||
ComDetectStruct
|
||||
}
|
||||
|
||||
func commonDetect(dr *ComDetectStruct, p []byte, isRead bool) {
|
||||
|
||||
dr.packetCount++
|
||||
p0 := p[0]
|
||||
p1 := p[1]
|
||||
p2 := p[2]
|
||||
|
||||
/*
|
||||
if p0 == 22 || p0 == 23 || p0 == 20 || (p0 == 21 && n == 31) {
|
||||
//客户端Read 时 少数情况首部会有21,首部为 [21 3 3 0 26 0 0 0 0 0], 一般总长度为31
|
||||
// 其它都是 能被捕捉到的。
|
||||
if p[1] == 3 {
|
||||
min := 5
|
||||
if n < 5 {
|
||||
min = n
|
||||
}
|
||||
log.Println(" TLS R,", n, err, p[:min])
|
||||
dr.IsTls = true
|
||||
return
|
||||
}
|
||||
}*/
|
||||
|
||||
if p0 == 23 && p1 == 3 && p2 == 3 {
|
||||
if PDD {
|
||||
str := "W"
|
||||
if isRead {
|
||||
str = "R"
|
||||
}
|
||||
log.Println(str, "got TLS!")
|
||||
}
|
||||
|
||||
if !dr.onlyTest {
|
||||
dr.IsTls = true
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
n := len(p)
|
||||
|
||||
// 打印没过滤到的数据
|
||||
if PDD || dr.onlyTest {
|
||||
min := 10
|
||||
if n < 10 {
|
||||
min = n
|
||||
}
|
||||
|
||||
str := "Write,"
|
||||
if isRead {
|
||||
str = "Read,"
|
||||
}
|
||||
log.Println(" ======== ", str, n, p[:min])
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 总之,我们在客户端的 Read 操作,就是 我们试图使用 Read 读取客户的请求,然后试图发往 外界
|
||||
// 所以在socks5后面 使用的这个 Read,是读取客户端发送的请求,比如 clienthello之类
|
||||
// 服务端的 Read 操作,是把 远程目标服务器 发来的 数据 发送到 客户端,比如 serverhello 之类
|
||||
//
|
||||
// 我们直接判断23 3 3字节,然后直接推定tls!不管三七二十一,判断错误就错误吧!快就得了!
|
||||
func (dr *DetectReader) Read(p []byte) (n int, err error) {
|
||||
n, err = dr.Reader.Read(p)
|
||||
if dr.IsTls {
|
||||
if !dr.onlyTest && dr.IsTls {
|
||||
return
|
||||
}
|
||||
|
||||
if dr.packetCount > 8 {
|
||||
//都8个包了还没断定tls?直接推定不是!
|
||||
return
|
||||
}
|
||||
|
||||
if n > 3 {
|
||||
dr.packetCount++
|
||||
p0 := p[0]
|
||||
p1 := p[1]
|
||||
p2 := p[2]
|
||||
|
||||
/*
|
||||
if p0 == 22 || p0 == 23 || p0 == 20 || (p0 == 21 && n == 31) {
|
||||
//少数情况首部会有21,首部为 [21 3 3 0 26 0 0 0 0 0], 一般总长度为31
|
||||
// 其它都是 能被捕捉到的。
|
||||
if p[1] == 3 {
|
||||
min := 5
|
||||
if n < 5 {
|
||||
min = n
|
||||
}
|
||||
log.Println(" TLS R,", n, err, p[:min])
|
||||
dr.IsTls = true
|
||||
return
|
||||
}
|
||||
}*/
|
||||
|
||||
if p0 == 23 && p1 == 3 && p2 == 3 {
|
||||
log.Println("R got TLS!")
|
||||
dr.IsTls = true
|
||||
return
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
eStr := err.Error()
|
||||
if strings.Contains(eStr, "use of closed") || strings.Contains(eStr, "reset by peer") || strings.Contains(eStr, "EOF") {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
min := 10
|
||||
if n < 10 {
|
||||
min = n
|
||||
if !dr.onlyTest && dr.packetCount > 8 {
|
||||
//都8个包了还没断定tls?直接推定不是!
|
||||
return
|
||||
}
|
||||
log.Println(" ======== Read,", n, err, p[:min], string(p[:min]))
|
||||
|
||||
if n > 3 {
|
||||
commonDetect(&dr.ComDetectStruct, p, true)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// DetectReader 对每个Read的数据进行分析,判断是否是tls流量
|
||||
type DetectWriter struct {
|
||||
io.Writer
|
||||
IsTls bool
|
||||
|
||||
packetCount int
|
||||
ComDetectStruct
|
||||
}
|
||||
|
||||
//我发现,数据基本就是 23 3 3, 22 3 3,22 3 1 , 20 3 3
|
||||
@@ -144,6 +189,7 @@ type DetectWriter struct {
|
||||
//
|
||||
// 总之,我们在客户端的 Write 操作,就是 外界试图使用我们的 Write 写入数据
|
||||
// 所以在socks5后面 使用的这个Write,应该是把 服务端的响应 写回 socks5,比如 serverhello之类
|
||||
// 服务端的 Write操作,是把客户端发来的 数据 发送到远程目标服务器,比如 clienthello之类
|
||||
//
|
||||
// 根据之前讨论,23 3 3 就是 数据部分,TLSCiphertext
|
||||
// https://halfrost.com/https_record_layer/
|
||||
@@ -151,45 +197,23 @@ type DetectWriter struct {
|
||||
// 进入direct模式; 目前从简,连握手包都不检测!测错就测错!
|
||||
func (dr *DetectWriter) Write(p []byte) (n int, err error) {
|
||||
n, err = dr.Writer.Write(p)
|
||||
if dr.IsTls {
|
||||
if !dr.onlyTest && dr.IsTls {
|
||||
return
|
||||
}
|
||||
|
||||
if dr.packetCount > 8 {
|
||||
if err != nil {
|
||||
eStr := err.Error()
|
||||
if strings.Contains(eStr, "use of closed") || strings.Contains(eStr, "reset by peer") || strings.Contains(eStr, "EOF") {
|
||||
return
|
||||
}
|
||||
}
|
||||
if !dr.onlyTest && dr.packetCount > 8 {
|
||||
//都8个包了还没断定tls?直接推定不是!
|
||||
return
|
||||
}
|
||||
|
||||
if n > 3 {
|
||||
dr.packetCount++
|
||||
|
||||
p0 := p[0]
|
||||
p1 := p[1]
|
||||
p2 := p[2]
|
||||
|
||||
/*
|
||||
if p0 == 22 || p0 == 23 || p0 == 20 {
|
||||
if p[1] == 3 {
|
||||
min := 5
|
||||
if n < 5 {
|
||||
min = n
|
||||
}
|
||||
log.Println(" TLS W,", n, err, p[:min])
|
||||
return
|
||||
}
|
||||
}*/
|
||||
|
||||
if p0 == 23 && p1 == 3 && p2 == 3 {
|
||||
log.Println("W got TLS!")
|
||||
dr.IsTls = true
|
||||
return
|
||||
}
|
||||
commonDetect(&dr.ComDetectStruct, p, false)
|
||||
}
|
||||
|
||||
min := 10
|
||||
if n < 10 {
|
||||
min = n
|
||||
}
|
||||
log.Println(" ======== Write,", n, err, p[:min], string(p[:min]))
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user