修订文档;令http层支持回落

This commit is contained in:
e1732a364fed
2000-01-01 00:00:00 +00:00
parent a44a83c5f3
commit 0f527cfba4
8 changed files with 69 additions and 26 deletions

View File

@@ -296,8 +296,6 @@ v0协议是直接兼容现有v2ray/xray的比如可以客户端用任何现
支持trojan协议 以及smux, 而且经过测速比trojan-go快。速度差距和本作的vless与v2ray的vless的差距基本一致所以就不放出测速文件了参考vless即可
不过 lazy特性是不支持trojan的。这种不稳定不安全的特性还是专用在一个协议上比较好。
在没有mmdb文件时自动下载mmdb
使用readv 进行加速
@@ -506,11 +504,6 @@ MIT协议即你用的时候也要附带一个MIT文件然后作者不承
启发自我fork的v2simple不过原作者的架构还是有点欠缺我就直接完全重构了完全使用我自己的代码。
这样也杜绝了 原作者跑路 导致的 一些不懂法律的人对于开源许可的 质疑。
实际上是毫无问题的,关键是他们太谨慎。无所谓,现在我完全自己写,没话说了吧—;
我fork也是尊重原作者既然你们这么谨慎正好推动了我的重构计划推动了历史发展
## 额外说明 以及 开发计划
计划有

View File

@@ -67,14 +67,17 @@ sudo cp examples/vlesss.server.toml server.toml
如果你不愿意使用linux的“后台服务”只是想手动去令它在后台运行那么实际上在verysimple所在位置运行如下一段命令即可。
```
nohup ./verysimple -c server.toml >/dev/null &
```
nohup ./verysimple -c server.toml >/dev/null &
这里将它的标准输出舍弃了因为一般来说我们会在toml配置文件中 配置好日志文件名称;如果不舍弃输出的话,就会多一个输出(到控制台),增加系统负担。
同样,视你的权限来酌情在命令前面添加 `sudo`
上面这个nohub这行命令可以写到一个文件里比如 run.sh, 然后用 `chmod +x run.sh` 将其变为可执行文件, 之后你只要运行 run.sh 就可以后台运行了。
如果你会crontab还可以在里面设置开机运行该脚本。这种方式就比 systemctl轻量多了而且还适用于openwrt。
### 标准方式

View File

