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