feat(vmess): support forward/udp (#199)

This commit is contained in:
mzz 2020-12-03 15:27:52 +08:00 committed by GitHub
parent 2db84bb7aa
commit 1b484cca8f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 41 additions and 9 deletions

View File

@ -35,9 +35,11 @@ const (
) )
// CMD types // CMD types
type CmdType byte
const ( const (
CmdTCP byte = 1 CmdTCP CmdType = 1
CmdUDP byte = 2 CmdUDP CmdType = 2
) )
// Client is a vmess client. // Client is a vmess client.
@ -107,7 +109,7 @@ func NewClient(uuidStr, security string, alterID int) (*Client, error) {
} }
// NewConn returns a new vmess conn. // NewConn returns a new vmess conn.
func (c *Client) NewConn(rc net.Conn, target string) (*Conn, error) { func (c *Client) NewConn(rc net.Conn, target string, cmd CmdType) (*Conn, error) {
r := rand.Intn(c.count) r := rand.Intn(c.count)
conn := &Conn{user: c.users[r], opt: c.opt, security: c.security, Conn: rc} conn := &Conn{user: c.users[r], opt: c.opt, security: c.security, Conn: rc}
@ -135,7 +137,7 @@ func (c *Client) NewConn(rc net.Conn, target string) (*Conn, error) {
} }
// Request // Request
err = conn.Request() err = conn.Request(cmd)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -158,7 +160,7 @@ func (c *Conn) Auth() error {
} }
// Request sends request to server. // Request sends request to server.
func (c *Conn) Request() error { func (c *Conn) Request(cmd CmdType) error {
buf := pool.GetBytesBuffer() buf := pool.GetBytesBuffer()
defer pool.PutBytesBuffer(buf) defer pool.PutBytesBuffer(buf)
@ -175,7 +177,7 @@ func (c *Conn) Request() error {
buf.WriteByte(pSec) buf.WriteByte(pSec)
buf.WriteByte(0) // reserved buf.WriteByte(0) // reserved
buf.WriteByte(CmdTCP) // cmd buf.WriteByte(byte(cmd)) // cmd
// target // target
err := binary.Write(buf, binary.BigEndian, uint16(c.port)) // port err := binary.Write(buf, binary.BigEndian, uint16(c.port)) // port

22
proxy/vmess/packet.go Normal file
View File

@ -0,0 +1,22 @@
package vmess
import (
"net"
)
// PktConn is a udp Packet.Conn.
type PktConn struct{ net.Conn }
// NewPktConn returns a PktConn.
func NewPktConn(c net.Conn) *PktConn { return &PktConn{Conn: c} }
// ReadFrom implements the necessary function of net.PacketConn.
func (pc *PktConn) ReadFrom(b []byte) (int, net.Addr, error) {
n, err := pc.Read(b)
return n, nil, err
}
// WriteTo implements the necessary function of net.PacketConn.
func (pc *PktConn) WriteTo(b []byte, addr net.Addr) (int, error) {
return pc.Write(b)
}

View File

@ -92,10 +92,18 @@ func (s *VMess) Dial(network, addr string) (net.Conn, error) {
return nil, err return nil, err
} }
return s.client.NewConn(rc, addr) return s.client.NewConn(rc, addr, CmdTCP)
} }
// DialUDP connects to the given address via the proxy. // DialUDP connects to the given address via the proxy.
func (s *VMess) DialUDP(network, addr string) (net.PacketConn, net.Addr, error) { func (s *VMess) DialUDP(network, addr string) (net.PacketConn, net.Addr, error) {
return nil, nil, proxy.ErrNotSupported rc, err := s.dialer.Dial("tcp", s.addr)
if err != nil {
return nil, nil, err
}
rc, err = s.client.NewConn(rc, addr, CmdUDP)
if err != nil {
return nil, nil, err
}
return NewPktConn(rc), nil, err
} }