mirror of
https://github.com/e1732a364fed/v2ray_simple.git
synced 2026-04-23 01:07:04 +08:00
重构所有udp部分的代码! 摒弃了过去非常复杂的upd转发机制;
不再使用 UDP_Putter 等机制去转发udp,而是用一个 netLayer.MsgConn 结构 proxy.Server 和 proxy.Client 接口改动, Client在握手udp时不再使用handshake方法, 而是用新的 EstablishUDPChannel 方法 Server 在 Handshake时会选择性返回两种接口,io.ReadWriteCloser 用于tcp, netLayer.MsgConn 用于 udp 此时vless、socks5、direct 的udp转发都已经成功经过了 go test 验证, 但是 main.go 还未修改。
This commit is contained in:
@@ -907,7 +907,7 @@ afterLocalServerHandshake:
|
||||
|
||||
if client.Name() == "direct" {
|
||||
|
||||
uc := wlc.(*vless.UserConn)
|
||||
uc := wlc.(*vless.UserTCPConn)
|
||||
|
||||
if uc.GetProtocolVersion() < 1 {
|
||||
break
|
||||
|
||||
+7
-1
@@ -84,6 +84,7 @@ func NewAddrByHostPort(hostPortStr string) (Addr, error) {
|
||||
|
||||
a := Addr{Port: port}
|
||||
if ip := net.ParseIP(host); ip != nil {
|
||||
|
||||
a.IP = ip
|
||||
} else {
|
||||
a.Name = host
|
||||
@@ -184,7 +185,12 @@ func NewAddrFromAny(thing any) (addr Addr, err error) {
|
||||
}
|
||||
|
||||
func (a *Addr) GetHashable() (ha HashableAddr) {
|
||||
ip, _ := netip.AddrFromSlice(a.IP)
|
||||
theip := a.IP
|
||||
if i4 := a.IP.To4(); i4 != nil {
|
||||
theip = i4 //能转成ipv4则必须转,否则虽然是同一个ip,但是如果被表示成了ipv6的形式,相等比较还是会失败
|
||||
}
|
||||
ip, _ := netip.AddrFromSlice(theip)
|
||||
|
||||
ha.AddrPort = netip.AddrPortFrom(ip, uint16(a.Port))
|
||||
ha.Network = a.Network
|
||||
ha.Name = a.Name
|
||||
|
||||
+39
-23
@@ -50,29 +50,6 @@ func HasIpv6Interface() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
/*
|
||||
if utils.LogLevel == utils.Log_debug {
|
||||
|
||||
log.Println("interfaces", len(addrs), addrs)
|
||||
|
||||
for _, address := range addrs {
|
||||
|
||||
if ipnet, ok := address.(*net.IPNet); ok {
|
||||
|
||||
isipv6 := false
|
||||
|
||||
if !ipnet.IP.IsLoopback() && !ipnet.IP.IsPrivate() && !ipnet.IP.IsLinkLocalUnicast() {
|
||||
if ipnet.IP.To4() == nil {
|
||||
isipv6 = true
|
||||
}
|
||||
}
|
||||
log.Println(ipnet.IP.String(), isipv6)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}*/
|
||||
|
||||
for _, address := range addrs {
|
||||
if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() && !ipnet.IP.IsPrivate() && !ipnet.IP.IsLinkLocalUnicast() {
|
||||
// IsLinkLocalUnicast: something starts with fe80:
|
||||
@@ -119,3 +96,42 @@ func IsStrUDP_network(s string) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
//使用Addr,是因为有可能申请的是域名,而不是ip
|
||||
type MsgConn interface {
|
||||
ReadFrom() ([]byte, Addr, error)
|
||||
WriteTo([]byte, Addr) error
|
||||
}
|
||||
|
||||
type UDPMsgConnWrapper struct {
|
||||
*net.UDPConn
|
||||
IsClient bool
|
||||
FirstAddr Addr
|
||||
}
|
||||
|
||||
func (u *UDPMsgConnWrapper) ReadFrom() ([]byte, Addr, error) {
|
||||
bs := utils.GetPacket()
|
||||
n, ad, err := u.UDPConn.ReadFromUDP(bs)
|
||||
if err != nil {
|
||||
return nil, Addr{}, err
|
||||
}
|
||||
return bs[:n], NewAddrFromUDPAddr(ad), err
|
||||
}
|
||||
|
||||
func (u *UDPMsgConnWrapper) WriteTo(bs []byte, ad Addr) error {
|
||||
|
||||
if u.IsClient {
|
||||
if ad.GetHashable() == u.FirstAddr.GetHashable() {
|
||||
_, err := u.UDPConn.Write(bs)
|
||||
return err
|
||||
} else {
|
||||
|
||||
return utils.ErrNotImplemented
|
||||
}
|
||||
} else {
|
||||
_, err := u.UDPConn.WriteTo(bs, ad.ToUDPAddr())
|
||||
return err
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+12
-5
@@ -22,28 +22,35 @@ var (
|
||||
//本文件内含 一些 转发 udp 数据的 接口与方法
|
||||
|
||||
// 阻塞.
|
||||
func RelayUDP(putter UDP_Putter, extractor UDP_Extractor, dialFunc func(targetAddr Addr) (io.ReadWriter, error)) {
|
||||
func RelayUDP(conn1, conn2 MsgConn) {
|
||||
|
||||
go func() {
|
||||
for {
|
||||
raddr, bs, err := extractor.GetNewUDPRequest()
|
||||
bs, raddr, err := conn1.ReadFrom()
|
||||
if err != nil {
|
||||
//log.Println("RelayUDP e1", err)
|
||||
break
|
||||
}
|
||||
err = putter.WriteUDPRequest(raddr, bs, dialFunc)
|
||||
err = conn2.WriteTo(bs, raddr)
|
||||
if err != nil {
|
||||
//log.Println("RelayUDP e2", err)
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
for {
|
||||
raddr, bs, err := putter.GetNewUDPResponse()
|
||||
bs, raddr, err := conn2.ReadFrom()
|
||||
if err != nil {
|
||||
//log.Println("RelayUDP e3", err)
|
||||
|
||||
break
|
||||
}
|
||||
err = extractor.WriteUDPResponse(raddr, bs)
|
||||
err = conn1.WriteTo(bs, raddr)
|
||||
if err != nil {
|
||||
//log.Println("RelayUDP e4", err)
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@ import (
|
||||
type UDPListener struct {
|
||||
conn *net.UDPConn
|
||||
|
||||
newConnChan chan *UDPConn
|
||||
connMap map[netip.AddrPort]*UDPConn
|
||||
newConnChan chan *Uni_UDPConn
|
||||
connMap map[netip.AddrPort]*Uni_UDPConn
|
||||
mux sync.RWMutex
|
||||
isclosed bool
|
||||
}
|
||||
@@ -35,20 +35,20 @@ func NewUDPListener(laddr *net.UDPAddr) (*UDPListener, error) {
|
||||
func NewUDPListenerConn(conn *net.UDPConn) (*UDPListener, error) {
|
||||
ul := new(UDPListener)
|
||||
ul.conn = conn
|
||||
ul.connMap = make(map[netip.AddrPort]*UDPConn)
|
||||
ul.newConnChan = make(chan *UDPConn, 100)
|
||||
ul.connMap = make(map[netip.AddrPort]*Uni_UDPConn)
|
||||
ul.newConnChan = make(chan *Uni_UDPConn, 100)
|
||||
go ul.run()
|
||||
|
||||
return ul, nil
|
||||
}
|
||||
|
||||
//It can be used to dial a remote udp
|
||||
func (ul *UDPListener) NewConn(raddr *net.UDPAddr) *UDPConn {
|
||||
func (ul *UDPListener) NewConn(raddr *net.UDPAddr) *Uni_UDPConn {
|
||||
return ul.newConn(raddr, UDPAddr2AddrPort(raddr))
|
||||
}
|
||||
|
||||
//newConn 创建一个新的 UDPConn,并存储在 ul.connMap 中
|
||||
func (ul *UDPListener) newConn(raddr *net.UDPAddr, addrport netip.AddrPort) *UDPConn {
|
||||
func (ul *UDPListener) newConn(raddr *net.UDPAddr, addrport netip.AddrPort) *Uni_UDPConn {
|
||||
newC := NewUDPConn(raddr, ul.conn, false)
|
||||
ul.mux.Lock()
|
||||
ul.connMap[addrport] = newC
|
||||
@@ -101,7 +101,7 @@ func (ul *UDPListener) closeClients() error {
|
||||
for _, c := range ul.connMap {
|
||||
close(c.inMsgChan)
|
||||
}
|
||||
ul.connMap = make(map[netip.AddrPort]*UDPConn)
|
||||
ul.connMap = make(map[netip.AddrPort]*Uni_UDPConn)
|
||||
ul.mux.Unlock()
|
||||
|
||||
return nil
|
||||
@@ -120,7 +120,7 @@ func (ul *UDPListener) run() {
|
||||
|
||||
go func(theraddr *net.UDPAddr, thebuf []byte) {
|
||||
addrport := UDPAddr2AddrPort(theraddr)
|
||||
var oldConn *UDPConn
|
||||
var oldConn *Uni_UDPConn
|
||||
|
||||
ul.mux.RLock()
|
||||
oldConn = ul.connMap[addrport]
|
||||
|
||||
@@ -49,13 +49,8 @@ func (d *Client) Handshake(underlay net.Conn, target netLayer.Addr) (io.ReadWrit
|
||||
|
||||
}
|
||||
|
||||
func (d *Client) GetNewUDP_Putter() netLayer.UDP_Putter {
|
||||
|
||||
//单单的pipe是无法做到转发的,它就像一个缓存一样;
|
||||
// 一方是未知的,向 UDP_Putter 放入请求,
|
||||
// 然后我们这边就要通过一个 goroutine 来不断提取请求然后转发到direct.
|
||||
|
||||
pipe := netLayer.NewUDP_Pipe()
|
||||
go netLayer.RelayUDP_to_Direct(pipe)
|
||||
return pipe
|
||||
//direct的Client的 EstablishUDPChannel 实际上就是直接拨号udp
|
||||
func (d *Client) EstablishUDPChannel(_ net.Conn, target netLayer.Addr) (netLayer.MsgConn, error) {
|
||||
conn, err := net.DialUDP("udp", nil, target.ToUDPAddr())
|
||||
return &netLayer.UDPMsgConnWrapper{UDPConn: conn, IsClient: true, FirstAddr: target}, err
|
||||
}
|
||||
|
||||
@@ -82,6 +82,7 @@ func NewServer() (proxy.Server, error) {
|
||||
}
|
||||
func (d *Server) Name() string { return name }
|
||||
|
||||
func (s *Server) Handshake(underlay net.Conn) (io.ReadWriteCloser, netLayer.Addr, error) {
|
||||
return underlay, s.targetAddr, nil
|
||||
//因为dokodemo的单目标性质, 不会建立任何udp通道.
|
||||
func (s *Server) Handshake(underlay net.Conn) (io.ReadWriteCloser, netLayer.MsgConn, netLayer.Addr, error) {
|
||||
return underlay, nil, s.targetAddr, nil
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ func (_ Server) Name() string {
|
||||
return name
|
||||
}
|
||||
|
||||
func (s *Server) Handshake(underlay net.Conn) (newconn io.ReadWriteCloser, targetAddr netLayer.Addr, err error) {
|
||||
func (s *Server) Handshake(underlay net.Conn) (newconn io.ReadWriteCloser, _ netLayer.MsgConn, targetAddr netLayer.Addr, err error) {
|
||||
var b = utils.GetMTU() //一般要获取请求信息,不需要那么长; 就算是http,加了path,也不用太长
|
||||
//因为要储存为 firstdata,所以也无法直接放回
|
||||
|
||||
|
||||
+7
-3
@@ -35,12 +35,15 @@ func PrintAllClientNames() {
|
||||
//服务端是一种 “泛目标”代理,所以我们客户端的 Handshake 要传入目标地址, 来告诉它 我们 想要到达的 目标地址.
|
||||
// 一个Client 掌握从最底层的tcp等到最上层的 代理协议间的所有数据;
|
||||
// 一旦一个 Client 被完整定义,则它的数据的流向就被完整确定了.
|
||||
//
|
||||
// 然而, udp的转发则不一样. 一般来说, udp只handshake一次, 建立一个通道, 然后在这个通道上
|
||||
// 不断申请发送到 各个远程udp地址的连接。客户端也可以选择建立多个udp通道。
|
||||
type Client interface {
|
||||
ProxyCommon
|
||||
|
||||
// Handshake的 underlay有可能传入nil,所以要求 所有的 Client 都要能够自己dial
|
||||
// 不过目前暂时全在main函数里dial
|
||||
Handshake(underlay net.Conn, target netLayer.Addr) (io.ReadWriteCloser, error)
|
||||
|
||||
EstablishUDPChannel(underlay net.Conn, target netLayer.Addr) (netLayer.MsgConn, error)
|
||||
}
|
||||
|
||||
// Server 用于监听 客户端 的连接.
|
||||
@@ -50,7 +53,8 @@ type Client interface {
|
||||
type Server interface {
|
||||
ProxyCommon
|
||||
|
||||
Handshake(underlay net.Conn) (io.ReadWriteCloser, netLayer.Addr, error)
|
||||
//ReadWriteCloser 为请求地址为tcp的情况, net.PacketConn 为 请求建立的udp通道
|
||||
Handshake(underlay net.Conn) (io.ReadWriteCloser, netLayer.MsgConn, netLayer.Addr, error)
|
||||
}
|
||||
|
||||
// FullName 可以完整表示 一个 代理的 VSI 层级.
|
||||
|
||||
+88
-131
@@ -11,7 +11,6 @@ import (
|
||||
|
||||
"github.com/hahahrfool/v2ray_simple/netLayer"
|
||||
"github.com/hahahrfool/v2ray_simple/utils"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/hahahrfool/v2ray_simple/proxy"
|
||||
)
|
||||
@@ -46,8 +45,8 @@ func (s *Server) Name() string { return Name }
|
||||
//中文: https://aber.sh/articles/Socks5/
|
||||
// 参考 https://studygolang.com/articles/31404
|
||||
|
||||
// 处理tcp收到的请求. 注意, udp associate后的 udp请求并不通过此函数处理, 而是由 UDPConn.StartReadRequest 处理
|
||||
func (s *Server) Handshake(underlay net.Conn) (result io.ReadWriteCloser, targetAddr netLayer.Addr, returnErr error) {
|
||||
// 处理tcp收到的请求. 注意, udp associate后的 udp请求并不通过此函数处理, 而是由 UDPConn 处理
|
||||
func (s *Server) Handshake(underlay net.Conn) (result io.ReadWriteCloser, udpChannel netLayer.MsgConn, targetAddr netLayer.Addr, returnErr error) {
|
||||
// Set handshake timeout 4 seconds
|
||||
if err := underlay.SetReadDeadline(time.Now().Add(time.Second * 4)); err != nil {
|
||||
returnErr = err
|
||||
@@ -179,7 +178,7 @@ func (s *Server) Handshake(underlay net.Conn) (result io.ReadWriteCloser, target
|
||||
clientSupposedAddr: clientFutureAddr.ToUDPAddr(),
|
||||
UDPConn: udpRC,
|
||||
}
|
||||
return uc, clientFutureAddr, nil
|
||||
return nil, uc, clientFutureAddr, nil
|
||||
|
||||
} else {
|
||||
|
||||
@@ -207,167 +206,125 @@ func (s *Server) Handshake(underlay net.Conn) (result io.ReadWriteCloser, target
|
||||
Port: thePort,
|
||||
}
|
||||
|
||||
return underlay, targetAddr, nil
|
||||
return underlay, nil, targetAddr, nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//用于socks5服务端的 udp连接, 实现 netLayer.MsgConn
|
||||
type UDPConn struct {
|
||||
*net.UDPConn
|
||||
clientSupposedAddr *net.UDPAddr //客户端指定的客户端自己未来将使用的公网UDP的Addr
|
||||
}
|
||||
|
||||
// 阻塞
|
||||
// 从 udpPutter.GetNewUDPResponse 循环阅读 所有需要发送给客户端的 数据,然后通过 u.UDPConn.Write 发送给客户端
|
||||
// 这些响应数据是 在其它地方 写入 udpPutter 的, 本 u 是不管 谁、如何 把这个信息 放进去的。
|
||||
func (u *UDPConn) StartPushResponse(udpPutter netLayer.UDP_Putter) {
|
||||
for {
|
||||
raddr, bs, err := udpPutter.GetNewUDPResponse()
|
||||
//log.Println("StartPushResponse got new response", raddr, string(bs), err)
|
||||
if err != nil {
|
||||
u.UDPConn.Close()
|
||||
break
|
||||
}
|
||||
buf := &bytes.Buffer{}
|
||||
buf.WriteByte(0) //rsv
|
||||
buf.WriteByte(0) //rsv
|
||||
buf.WriteByte(0) //frag
|
||||
//将远程地址发来的响应 传给客户端
|
||||
func (u *UDPConn) WriteTo(bs []byte, raddr netLayer.Addr) error {
|
||||
|
||||
var atyp byte = ATypIP4
|
||||
if len(raddr.IP) > 4 {
|
||||
atyp = ATypIP6
|
||||
}
|
||||
buf.WriteByte(atyp)
|
||||
|
||||
buf.Write(raddr.IP)
|
||||
buf.WriteByte(byte(int16(raddr.Port) >> 8))
|
||||
buf.WriteByte(byte(int16(raddr.Port) << 8 >> 8))
|
||||
buf.Write(bs)
|
||||
|
||||
//必须要指明raddr
|
||||
_, err = u.UDPConn.WriteToUDP(buf.Bytes(), u.clientSupposedAddr)
|
||||
|
||||
if err != nil {
|
||||
if ce := utils.CanLogErr("socks5, StartPushResponse, write"); ce != nil {
|
||||
//log.Println("socks5, StartPushResponse, write err ", err)
|
||||
ce.Write(zap.Error(err))
|
||||
|
||||
}
|
||||
break
|
||||
}
|
||||
buf := &bytes.Buffer{}
|
||||
buf.WriteByte(0) //rsv
|
||||
buf.WriteByte(0) //rsv
|
||||
buf.WriteByte(0) //frag
|
||||
|
||||
var atyp byte = ATypIP4
|
||||
if len(raddr.IP) > 4 {
|
||||
atyp = ATypIP6
|
||||
}
|
||||
buf.WriteByte(atyp)
|
||||
|
||||
buf.Write(raddr.IP)
|
||||
buf.WriteByte(byte(int16(raddr.Port) >> 8))
|
||||
buf.WriteByte(byte(int16(raddr.Port) << 8 >> 8))
|
||||
buf.Write(bs)
|
||||
|
||||
//必须要指明raddr
|
||||
_, err := u.UDPConn.WriteToUDP(buf.Bytes(), u.clientSupposedAddr)
|
||||
|
||||
return err
|
||||
|
||||
}
|
||||
|
||||
// 阻塞
|
||||
// 监听 与客户端的udp连接 (u.UDPConn);循环查看客户端发来的请求信息;
|
||||
// 然后将该请求 用 udpPutter.WriteUDPRequest 发送给 udpPutter
|
||||
// 至于fullcone与否它是不管的。
|
||||
// 如果客户端一开始没有指明自己连接本服务端的ip和端口, 则将第一个发来的正确的socks5请求视为该客户端,并记录。
|
||||
func (u *UDPConn) StartReadRequest(udpPutter netLayer.UDP_Putter, dialFunc func(targetAddr netLayer.Addr) (io.ReadWriter, error)) {
|
||||
//从 客户端读取 udp请求
|
||||
func (u *UDPConn) ReadFrom() ([]byte, netLayer.Addr, error) {
|
||||
|
||||
var clientSupposedAddrIsNothing bool
|
||||
if len(u.clientSupposedAddr.IP) < 3 || u.clientSupposedAddr.IP.IsUnspecified() {
|
||||
clientSupposedAddrIsNothing = true
|
||||
}
|
||||
|
||||
bs := make([]byte, netLayer.MaxUDP_packetLen)
|
||||
for {
|
||||
bs := utils.GetPacket()
|
||||
|
||||
n, addr, err := u.UDPConn.ReadFromUDP(bs)
|
||||
if err != nil {
|
||||
n, addr, err := u.UDPConn.ReadFromUDP(bs)
|
||||
if err != nil {
|
||||
|
||||
u.UDPConn.Close()
|
||||
udpPutter.CloseUDPRequestWriter() //只要读udp发生致命错误,我们就关闭RequestWriter,这样 StartPushResponse 方法中调用的 udpPutter.GetNewUDPResponse 就应该同步退出了
|
||||
|
||||
if ce := utils.CanLogWarn("socks5 failed UDPConn read"); ce != nil {
|
||||
|
||||
ce.Write(zap.Error(err))
|
||||
}
|
||||
|
||||
break
|
||||
if n <= 0 {
|
||||
return nil, netLayer.Addr{}, err
|
||||
}
|
||||
return bs[:n], netLayer.NewAddrFromUDPAddr(addr), err
|
||||
}
|
||||
|
||||
if n < 6 {
|
||||
if ce := utils.CanLogWarn("socks5 UDPConn short read"); ce != nil {
|
||||
if n < 6 {
|
||||
|
||||
ce.Write(zap.Error(err))
|
||||
}
|
||||
continue
|
||||
}
|
||||
return nil, netLayer.Addr{}, utils.ErrInErr{ErrDesc: "socks5 UDPConn short read", Data: n}
|
||||
}
|
||||
|
||||
if !clientSupposedAddrIsNothing {
|
||||
if !clientSupposedAddrIsNothing {
|
||||
|
||||
if !addr.IP.Equal(u.clientSupposedAddr.IP) || addr.Port != u.clientSupposedAddr.Port {
|
||||
if !addr.IP.Equal(u.clientSupposedAddr.IP) || addr.Port != u.clientSupposedAddr.Port {
|
||||
|
||||
//just random attack message.
|
||||
continue
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
atyp := bs[3]
|
||||
|
||||
l := 2 //supposed Minimum Remain Data Lenth
|
||||
off := 4 //offset from which the addr data really starts
|
||||
|
||||
var theIP net.IP
|
||||
switch atyp {
|
||||
case ATypIP4:
|
||||
l += net.IPv4len
|
||||
theIP = make(net.IP, net.IPv4len)
|
||||
case ATypIP6:
|
||||
l += net.IPv6len
|
||||
theIP = make(net.IP, net.IPv6len)
|
||||
case ATypDomain:
|
||||
l += int(bs[4])
|
||||
off = 5
|
||||
default:
|
||||
if ce := utils.CanLogWarn("socks5 read UDPConn unknown address"); ce != nil {
|
||||
|
||||
ce.Write(zap.Uint8("atype", atyp))
|
||||
}
|
||||
continue
|
||||
//just random attack message.
|
||||
return nil, netLayer.Addr{}, errors.New("socks5 UDPConn random attack message")
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if len(bs[off:]) < l {
|
||||
if ce := utils.CanLogWarn("socks5 UDPConn short command request"); ce != nil {
|
||||
atyp := bs[3]
|
||||
|
||||
ce.Write(zap.Uint8("atype", atyp))
|
||||
}
|
||||
continue
|
||||
l := 2 //supposed Minimum Remain Data Lenth
|
||||
off := 4 //offset from which the addr data really starts
|
||||
|
||||
}
|
||||
var theIP net.IP
|
||||
switch atyp {
|
||||
case ATypIP4:
|
||||
l += net.IPv4len
|
||||
theIP = make(net.IP, net.IPv4len)
|
||||
case ATypIP6:
|
||||
l += net.IPv6len
|
||||
theIP = make(net.IP, net.IPv6len)
|
||||
case ATypDomain:
|
||||
l += int(bs[4])
|
||||
off = 5
|
||||
default:
|
||||
|
||||
var theName string
|
||||
|
||||
if theIP != nil {
|
||||
copy(theIP, bs[off:])
|
||||
} else {
|
||||
theName = string(bs[off : off+l-2])
|
||||
}
|
||||
var thePort int
|
||||
thePort = int(bs[off+l-2])<<8 | int(bs[off+l-1])
|
||||
|
||||
newStart := off + l
|
||||
|
||||
//为了解析域名, 我们用 netLayer.Addr 作为中介.
|
||||
requestAddr := &netLayer.Addr{
|
||||
IP: theIP,
|
||||
Name: theName,
|
||||
Port: thePort,
|
||||
Network: "udp",
|
||||
}
|
||||
|
||||
if clientSupposedAddrIsNothing {
|
||||
clientSupposedAddrIsNothing = false
|
||||
u.clientSupposedAddr = addr
|
||||
}
|
||||
|
||||
//log.Println("socks5 server,StartReadRequest, got msg", thisaddr, string(bs[newStart:n]))
|
||||
|
||||
udpPutter.WriteUDPRequest(*requestAddr.ToUDPAddr(), bs[newStart:n], dialFunc)
|
||||
return nil, netLayer.Addr{}, utils.ErrInErr{ErrDesc: "socks5 read UDPConn unknown atype", Data: atyp}
|
||||
|
||||
}
|
||||
|
||||
if len(bs[off:]) < l {
|
||||
|
||||
return nil, netLayer.Addr{}, utils.ErrInErr{ErrDesc: "socks5 UDPConn short command request", Data: atyp}
|
||||
|
||||
}
|
||||
|
||||
var theName string
|
||||
|
||||
if theIP != nil {
|
||||
copy(theIP, bs[off:])
|
||||
} else {
|
||||
theName = string(bs[off : off+l-2])
|
||||
}
|
||||
var thePort int
|
||||
thePort = int(bs[off+l-2])<<8 | int(bs[off+l-1])
|
||||
|
||||
newStart := off + l
|
||||
|
||||
if clientSupposedAddrIsNothing {
|
||||
clientSupposedAddrIsNothing = false
|
||||
u.clientSupposedAddr = addr
|
||||
}
|
||||
return bs[newStart:n], netLayer.Addr{
|
||||
IP: theIP,
|
||||
Name: theName,
|
||||
Port: thePort,
|
||||
Network: "udp",
|
||||
}, nil
|
||||
}
|
||||
|
||||
+29
-28
@@ -1,7 +1,6 @@
|
||||
package socks5_test
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -38,44 +37,46 @@ func TestUDP(t *testing.T) {
|
||||
t.Fail()
|
||||
}
|
||||
t.Log("socks5 server got new conn")
|
||||
wlc, targetAddr, err := s.Handshake(lc)
|
||||
_, wlc, targetAddr, err := s.Handshake(lc)
|
||||
if targetAddr.IsUDP() {
|
||||
t.Log("socks5 server got udp associate")
|
||||
}
|
||||
//此时wlc返回的是socks5新监听的 conn
|
||||
|
||||
udpConn := wlc.(*socks5.UDPConn)
|
||||
go func() {
|
||||
for {
|
||||
t.Log("socks5 server start read udp channel")
|
||||
|
||||
dialFunc := func(targetAddr netLayer.Addr) (io.ReadWriter, error) {
|
||||
return targetAddr.Dial()
|
||||
}
|
||||
bs, addr, err := wlc.ReadFrom()
|
||||
if err != nil {
|
||||
t.Log("socks5 server read udp channel err,", err)
|
||||
|
||||
if putter, ok := direct.(netLayer.UDP_Putter); ok {
|
||||
break
|
||||
}
|
||||
|
||||
//UDP_Putter 不使用传统的Handshake过程,因为Handshake是用于第一次数据,然后后面接着的双向传输都不再需要额外信息;而 UDP_Putter 每一次数据传输都是需要传输 目标地址的,所以每一次都需要一些额外数据,这就是我们 UDP_Putter 接口去解决的事情。
|
||||
t.Log("socks5 server got udp msg")
|
||||
|
||||
//因为UDP Associate后,就会保证以后的向 wlc 的 所有请求数据都是udp请求,所以可以在这里直接循环转发了。
|
||||
|
||||
go udpConn.StartPushResponse(putter)
|
||||
|
||||
udpConn.StartReadRequest(putter, dialFunc)
|
||||
|
||||
} else if pc, ok := direct.(netLayer.UDP_Putter_Generator); ok {
|
||||
|
||||
// direct 通过 UDP_Pipe和 RelayUDP_to_Direct函数 实现了 UDP_Putter_Generator
|
||||
|
||||
putter := pc.GetNewUDP_Putter()
|
||||
if putter != nil {
|
||||
go udpConn.StartPushResponse(putter)
|
||||
|
||||
udpConn.StartReadRequest(putter, dialFunc)
|
||||
msgConn, err := direct.EstablishUDPChannel(nil, addr)
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
return
|
||||
}
|
||||
err = msgConn.WriteTo(bs, addr)
|
||||
if err != nil {
|
||||
t.Log("socks5 server Write To direct failed,", len(bs), err)
|
||||
}
|
||||
go func() {
|
||||
for {
|
||||
rbs, raddr, err := msgConn.ReadFrom()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
wlc.WriteTo(rbs, raddr)
|
||||
}
|
||||
}()
|
||||
}
|
||||
} else {
|
||||
}()
|
||||
|
||||
t.Log("socks5 server -> client for udp, but client didn't implement netLayer.UDP_Putter", direct.Name())
|
||||
t.Fail()
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
|
||||
+36
-20
@@ -1,6 +1,7 @@
|
||||
package trojan
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
@@ -38,20 +39,8 @@ type Client struct {
|
||||
func (c *Client) Name() string {
|
||||
return name
|
||||
}
|
||||
func (c *Client) Handshake(underlay net.Conn, target netLayer.Addr) (io.ReadWriteCloser, error) {
|
||||
if target.Port <= 0 {
|
||||
return nil, errors.New("Trojan Client Handshake failed, target port invalid")
|
||||
|
||||
}
|
||||
buf := utils.GetBuf()
|
||||
buf.Write(c.password_hexStringBytes)
|
||||
buf.Write(crlf)
|
||||
isudp := target.IsUDP()
|
||||
if isudp {
|
||||
buf.WriteByte(CmdUDPAssociate)
|
||||
} else {
|
||||
buf.WriteByte(CmdConnect)
|
||||
}
|
||||
func WriteTargetToBuf(target netLayer.Addr, buf *bytes.Buffer) {
|
||||
if len(target.IP) > 0 {
|
||||
if ip4 := target.IP.To4(); ip4 == nil {
|
||||
buf.WriteByte(netLayer.AtypIP6)
|
||||
@@ -64,21 +53,48 @@ func (c *Client) Handshake(underlay net.Conn, target netLayer.Addr) (io.ReadWrit
|
||||
buf.WriteByte(ATypDomain)
|
||||
buf.WriteByte(byte(l))
|
||||
buf.WriteString(target.Name)
|
||||
} else {
|
||||
return nil, errors.New("Trojan Client Handshake failed, target has no domain and ip at all.")
|
||||
}
|
||||
|
||||
buf.WriteByte(byte(target.Port >> 8))
|
||||
buf.WriteByte(byte(target.Port << 8 >> 8))
|
||||
buf.Write(crlf)
|
||||
}
|
||||
|
||||
func (c *Client) Handshake(underlay net.Conn, target netLayer.Addr) (io.ReadWriteCloser, error) {
|
||||
if target.Port <= 0 {
|
||||
return nil, errors.New("Trojan Client Handshake failed, target port invalid")
|
||||
|
||||
}
|
||||
buf := utils.GetBuf()
|
||||
buf.Write(c.password_hexStringBytes)
|
||||
buf.Write(crlf)
|
||||
buf.WriteByte(CmdConnect)
|
||||
WriteTargetToBuf(target, buf)
|
||||
|
||||
_, err := underlay.Write(buf.Bytes())
|
||||
utils.PutBuf(buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if isudp {
|
||||
return UDPConn{underlay}, nil
|
||||
} else {
|
||||
return underlay, nil
|
||||
}
|
||||
return underlay, nil
|
||||
}
|
||||
|
||||
func (c *Client) EstablishUDPChannel(underlay net.Conn, target netLayer.Addr) (netLayer.MsgConn, error) {
|
||||
if target.Port <= 0 {
|
||||
return nil, errors.New("Trojan Client Handshake failed, target port invalid")
|
||||
|
||||
}
|
||||
buf := utils.GetBuf()
|
||||
buf.Write(c.password_hexStringBytes)
|
||||
buf.Write(crlf)
|
||||
buf.WriteByte(CmdUDPAssociate)
|
||||
WriteTargetToBuf(target, buf)
|
||||
_, err := underlay.Write(buf.Bytes())
|
||||
utils.PutBuf(buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return UDPConn{underlay}, nil
|
||||
}
|
||||
|
||||
+15
-1
@@ -1,7 +1,21 @@
|
||||
package trojan
|
||||
|
||||
import "net"
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/hahahrfool/v2ray_simple/netLayer"
|
||||
)
|
||||
|
||||
type UDPConn struct {
|
||||
net.Conn
|
||||
}
|
||||
|
||||
func (u UDPConn) ReadFrom() ([]byte, netLayer.Addr, error) {
|
||||
|
||||
return nil, netLayer.Addr{}, nil
|
||||
}
|
||||
|
||||
func (u UDPConn) WriteTo([]byte, netLayer.Addr) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
+68
-118
@@ -105,61 +105,10 @@ func (c *Client) GetUser() proxy.User {
|
||||
func (c *Client) Handshake(underlay net.Conn, target netLayer.Addr) (io.ReadWriteCloser, error) {
|
||||
var err error
|
||||
|
||||
if underlay == nil {
|
||||
underlay, err = target.Dial() //不建议传入underlay为nil,因为这里dial处于裸奔状态
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
port := target.Port
|
||||
addr, atyp := target.AddressBytes()
|
||||
|
||||
cmd := CmdTCP
|
||||
if target.Network == "udp" {
|
||||
if c.version == 1 && !c.is_CRUMFURS_established {
|
||||
|
||||
//log.Println("尝试拨号 Cmd_CRUMFURS 信道")
|
||||
|
||||
//这段代码明显有问题,如果直接dial的话,那就是脱离tls的裸协议,所以这里以后需要处理一下
|
||||
UMFURS_conn, err := target.Dial()
|
||||
if err != nil {
|
||||
if ce := utils.CanLogErr("尝试拨号 Cmd_CRUMFURS 信道时发生错误"); ce != nil {
|
||||
|
||||
//log.Println("尝试拨号 Cmd_CRUMFURS 信道时发生错误")
|
||||
ce.Write(zap.Error(err))
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
buf := c.getBufWithCmd(Cmd_CRUMFURS)
|
||||
|
||||
UMFURS_conn.Write(buf.Bytes())
|
||||
|
||||
utils.PutBuf(buf)
|
||||
|
||||
bs := []byte{0}
|
||||
n, err := UMFURS_conn.Read(bs)
|
||||
if err != nil || n == 0 || bs[0] != CRUMFURS_ESTABLISHED {
|
||||
if ce := utils.CanLogErr("尝试读取 Cmd_CRUMFURS 信道返回值 时发生错误"); ce != nil {
|
||||
|
||||
//log.Println("尝试读取 Cmd_CRUMFURS 信道返回值 时发生错误")
|
||||
ce.Write(zap.Error(err))
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c.is_CRUMFURS_established = true
|
||||
|
||||
// 循环监听 UMFURS 信息
|
||||
go c.handle_CRUMFURS(UMFURS_conn)
|
||||
|
||||
}
|
||||
|
||||
cmd = CmdUDP
|
||||
|
||||
}
|
||||
|
||||
buf := c.getBufWithCmd(cmd)
|
||||
buf := c.getBufWithCmd(CmdTCP)
|
||||
|
||||
buf.WriteByte(byte(uint16(port) >> 8))
|
||||
buf.WriteByte(byte(uint16(port) << 8 >> 8))
|
||||
@@ -171,74 +120,75 @@ func (c *Client) Handshake(underlay net.Conn, target netLayer.Addr) (io.ReadWrit
|
||||
|
||||
utils.PutBuf(buf)
|
||||
|
||||
return &UserConn{
|
||||
Conn: underlay,
|
||||
uuid: *c.user,
|
||||
version: c.version,
|
||||
isUDP: target.IsUDP(),
|
||||
underlayIsBasic: netLayer.IsBasicConn(underlay),
|
||||
}, err
|
||||
}
|
||||
|
||||
func (u *Client) CloseUDPRequestWriter() {
|
||||
//因为我们的vless的client是 【一个 outClient实例 处理 一切 dial 的udp连接】
|
||||
// 所以不能直接close c.udpResponseChan
|
||||
}
|
||||
|
||||
func (c *Client) GetNewUDPResponse() (net.UDPAddr, []byte, error) {
|
||||
x := <-c.udpResponseChan //v1的话,由 handle_CRUMFURS 以及 WriteUDPRequest 中的 goroutine 填充;v0的话,由 WriteUDPRequest 填充
|
||||
return x.Addr, x.Data, nil
|
||||
}
|
||||
|
||||
//一般由socks5或者透明代理等地方 获取到 udp请求后,被传入这里
|
||||
func (c *Client) WriteUDPRequest(a net.UDPAddr, b []byte, dialFunc func(targetAddr netLayer.Addr) (io.ReadWriter, error)) (err error) {
|
||||
|
||||
astr := a.String()
|
||||
|
||||
c.mutex.RLock()
|
||||
knownConn := c.knownUDPDestinations[astr]
|
||||
c.mutex.RUnlock()
|
||||
|
||||
if knownConn == nil {
|
||||
|
||||
knownConn, err = dialFunc(netLayer.NewAddrFromUDPAddr(&a))
|
||||
if err != nil || knownConn == nil {
|
||||
return utils.ErrInErr{ErrDesc: "vless WriteUDPRequest, err when creating an underlay", ErrDetail: err}
|
||||
}
|
||||
//这里原来的代码是调用 c.Handshake,会自动帮我们拨号代理节点CmdUDP
|
||||
// 但是有问题,因为不应该由client自己拨号vless,因为我们还有上层的tls;
|
||||
// 自己拨号的话,那就是裸奔状态
|
||||
// 最新代码采用dialFunc的方式解决
|
||||
|
||||
c.mutex.Lock()
|
||||
c.knownUDPDestinations[astr] = knownConn
|
||||
c.mutex.Unlock()
|
||||
|
||||
go func() {
|
||||
bs := make([]byte, netLayer.MaxUDP_packetLen)
|
||||
for {
|
||||
n, err := knownConn.Read(bs)
|
||||
//一般knownConn为tcp连接. 在远程节点的 udp的direct的Read一直读不到数据导致timeout后, 就会关闭对应的vless的tcp连接, 然后我们这里的Read就会收到通知
|
||||
// 不过我们不用管 inServer的conn的关闭, 因为监听udp的conn是不需要关闭的, 它还要接着监听其它客户端发来的连接.
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
if n <= 0 {
|
||||
continue
|
||||
}
|
||||
msg := make([]byte, n)
|
||||
copy(msg, bs[:n])
|
||||
|
||||
c.udpResponseChan <- netLayer.UDPAddrData{
|
||||
Addr: a,
|
||||
Data: msg,
|
||||
}
|
||||
}
|
||||
}()
|
||||
if c.version == 0 {
|
||||
return &UserTCPConn{
|
||||
Conn: underlay,
|
||||
uuid: *c.user,
|
||||
version: c.version,
|
||||
underlayIsBasic: netLayer.IsBasicConn(underlay),
|
||||
}, err
|
||||
} else {
|
||||
return underlay, nil
|
||||
}
|
||||
|
||||
_, err = knownConn.Write(b)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Client) EstablishUDPChannel(underlay net.Conn, target netLayer.Addr) (netLayer.MsgConn, error) {
|
||||
var err error
|
||||
|
||||
if c.version == 1 && !c.is_CRUMFURS_established {
|
||||
|
||||
//log.Println("尝试拨号 Cmd_CRUMFURS 信道")
|
||||
|
||||
//这段代码明显有问题,如果直接dial的话,那就是脱离tls的裸协议,所以这里以后需要处理一下
|
||||
UMFURS_conn, err := target.Dial()
|
||||
if err != nil {
|
||||
if ce := utils.CanLogErr("尝试拨号 Cmd_CRUMFURS 信道时发生错误"); ce != nil {
|
||||
|
||||
//log.Println("尝试拨号 Cmd_CRUMFURS 信道时发生错误")
|
||||
ce.Write(zap.Error(err))
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
buf := c.getBufWithCmd(Cmd_CRUMFURS)
|
||||
|
||||
UMFURS_conn.Write(buf.Bytes())
|
||||
|
||||
utils.PutBuf(buf)
|
||||
|
||||
bs := []byte{0}
|
||||
n, err := UMFURS_conn.Read(bs)
|
||||
if err != nil || n == 0 || bs[0] != CRUMFURS_ESTABLISHED {
|
||||
if ce := utils.CanLogErr("尝试读取 Cmd_CRUMFURS 信道返回值 时发生错误"); ce != nil {
|
||||
|
||||
//log.Println("尝试读取 Cmd_CRUMFURS 信道返回值 时发生错误")
|
||||
ce.Write(zap.Error(err))
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c.is_CRUMFURS_established = true
|
||||
|
||||
// 循环监听 UMFURS 信息
|
||||
go c.handle_CRUMFURS(UMFURS_conn)
|
||||
|
||||
}
|
||||
|
||||
buf := c.getBufWithCmd(CmdUDP)
|
||||
port := target.Port
|
||||
|
||||
buf.WriteByte(byte(uint16(port) >> 8))
|
||||
buf.WriteByte(byte(uint16(port) << 8 >> 8))
|
||||
addr, atyp := target.AddressBytes()
|
||||
|
||||
buf.WriteByte(atyp)
|
||||
buf.Write(addr)
|
||||
|
||||
_, err = underlay.Write(buf.Bytes())
|
||||
|
||||
utils.PutBuf(buf)
|
||||
|
||||
return &UDPConn{Conn: underlay, version: c.version, isClientEnd: true, raddr: target}, err
|
||||
}
|
||||
|
||||
func (c *Client) getBufWithCmd(cmd byte) *bytes.Buffer {
|
||||
|
||||
+24
-12
@@ -6,6 +6,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"net/url"
|
||||
"sync"
|
||||
@@ -133,7 +134,7 @@ func (s *Server) GetUserByStr(str string) proxy.User {
|
||||
func (s *Server) Name() string { return Name }
|
||||
|
||||
// 返回的bytes.Buffer 是用于 回落使用的,内含了整个读取的数据;不回落时不要使用该Buffer
|
||||
func (s *Server) Handshake(underlay net.Conn) (result io.ReadWriteCloser, targetAddr netLayer.Addr, returnErr error) {
|
||||
func (s *Server) Handshake(underlay net.Conn) (result io.ReadWriteCloser, msgConn netLayer.MsgConn, targetAddr netLayer.Addr, returnErr error) {
|
||||
|
||||
if err := underlay.SetReadDeadline(time.Now().Add(time.Second * 4)); err != nil {
|
||||
returnErr = err
|
||||
@@ -147,7 +148,6 @@ func (s *Server) Handshake(underlay net.Conn) (result io.ReadWriteCloser, target
|
||||
|
||||
readbs := utils.GetBytes(utils.StandardBytesLength)
|
||||
|
||||
//var auth [17]byte
|
||||
wholeReadLen, err := underlay.Read(readbs)
|
||||
if err != nil {
|
||||
returnErr = utils.ErrInErr{ErrDesc: "read err", ErrDetail: err, Data: wholeReadLen}
|
||||
@@ -334,6 +334,7 @@ realPart:
|
||||
_, err = readbuf.Read(ip_or_domain)
|
||||
|
||||
if err != nil {
|
||||
utils.PutBytes(ip_or_domain)
|
||||
returnErr = errors.New("fallback, reason 6")
|
||||
return
|
||||
}
|
||||
@@ -352,16 +353,27 @@ realPart:
|
||||
goto errorPart
|
||||
}
|
||||
|
||||
return &UserConn{
|
||||
Conn: underlay,
|
||||
optionalReader: io.MultiReader(readbuf, underlay),
|
||||
remainFirstBufLen: readbuf.Len(),
|
||||
uuid: thisUUIDBytes,
|
||||
version: int(version),
|
||||
isUDP: targetAddr.IsUDP(),
|
||||
underlayIsBasic: netLayer.IsBasicConn(underlay),
|
||||
isServerEnd: true,
|
||||
}, targetAddr, nil
|
||||
if targetAddr.IsUDP() {
|
||||
log.Println("targetAddr", targetAddr.IP, targetAddr.Name)
|
||||
return nil, &UDPConn{
|
||||
Conn: underlay,
|
||||
version: int(version),
|
||||
raddr: targetAddr,
|
||||
optionalReader: io.MultiReader(readbuf, underlay),
|
||||
remainFirstBufLen: readbuf.Len(),
|
||||
}, targetAddr, nil
|
||||
|
||||
} else {
|
||||
return &UserTCPConn{
|
||||
Conn: underlay,
|
||||
optionalReader: io.MultiReader(readbuf, underlay),
|
||||
remainFirstBufLen: readbuf.Len(),
|
||||
uuid: thisUUIDBytes,
|
||||
version: int(version),
|
||||
underlayIsBasic: netLayer.IsBasicConn(underlay),
|
||||
isServerEnd: true,
|
||||
}, nil, targetAddr, nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,248 @@
|
||||
package vless
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
|
||||
"github.com/hahahrfool/v2ray_simple/netLayer"
|
||||
"github.com/hahahrfool/v2ray_simple/utils"
|
||||
)
|
||||
|
||||
//实现 net.Conn, io.ReaderFrom, utils.MultiWriter, netLayer.Splicer
|
||||
type UserTCPConn struct {
|
||||
net.Conn
|
||||
optionalReader io.Reader //在使用了缓存读取握手包头后,就产生了buffer中有剩余数据的可能性,此时就要使用MultiReader
|
||||
|
||||
remainFirstBufLen int //记录读取握手包头时读到的buf的长度. 如果我们读超过了这个部分的话,实际上我们就可以不再使用 optionalReader 读取, 而是直接从Conn读取
|
||||
|
||||
underlayIsBasic bool
|
||||
|
||||
uuid [16]byte
|
||||
convertedUUIDStr string
|
||||
version int
|
||||
isServerEnd bool //for v0
|
||||
|
||||
// udpUnreadPart 不为空,则表示上一次读取没读完整个包(给Read传入的buf太小),须接着读
|
||||
udpUnreadPart []byte //for udp
|
||||
|
||||
bufr *bufio.Reader //for udp
|
||||
isntFirstPacket bool //for v0
|
||||
|
||||
hasAdvancedLayer bool //for v1, 在用ws或grpc时,这个开关保持打开
|
||||
}
|
||||
|
||||
func (uc *UserTCPConn) GetProtocolVersion() int {
|
||||
return uc.version
|
||||
}
|
||||
func (uc *UserTCPConn) GetIdentityStr() string {
|
||||
if uc.convertedUUIDStr == "" {
|
||||
uc.convertedUUIDStr = utils.UUIDToStr(uc.uuid)
|
||||
}
|
||||
|
||||
return uc.convertedUUIDStr
|
||||
}
|
||||
|
||||
//当前连接状态是否可以直接写入底层Conn而不经任何改动/包装
|
||||
func (c *UserTCPConn) canDirectWrite() bool {
|
||||
return c.version == 1 || c.version == 0 && !(c.isServerEnd && !c.isntFirstPacket)
|
||||
}
|
||||
|
||||
func (c *UserTCPConn) EverPossibleToSplice() bool {
|
||||
|
||||
if netLayer.IsBasicConn(c.Conn) {
|
||||
return true
|
||||
}
|
||||
if s, ok := c.Conn.(netLayer.Splicer); ok {
|
||||
return s.EverPossibleToSplice()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *UserTCPConn) CanSplice() (r bool, conn net.Conn) {
|
||||
|
||||
if !c.canDirectWrite() {
|
||||
return
|
||||
}
|
||||
|
||||
if netLayer.IsBasicConn(c.Conn) {
|
||||
r = true
|
||||
conn = c.Conn
|
||||
|
||||
} else if s, ok := c.Conn.(netLayer.Splicer); ok {
|
||||
r, conn = s.CanSplice()
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (c *UserTCPConn) WriteBuffers(buffers [][]byte) (int64, error) {
|
||||
|
||||
if c.canDirectWrite() {
|
||||
|
||||
//底层连接可以是 ws,或者 tls,或者 基本连接; tls 我们暂不支持 utils.MultiWriter
|
||||
// 理论上tls是可以支持的,但是要我们魔改tls库
|
||||
|
||||
//本作的 ws.Conn 实现了 utils.MultiWriter
|
||||
|
||||
if c.underlayIsBasic {
|
||||
//如果是基本Conn,则不用担心 WriteTo篡改buffers的问题, 因为它会直接调用底层 writev
|
||||
//nb := net.Buffers(buffers)
|
||||
//return nb.WriteTo(c.Conn) //发现它还是会篡改??什么鬼
|
||||
return utils.BuffersWriteTo(buffers, c.Conn)
|
||||
|
||||
} else if mr, ok := c.Conn.(utils.MultiWriter); ok {
|
||||
return mr.WriteBuffers(buffers)
|
||||
}
|
||||
}
|
||||
|
||||
bigbs, dup := utils.MergeBuffers(buffers)
|
||||
n, e := c.Write(bigbs)
|
||||
if dup {
|
||||
utils.PutPacket(bigbs)
|
||||
}
|
||||
return int64(n), e
|
||||
|
||||
}
|
||||
|
||||
//专门适用于 裸奔splice的情况
|
||||
func (uc *UserTCPConn) ReadFrom(r io.Reader) (written int64, err error) {
|
||||
|
||||
return netLayer.TryReadFrom_withSplice(uc, uc.Conn, r, uc.canDirectWrite)
|
||||
}
|
||||
|
||||
//如果是udp,则是多线程不安全的,如果是tcp,则安不安全看底层的链接。
|
||||
// 这里规定,如果是UDP,则 每Write一遍,都要Write一个 完整的UDP 数据包
|
||||
func (uc *UserTCPConn) Write(p []byte) (int, error) {
|
||||
|
||||
if uc.version == 0 {
|
||||
|
||||
originalSupposedWrittenLenth := len(p)
|
||||
|
||||
var writeBuf *bytes.Buffer
|
||||
|
||||
if uc.isServerEnd && !uc.isntFirstPacket {
|
||||
uc.isntFirstPacket = true
|
||||
|
||||
writeBuf = utils.GetBuf()
|
||||
|
||||
//v0 中,服务端的回复的第一个包也是要有数据头的(和客户端的handshake类似,只是第一个包有),第一字节版本,第二字节addon长度(都是0)
|
||||
|
||||
writeBuf.WriteByte(0)
|
||||
writeBuf.WriteByte(0)
|
||||
|
||||
}
|
||||
|
||||
if writeBuf != nil {
|
||||
writeBuf.Write(p)
|
||||
|
||||
_, err := uc.Conn.Write(writeBuf.Bytes()) //“直接return这个的长度” 是错的,因为写入长度只能小于等于len(p)
|
||||
|
||||
utils.PutBuf(writeBuf)
|
||||
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return originalSupposedWrittenLenth, nil
|
||||
|
||||
} else {
|
||||
_, err := uc.Conn.Write(p) //“直接return这个的长度” 是错的,因为写入长度只能小于等于len(p)
|
||||
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return originalSupposedWrittenLenth, nil
|
||||
}
|
||||
|
||||
} else {
|
||||
/*
|
||||
if uc.isUDP && !uc.hasAdvancedLayer {
|
||||
|
||||
// 这里暂时认为包裹它的连接是 tcp或者tls,而不是udp,如果udp的话,就不需要考虑粘包问题了,比如socks5的实现
|
||||
// 我们目前认为只有tls是最防墙的,而且 魔改tls是有毒的,所以反推过来,这里udp就必须加长度头。
|
||||
|
||||
// 目前是这个样子。之后verysimple实现了websocket和grpc后,会添加判断,如果连接是websocket或者grpc连接,则不再加长度头
|
||||
|
||||
// tls和tcp都是基于流的,可以分开写两次,不需要buf存在;如果连接是websocket或者grpc的话,直接传输。
|
||||
|
||||
l := int16(len(p))
|
||||
var lenBytes []byte
|
||||
|
||||
if l <= 255 {
|
||||
lenBytes = []byte{0, byte(l)}
|
||||
}
|
||||
|
||||
lenBytes = []byte{byte(l >> 8), byte(l << 8 >> 8)}
|
||||
|
||||
_, err := uc.Conn.Write(lenBytes)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return uc.Conn.Write(p)
|
||||
|
||||
}
|
||||
*/
|
||||
return uc.Conn.Write(p)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//如果是udp,则是多线程不安全的,如果是tcp,则安不安全看底层的链接。
|
||||
// 这里规定,如果是UDP,则 每次 Read 得到的都是一个 完整的UDP 数据包,除非p给的太小……
|
||||
func (uc *UserTCPConn) Read(p []byte) (int, error) {
|
||||
|
||||
var from io.Reader = uc.Conn
|
||||
if uc.optionalReader != nil {
|
||||
from = uc.optionalReader
|
||||
}
|
||||
|
||||
if uc.version == 0 {
|
||||
|
||||
if !uc.isServerEnd && !uc.isntFirstPacket {
|
||||
//先读取响应头
|
||||
|
||||
uc.isntFirstPacket = true
|
||||
|
||||
bs := utils.GetPacket()
|
||||
n, e := from.Read(bs)
|
||||
|
||||
if e != nil {
|
||||
utils.PutPacket(bs)
|
||||
return 0, e
|
||||
}
|
||||
|
||||
if n < 2 {
|
||||
utils.PutPacket(bs)
|
||||
return 0, errors.New("vless response head too short")
|
||||
}
|
||||
n = copy(p, bs[2:n])
|
||||
utils.PutPacket(bs)
|
||||
return n, nil
|
||||
|
||||
}
|
||||
|
||||
return from.Read(p)
|
||||
|
||||
} else {
|
||||
/*
|
||||
if uc.isUDP && !uc.hasAdvancedLayer {
|
||||
|
||||
if len(uc.udpUnreadPart) > 0 {
|
||||
copiedN := copy(p, uc.udpUnreadPart)
|
||||
if copiedN < len(uc.udpUnreadPart) {
|
||||
uc.udpUnreadPart = uc.udpUnreadPart[copiedN:]
|
||||
} else {
|
||||
uc.udpUnreadPart = nil
|
||||
}
|
||||
return copiedN, nil
|
||||
}
|
||||
|
||||
return uc.readudp_withLenthHead(p)
|
||||
}*/
|
||||
return from.Read(p)
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
package vless
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
"net"
|
||||
|
||||
"github.com/hahahrfool/v2ray_simple/netLayer"
|
||||
"github.com/hahahrfool/v2ray_simple/utils"
|
||||
)
|
||||
|
||||
type UDPConn struct {
|
||||
net.Conn
|
||||
optionalReader io.Reader
|
||||
|
||||
remainFirstBufLen int
|
||||
|
||||
version int
|
||||
isClientEnd bool
|
||||
|
||||
bufr *bufio.Reader
|
||||
|
||||
notFirst bool //for v0
|
||||
raddr netLayer.Addr
|
||||
}
|
||||
|
||||
func (u *UDPConn) WriteTo(p []byte, raddr netLayer.Addr) error {
|
||||
|
||||
//v0很垃圾,不支持fullcone,无视raddr,始终向最开始的raddr发送。
|
||||
if u.version == 0 {
|
||||
writeBuf := utils.GetBuf()
|
||||
|
||||
if !u.isClientEnd && !u.notFirst {
|
||||
u.notFirst = true
|
||||
|
||||
//v0 中,服务端的回复的第一个包也是要有数据头的(和客户端的handshake类似,只是第一个包有),第一字节版本,第二字节addon长度(都是0)
|
||||
|
||||
writeBuf.WriteByte(0)
|
||||
writeBuf.WriteByte(0)
|
||||
|
||||
}
|
||||
|
||||
l := int16(len(p))
|
||||
|
||||
writeBuf.WriteByte(byte(l >> 8))
|
||||
writeBuf.WriteByte(byte(l << 8 >> 8))
|
||||
|
||||
writeBuf.Write(p)
|
||||
|
||||
_, err := u.Conn.Write(writeBuf.Bytes()) //“直接return这个的长度” 是错的,因为写入长度只能小于等于len(p)
|
||||
|
||||
utils.PutBuf(writeBuf)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
//从 客户端读取 udp请求
|
||||
func (u *UDPConn) ReadFrom() ([]byte, netLayer.Addr, error) {
|
||||
|
||||
var from io.Reader = u.Conn
|
||||
if u.optionalReader != nil {
|
||||
from = u.optionalReader
|
||||
}
|
||||
|
||||
if u.version == 0 {
|
||||
|
||||
if u.isClientEnd {
|
||||
if !u.notFirst {
|
||||
u.notFirst = true
|
||||
u.bufr = bufio.NewReader(from)
|
||||
|
||||
_, err := u.bufr.ReadByte() //version byte
|
||||
if err != nil {
|
||||
return nil, netLayer.Addr{}, err
|
||||
}
|
||||
|
||||
_, err = u.bufr.ReadByte() //addon len byte
|
||||
if err != nil {
|
||||
return nil, netLayer.Addr{}, err
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
if u.bufr == nil {
|
||||
u.bufr = bufio.NewReader(from)
|
||||
|
||||
}
|
||||
}
|
||||
bs, err := u.read_with_v0_Head()
|
||||
return bs, u.raddr, err
|
||||
} else {
|
||||
|
||||
}
|
||||
return nil, netLayer.Addr{}, nil
|
||||
}
|
||||
|
||||
func (uc *UDPConn) read_with_v0_Head() ([]byte, error) {
|
||||
|
||||
b1, err := uc.bufr.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b2, err := uc.bufr.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
l := int(int16(b1)<<8 + int16(b2))
|
||||
|
||||
bs := utils.GetBytes(l)
|
||||
n, err := io.ReadFull(uc.bufr, bs)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return bs[:n], nil
|
||||
|
||||
}
|
||||
@@ -1,345 +0,0 @@
|
||||
package vless
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
|
||||
"github.com/hahahrfool/v2ray_simple/netLayer"
|
||||
"github.com/hahahrfool/v2ray_simple/utils"
|
||||
)
|
||||
|
||||
//实现 net.Conn, io.ReaderFrom, utils.MultiWriter, netLayer.Splicer
|
||||
type UserConn struct {
|
||||
net.Conn
|
||||
optionalReader io.Reader //在使用了缓存读取握手包头后,就产生了buffer中有剩余数据的可能性,此时就要使用MultiReader
|
||||
|
||||
remainFirstBufLen int //记录读取握手包头时读到的buf的长度. 如果我们读超过了这个部分的话,实际上我们就可以不再使用 optionalReader 读取, 而是直接从Conn读取
|
||||
|
||||
underlayIsBasic bool
|
||||
|
||||
uuid [16]byte
|
||||
convertedUUIDStr string
|
||||
version int
|
||||
isUDP bool
|
||||
isServerEnd bool //for v0
|
||||
|
||||
// udpUnreadPart 不为空,则表示上一次读取没读完整个包(给Read传入的buf太小),须接着读
|
||||
udpUnreadPart []byte //for udp
|
||||
|
||||
bufr *bufio.Reader //for udp
|
||||
isntFirstPacket bool //for v0
|
||||
|
||||
hasAdvancedLayer bool //for v1, 在用ws或grpc时,这个开关保持打开
|
||||
}
|
||||
|
||||
func (uc *UserConn) GetProtocolVersion() int {
|
||||
return uc.version
|
||||
}
|
||||
func (uc *UserConn) GetIdentityStr() string {
|
||||
if uc.convertedUUIDStr == "" {
|
||||
uc.convertedUUIDStr = utils.UUIDToStr(uc.uuid)
|
||||
}
|
||||
|
||||
return uc.convertedUUIDStr
|
||||
}
|
||||
|
||||
//当前连接状态是否可以直接写入底层Conn而不经任何改动/包装
|
||||
func (c *UserConn) canDirectWrite() bool {
|
||||
return c.version == 1 && !c.isUDP || c.version == 0 && !(c.isServerEnd && !c.isntFirstPacket)
|
||||
}
|
||||
|
||||
func (c *UserConn) EverPossibleToSplice() bool {
|
||||
if c.isUDP {
|
||||
return false //udp 在底层就是无法splice的,没办法
|
||||
}
|
||||
if netLayer.IsBasicConn(c.Conn) {
|
||||
return true
|
||||
}
|
||||
if s, ok := c.Conn.(netLayer.Splicer); ok {
|
||||
return s.EverPossibleToSplice()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *UserConn) CanSplice() (r bool, conn net.Conn) {
|
||||
|
||||
if c.isUDP {
|
||||
return
|
||||
}
|
||||
|
||||
if !c.canDirectWrite() {
|
||||
return
|
||||
}
|
||||
|
||||
if netLayer.IsBasicConn(c.Conn) {
|
||||
r = true
|
||||
conn = c.Conn
|
||||
|
||||
} else if s, ok := c.Conn.(netLayer.Splicer); ok {
|
||||
r, conn = s.CanSplice()
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (c *UserConn) WriteBuffers(buffers [][]byte) (int64, error) {
|
||||
|
||||
if c.canDirectWrite() {
|
||||
|
||||
//底层连接可以是 ws,或者 tls,或者 基本连接; tls 我们暂不支持 utils.MultiWriter
|
||||
// 理论上tls是可以支持的,但是要我们魔改tls库
|
||||
|
||||
//本作的 ws.Conn 实现了 utils.MultiWriter
|
||||
|
||||
if c.underlayIsBasic {
|
||||
//如果是基本Conn,则不用担心 WriteTo篡改buffers的问题, 因为它会直接调用底层 writev
|
||||
//nb := net.Buffers(buffers)
|
||||
//return nb.WriteTo(c.Conn) //发现它还是会篡改??什么鬼
|
||||
return utils.BuffersWriteTo(buffers, c.Conn)
|
||||
|
||||
} else if mr, ok := c.Conn.(utils.MultiWriter); ok {
|
||||
return mr.WriteBuffers(buffers)
|
||||
}
|
||||
}
|
||||
|
||||
bigbs, dup := utils.MergeBuffers(buffers)
|
||||
n, e := c.Write(bigbs)
|
||||
if dup {
|
||||
utils.PutPacket(bigbs)
|
||||
}
|
||||
return int64(n), e
|
||||
|
||||
}
|
||||
|
||||
//专门适用于 裸奔splice的情况
|
||||
func (uc *UserConn) ReadFrom(r io.Reader) (written int64, err error) {
|
||||
if uc.isUDP {
|
||||
return netLayer.ClassicCopy(uc, r)
|
||||
}
|
||||
return netLayer.TryReadFrom_withSplice(uc, uc.Conn, r, uc.canDirectWrite)
|
||||
}
|
||||
|
||||
//如果是udp,则是多线程不安全的,如果是tcp,则安不安全看底层的链接。
|
||||
// 这里规定,如果是UDP,则 每Write一遍,都要Write一个 完整的UDP 数据包
|
||||
func (uc *UserConn) Write(p []byte) (int, error) {
|
||||
|
||||
if uc.version == 0 {
|
||||
|
||||
originalSupposedWrittenLenth := len(p)
|
||||
|
||||
var writeBuf *bytes.Buffer
|
||||
|
||||
if uc.isServerEnd && !uc.isntFirstPacket {
|
||||
uc.isntFirstPacket = true
|
||||
|
||||
writeBuf = utils.GetBuf()
|
||||
|
||||
//v0 中,服务端的回复的第一个包也是要有数据头的(和客户端的handshake类似,只是第一个包有),第一字节版本,第二字节addon长度(都是0)
|
||||
|
||||
writeBuf.WriteByte(0)
|
||||
writeBuf.WriteByte(0)
|
||||
|
||||
}
|
||||
|
||||
if !uc.isUDP {
|
||||
|
||||
if writeBuf != nil {
|
||||
writeBuf.Write(p)
|
||||
|
||||
_, err := uc.Conn.Write(writeBuf.Bytes()) //“直接return这个的长度” 是错的,因为写入长度只能小于等于len(p)
|
||||
|
||||
utils.PutBuf(writeBuf)
|
||||
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return originalSupposedWrittenLenth, nil
|
||||
|
||||
} else {
|
||||
_, err := uc.Conn.Write(p) //“直接return这个的长度” 是错的,因为写入长度只能小于等于len(p)
|
||||
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return originalSupposedWrittenLenth, nil
|
||||
}
|
||||
|
||||
} else {
|
||||
l := int16(len(p))
|
||||
if writeBuf == nil {
|
||||
writeBuf = utils.GetBuf()
|
||||
}
|
||||
|
||||
writeBuf.WriteByte(byte(l >> 8))
|
||||
writeBuf.WriteByte(byte(l << 8 >> 8))
|
||||
writeBuf.Write(p)
|
||||
|
||||
_, err := uc.Conn.Write(writeBuf.Bytes()) //“直接return这个的长度” 是错的,因为写入长度只能小于等于len(p)
|
||||
|
||||
utils.PutBuf(writeBuf)
|
||||
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return originalSupposedWrittenLenth, nil
|
||||
}
|
||||
|
||||
} else {
|
||||
if uc.isUDP && !uc.hasAdvancedLayer {
|
||||
|
||||
// 这里暂时认为包裹它的连接是 tcp或者tls,而不是udp,如果udp的话,就不需要考虑粘包问题了,比如socks5的实现
|
||||
// 我们目前认为只有tls是最防墙的,而且 魔改tls是有毒的,所以反推过来,这里udp就必须加长度头。
|
||||
|
||||
// 目前是这个样子。之后verysimple实现了websocket和grpc后,会添加判断,如果连接是websocket或者grpc连接,则不再加长度头
|
||||
|
||||
// tls和tcp都是基于流的,可以分开写两次,不需要buf存在;如果连接是websocket或者grpc的话,直接传输。
|
||||
|
||||
l := int16(len(p))
|
||||
var lenBytes []byte
|
||||
|
||||
if l <= 255 {
|
||||
lenBytes = []byte{0, byte(l)}
|
||||
}
|
||||
|
||||
lenBytes = []byte{byte(l >> 8), byte(l << 8 >> 8)}
|
||||
|
||||
_, err := uc.Conn.Write(lenBytes)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return uc.Conn.Write(p)
|
||||
|
||||
}
|
||||
return uc.Conn.Write(p)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//如果是udp,则是多线程不安全的,如果是tcp,则安不安全看底层的链接。
|
||||
// 这里规定,如果是UDP,则 每次 Read 得到的都是一个 完整的UDP 数据包,除非p给的太小……
|
||||
func (uc *UserConn) Read(p []byte) (int, error) {
|
||||
|
||||
var from io.Reader = uc.Conn
|
||||
if uc.optionalReader != nil {
|
||||
from = uc.optionalReader
|
||||
}
|
||||
|
||||
if uc.version == 0 {
|
||||
|
||||
if !uc.isUDP {
|
||||
|
||||
if !uc.isServerEnd && !uc.isntFirstPacket {
|
||||
//先读取响应头
|
||||
|
||||
uc.isntFirstPacket = true
|
||||
|
||||
bs := utils.GetPacket()
|
||||
n, e := from.Read(bs)
|
||||
|
||||
if e != nil {
|
||||
utils.PutPacket(bs)
|
||||
return 0, e
|
||||
}
|
||||
|
||||
if n < 2 {
|
||||
utils.PutPacket(bs)
|
||||
return 0, errors.New("vless response head too short")
|
||||
}
|
||||
n = copy(p, bs[2:n])
|
||||
utils.PutPacket(bs)
|
||||
return n, nil
|
||||
|
||||
}
|
||||
|
||||
return from.Read(p)
|
||||
} else {
|
||||
|
||||
if uc.bufr == nil {
|
||||
uc.bufr = bufio.NewReader(from)
|
||||
}
|
||||
|
||||
if len(uc.udpUnreadPart) > 0 {
|
||||
copiedN := copy(p, uc.udpUnreadPart)
|
||||
if copiedN < len(uc.udpUnreadPart) {
|
||||
uc.udpUnreadPart = uc.udpUnreadPart[copiedN:]
|
||||
} else {
|
||||
uc.udpUnreadPart = nil
|
||||
}
|
||||
return copiedN, nil
|
||||
}
|
||||
|
||||
//v0 先读取vless响应头,再读取udp长度头
|
||||
|
||||
if !uc.isServerEnd && !uc.isntFirstPacket {
|
||||
uc.isntFirstPacket = true
|
||||
|
||||
_, err := uc.bufr.ReadByte() //version byte
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
_, err = uc.bufr.ReadByte() //addon len byte
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return uc.readudp_withLenthHead(p)
|
||||
}
|
||||
|
||||
} else {
|
||||
if uc.isUDP && !uc.hasAdvancedLayer {
|
||||
|
||||
if len(uc.udpUnreadPart) > 0 {
|
||||
copiedN := copy(p, uc.udpUnreadPart)
|
||||
if copiedN < len(uc.udpUnreadPart) {
|
||||
uc.udpUnreadPart = uc.udpUnreadPart[copiedN:]
|
||||
} else {
|
||||
uc.udpUnreadPart = nil
|
||||
}
|
||||
return copiedN, nil
|
||||
}
|
||||
|
||||
return uc.readudp_withLenthHead(p)
|
||||
}
|
||||
return from.Read(p)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func (uc *UserConn) readudp_withLenthHead(p []byte) (int, error) {
|
||||
if uc.bufr == nil {
|
||||
uc.bufr = bufio.NewReader(uc.Conn)
|
||||
}
|
||||
b1, err := uc.bufr.ReadByte()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
b2, err := uc.bufr.ReadByte()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
l := int(int16(b1)<<8 + int16(b2))
|
||||
bs := utils.GetBytes(l)
|
||||
n, err := io.ReadFull(uc.bufr, bs)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
/*// 测试代码
|
||||
if uc.version == 1 {
|
||||
log.Println("read", bs[:n], string(bs[:n]))
|
||||
|
||||
}*/
|
||||
|
||||
copiedN := copy(p, bs)
|
||||
if copiedN < n { //p is short
|
||||
uc.udpUnreadPart = bs[copiedN:]
|
||||
}
|
||||
|
||||
return copiedN, nil
|
||||
}
|
||||
+42
-31
@@ -55,7 +55,7 @@ func testVLess(version int, port string, t *testing.T) {
|
||||
t.Log("vless server got new conn")
|
||||
go func() {
|
||||
defer lc.Close()
|
||||
wlc, targetAddr, err := server.Handshake(lc)
|
||||
wlc, _, targetAddr, err := server.Handshake(lc)
|
||||
if err != nil {
|
||||
t.Logf("failed in handshake form %v: %v", server.AddrStr(), err)
|
||||
t.Fail()
|
||||
@@ -141,6 +141,8 @@ func testVLessUDP(version int, port string, t *testing.T) {
|
||||
|
||||
thePort := netLayer.RandPort()
|
||||
|
||||
t.Log("fake remote udp server port is ", thePort)
|
||||
|
||||
fakeRealUDPServerListener, err := net.ListenUDP("udp4", &net.UDPAddr{
|
||||
IP: net.IPv4(0, 0, 0, 0),
|
||||
Port: thePort,
|
||||
@@ -201,7 +203,7 @@ func testVLessUDP(version int, port string, t *testing.T) {
|
||||
|
||||
targetStr_forFakeUDPServer := "127.0.0.1:" + strconv.Itoa(thePort)
|
||||
targetStruct_forFakeUDPServer := netLayer.Addr{
|
||||
Name: "127.0.0.1",
|
||||
IP: net.IPv4(127, 0, 0, 1),
|
||||
Port: thePort,
|
||||
Network: "udp",
|
||||
}
|
||||
@@ -222,7 +224,7 @@ func testVLessUDP(version int, port string, t *testing.T) {
|
||||
}
|
||||
go func() {
|
||||
defer lc.Close()
|
||||
wlc, targetAddr, err := fakeServerEndLocalServer.Handshake(lc)
|
||||
_, wlc, targetAddr, err := fakeServerEndLocalServer.Handshake(lc)
|
||||
if err != nil {
|
||||
t.Logf("failed in handshake form %v: %v", fakeServerEndLocalServer.AddrStr(), err)
|
||||
t.Fail()
|
||||
@@ -230,13 +232,31 @@ func testVLessUDP(version int, port string, t *testing.T) {
|
||||
}
|
||||
|
||||
remoteAddrStr := targetAddr.String()
|
||||
t.Log("vless server got new wlc", remoteAddrStr)
|
||||
|
||||
if remoteAddrStr != targetStr_forFakeUDPServer || targetAddr.Network != "udp" {
|
||||
t.Log("remoteAddrStr != targetStr_forFakeUDPServer || targetAddr.IsUDP == false ")
|
||||
t.Log("remoteAddrStr != targetStr_forFakeUDPServer || targetAddr.IsUDP == false ", remoteAddrStr, targetStr_forFakeUDPServer, targetAddr.Network)
|
||||
t.Fail()
|
||||
return
|
||||
}
|
||||
|
||||
//这里的测试是,第一个发来的包必须是 hello,然后传递到目标udp服务器中
|
||||
|
||||
//发现既可能读取 firstbuf,也可能读取 wlc,随机发生?
|
||||
|
||||
t.Log("vless read from wlc")
|
||||
bs, raddr, _ := wlc.ReadFrom()
|
||||
|
||||
t.Log("vless got wlc", bs)
|
||||
|
||||
if !bytes.Equal(bs, hellodata) {
|
||||
t.Log("!bytes.Equal(hello[:], hellodata)")
|
||||
t.Fail()
|
||||
return
|
||||
}
|
||||
|
||||
t.Log("vless got wlc with right hello data")
|
||||
|
||||
rc, err := net.Dial("udp", remoteAddrStr)
|
||||
if err != nil {
|
||||
t.Logf("failed to connect FakeUDPServer : %v", err)
|
||||
@@ -244,33 +264,27 @@ func testVLessUDP(version int, port string, t *testing.T) {
|
||||
return
|
||||
}
|
||||
|
||||
//这里的测试是,第一个发来的包必须是 hello,然后传递到目标udp服务器中
|
||||
t.Log("vless server dialed remote udp server", remoteAddrStr)
|
||||
|
||||
var hello [5]byte
|
||||
//发现既可能读取 firstbuf,也可能读取 wlc,随机发生?
|
||||
na, _ := netLayer.NewAddr(remoteAddrStr)
|
||||
na.Network = "udp"
|
||||
|
||||
t.Log("read from wlc")
|
||||
io.ReadFull(wlc, hello[:])
|
||||
wrc := &netLayer.UDPMsgConnWrapper{UDPConn: rc.(*net.UDPConn), IsClient: true, FirstAddr: na}
|
||||
|
||||
if !bytes.Equal(hello[:], hellodata) {
|
||||
t.Log("!bytes.Equal(hello[:], hellodata)")
|
||||
t.Fail()
|
||||
return
|
||||
}
|
||||
_, err = rc.Write(hello[:])
|
||||
_, err = rc.Write(bs)
|
||||
if err != nil {
|
||||
t.Logf("failed to write to FakeUDPServer : %v", err)
|
||||
t.Fail()
|
||||
return
|
||||
}
|
||||
_, err = io.ReadFull(rc, hello[:])
|
||||
_, err = io.ReadFull(rc, bs)
|
||||
if err != nil {
|
||||
t.Logf("failed io.ReadFull(rc, hello[:]) : %v", err)
|
||||
t.Fail()
|
||||
return
|
||||
}
|
||||
|
||||
_, err = wlc.Write(hello[:])
|
||||
err = wlc.WriteTo(bs, raddr)
|
||||
if err != nil {
|
||||
t.Logf("failed wlc.Write(hello[:]) : %v", err)
|
||||
t.Fail()
|
||||
@@ -278,8 +292,7 @@ func testVLessUDP(version int, port string, t *testing.T) {
|
||||
}
|
||||
|
||||
// 之后转发所有流量,不再特定限制数据
|
||||
go io.Copy(rc, wlc)
|
||||
_, err = io.Copy(wlc, rc)
|
||||
netLayer.RelayUDP(wlc, wrc)
|
||||
|
||||
t.Log("Copy End?!", err)
|
||||
}()
|
||||
@@ -292,7 +305,7 @@ func testVLessUDP(version int, port string, t *testing.T) {
|
||||
|
||||
t.Log("client Dial success")
|
||||
|
||||
wrc, err := fakeClientEndRemoteClient.Handshake(rc, targetStruct_forFakeUDPServer)
|
||||
wrc, err := fakeClientEndRemoteClient.EstablishUDPChannel(rc, targetStruct_forFakeUDPServer)
|
||||
if err != nil {
|
||||
log.Printf("failed in handshake to %v: %v", fakeServerEndLocalServer.AddrStr(), err)
|
||||
t.FailNow()
|
||||
@@ -300,7 +313,7 @@ func testVLessUDP(version int, port string, t *testing.T) {
|
||||
|
||||
t.Log("client vless handshake success")
|
||||
|
||||
_, err = wrc.Write(hellodata)
|
||||
err = wrc.WriteTo(hellodata, targetStruct_forFakeUDPServer)
|
||||
if err != nil {
|
||||
t.Log("failed in write to ", fakeServerEndLocalServer.AddrStr(), err)
|
||||
t.FailNow()
|
||||
@@ -308,10 +321,9 @@ func testVLessUDP(version int, port string, t *testing.T) {
|
||||
|
||||
t.Log("client write hello success")
|
||||
|
||||
var world [5]byte
|
||||
io.ReadFull(wrc, world[:])
|
||||
if !bytes.Equal(world[:], replydata) {
|
||||
t.Log("!bytes.Equal(world[:], replydata) ", world[:], replydata)
|
||||
bs, _, _ := wrc.ReadFrom()
|
||||
if !bytes.Equal(bs, replydata) {
|
||||
t.Log("!bytes.Equal(world[:], replydata) ", bs, replydata)
|
||||
t.FailNow()
|
||||
}
|
||||
t.Log("读到正确reply!")
|
||||
@@ -330,7 +342,7 @@ func testVLessUDP(version int, port string, t *testing.T) {
|
||||
|
||||
t.Log("rand generated", len(longbs))
|
||||
|
||||
_, err = wrc.Write(longbs)
|
||||
err = wrc.WriteTo(longbs, targetStruct_forFakeUDPServer)
|
||||
if err != nil {
|
||||
t.Log("failed in write long data to ", fakeServerEndLocalServer.AddrStr(), err)
|
||||
t.FailNow()
|
||||
@@ -338,17 +350,16 @@ func testVLessUDP(version int, port string, t *testing.T) {
|
||||
|
||||
t.Log("data written")
|
||||
|
||||
var world [5]byte
|
||||
n, err := io.ReadFull(wrc, world[:])
|
||||
bs, _, _ := wrc.ReadFrom()
|
||||
if err != nil {
|
||||
t.Log("ReadFull err ", n, err)
|
||||
t.Log("ReadFull err ", err)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
t.Log("data read complete")
|
||||
|
||||
if !bytes.Equal(world[:], replydata) {
|
||||
t.Log("reply not equal ", string(replydata), string(world[:]))
|
||||
if !bytes.Equal(bs, replydata) {
|
||||
t.Log("reply not equal ", string(replydata), string(bs))
|
||||
t.FailNow()
|
||||
}
|
||||
t.Log("compare success")
|
||||
|
||||
@@ -73,7 +73,7 @@ func testTls(protocol string, port string, t *testing.T) {
|
||||
|
||||
t.Log("server pass tls handshake")
|
||||
|
||||
wlc, targetAddr, err := server.Handshake(lc)
|
||||
wlc, _, targetAddr, err := server.Handshake(lc)
|
||||
if err != nil {
|
||||
t.Log("failed in handshake from ", server.AddrStr(), err)
|
||||
t.Fail()
|
||||
|
||||
+1
-1
@@ -83,7 +83,7 @@ func tryTlsLazyRawCopy(useSecureMethod bool, proxy_client proxy.UserClient, prox
|
||||
// 不过实际上客户端 wrc 是 vless的 UserConn, 而UserConn的底层连接才是TLS
|
||||
// 很明显,目前我们只支持vless所以才可这么操作,以后再说。
|
||||
|
||||
wrcVless := wrc.(*vless.UserConn)
|
||||
wrcVless := wrc.(*vless.UserTCPConn)
|
||||
tlsConn := wrcVless.Conn.(*tlsLayer.Conn)
|
||||
rawWRC = tlsConn.GetRaw(tls_lazy_encrypt)
|
||||
|
||||
|
||||
@@ -2,10 +2,13 @@ package utils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
var ErrNotImplemented = errors.New("not implemented")
|
||||
|
||||
//没啥特殊的
|
||||
type NumErr struct {
|
||||
N int
|
||||
|
||||
Reference in New Issue
Block a user