mirror of
https://github.com/e1732a364fed/v2ray_simple.git
synced 2025-10-08 02:00:33 +08:00
修订代码,文档, 示例
This commit is contained in:
@@ -1,8 +1,5 @@
|
|||||||
package grpcSimple
|
package grpcSimple
|
||||||
|
|
||||||
// Modified from: https://github.com/Dreamacro/clash/blob/master/transport/gun/gun.go
|
|
||||||
// License: MIT
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
@@ -174,8 +171,6 @@ func (c *Client) GetCommonConn(underlay net.Conn) (any, error) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) ProcessWhenFull(underlay any) {}
|
|
||||||
|
|
||||||
func (c *Client) DialSubConn(underlay any) (net.Conn, error) {
|
func (c *Client) DialSubConn(underlay any) (net.Conn, error) {
|
||||||
|
|
||||||
if underlay == nil {
|
if underlay == nil {
|
||||||
|
@@ -11,6 +11,9 @@ import (
|
|||||||
"github.com/e1732a364fed/v2ray_simple/utils"
|
"github.com/e1732a364fed/v2ray_simple/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Modified from: https://github.com/Dreamacro/clash/blob/master/transport/gun/gun.go
|
||||||
|
// License: MIT
|
||||||
|
|
||||||
func commonWrite(b []byte) *bytes.Buffer {
|
func commonWrite(b []byte) *bytes.Buffer {
|
||||||
protobufHeader := [binary.MaxVarintLen64 + 1]byte{0x0A}
|
protobufHeader := [binary.MaxVarintLen64 + 1]byte{0x0A}
|
||||||
varuintSize := binary.PutUvarint(protobufHeader[1:], uint64(len(b)))
|
varuintSize := binary.PutUvarint(protobufHeader[1:], uint64(len(b)))
|
||||||
@@ -58,7 +61,7 @@ func (c *commonPart) Read(b []byte) (n int, err error) {
|
|||||||
|
|
||||||
protobufPayloadLen, err := binary.ReadUvarint(c.br)
|
protobufPayloadLen, err := binary.ReadUvarint(c.br)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, utils.ErrInErr{ErrDesc: "binary.ReadUvarint failed", ErrDetail: err, ExtraIs: []error{utils.ErrInvalidData}}
|
return 0, utils.ErrInErr{ErrDesc: "grpc Read, binary.ReadUvarint failed", ErrDetail: err, ExtraIs: []error{utils.ErrInvalidData}}
|
||||||
}
|
}
|
||||||
|
|
||||||
size := int(protobufPayloadLen)
|
size := int(protobufPayloadLen)
|
||||||
|
@@ -122,7 +122,7 @@ func (s *Server) StartHandle(underlay net.Conn, newSubConnChan chan net.Conn, fa
|
|||||||
|
|
||||||
var buf *bytes.Buffer
|
var buf *bytes.Buffer
|
||||||
|
|
||||||
sc := &netLayer.IOWrapper{
|
respConn := &netLayer.IOWrapper{
|
||||||
Reader: rq.Body,
|
Reader: rq.Body,
|
||||||
Writer: rw,
|
Writer: rw,
|
||||||
CloseChan: make(chan struct{}),
|
CloseChan: make(chan struct{}),
|
||||||
@@ -130,7 +130,7 @@ func (s *Server) StartHandle(underlay net.Conn, newSubConnChan chan net.Conn, fa
|
|||||||
|
|
||||||
fm := httpLayer.FallbackMeta{
|
fm := httpLayer.FallbackMeta{
|
||||||
Path: p,
|
Path: p,
|
||||||
Conn: sc,
|
Conn: respConn,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果使用 rq.Write, 那么实际上就是回落到 http1.1, 只有用 http2.Transport.RoundTrip 才是 h2 请求
|
// 如果使用 rq.Write, 那么实际上就是回落到 http1.1, 只有用 http2.Transport.RoundTrip 才是 h2 请求
|
||||||
@@ -141,9 +141,9 @@ func (s *Server) StartHandle(underlay net.Conn, newSubConnChan chan net.Conn, fa
|
|||||||
buf = utils.GetBuf()
|
buf = utils.GetBuf()
|
||||||
rq.Write(buf)
|
rq.Write(buf)
|
||||||
|
|
||||||
sc.FirstWriteChan = make(chan struct{})
|
respConn.FirstWriteChan = make(chan struct{})
|
||||||
|
|
||||||
fm.FirstBuffer = buf
|
fm.H1RequestBuf = buf
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
fm.IsH2 = true
|
fm.IsH2 = true
|
||||||
@@ -156,7 +156,7 @@ func (s *Server) StartHandle(underlay net.Conn, newSubConnChan chan net.Conn, fa
|
|||||||
|
|
||||||
fallbackConnChan <- fm
|
fallbackConnChan <- fm
|
||||||
|
|
||||||
<-sc.CloseChan
|
<-respConn.CloseChan
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -57,7 +57,7 @@ func (s *Server) Handshake(underlay net.Conn) (net.Conn, error) {
|
|||||||
|
|
||||||
//我们目前只支持 ws on http1.1
|
//我们目前只支持 ws on http1.1
|
||||||
|
|
||||||
var rp httpLayer.RequestParser
|
var rp httpLayer.H1RequestParser
|
||||||
re := rp.ReadAndParse(underlay)
|
re := rp.ReadAndParse(underlay)
|
||||||
if re != nil {
|
if re != nil {
|
||||||
if re == httpLayer.ErrNotHTTP_Request {
|
if re == httpLayer.ErrNotHTTP_Request {
|
||||||
@@ -77,10 +77,10 @@ func (s *Server) Handshake(underlay net.Conn) (net.Conn, error) {
|
|||||||
|
|
||||||
if rp.Method != "GET" || s.Thepath != rp.Path {
|
if rp.Method != "GET" || s.Thepath != rp.Path {
|
||||||
return httpLayer.FallbackMeta{
|
return httpLayer.FallbackMeta{
|
||||||
Conn: underlay,
|
Conn: underlay,
|
||||||
FirstBuffer: optionalFirstBuffer,
|
H1RequestBuf: optionalFirstBuffer,
|
||||||
Path: rp.Path,
|
Path: rp.Path,
|
||||||
Method: rp.Method,
|
Method: rp.Method,
|
||||||
}, httpLayer.ErrShouldFallback
|
}, httpLayer.ErrShouldFallback
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -354,12 +354,19 @@ func mainFunc() (result int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//如果在非linux系统 上,仅设置了tproxy,则会遇到下面情况
|
||||||
|
if len(tproxyList) == 0 {
|
||||||
|
if !(defaultInServer != nil || len(allServers) > 0) {
|
||||||
|
configFileQualifiedToRun = false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
//没配置可用的listen或者dial,而且还无法动态更改配置
|
//没可用的listen或者dial,而且还无法动态更改配置
|
||||||
if !configFileQualifiedToRun && !isFlexible() {
|
if !configFileQualifiedToRun && !isFlexible() {
|
||||||
utils.Error("No valid proxy settings available, nor cli or apiServer feature enabled, exit now.")
|
utils.Error("No valid proxy settings available, nor cli or apiServer feature enabled, exit now.")
|
||||||
return -1
|
return -1
|
||||||
|
@@ -5,7 +5,7 @@ host = "0.0.0.0"
|
|||||||
port = 4434
|
port = 4434
|
||||||
version = 0
|
version = 0
|
||||||
insecure = true
|
insecure = true
|
||||||
fallback = ":80"
|
fallback = "udp://127.0.0.1:80" #试图回落到 nginx的 无tls 的 udp的 http3 服务端口 (目前尚未支持quic的回落功能,请期待)
|
||||||
cert = "cert.pem"
|
cert = "cert.pem"
|
||||||
key = "cert.key"
|
key = "cert.key"
|
||||||
advancedLayer = "quic"
|
advancedLayer = "quic"
|
||||||
|
@@ -7,7 +7,7 @@ host = "0.0.0.0"
|
|||||||
port = 4433
|
port = 4433
|
||||||
version = 0
|
version = 0
|
||||||
insecure = true
|
insecure = true
|
||||||
fallback = ":80" # 默认回落地址.ip必须是本机ip(可以省略ip而只写端口,程序会默认补全127.0.0.1), 或者unix domain socket的文件名/路径, 或者 udp://127.0.0.1:80 这种url格式。 (用udp以试图回落到 nginx的 无tls 的 http3 服务端口)
|
fallback = ":80" # 默认回落地址.ip必须是本机ip(可以省略ip而只写端口,程序会默认补全127.0.0.1), 或者unix domain socket的文件名/路径, 或者 udp://127.0.0.1:80 这种url格式。 (用udp以试图回落到 nginx的 无tls 的 udp的 http3 服务端口,适用于 quic的情况)
|
||||||
|
|
||||||
#cert = "cert.pem" # 这里既可以默认放在程序本身目录下,也可以指定完整路径
|
#cert = "cert.pem" # 这里既可以默认放在程序本身目录下,也可以指定完整路径
|
||||||
#key = "cert.key" # 如果 cert和key中 有一项没给出, 或者文件不存在, 就会自动在内存中生成随机证书,
|
#key = "cert.key" # 如果 cert和key中 有一项没给出, 或者文件不存在, 就会自动在内存中生成随机证书,
|
||||||
|
@@ -13,10 +13,13 @@ import (
|
|||||||
"golang.org/x/exp/slices"
|
"golang.org/x/exp/slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
//观察v2ray的实现,在没有header时,还会添加一个 Date ,这个v2ray的文档里没提
|
/*
|
||||||
// https://www.v2fly.org/config/transport/tcp.html#noneheaderobject
|
观察v2ray的实现,在没有header时,还会添加一个 Date ,这个v2ray的文档里没提
|
||||||
//
|
|
||||||
// transport/internet/headers/http/http.go
|
v2ray文档: https://www.v2fly.org/config/transport/tcp.html#noneheaderobject
|
||||||
|
|
||||||
|
相关 v2ray代码: transport/internet/headers/http/http.go
|
||||||
|
*/
|
||||||
|
|
||||||
type RequestHeader struct {
|
type RequestHeader struct {
|
||||||
Version string `toml:"version"` //默认值为 "1.1"
|
Version string `toml:"version"` //默认值为 "1.1"
|
||||||
@@ -90,7 +93,7 @@ func (hh *HeaderPreset) AssignDefaultValue() {
|
|||||||
|
|
||||||
func (h *HeaderPreset) ReadRequest(underlay net.Conn) (err error, leftBuf *bytes.Buffer) {
|
func (h *HeaderPreset) ReadRequest(underlay net.Conn) (err error, leftBuf *bytes.Buffer) {
|
||||||
|
|
||||||
var rp RequestParser
|
var rp H1RequestParser
|
||||||
err = rp.ReadAndParse(underlay)
|
err = rp.ReadAndParse(underlay)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
@@ -16,6 +16,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/e1732a364fed/v2ray_simple/utils"
|
"github.com/e1732a364fed/v2ray_simple/utils"
|
||||||
|
|
||||||
@@ -72,13 +73,34 @@ type RequestErr struct {
|
|||||||
Method string
|
Method string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pe *RequestErr) Error() string {
|
func (e *RequestErr) Is(err error) bool {
|
||||||
return "InvaidRequest " + pe.Method + "," + pe.Path
|
if err == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if re, ok := err.(*RequestErr); ok && re != nil {
|
||||||
|
return (e.Path == re.Path && e.Method == re.Path)
|
||||||
|
}
|
||||||
|
if err == utils.ErrInvalidData {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// RequestParser被用于 预读一个链接,判断该连接是否是有效的http请求,
|
func (pe *RequestErr) Error() string {
|
||||||
|
var sb strings.Builder
|
||||||
|
sb.WriteString("InvaidRequest ")
|
||||||
|
sb.WriteString(pe.Method)
|
||||||
|
sb.WriteString(",")
|
||||||
|
sb.WriteString(pe.Path)
|
||||||
|
|
||||||
|
return sb.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// H1RequestParser被用于 预读一个链接,判断该连接是否是有效的http请求,
|
||||||
// 并将Version,Path,Method 记录在结构中.
|
// 并将Version,Path,Method 记录在结构中.
|
||||||
type RequestParser struct {
|
//
|
||||||
|
// 只能过滤 http 0.9, 1.0 和 1.1. 无法过滤h2和h3.
|
||||||
|
type H1RequestParser struct {
|
||||||
Version string
|
Version string
|
||||||
Path string
|
Path string
|
||||||
Method string
|
Method string
|
||||||
@@ -88,7 +110,7 @@ type RequestParser struct {
|
|||||||
|
|
||||||
// 尝试读取数据并解析HTTP请求, 解析道道 数据会存入 RequestParser 结构中.
|
// 尝试读取数据并解析HTTP请求, 解析道道 数据会存入 RequestParser 结构中.
|
||||||
//如果读取错误,会返回该错误; 如果读到的不是HTTP请求,返回 ErrNotHTTP_Request;
|
//如果读取错误,会返回该错误; 如果读到的不是HTTP请求,返回 ErrNotHTTP_Request;
|
||||||
func (rhr *RequestParser) ReadAndParse(r io.Reader) error {
|
func (rhr *H1RequestParser) ReadAndParse(r io.Reader) error {
|
||||||
bs := utils.GetPacket()
|
bs := utils.GetPacket()
|
||||||
|
|
||||||
n, e := r.Read(bs)
|
n, e := r.Read(bs)
|
||||||
@@ -109,10 +131,10 @@ func (rhr *RequestParser) ReadAndParse(r io.Reader) error {
|
|||||||
// http level fallback metadata
|
// http level fallback metadata
|
||||||
type FallbackMeta struct {
|
type FallbackMeta struct {
|
||||||
net.Conn
|
net.Conn
|
||||||
FirstBuffer *bytes.Buffer
|
H1RequestBuf *bytes.Buffer
|
||||||
Path string
|
Path string
|
||||||
Method string
|
Method string
|
||||||
IsH2 bool
|
IsH2 bool
|
||||||
|
|
||||||
H2Request *http.Request
|
H2Request *http.Request
|
||||||
}
|
}
|
||||||
|
4
main.go
4
main.go
@@ -346,7 +346,7 @@ func handleNewIncomeConnection(inServer proxy.Server, defaultClientForThis proxy
|
|||||||
newiics := iics
|
newiics := iics
|
||||||
|
|
||||||
newiics.theRequestPath = fallbackMeta.Path
|
newiics.theRequestPath = fallbackMeta.Path
|
||||||
newiics.theFallbackFirstBuffer = fallbackMeta.FirstBuffer
|
newiics.theFallbackFirstBuffer = fallbackMeta.H1RequestBuf
|
||||||
newiics.wrappedConn = fallbackMeta.Conn
|
newiics.wrappedConn = fallbackMeta.Conn
|
||||||
newiics.isFallbackH2 = fallbackMeta.IsH2
|
newiics.isFallbackH2 = fallbackMeta.IsH2
|
||||||
newiics.fallbackH2Request = fallbackMeta.H2Request
|
newiics.fallbackH2Request = fallbackMeta.H2Request
|
||||||
@@ -383,7 +383,7 @@ func handleNewIncomeConnection(inServer proxy.Server, defaultClientForThis proxy
|
|||||||
meta := wsConn.(httpLayer.FallbackMeta)
|
meta := wsConn.(httpLayer.FallbackMeta)
|
||||||
|
|
||||||
iics.theRequestPath = meta.Path
|
iics.theRequestPath = meta.Path
|
||||||
iics.theFallbackFirstBuffer = meta.FirstBuffer
|
iics.theFallbackFirstBuffer = meta.H1RequestBuf
|
||||||
iics.wrappedConn = meta.Conn
|
iics.wrappedConn = meta.Conn
|
||||||
|
|
||||||
if ce := utils.CanLogDebug("Single AdvLayer Check failed, will fallback."); ce != nil {
|
if ce := utils.CanLogDebug("Single AdvLayer Check failed, will fallback."); ce != nil {
|
||||||
|
16
utils/io.go
16
utils/io.go
@@ -17,6 +17,7 @@ type ByteWriter interface {
|
|||||||
Write(p []byte) (n int, err error)
|
Write(p []byte) (n int, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//optionally read from OptionalReader
|
||||||
type ReadWrapper struct {
|
type ReadWrapper struct {
|
||||||
io.Reader
|
io.Reader
|
||||||
OptionalReader io.Reader
|
OptionalReader io.Reader
|
||||||
@@ -47,6 +48,7 @@ type DummyReadCloser struct {
|
|||||||
ReadCount int
|
ReadCount int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadCount -= 1 at each call.
|
||||||
//if ReadCount<0, return 0, io.EOF
|
//if ReadCount<0, return 0, io.EOF
|
||||||
func (d *DummyReadCloser) Read(p []byte) (int, error) {
|
func (d *DummyReadCloser) Read(p []byte) (int, error) {
|
||||||
d.ReadCount -= 1
|
d.ReadCount -= 1
|
||||||
@@ -68,6 +70,7 @@ type DummyWriteCloser struct {
|
|||||||
WriteCount int
|
WriteCount int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WriteCount -= 1 at each call.
|
||||||
//if WriteCount<0, return 0, io.EOF
|
//if WriteCount<0, return 0, io.EOF
|
||||||
func (d *DummyWriteCloser) Write(p []byte) (int, error) {
|
func (d *DummyWriteCloser) Write(p []byte) (int, error) {
|
||||||
d.WriteCount -= 1
|
d.WriteCount -= 1
|
||||||
@@ -86,10 +89,12 @@ func (DummyWriteCloser) Close() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//先从Old读,若SwitchChan被关闭, 立刻改为从New读
|
||||||
type ReadSwitcher struct {
|
type ReadSwitcher struct {
|
||||||
Old, New io.Reader
|
Old, New io.Reader //non-nil
|
||||||
|
SwitchChan chan struct{} //non-nil
|
||||||
|
|
||||||
io.Closer
|
io.Closer
|
||||||
SwitchChan chan struct{}
|
|
||||||
|
|
||||||
readOnce sync.Once
|
readOnce sync.Once
|
||||||
|
|
||||||
@@ -129,7 +134,6 @@ func (d *ReadSwitcher) Read(p []byte) (int, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//return nil
|
|
||||||
func (d *ReadSwitcher) Close() error {
|
func (d *ReadSwitcher) Close() error {
|
||||||
if d.Closer != nil {
|
if d.Closer != nil {
|
||||||
return d.Closer.Close()
|
return d.Closer.Close()
|
||||||
@@ -137,10 +141,11 @@ func (d *ReadSwitcher) Close() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//先向Old写,若SwitchChan被关闭, 改为向New写
|
||||||
type WriteSwitcher struct {
|
type WriteSwitcher struct {
|
||||||
Old, New io.Writer
|
Old, New io.Writer //non-nil
|
||||||
|
SwitchChan chan struct{} //non-nil
|
||||||
io.Closer
|
io.Closer
|
||||||
SwitchChan chan struct{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *WriteSwitcher) Write(p []byte) (int, error) {
|
func (d *WriteSwitcher) Write(p []byte) (int, error) {
|
||||||
@@ -154,7 +159,6 @@ func (d *WriteSwitcher) Write(p []byte) (int, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//return nil
|
|
||||||
func (d *WriteSwitcher) Close() error {
|
func (d *WriteSwitcher) Close() error {
|
||||||
if d.Closer != nil {
|
if d.Closer != nil {
|
||||||
return d.Closer.Close()
|
return d.Closer.Close()
|
||||||
|
Reference in New Issue
Block a user