mirror of
https://github.com/e1732a364fed/v2ray_simple.git
synced 2025-10-07 17:51:14 +08:00
修订代码,注释,示例
This commit is contained in:
@@ -25,10 +25,10 @@ host = "127.0.0.1" # 必填, 可填ip或域名;如果 network是unix的话,
|
|||||||
port = 10800 # 必填
|
port = 10800 # 必填
|
||||||
|
|
||||||
[[dial]]
|
[[dial]]
|
||||||
tag = "my_vlesss1" # 可选, 但不可与其他tag重复
|
tag = "my_vlesss1" # 同listen对应配置, 可选, 但不可与其他tag重复
|
||||||
protocol = "vlesss" # vless 的 尾缀s 表示 使用tls
|
protocol = "vlesss" # vless 的 尾缀s 表示 使用tls
|
||||||
uuid = "a684455c-b14f-11ea-bf0d-42010aaa0003" # 这个只是一个示例uuid,请自己生成一个新的.
|
uuid = "a684455c-b14f-11ea-bf0d-42010aaa0003" # 这个只是一个示例uuid,请自己生成一个新的.
|
||||||
host = "127.0.0.1"
|
host = "127.0.0.1" # 同listen对应配置, 可填ip或域名;如果 network是unix的话,要填一个文件名(不需要已存在,可以是完整路径).
|
||||||
#network = "udp"
|
#network = "udp"
|
||||||
|
|
||||||
# network 目前支持 tcp,udp 和unix;如果不给出则默认为 tcp; dial和listen都可配置此项
|
# network 目前支持 tcp,udp 和unix;如果不给出则默认为 tcp; dial和listen都可配置此项
|
||||||
@@ -47,7 +47,7 @@ host = "127.0.0.1"
|
|||||||
# 除了在 protocol 字段使用 s尾缀 之外,还可以明示使用tls.
|
# 除了在 protocol 字段使用 s尾缀 之外,还可以明示使用tls.
|
||||||
# 这两种方法不可重复使用.我们首选前者, 更简约, 当然如果你使用时,需要频繁开关tls,那么可以单独列出来 便于配置
|
# 这两种方法不可重复使用.我们首选前者, 更简约, 当然如果你使用时,需要频繁开关tls,那么可以单独列出来 便于配置
|
||||||
|
|
||||||
port = 4433
|
port = 4433 # 必填
|
||||||
version = 0 # 协议版本, 可省略, 省略则默认为最老版本
|
version = 0 # 协议版本, 可省略, 省略则默认为最老版本
|
||||||
insecure = true # 我们示例使用自签名证书,所以要开启 insecure. 实际场合请使用真证书并关闭 insecure
|
insecure = true # 我们示例使用自签名证书,所以要开启 insecure. 实际场合请使用真证书并关闭 insecure
|
||||||
utls = true #是否使用 utls 来应用 chrome指纹进行伪装
|
utls = true #是否使用 utls 来应用 chrome指纹进行伪装
|
||||||
|
@@ -3,7 +3,7 @@ package grpc
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net"
|
"net"
|
||||||
sync "sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/hahahrfool/v2ray_simple/netLayer"
|
"github.com/hahahrfool/v2ray_simple/netLayer"
|
||||||
@@ -21,11 +21,11 @@ var (
|
|||||||
type ClientConn *grpc.ClientConn
|
type ClientConn *grpc.ClientConn
|
||||||
|
|
||||||
/*
|
/*
|
||||||
调用过程
|
建立新客户端连接的调用过程:
|
||||||
|
|
||||||
先用 GetEstablishedConnFor 看看有没有已存在的 clientConn
|
先用 GetEstablishedConnFor 看看有没有已存在的 clientConn
|
||||||
|
|
||||||
没有已存在的话,自己先拨号tcp,然后拨号tls,然后把tls连接 传递给 ClientHandshake, 生成一个 clientConn
|
没有 已存在的 时,自己先拨号tcp,然后拨号tls,然后把tls连接 传递给 ClientHandshake, 生成一个 clientConn
|
||||||
|
|
||||||
然后把获取到的 clientConn传递给 DialNewSubConn, 获取可用的一条 grpc 连接
|
然后把获取到的 clientConn传递给 DialNewSubConn, 获取可用的一条 grpc 连接
|
||||||
|
|
||||||
@@ -34,16 +34,18 @@ type ClientConn *grpc.ClientConn
|
|||||||
//获取与 某grpc服务器的 已存在的grpc连接
|
//获取与 某grpc服务器的 已存在的grpc连接
|
||||||
func GetEstablishedConnFor(addr *netLayer.Addr) ClientConn {
|
func GetEstablishedConnFor(addr *netLayer.Addr) ClientConn {
|
||||||
clientconnMutex.RLock()
|
clientconnMutex.RLock()
|
||||||
clieintconn := clientconnMap[addr.GetHashable()]
|
clientconn := clientconnMap[addr.GetHashable()]
|
||||||
clientconnMutex.RUnlock()
|
clientconnMutex.RUnlock()
|
||||||
|
|
||||||
if clieintconn == nil {
|
if clientconn == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*grpc.ClientConn)(clieintconn).GetState() != connectivity.Shutdown {
|
if (*grpc.ClientConn)(clientconn).GetState() != connectivity.Shutdown {
|
||||||
return clieintconn
|
return clientconn
|
||||||
}
|
}
|
||||||
|
//如果state是shutdown的话,我们也不用特地清除map,因为下一次申请就会覆盖map中的该项.
|
||||||
|
//如果底层tcp被关闭,state就会为 Shutdown
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,10 +53,11 @@ func GetEstablishedConnFor(addr *netLayer.Addr) ClientConn {
|
|||||||
//该 underlay一般为 tls连接。 addr为实际的远程地址,我们不从 underlay里获取addr,避免转换.
|
//该 underlay一般为 tls连接。 addr为实际的远程地址,我们不从 underlay里获取addr,避免转换.
|
||||||
func ClientHandshake(underlay net.Conn, addr *netLayer.Addr) (ClientConn, error) {
|
func ClientHandshake(underlay net.Conn, addr *netLayer.Addr) (ClientConn, error) {
|
||||||
|
|
||||||
//v2ray的实现中用到了一个 globalDialerMap[dest], 可以利用现有连接,
|
// 用到了一个 clientconnMap , 可以利用现有连接,
|
||||||
// 只有map里没有与对应目标远程地址的连接的时候才会拨号;
|
// 只有map里没有与对应目标远程地址的连接的时候才会拨号;
|
||||||
// 这 应该就是一种mux的实现
|
// 这就是一种mux的实现
|
||||||
// 如果有之前播过的client的话,直接利用现有client进行 NewStream, 然后服务端的话, 实际上会获得到第二条连接;
|
// 如果有之前拨号过的client的话,直接利用现有client进行 NewStream,
|
||||||
|
// 然后服务端的话, 实际上会获得到同一条tcp链接上的第二条子连接;
|
||||||
|
|
||||||
//也就是说,底层连接在客户端-服务端只用了一条,但是 服务端处理时却会抽象出 多条Stream连接进行处理
|
//也就是说,底层连接在客户端-服务端只用了一条,但是 服务端处理时却会抽象出 多条Stream连接进行处理
|
||||||
|
|
||||||
@@ -84,7 +87,8 @@ func ClientHandshake(underlay net.Conn, addr *netLayer.Addr) (ClientConn, error)
|
|||||||
//在一个已存在的grpc连接中 进行新的子连接申请
|
//在一个已存在的grpc连接中 进行新的子连接申请
|
||||||
func DialNewSubConn(path string, clientconn ClientConn, addr *netLayer.Addr) (net.Conn, error) {
|
func DialNewSubConn(path string, clientconn ClientConn, addr *netLayer.Addr) (net.Conn, error) {
|
||||||
|
|
||||||
//不像服务端需要自己写一个实现StreamServer接口的结构, 我们Client端直接可以调用函数生成 StreamClient
|
// 帮助理解:
|
||||||
|
// 不像服务端需要自己写一个实现StreamServer接口的结构, 我们Client端直接可以调用函数生成 StreamClient
|
||||||
// 这也是grpc的特点, 客户端只负责 “调用“ ”service“,而具体的service的实现 是在服务端.
|
// 这也是grpc的特点, 客户端只负责 “调用“ ”service“,而具体的service的实现 是在服务端.
|
||||||
|
|
||||||
streamClient := NewStreamClient((*grpc.ClientConn)(clientconn)).(StreamClient_withName)
|
streamClient := NewStreamClient((*grpc.ClientConn)(clientconn)).(StreamClient_withName)
|
||||||
|
@@ -9,8 +9,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// google.golang.org/grpc.(*Server).handleRawConn
|
// google.golang.org/grpc.(*Server).handleRawConn
|
||||||
//go:linkname HandleRawConn google.golang.org/grpc.(*Server).handleRawConn
|
//go:linkname handle_grpcRawConn google.golang.org/grpc.(*Server).handleRawConn
|
||||||
func HandleRawConn(c *grpc.Server, lisAddr string, rawConn net.Conn)
|
func handle_grpcRawConn(c *grpc.Server, lisAddr string, rawConn net.Conn)
|
||||||
|
|
||||||
//Server实现 grpc生成的 StreamServer 接口,用于不断处理一个客户端传来的新需求
|
//Server实现 grpc生成的 StreamServer 接口,用于不断处理一个客户端传来的新需求
|
||||||
type Server struct {
|
type Server struct {
|
||||||
@@ -25,15 +25,17 @@ type Server struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// StartHandle方法 被用于 手动给 grpc提供新连接.
|
// StartHandle方法 被用于 手动给 grpc提供新连接.
|
||||||
// 在本作中 我们不使用 grpc的listen的方法。
|
// 在本作中 我们不使用 grpc的listen的方法。这样更加灵活.
|
||||||
//非阻塞,
|
//非阻塞.
|
||||||
func (s *Server) StartHandle(conn net.Conn) {
|
func (s *Server) StartHandle(conn net.Conn) {
|
||||||
|
|
||||||
//非阻塞,因为 grpc.(*Server).handleRawConn 是非阻塞的,里面用了新的goroutine
|
//非阻塞,因为 grpc.(*Server).handleRawConn 是非阻塞的,里面用了新的goroutine
|
||||||
HandleRawConn(s.gs, "", conn)
|
handle_grpcRawConn(s.gs, "", conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 该 Tun方法会被 grpc包调用, stream_TunServer就是获取到的新连接;
|
// 该 Tun方法会被 grpc包调用, stream_TunServer就是获取到的新连接;
|
||||||
|
// 实际上就是在 handle_grpcRawConn 后, 每一条客户端发来的子连接 都会调用一次 s.Tun .
|
||||||
|
//
|
||||||
// 我们把该 stream_TunServer 包装成 net.Conn 并传入 NewConnChan
|
// 我们把该 stream_TunServer 包装成 net.Conn 并传入 NewConnChan
|
||||||
// 该方法是自动调用的, 我们不用管.
|
// 该方法是自动调用的, 我们不用管.
|
||||||
func (s *Server) Tun(stream_TunServer Stream_TunServer) error {
|
func (s *Server) Tun(stream_TunServer Stream_TunServer) error {
|
||||||
@@ -66,7 +68,7 @@ func NewServer(serviceName string) *Server {
|
|||||||
newConnChan := make(chan net.Conn, 10)
|
newConnChan := make(chan net.Conn, 10)
|
||||||
|
|
||||||
s := &Server{
|
s := &Server{
|
||||||
NewConnChan: newConnChan,
|
NewConnChan: newConnChan, //该NewConnChan目前是永远不会被关闭的, 因为我们始终在监听新连接
|
||||||
gs: gs,
|
gs: gs,
|
||||||
serviceName: serviceName,
|
serviceName: serviceName,
|
||||||
}
|
}
|
||||||
|
74
main.go
74
main.go
@@ -399,9 +399,8 @@ func handleNewIncomeConnection(inServer proxy.Server, defaultClientForThis proxy
|
|||||||
for {
|
for {
|
||||||
newGConn, ok := <-grpcs.NewConnChan
|
newGConn, ok := <-grpcs.NewConnChan
|
||||||
if !ok {
|
if !ok {
|
||||||
if utils.CanLogErr() {
|
if utils.CanLogWarn() {
|
||||||
log.Println("upgrade grpc not ok")
|
log.Println("grpc getNewSubConn not ok")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
iics.baseLocalConn.Close()
|
iics.baseLocalConn.Close()
|
||||||
@@ -706,35 +705,34 @@ afterLocalServerHandshake:
|
|||||||
// server也一样,会在特定的场合给 CRUMFURS 传值,这个机制是与main函数无关的
|
// server也一样,会在特定的场合给 CRUMFURS 传值,这个机制是与main函数无关的
|
||||||
|
|
||||||
// 而且 wrappedConn 会被 inServer 保存起来,用于后面的 unknownRemoteAddrMsgWriter
|
// 而且 wrappedConn 会被 inServer 保存起来,用于后面的 unknownRemoteAddrMsgWriter
|
||||||
|
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
//如果不是CRUMFURS命令,那就是普通的针对某udp地址的连接,见下文 uniExtractor 的使用
|
//如果不是CRUMFURS命令,那就是普通的针对某udp地址的连接,见下文 uniExtractor 的使用
|
||||||
//defer wrappedConn.Close()
|
|
||||||
iics.shouldCloseBaseConnAfterCopyComplete = true
|
iics.shouldCloseBaseConnAfterCopyComplete = true
|
||||||
}
|
}
|
||||||
|
|
||||||
case "socks5":
|
case "socks5":
|
||||||
|
|
||||||
// UDP Associate:
|
// UDP Associate:
|
||||||
//
|
|
||||||
// 因为socks5的 UDP Associate 办法是较为特殊的,不使用现有tcp而是新建立udp,所以此时该tcp连接已经没用了
|
// 因为socks5的 UDP Associate 办法是较为特殊的,不使用现有tcp而是新建立udp,所以此时该tcp连接已经没用了
|
||||||
// 另外,此时 targetAddr.IsUDP 只是用于告知此链接是udp Associate,并不包含实际地址信息
|
// 另外,此时 targetAddr.IsUDP 只是用于告知此链接是udp Associate,并不包含实际地址信息
|
||||||
|
|
||||||
//但是根据socks5标准,这个tcp链接同样是 keep alive的,否则客户端就会认为服务端挂掉了.
|
//但是根据socks5标准,这个tcp链接同样是 keep alive的,否则客户端就会认为服务端挂掉了.
|
||||||
|
|
||||||
default:
|
default:
|
||||||
//defer wrappedConn.Close()
|
|
||||||
iics.shouldCloseBaseConnAfterCopyComplete = true
|
iics.shouldCloseBaseConnAfterCopyComplete = true
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if !(iics.isTlsLazyServerEnd) {
|
|
||||||
|
|
||||||
//lazy_encrypt情况比较特殊
|
//lazy_encrypt情况比较特殊,基础连接何时被关闭会在tlslazy相关代码中处理。
|
||||||
// 如果不是lazy的情况的话,转发结束后,要自动关闭
|
// 如果不是lazy的情况的话,转发结束后,要自动关闭
|
||||||
//defer wrappedConn.Close()
|
if !iics.isTlsLazyServerEnd {
|
||||||
iics.shouldCloseBaseConnAfterCopyComplete = true
|
|
||||||
|
//实测 grpc.Conn 被调用了Close 也不会实际关闭连接,而是会卡住,阻塞,直到底层tcp连接被关闭后才会返回
|
||||||
|
// 但是我们还是 直接避免这种情况
|
||||||
|
if !inServer.IsMux() {
|
||||||
|
iics.shouldCloseBaseConnAfterCopyComplete = true
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -742,7 +740,7 @@ afterLocalServerHandshake:
|
|||||||
|
|
||||||
// 下面一段代码 单独处理 udp承载数据的特殊转发。
|
// 下面一段代码 单独处理 udp承载数据的特殊转发。
|
||||||
//
|
//
|
||||||
// 这里只处理 vless v1 的CRUMFURS 转发到direct的情况 以及 socks5 的udp associate 转发到vless v1的情况;
|
// 这里只处理 vless v1 的CRUMFURS 转发到direct的情况 以及 socks5 的udp associate 转发到vless 的情况;
|
||||||
// 如果条件不符合则会跳过而进入下一阶段
|
// 如果条件不符合则会跳过而进入下一阶段
|
||||||
if targetAddr.IsUDP() {
|
if targetAddr.IsUDP() {
|
||||||
|
|
||||||
@@ -791,11 +789,11 @@ afterLocalServerHandshake:
|
|||||||
|
|
||||||
// 将 outClient 视为 UDP_Putter ,就可以转发udp信息了
|
// 将 outClient 视为 UDP_Putter ,就可以转发udp信息了
|
||||||
|
|
||||||
//direct 和 vless 都实现了 UDP_Putter.
|
//direct 和 vless 的Client 都实现了 UDP_Putter.
|
||||||
|
|
||||||
// direct 实现了 UDP_Putter (通过 UDP_Pipe和 RelayUDP_to_Direct函数), 所以目前 socks5直接转发udp到direct 的功能 已经实现。
|
// direct 通过 UDP_Pipe和 RelayUDP_to_Direct函数 实现了 UDP_Putter
|
||||||
|
|
||||||
// 我在 vless 的client 的 UserConn 中实现了 UDP_Putter, 新连接的Handshake过程会在 dialFunc 被调用 时发生
|
// vless 的client 实现了 UDP_Putter, 新连接的Handshake过程会在 dialFunc 被调用 时发生
|
||||||
|
|
||||||
if putter := client.(netLayer.UDP_Putter); putter != nil {
|
if putter := client.(netLayer.UDP_Putter); putter != nil {
|
||||||
|
|
||||||
@@ -818,6 +816,9 @@ afterLocalServerHandshake:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////// 拨号阶段 /////////////////////////////////////
|
||||||
|
|
||||||
|
//log.Println("will dial", iics.shouldCloseBaseConnAfterCopyComplete)
|
||||||
dialClient(iics, targetAddr, client, isTlsLazy_clientEnd, wlc, false)
|
dialClient(iics, targetAddr, client, isTlsLazy_clientEnd, wlc, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -830,11 +831,19 @@ afterLocalServerHandshake:
|
|||||||
func dialClient(iics incomingInserverConnState, targetAddr *netLayer.Addr, client proxy.Client, isTlsLazy_clientEnd bool, wlc io.ReadWriter, noCopy bool) (io.ReadWriter, error) {
|
func dialClient(iics incomingInserverConnState, targetAddr *netLayer.Addr, client proxy.Client, isTlsLazy_clientEnd bool, wlc io.ReadWriter, noCopy bool) (io.ReadWriter, error) {
|
||||||
|
|
||||||
if iics.shouldCloseBaseConnAfterCopyComplete && !noCopy {
|
if iics.shouldCloseBaseConnAfterCopyComplete && !noCopy {
|
||||||
|
|
||||||
|
/*
|
||||||
|
log.Println("iics.wrappedConn will close after", reflect.TypeOf(iics.wrappedConn))
|
||||||
|
defer func() {
|
||||||
|
log.Println("iics.wrappedConn called")
|
||||||
|
iics.wrappedConn.Close()
|
||||||
|
log.Println("iics.wrappedConn closed")
|
||||||
|
}()
|
||||||
|
*/
|
||||||
defer iics.wrappedConn.Close()
|
defer iics.wrappedConn.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
////////////////////////////// 拨号阶段 /////////////////////////////////////
|
|
||||||
|
|
||||||
//先确认拨号地址
|
//先确认拨号地址
|
||||||
|
|
||||||
@@ -847,7 +856,7 @@ func dialClient(iics incomingInserverConnState, targetAddr *netLayer.Addr, clien
|
|||||||
log.Println("request isn't the appointed domain", targetAddr, uniqueTestDomain)
|
log.Println("request isn't the appointed domain", targetAddr, uniqueTestDomain)
|
||||||
|
|
||||||
}
|
}
|
||||||
return nil, &utils.NumErr{N: 1, Prefix: "dialClient err, "}
|
return nil, utils.NumErr{N: 1, Prefix: "dialClient err, "}
|
||||||
}
|
}
|
||||||
|
|
||||||
if utils.CanLogInfo() {
|
if utils.CanLogInfo() {
|
||||||
@@ -890,7 +899,7 @@ func dialClient(iics incomingInserverConnState, targetAddr *netLayer.Addr, clien
|
|||||||
log.Println("failed in dial", realTargetAddr.String(), ", Reason: ", err)
|
log.Println("failed in dial", realTargetAddr.String(), ", Reason: ", err)
|
||||||
|
|
||||||
}
|
}
|
||||||
return nil, &utils.NumErr{N: 2, Prefix: "dialClient err, "}
|
return nil, utils.NumErr{N: 2, Prefix: "dialClient err, "}
|
||||||
}
|
}
|
||||||
|
|
||||||
//log.Println("dial real addr ok", realTargetAddr)
|
//log.Println("dial real addr ok", realTargetAddr)
|
||||||
@@ -912,7 +921,7 @@ func dialClient(iics incomingInserverConnState, targetAddr *netLayer.Addr, clien
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, &utils.NumErr{N: 3, Prefix: "dialClient err, "}
|
return nil, utils.NumErr{N: 3, Prefix: "dialClient err, "}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
clientEndRemoteClientTlsRawReadRecorder = tlsLayer.NewRecorder()
|
clientEndRemoteClientTlsRawReadRecorder = tlsLayer.NewRecorder()
|
||||||
@@ -925,7 +934,7 @@ func dialClient(iics incomingInserverConnState, targetAddr *netLayer.Addr, clien
|
|||||||
tlsConn, err := client.GetTLS_Client().Handshake(clientConn)
|
tlsConn, err := client.GetTLS_Client().Handshake(clientConn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("failed in handshake outClient tls", targetAddr.String(), ", Reason: ", err)
|
log.Println("failed in handshake outClient tls", targetAddr.String(), ", Reason: ", err)
|
||||||
return nil, &utils.NumErr{N: 4, Prefix: "dialClient err, "}
|
return nil, utils.NumErr{N: 4, Prefix: "dialClient err, "}
|
||||||
}
|
}
|
||||||
|
|
||||||
clientConn = tlsConn
|
clientConn = tlsConn
|
||||||
@@ -950,7 +959,7 @@ advLayerStep:
|
|||||||
iics.baseLocalConn.Close()
|
iics.baseLocalConn.Close()
|
||||||
|
|
||||||
}
|
}
|
||||||
return nil, &utils.NumErr{N: 5, Prefix: "dialClient err, "}
|
return nil, utils.NumErr{N: 5, Prefix: "dialClient err, "}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -960,11 +969,14 @@ advLayerStep:
|
|||||||
if utils.CanLogErr() {
|
if utils.CanLogErr() {
|
||||||
log.Println("grpc.DialNewSubConn failed,", err)
|
log.Println("grpc.DialNewSubConn failed,", err)
|
||||||
|
|
||||||
|
//如果底层tcp连接被关闭了的话,错误会是:
|
||||||
|
// rpc error: code = Unavailable desc = connection error: desc = "transport: failed to write client preface: tls: use of closed connection"
|
||||||
|
|
||||||
}
|
}
|
||||||
if iics.baseLocalConn != nil {
|
if iics.baseLocalConn != nil {
|
||||||
iics.baseLocalConn.Close()
|
iics.baseLocalConn.Close()
|
||||||
}
|
}
|
||||||
return nil, &utils.NumErr{N: 6, Prefix: "dialClient err, "}
|
return nil, utils.NumErr{N: 6, Prefix: "dialClient err, "}
|
||||||
}
|
}
|
||||||
|
|
||||||
case "ws":
|
case "ws":
|
||||||
@@ -981,7 +993,7 @@ advLayerStep:
|
|||||||
if utils.CanLogErr() {
|
if utils.CanLogErr() {
|
||||||
log.Println("err when reading ws early data", e)
|
log.Println("err when reading ws early data", e)
|
||||||
}
|
}
|
||||||
return nil, &utils.NumErr{N: 7, Prefix: "dialClient err, "}
|
return nil, utils.NumErr{N: 7, Prefix: "dialClient err, "}
|
||||||
}
|
}
|
||||||
ed = edBuf[:n]
|
ed = edBuf[:n]
|
||||||
//log.Println("will send early data", n, ed)
|
//log.Println("will send early data", n, ed)
|
||||||
@@ -1007,7 +1019,7 @@ advLayerStep:
|
|||||||
log.Println("failed in handshake ws to", targetAddr.String(), ", Reason: ", err)
|
log.Println("failed in handshake ws to", targetAddr.String(), ", Reason: ", err)
|
||||||
|
|
||||||
}
|
}
|
||||||
return nil, &utils.NumErr{N: 8, Prefix: "dialClient err, "}
|
return nil, utils.NumErr{N: 8, Prefix: "dialClient err, "}
|
||||||
}
|
}
|
||||||
|
|
||||||
clientConn = wc
|
clientConn = wc
|
||||||
@@ -1022,7 +1034,7 @@ advLayerStep:
|
|||||||
log.Println("failed in handshake to", targetAddr.String(), ", Reason: ", err)
|
log.Println("failed in handshake to", targetAddr.String(), ", Reason: ", err)
|
||||||
|
|
||||||
}
|
}
|
||||||
return nil, &utils.NumErr{N: 9, Prefix: "dialClient err, "}
|
return nil, utils.NumErr{N: 9, Prefix: "dialClient err, "}
|
||||||
}
|
}
|
||||||
//log.Println("all handshake finished")
|
//log.Println("all handshake finished")
|
||||||
|
|
||||||
@@ -1041,7 +1053,7 @@ advLayerStep:
|
|||||||
//必须是 UserClient
|
//必须是 UserClient
|
||||||
if userClient := client.(proxy.UserClient); userClient != nil {
|
if userClient := client.(proxy.UserClient); userClient != nil {
|
||||||
tryTlsLazyRawCopy(false, userClient, nil, nil, wrc, wlc, iics.baseLocalConn, true, clientEndRemoteClientTlsRawReadRecorder)
|
tryTlsLazyRawCopy(false, userClient, nil, nil, wrc, wlc, iics.baseLocalConn, true, clientEndRemoteClientTlsRawReadRecorder)
|
||||||
return nil, &utils.NumErr{N: 11, Prefix: "dialClient err, "}
|
return nil, utils.NumErr{N: 11, Prefix: "dialClient err, "}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1052,7 +1064,7 @@ advLayerStep:
|
|||||||
|
|
||||||
if userServer, ok := iics.inServer.(proxy.UserServer); ok {
|
if userServer, ok := iics.inServer.(proxy.UserServer); ok {
|
||||||
tryTlsLazyRawCopy(false, nil, userServer, nil, wrc, wlc, iics.baseLocalConn, false, iics.inServerTlsRawReadRecorder)
|
tryTlsLazyRawCopy(false, nil, userServer, nil, wrc, wlc, iics.baseLocalConn, false, iics.inServerTlsRawReadRecorder)
|
||||||
return nil, &utils.NumErr{N: 12, Prefix: "dialClient err, "}
|
return nil, utils.NumErr{N: 12, Prefix: "dialClient err, "}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -29,7 +29,7 @@ func Client_EstablishUDPAssociate(conn net.Conn) (port int, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if n != 2 || ba[0] != Version5 || ba[1] != 0 {
|
if n != 2 || ba[0] != Version5 || ba[1] != 0 {
|
||||||
return 0, &utils.NumErr{Prefix: "EstablishUDPAssociate,protocol err", N: 1}
|
return 0, utils.NumErr{Prefix: "EstablishUDPAssociate,protocol err", N: 1}
|
||||||
}
|
}
|
||||||
|
|
||||||
//请求udp associate 阶段
|
//请求udp associate 阶段
|
||||||
@@ -45,6 +45,8 @@ func Client_EstablishUDPAssociate(conn net.Conn) (port int, err error) {
|
|||||||
ba[8] = 0 //port
|
ba[8] = 0 //port
|
||||||
ba[9] = 0 //port
|
ba[9] = 0 //port
|
||||||
// 按理说要告诉服务端我们要用到的ip和端口,但是我们不知道,所以全填零
|
// 按理说要告诉服务端我们要用到的ip和端口,但是我们不知道,所以全填零
|
||||||
|
// 在内网中的话,我们是可以知道的,但是因为内网很安全所以无所谓;在NAT中我们肯定是不知道的。
|
||||||
|
// 如果是在纯外网中则是可以知道的,但是为啥非要socks5这么不安全的协议呢?所以还是不予考虑。
|
||||||
|
|
||||||
_, err = conn.Write(ba[:10])
|
_, err = conn.Write(ba[:10])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -56,7 +58,7 @@ func Client_EstablishUDPAssociate(conn net.Conn) (port int, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if n != 10 || ba[0] != Version5 || ba[1] != 0 || ba[2] != 0 || ba[3] != 1 || ba[4] != 0 || ba[5] != 0 || ba[6] != 0 || ba[7] != 0 {
|
if n != 10 || ba[0] != Version5 || ba[1] != 0 || ba[2] != 0 || ba[3] != 1 || ba[4] != 0 || ba[5] != 0 || ba[6] != 0 || ba[7] != 0 {
|
||||||
return 0, &utils.NumErr{Prefix: "EstablishUDPAssociate,protocol err", N: 2}
|
return 0, utils.NumErr{Prefix: "EstablishUDPAssociate,protocol err", N: 2}
|
||||||
}
|
}
|
||||||
|
|
||||||
port = int(ba[8])<<8 | int(ba[9])
|
port = int(ba[8])<<8 | int(ba[9])
|
||||||
@@ -126,7 +128,7 @@ func Client_ReadUDPResponse(udpConn *net.UDPConn, supposedServerAddr *net.UDPAdd
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if buf[0] != 0 || buf[1] != 0 || buf[2] != 0 {
|
if buf[0] != 0 || buf[1] != 0 || buf[2] != 0 {
|
||||||
e = &utils.NumErr{Prefix: "EstablishUDPAssociate,protocol err", N: 1}
|
e = utils.NumErr{Prefix: "EstablishUDPAssociate,protocol err", N: 1}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
atype := buf[3]
|
atype := buf[3]
|
||||||
@@ -149,7 +151,7 @@ func Client_ReadUDPResponse(udpConn *net.UDPConn, supposedServerAddr *net.UDPAdd
|
|||||||
target.Name = string(nameBuf)
|
target.Name = string(nameBuf)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
e = &utils.NumErr{Prefix: "EstablishUDPAssociate,protocol err", N: 2}
|
e = utils.NumErr{Prefix: "EstablishUDPAssociate,protocol err", N: 2}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -164,7 +164,7 @@ func (s *Server) Handshake(underlay net.Conn) (io.ReadWriter, *netLayer.Addr, er
|
|||||||
Network: "udp",
|
Network: "udp",
|
||||||
}
|
}
|
||||||
|
|
||||||
//这里为了解析域名, 就是用了用 netLayer.Addr 作为中介的方式
|
//这里为了解析域名, 就用了 netLayer.Addr 作为中介的方式
|
||||||
uc := &UDPConn{
|
uc := &UDPConn{
|
||||||
clientSupposedAddr: clientFutureAddr.ToUDPAddr(),
|
clientSupposedAddr: clientFutureAddr.ToUDPAddr(),
|
||||||
UDPConn: udpRC,
|
UDPConn: udpRC,
|
||||||
@@ -243,6 +243,7 @@ func (u *UDPConn) StartPushResponse(udpPutter netLayer.UDP_Putter) {
|
|||||||
// 监听 与客户端的udp连接 (u.UDPConn);循环查看客户端发来的请求信息;
|
// 监听 与客户端的udp连接 (u.UDPConn);循环查看客户端发来的请求信息;
|
||||||
// 然后将该请求 用 udpPutter.WriteUDPRequest 发送给 udpPutter
|
// 然后将该请求 用 udpPutter.WriteUDPRequest 发送给 udpPutter
|
||||||
// 至于fullcone与否它是不管的。
|
// 至于fullcone与否它是不管的。
|
||||||
|
// 如果客户端一开始没有指明自己连接本服务端的ip和端口, 则将第一个发来的正确的socks5请求视为该客户端,并记录。
|
||||||
func (u *UDPConn) StartReadRequest(udpPutter netLayer.UDP_Putter, dialFunc func(targetAddr *netLayer.Addr) (io.ReadWriter, error)) {
|
func (u *UDPConn) StartReadRequest(udpPutter netLayer.UDP_Putter, dialFunc func(targetAddr *netLayer.Addr) (io.ReadWriter, error)) {
|
||||||
|
|
||||||
var clientSupposedAddrIsNothing bool
|
var clientSupposedAddrIsNothing bool
|
||||||
@@ -269,11 +270,14 @@ func (u *UDPConn) StartReadRequest(udpPutter netLayer.UDP_Putter, dialFunc func(
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if !clientSupposedAddrIsNothing && (!addr.IP.Equal(u.clientSupposedAddr.IP) || addr.Port != u.clientSupposedAddr.Port) {
|
if !clientSupposedAddrIsNothing {
|
||||||
|
|
||||||
//just random attack message.
|
if !addr.IP.Equal(u.clientSupposedAddr.IP) || addr.Port != u.clientSupposedAddr.Port {
|
||||||
continue
|
|
||||||
|
|
||||||
|
//just random attack message.
|
||||||
|
continue
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
atyp := bs[3]
|
atyp := bs[3]
|
||||||
@@ -322,7 +326,8 @@ func (u *UDPConn) StartReadRequest(udpPutter netLayer.UDP_Putter, dialFunc func(
|
|||||||
|
|
||||||
newStart := off + l
|
newStart := off + l
|
||||||
|
|
||||||
thisaddr := &netLayer.Addr{
|
//为了解析域名, 我们用 netLayer.Addr 作为中介.
|
||||||
|
requestAddr := &netLayer.Addr{
|
||||||
IP: theIP,
|
IP: theIP,
|
||||||
Name: theName,
|
Name: theName,
|
||||||
Port: thePort,
|
Port: thePort,
|
||||||
@@ -336,7 +341,7 @@ func (u *UDPConn) StartReadRequest(udpPutter netLayer.UDP_Putter, dialFunc func(
|
|||||||
|
|
||||||
//log.Println("socks5 server,StartReadRequest, got msg", thisaddr, string(bs[newStart:n]))
|
//log.Println("socks5 server,StartReadRequest, got msg", thisaddr, string(bs[newStart:n]))
|
||||||
|
|
||||||
udpPutter.WriteUDPRequest(thisaddr.ToUDPAddr(), bs[newStart:n], dialFunc)
|
udpPutter.WriteUDPRequest(requestAddr.ToUDPAddr(), bs[newStart:n], dialFunc)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -12,7 +12,7 @@ type NumErr struct {
|
|||||||
Prefix string
|
Prefix string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ne *NumErr) Error() string {
|
func (ne NumErr) Error() string {
|
||||||
|
|
||||||
return ne.Prefix + strconv.Itoa(ne.N)
|
return ne.Prefix + strconv.Itoa(ne.N)
|
||||||
}
|
}
|
||||||
@@ -23,57 +23,51 @@ type ErrFirstBuffer struct {
|
|||||||
First *bytes.Buffer
|
First *bytes.Buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ef *ErrFirstBuffer) Unwarp() error {
|
func (ef ErrFirstBuffer) Unwarp() error {
|
||||||
|
|
||||||
return ef.Err
|
return ef.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ef *ErrFirstBuffer) Error() string {
|
func (ef ErrFirstBuffer) Error() string {
|
||||||
|
|
||||||
return ef.Err.Error()
|
return ef.Err.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewErr(desc string, e error) *ErrInErr {
|
// 返回结构体,而不是指针, 这样可以避免内存逃逸到堆
|
||||||
return &ErrInErr{
|
func NewErr(desc string, e error) ErrInErr {
|
||||||
|
return ErrInErr{
|
||||||
ErrDesc: desc,
|
ErrDesc: desc,
|
||||||
ErrDetail: e,
|
ErrDetail: e,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDataErr(desc string, e error, data interface{}) *ErrInErr {
|
// 返回结构体,而不是指针, 这样可以避免内存逃逸到堆
|
||||||
return &ErrInErr{
|
func NewDataErr(desc string, e error, data interface{}) ErrInErr {
|
||||||
|
return ErrInErr{
|
||||||
ErrDesc: desc,
|
ErrDesc: desc,
|
||||||
ErrDetail: e,
|
ErrDetail: e,
|
||||||
Data: data,
|
Data: data,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrInErr 很适合一个err包含另一个err,并且提供附带数据的情况
|
// ErrInErr 很适合一个err包含另一个err,并且提供附带数据的情况.
|
||||||
type ErrInErr struct {
|
type ErrInErr struct {
|
||||||
ErrDesc string
|
ErrDesc string
|
||||||
ErrDetail error
|
ErrDetail error
|
||||||
Data any
|
Data any
|
||||||
|
|
||||||
cachedStr string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *ErrInErr) Error() string {
|
func (e ErrInErr) Error() string {
|
||||||
return e.String()
|
return e.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *ErrInErr) Unwarp() error {
|
func (e ErrInErr) Unwarp() error {
|
||||||
|
|
||||||
return e.ErrDetail
|
return e.ErrDetail
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *ErrInErr) String() string {
|
func (e ErrInErr) String() string {
|
||||||
if e.cachedStr == "" {
|
|
||||||
e.cachedStr = e.string()
|
|
||||||
}
|
|
||||||
return e.cachedStr
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *ErrInErr) string() string {
|
|
||||||
if e.Data != nil {
|
if e.Data != nil {
|
||||||
|
|
||||||
if e.ErrDetail != nil {
|
if e.ErrDetail != nil {
|
||||||
|
Reference in New Issue
Block a user