@@ -172,9 +172,8 @@ func (h *HeaderPreset) AssignDefaultValue() {
h.Prepare()
}
func (h *HeaderPreset) ReadRequest(underlay net.Conn) (leftBuf *bytes.Buffer, err error) {
func (h *HeaderPreset) ReadRequest(underlay io.Reader) (rp H1RequestParser, leftBuf *bytes.Buffer, err error) {
var rp H1RequestParser
err = rp.ReadAndParse(underlay)
if err != nil {
return
@@ -193,14 +192,18 @@ func (h *HeaderPreset) ReadRequest(underlay net.Conn) (leftBuf *bytes.Buffer, er
err = utils.ErrInErr{ErrDesc: "ReadRequest failed, wrong path", ErrDetail: utils.ErrInvalidData, Data: rp.Path}
return
}
allbytes := rp.WholeRequestBuf.Bytes()
leftBuf = bytes.NewBuffer(allbytes)
indexOfEnding := bytes.Index(allbytes, HeaderENDING_bytes)
if indexOfEnding < 0 {
err = utils.ErrInvalidData
return
}
headerBytes := rp.WholeRequestBuf.Next(indexOfEnding)
headerBytes := leftBuf.Next(indexOfEnding)
if h.Strict {
indexOfFirstCRLF := bytes.Index(allbytes, []byte(CRLF))
@@ -258,12 +261,12 @@ func (h *HeaderPreset) ReadRequest(underlay net.Conn) (leftBuf *bytes.Buffer, er
}
rp.WholeRequestBuf.Next(4)
leftBuf.Next(len(HeaderENDING))
return rp.WholeRequestBuf, nil
return
}
func (h *HeaderPreset) WriteRequest(underlay net.Conn, payload []byte) error {
func (h *HeaderPreset) WriteRequest(underlay io.Writer, payload []byte) error {
buf := bytes.NewBuffer(payload)
r, err := http.NewRequest(h.Request.Method, h.Request.Path[0], buf)
@@ -281,7 +284,7 @@ func (h *HeaderPreset) WriteRequest(underlay net.Conn, payload []byte) error {
return r.Write(underlay)
}
func (h *HeaderPreset) ReadResponse(underlay net.Conn) (leftBuf *bytes.Buffer, err error) {
func (h *HeaderPreset) ReadResponse(underlay io.Reader) (leftBuf *bytes.Buffer, err error) {
bs := utils.GetPacket()
var n int
@@ -307,7 +310,7 @@ func (h *HeaderPreset) ReadResponse(underlay net.Conn) (leftBuf *bytes.Buffer, e
return buf, nil
}
func (h *HeaderPreset) WriteResponse(underlay net.Conn, payload []byte) error {
func (h *HeaderPreset) WriteResponse(underlay io.Writer, payload []byte) error {
buf := utils.GetBuf()
buf.WriteString("HTTP/")
@@ -347,6 +350,7 @@ type HeaderConn struct {
IsServerEnd bool
optionalReader io.Reader
ReadOkCallback func(*bytes.Buffer)
notFirstWrite bool
}
@@ -356,11 +360,21 @@ func (c *HeaderConn) Read(p []byte) (n int, err error) {
if c.IsServerEnd {
if c.optionalReader == nil {
buf, err = c.H.ReadRequest(c.Conn)
var rp H1RequestParser
rp, buf, err = c.H.ReadRequest(c.Conn)
if err != nil {
err = utils.ErrInErr{ErrDesc: "http HeaderConn Read failed, at serverEnd", ErrDetail: err}
err = &utils.ErrBuffer{
Err: utils.ErrInErr{ErrDesc: "http HeaderConn Read failed, at serverEnd", ErrDetail: err},
Buf: rp.WholeRequestBuf,
}
return
}
if c.ReadOkCallback != nil {
c.ReadOkCallback(rp.WholeRequestBuf)
}
c.optionalReader = io.MultiReader(buf, c.Conn)
}

View File

@@ -118,7 +118,7 @@ type H1RequestParser struct {
Headers []RawHeader
}
// 尝试读取数据并解析HTTP请求, 解析道道 数据会存入 RequestParser 结构中.
// 尝试读取数据并解析HTTP请求, 解析 数据会存入 RequestParser 结构中.
//如果读取错误,会返回该错误; 如果读到的不是HTTP请求返回 的err 的 errors.Is(err,ErrNotHTTP_Request) == true;
//
// 该函数有个小问题,就是如果一次Read是短Read可能是网络原因没读完整个http头部则仍然会认为是错误

21
iics.go
View File

@@ -91,6 +91,13 @@ type incomingInserverConnState struct {
routedToDirect bool
routingEnv *proxy.RoutingEnv //used in passToOutClient
heapObj *heapObj
}
type heapObj struct {
headerPass bool
wholeBuffer *bytes.Buffer
}
//每个iics使用之前必须调用 genID
@@ -103,7 +110,10 @@ func (iics *incomingInserverConnState) genID() {
// 在调用 passToOutClient前遇到err时调用, 若找出了buf设置iics并返回true
func (iics *incomingInserverConnState) extractFirstBufFromErr(err error) bool {
if !iics.inServer.CanFallback() {
var hasHeader = iics.inServer.HasHeader() != nil
var canFallback = iics.inServer.CanFallback() || hasHeader
if !canFallback {
if iics.wrappedConn != nil {
iics.wrappedConn.Close()
@@ -116,6 +126,15 @@ func (iics *incomingInserverConnState) extractFirstBufFromErr(err error) bool {
be, ok := err.(*utils.ErrBuffer)
if !ok {
if iics.heapObj != nil {
if iics.heapObj.headerPass && iics.heapObj.wholeBuffer != nil {
//http header通过了但是后面出错有可能是类似 vmess+http 的情况收到了一个正常的Get请求后面的vmess读取不到数据导致了 read timeout此时依然可以回落.
iics.fallbackFirstBuffer = iics.heapObj.wholeBuffer
iics.heapObj = nil
return true
}
}
// 能fallback 但是返回的 err却不是fallback err证明遇到了更大问题可能是底层read问题所以也不用继续fallback了
if iics.wrappedConn != nil {
iics.wrappedConn.Close()

11
main.go
View File

@@ -249,10 +249,21 @@ func handleNewIncomeConnection(inServer proxy.Server, defaultClientForThis proxy
//websocket 可以自行处理header, 不需要额外http包装
if !(advSer != nil && advSer.CanHandleHeaders()) {
var ho *heapObj = iics.heapObj
if iics.heapObj == nil {
ho = &heapObj{}
iics.heapObj = ho
}
wrappedConn = &httpLayer.HeaderConn{
Conn: wrappedConn,
H: header,
IsServerEnd: true,
ReadOkCallback: func(b *bytes.Buffer) {
ho.headerPass = true
ho.wholeBuffer = b
},
}
}

View File

@@ -13,7 +13,6 @@ import (
"math/rand"
"net"
"net/url"
"runtime"
"strings"
"time"
@@ -23,8 +22,6 @@ import (
"golang.org/x/crypto/chacha20poly1305"
)
const systemAutoUseAes = runtime.GOARCH == "amd64" || runtime.GOARCH == "s390x" || runtime.GOARCH == "arm64"
const vmess_security_confStr string = "vmess_security"
func init() {
@@ -110,7 +107,7 @@ func (c *Client) specifySecurityByStr(security string) error {
case "chacha20-poly1305":
c.security = SecurityChacha20Poly1305
case "auto", "": //这里我们为了保护用户当字符串为空时依然设为auto而不是zero
if systemAutoUseAes {
if utils.SystemAutoUseAes {
c.security = SecurityAES128GCM
} else {
c.security = SecurityChacha20Poly1305

6
utils/crypto.go Normal file
View File

@@ -0,0 +1,6 @@
package utils
import "runtime"
//有些系统对aes支持不好有些支持好。SystemAutoUseAes若为true则说明支持很好使用aes作为加密算法速度最佳。
const SystemAutoUseAes = runtime.GOARCH == "amd64" || runtime.GOARCH == "s390x" || runtime.GOARCH == "arm64"