vmess.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. package vmess
  2. import (
  3. "fmt"
  4. "net"
  5. "runtime"
  6. "github.com/metacubex/mihomo/common/utils"
  7. "github.com/gofrs/uuid/v5"
  8. "github.com/metacubex/randv2"
  9. )
  10. // Version of vmess
  11. const Version byte = 1
  12. // Request Options
  13. const (
  14. OptionChunkStream byte = 1
  15. OptionChunkMasking byte = 4
  16. )
  17. // Security type vmess
  18. type Security = byte
  19. // Cipher types
  20. const (
  21. SecurityAES128GCM Security = 3
  22. SecurityCHACHA20POLY1305 Security = 4
  23. SecurityNone Security = 5
  24. )
  25. // CipherMapping return
  26. var CipherMapping = map[string]byte{
  27. "none": SecurityNone,
  28. "aes-128-gcm": SecurityAES128GCM,
  29. "chacha20-poly1305": SecurityCHACHA20POLY1305,
  30. }
  31. // Command types
  32. const (
  33. CommandTCP byte = 1
  34. CommandUDP byte = 2
  35. )
  36. // Addr types
  37. const (
  38. AtypIPv4 byte = 1
  39. AtypDomainName byte = 2
  40. AtypIPv6 byte = 3
  41. )
  42. // DstAddr store destination address
  43. type DstAddr struct {
  44. UDP bool
  45. AddrType byte
  46. Addr []byte
  47. Port uint
  48. }
  49. // Client is vmess connection generator
  50. type Client struct {
  51. user []*ID
  52. uuid *uuid.UUID
  53. security Security
  54. isAead bool
  55. }
  56. // Config of vmess
  57. type Config struct {
  58. UUID string
  59. AlterID uint16
  60. Security string
  61. Port string
  62. HostName string
  63. IsAead bool
  64. }
  65. // StreamConn return a Conn with net.Conn and DstAddr
  66. func (c *Client) StreamConn(conn net.Conn, dst *DstAddr) (net.Conn, error) {
  67. r := randv2.IntN(len(c.user))
  68. return newConn(conn, c.user[r], dst, c.security, c.isAead)
  69. }
  70. // NewClient return Client instance
  71. func NewClient(config Config) (*Client, error) {
  72. uid, err := utils.UUIDMap(config.UUID)
  73. if err != nil {
  74. return nil, err
  75. }
  76. var security Security
  77. switch config.Security {
  78. case "aes-128-gcm":
  79. security = SecurityAES128GCM
  80. case "chacha20-poly1305":
  81. security = SecurityCHACHA20POLY1305
  82. case "none":
  83. security = SecurityNone
  84. case "auto":
  85. security = SecurityCHACHA20POLY1305
  86. if runtime.GOARCH == "amd64" || runtime.GOARCH == "s390x" || runtime.GOARCH == "arm64" {
  87. security = SecurityAES128GCM
  88. }
  89. default:
  90. return nil, fmt.Errorf("unknown security type: %s", config.Security)
  91. }
  92. return &Client{
  93. user: newAlterIDs(newID(&uid), config.AlterID),
  94. uuid: &uid,
  95. security: security,
  96. isAead: config.IsAead,
  97. }, nil
  98. }