令trojan读到crlf后再结束;修订代码,添加read_timeout的app配置;

根据 https://www.ihcblog.com/a-better-tls-obfs-proxy/
trojan的crlf是模仿http协议,令服务端具有和真实http服务器一样的响应特征
This commit is contained in:
e1732a364fed
2000-01-01 00:00:00 +00:00
parent 29517ec226
commit 49c25bf1e4
3 changed files with 37 additions and 7 deletions

View File

@@ -41,6 +41,7 @@ type AppConf struct {
UDP_timeout *int `toml:"udp_timeout"`
DialTimeoutSeconds *int `toml:"dial_timeout"`
ReadTimeoutSeconds *int `toml:"read_timeout"`
GeoipFile *string `toml:"geoip_file"`
GeositeFolder *string `toml:"geosite_folder"`
@@ -75,6 +76,13 @@ func setupByAppConf(ac *AppConf) {
}
}
if ac.ReadTimeoutSeconds != nil {
if s := *ac.ReadTimeoutSeconds; s > 0 {
proxy.CommonReadTimeout = time.Duration(s) * time.Second
}
}
if ac.GeoipFile != nil {
netLayer.GeoipFileName = *ac.GeoipFile
}

View File

@@ -13,7 +13,9 @@ import (
)
// default recommended handshake read timeout
const CommonReadTimeout = time.Second * 4
const DefaultCommonReadTimeout = time.Second * 4
var CommonReadTimeout = DefaultCommonReadTimeout
// set read timeout after CommonReadTimeout
func SetCommonReadTimeout(c net.Conn) error {

View File

@@ -90,14 +90,33 @@ func (s *Server) Handshake(underlay net.Conn) (result net.Conn, msgConn netLayer
readbs := utils.GetBytes(utils.MTU)
wholeReadLen, err := underlay.Read(readbs)
if err != nil {
returnErr = utils.ErrInErr{ErrDesc: "read underlay failed", ErrDetail: err, Data: wholeReadLen}
return
}
//todo: 根据 https://www.ihcblog.com/a-better-tls-obfs-proxy/
var wholeReadLen int
//根据 https://www.ihcblog.com/a-better-tls-obfs-proxy/
//trojan的 CRLF 是为了模拟http服务器的行为, 所以此时不要一次性Read而是要Read到CRLF为止
// wholeReadLen, err := underlay.Read(readbs)
// if err != nil {
// returnErr = utils.ErrInErr{ErrDesc: "read underlay failed", ErrDetail: err, Data: wholeReadLen}
// return
// }
for {
thislen, e := underlay.Read(readbs[wholeReadLen:])
if e != nil {
returnErr = utils.ErrInErr{ErrDesc: "read underlay failed", ErrDetail: e, Data: wholeReadLen}
return
}
lastTail := wholeReadLen
wholeReadLen += thislen
index_crlf := bytes.Index(readbs[lastTail:wholeReadLen], crlf)
if index_crlf > 0 {
break
}
}
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
@@ -173,6 +192,7 @@ realPart:
//关于 trojan实现多路复用的方式可参考 https://p4gefau1t.github.io/trojan-go/developer/mux/ (该链接只是泛泛提了一下而已,没有制定具体实现的标准)
ismux = true
}
var err error
targetAddr, err = GetAddrFrom(readbuf, ismux)
if err != nil {