mirror of
https://github.com/nadoo/glider.git
synced 2025-02-23 09:25:41 +08:00
vmess: support alterID
This commit is contained in:
parent
14cded4665
commit
f6fae13d88
@ -40,7 +40,14 @@ const (
|
||||
|
||||
// Client vmess client
|
||||
type Client struct {
|
||||
user *User
|
||||
users []*User
|
||||
count int
|
||||
}
|
||||
|
||||
// Conn is a connection to vmess server
|
||||
type Conn struct {
|
||||
user *User
|
||||
|
||||
atype AType
|
||||
addr Addr
|
||||
port Port
|
||||
@ -56,15 +63,28 @@ type Client struct {
|
||||
}
|
||||
|
||||
// NewClient .
|
||||
func NewClient(uuid, target string) (*Client, error) {
|
||||
user, err := NewUser(uuid)
|
||||
func NewClient(uuidStr string, alterID int) (*Client, error) {
|
||||
uuid, err := StrToUUID(uuidStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c := &Client{user: user}
|
||||
c := &Client{}
|
||||
user := NewUser(uuid)
|
||||
c.users = append(c.users, user)
|
||||
c.users = append(c.users, user.GenAlterIDUsers(alterID)...)
|
||||
c.count = len(c.users)
|
||||
|
||||
c.atype, c.addr, c.port, err = ParseAddr(target)
|
||||
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]}
|
||||
|
||||
var err error
|
||||
conn.atype, conn.addr, conn.port, err = ParseAddr(target)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -72,18 +92,30 @@ func NewClient(uuid, target string) (*Client, error) {
|
||||
randBytes := make([]byte, 33)
|
||||
rand.Read(randBytes)
|
||||
|
||||
copy(c.reqBodyIV[:], randBytes[:16])
|
||||
copy(c.reqBodyKey[:], randBytes[16:32])
|
||||
c.reqRespV = randBytes[32]
|
||||
copy(conn.reqBodyIV[:], randBytes[:16])
|
||||
copy(conn.reqBodyKey[:], randBytes[16:32])
|
||||
conn.reqRespV = randBytes[32]
|
||||
|
||||
c.respBodyIV = md5.Sum(c.reqBodyIV[:])
|
||||
c.respBodyKey = md5.Sum(c.reqBodyKey[:])
|
||||
conn.respBodyIV = md5.Sum(conn.reqBodyIV[:])
|
||||
conn.respBodyKey = md5.Sum(conn.reqBodyKey[:])
|
||||
|
||||
return c, nil
|
||||
// AuthInfo
|
||||
rc.Write(conn.EncodeAuthInfo())
|
||||
|
||||
// Request
|
||||
req, err := conn.EncodeRequest()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rc.Write(req)
|
||||
|
||||
conn.Conn = rc
|
||||
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
// EncodeAuthInfo returns HMAC("md5", UUID, UTC) result
|
||||
func (c *Client) EncodeAuthInfo() []byte {
|
||||
func (c *Conn) EncodeAuthInfo() []byte {
|
||||
ts := make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(ts, uint64(time.Now().UTC().Unix()))
|
||||
|
||||
@ -94,7 +126,7 @@ func (c *Client) EncodeAuthInfo() []byte {
|
||||
}
|
||||
|
||||
// EncodeRequest encodes requests to network bytes
|
||||
func (c *Client) EncodeRequest() ([]byte, error) {
|
||||
func (c *Conn) EncodeRequest() ([]byte, error) {
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
// Request
|
||||
@ -141,7 +173,7 @@ func (c *Client) EncodeRequest() ([]byte, error) {
|
||||
}
|
||||
|
||||
// DecodeRespHeader .
|
||||
func (c *Client) DecodeRespHeader() error {
|
||||
func (c *Conn) DecodeRespHeader() error {
|
||||
block, err := aes.NewCipher(c.respBodyKey[:])
|
||||
if err != nil {
|
||||
return err
|
||||
@ -167,24 +199,7 @@ func (c *Client) DecodeRespHeader() error {
|
||||
|
||||
}
|
||||
|
||||
// NewConn wraps a net.Conn to VMessConn
|
||||
func (c *Client) NewConn(rc net.Conn) (net.Conn, error) {
|
||||
// AuthInfo
|
||||
rc.Write(c.EncodeAuthInfo())
|
||||
|
||||
// Request
|
||||
req, err := c.EncodeRequest()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rc.Write(req)
|
||||
|
||||
c.Conn = rc
|
||||
|
||||
return c, err
|
||||
}
|
||||
|
||||
func (c *Client) Read(b []byte) (n int, err error) {
|
||||
func (c *Conn) Read(b []byte) (n int, err error) {
|
||||
if !c.connected {
|
||||
c.DecodeRespHeader()
|
||||
}
|
||||
@ -192,6 +207,6 @@ func (c *Client) Read(b []byte) (n int, err error) {
|
||||
return c.Conn.Read(b)
|
||||
}
|
||||
|
||||
func (c *Client) Write(b []byte) (n int, err error) {
|
||||
func (c *Conn) Write(b []byte) (n int, err error) {
|
||||
return c.Conn.Write(b)
|
||||
}
|
||||
|
@ -1,12 +1,15 @@
|
||||
package vmess
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/nadoo/glider/common/log"
|
||||
)
|
||||
|
||||
// User of vmess client
|
||||
@ -16,16 +19,38 @@ type User struct {
|
||||
}
|
||||
|
||||
// NewUser .
|
||||
func NewUser(uuidStr string) (*User, error) {
|
||||
uuid, err := StrToUUID(uuidStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func NewUser(uuid [16]byte) *User {
|
||||
u := &User{UUID: uuid}
|
||||
copy(u.CmdKey[:], GetKey(uuid))
|
||||
return u
|
||||
}
|
||||
|
||||
return u, nil
|
||||
func nextID(oldID [16]byte) (newID [16]byte) {
|
||||
md5hash := md5.New()
|
||||
md5hash.Write(oldID[:])
|
||||
md5hash.Write([]byte("16167dc8-16b6-4e6d-b8bb-65dd68113a81"))
|
||||
for {
|
||||
md5hash.Sum(newID[:0])
|
||||
if !bytes.Equal(oldID[:], newID[:]) {
|
||||
log.F("oldID: %x, newID: %x", oldID, newID)
|
||||
return
|
||||
}
|
||||
md5hash.Write([]byte("533eff8a-4113-4b10-b5ce-0f5d76b98cd2"))
|
||||
}
|
||||
}
|
||||
|
||||
// GenAlterIDUsers generates users according to primary user's id and alterID
|
||||
func (u *User) GenAlterIDUsers(alterID int) []*User {
|
||||
users := make([]*User, alterID)
|
||||
preID := u.UUID
|
||||
for i := 0; i < alterID; i++ {
|
||||
newID := nextID(preID)
|
||||
// NOTE: alterID user is a user which have a different uuid but a same cmdkey with the primary user.
|
||||
users[i] = &User{UUID: newID, CmdKey: u.CmdKey}
|
||||
preID = newID
|
||||
}
|
||||
|
||||
return users
|
||||
}
|
||||
|
||||
// StrToUUID converts string to uuid.
|
||||
|
@ -16,8 +16,10 @@ type VMess struct {
|
||||
addr string
|
||||
|
||||
uuid string
|
||||
alertID uint32
|
||||
alterID int
|
||||
security string
|
||||
|
||||
client *Client
|
||||
}
|
||||
|
||||
func init() {
|
||||
@ -46,13 +48,19 @@ func NewVMess(s string, dialer proxy.Dialer) (*VMess, error) {
|
||||
|
||||
aid := "0"
|
||||
params, _ := url.ParseQuery(u.RawQuery)
|
||||
if v, ok := params["alertId"]; ok {
|
||||
if v, ok := params["alterID"]; ok {
|
||||
aid = v[0]
|
||||
}
|
||||
|
||||
alertID, err := strconv.ParseUint(aid, 10, 32)
|
||||
alterID, err := strconv.ParseUint(aid, 10, 32)
|
||||
if err != nil {
|
||||
log.F("parse alertID err: %s", err)
|
||||
log.F("parse alterID err: %s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client, err := NewClient(uuid, int(alterID))
|
||||
if err != nil {
|
||||
log.F("create vmess client err: %s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -60,8 +68,9 @@ func NewVMess(s string, dialer proxy.Dialer) (*VMess, error) {
|
||||
dialer: dialer,
|
||||
addr: addr,
|
||||
uuid: uuid,
|
||||
alertID: uint32(alertID),
|
||||
alterID: int(alterID),
|
||||
security: security,
|
||||
client: client,
|
||||
}
|
||||
|
||||
return p, nil
|
||||
@ -85,12 +94,7 @@ func (s *VMess) Dial(network, addr string) (net.Conn, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client, err := NewClient(s.uuid, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return client.NewConn(rc)
|
||||
return s.client.NewConn(rc, addr)
|
||||
}
|
||||
|
||||
// DialUDP connects to the given address via the proxy.
|
||||
|
Loading…
Reference in New Issue
Block a user