diff --git a/README.md b/README.md index fca4305..8dd6d73 100644 --- a/README.md +++ b/README.md @@ -145,7 +145,7 @@ SSR scheme: ssr://method:pass@host:port?protocol=xxx&protocol_param=yyy&obfs=zzz&obfs_param=xyz VMess scheme: - vmess://uuid[:method]@host:port?alterID=num + vmess://[security:]uuid@host:port?alterID=num Available methods for vmess: NONE, (will add aes-128-gcm and chacha20-poly1305 later) diff --git a/conf.go b/conf.go index e31a5b7..7772c2a 100644 --- a/conf.go +++ b/conf.go @@ -168,7 +168,7 @@ func usage() { fmt.Fprintf(os.Stderr, "\n") fmt.Fprintf(os.Stderr, "VMess scheme:\n") - fmt.Fprintf(os.Stderr, " vmess://uuid[:method]@host:port?alterID=num\n") + fmt.Fprintf(os.Stderr, " vmess://[security:]uuid@host:port?alterID=num\n") fmt.Fprintf(os.Stderr, "\n") fmt.Fprintf(os.Stderr, "Available methods for vmess:\n") diff --git a/proxy/vmess/client.go b/proxy/vmess/client.go index 4043f4e..251df63 100644 --- a/proxy/vmess/client.go +++ b/proxy/vmess/client.go @@ -12,6 +12,7 @@ import ( "io" "math/rand" "net" + "strings" "time" ) @@ -22,14 +23,14 @@ const ( OptMetadataObfuscate byte = 4 ) -// SEC types +// Security types const ( - SecTypeUnknown byte = 0 // don't use in client - SecTypeLegacy byte = 1 // don't use in client (aes-128-cfb) - SecTypeAuto byte = 2 // don't use in client - SecTypeAES128GCM byte = 3 - SecTypeChacha20Poly1305 byte = 4 - SecTypeNone byte = 5 + SecurityUnknown byte = 0 // don't use in client + SecurityLegacy byte = 1 // don't use in client (aes-128-cfb) + SecurityAuto byte = 2 // don't use in client + SecurityAES128GCM byte = 3 + SecurityChacha20Poly1305 byte = 4 + SecurityNone byte = 5 ) // CMD types @@ -40,13 +41,15 @@ const ( // Client vmess client type Client struct { - users []*User - count int + users []*User + count int + security byte } // Conn is a connection to vmess server type Conn struct { - user *User + user *User + security byte atype AType addr Addr @@ -63,7 +66,7 @@ type Conn struct { } // NewClient . -func NewClient(uuidStr string, alterID int) (*Client, error) { +func NewClient(uuidStr, security string, alterID int) (*Client, error) { uuid, err := StrToUUID(uuidStr) if err != nil { return nil, err @@ -75,13 +78,25 @@ func NewClient(uuidStr string, alterID int) (*Client, error) { c.users = append(c.users, user.GenAlterIDUsers(alterID)...) c.count = len(c.users) + security = strings.ToLower(security) + switch security { + case "aes-128-cfb": + c.security = SecurityLegacy + case "aes-128-gcm": + c.security = SecurityAES128GCM + case "chacha20-poly1305": + c.security = SecurityChacha20Poly1305 + default: + c.security = SecurityNone + } + return c, nil } // NewConn . func (c *Client) NewConn(rc net.Conn, target string) (*Conn, error) { r := rand.Intn(c.count) - conn := &Conn{user: c.users[r]} + conn := &Conn{user: c.users[r], security: c.security} var err error conn.atype, conn.addr, conn.port, err = ParseAddr(target) @@ -138,7 +153,7 @@ func (c *Conn) EncodeRequest() ([]byte, error) { // pLen and Sec paddingLen := rand.Intn(16) - pSec := byte(paddingLen<<4) | SecTypeNone // P(4bit) and Sec(4bit) + pSec := byte(paddingLen<<4) | c.security // P(4bit) and Sec(4bit) buf.WriteByte(pSec) buf.WriteByte(0) // reserved @@ -203,6 +218,7 @@ func (c *Conn) Read(b []byte) (n int, err error) { if !c.connected { c.DecodeRespHeader() } + return c.Conn.Read(b) } diff --git a/proxy/vmess/vmess.go b/proxy/vmess/vmess.go index bb22d46..6e85886 100644 --- a/proxy/vmess/vmess.go +++ b/proxy/vmess/vmess.go @@ -27,6 +27,7 @@ func init() { } // NewVMess returns a vmess proxy. +// vmess://security:uuid@host:port?alertID=num func NewVMess(s string, dialer proxy.Dialer) (*VMess, error) { u, err := url.Parse(s) if err != nil { @@ -36,14 +37,16 @@ func NewVMess(s string, dialer proxy.Dialer) (*VMess, error) { addr := u.Host - var uuid, security string + var security, uuid string if u.User != nil { - uuid = u.User.Username() - security, _ = u.User.Password() + security = u.User.Username() } - if security == "" { - security = "NONE" + uuid, ok := u.User.Password() + if !ok { + // vmess://uuid@host:port?alertID=num, no security specified + uuid = security + security = "" } query := u.Query() @@ -55,7 +58,7 @@ func NewVMess(s string, dialer proxy.Dialer) (*VMess, error) { return nil, err } - client, err := NewClient(uuid, int(alterID)) + client, err := NewClient(uuid, security, int(alterID)) if err != nil { log.F("create vmess client err: %s", err) return nil, err