mirror of
https://github.com/e1732a364fed/v2ray_simple.git
synced 2025-12-24 13:27:56 +08:00
修订文档;令http层支持回落
This commit is contained in:
@@ -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也是尊重原作者,既然你们这么谨慎,正好推动了我的重构计划,推动了历史发展
|
||||
## 额外说明 以及 开发计划
|
||||
|
||||
计划有
|
||||
|
||||
@@ -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。
|
||||
|
||||
### 标准方式
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
21
iics.go
@@ -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
11
main.go
@@ -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
|
||||
},
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
6
utils/crypto.go
Normal file
@@ -0,0 +1,6 @@
|
||||
package utils
|
||||
|
||||
import "runtime"
|
||||
|
||||
//有些系统对aes支持不好,有些支持好。SystemAutoUseAes若为true,则说明支持很好,使用aes作为加密算法速度最佳。
|
||||
const SystemAutoUseAes = runtime.GOARCH == "amd64" || runtime.GOARCH == "s390x" || runtime.GOARCH == "arm64"
|
||||
Reference in New Issue
Block a user