vmess.go 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. package outbound
  2. import (
  3. "context"
  4. "net"
  5. "github.com/sagernet/sing-box/adapter"
  6. "github.com/sagernet/sing-box/common/dialer"
  7. C "github.com/sagernet/sing-box/constant"
  8. "github.com/sagernet/sing-box/log"
  9. "github.com/sagernet/sing-box/option"
  10. "github.com/sagernet/sing-vmess"
  11. "github.com/sagernet/sing/common"
  12. M "github.com/sagernet/sing/common/metadata"
  13. N "github.com/sagernet/sing/common/network"
  14. )
  15. var _ adapter.Outbound = (*VMess)(nil)
  16. type VMess struct {
  17. myOutboundAdapter
  18. dialer N.Dialer
  19. client *vmess.Client
  20. serverAddr M.Socksaddr
  21. }
  22. func NewVMess(router adapter.Router, logger log.ContextLogger, tag string, options option.VMessOutboundOptions) (*VMess, error) {
  23. var clientOptions []vmess.ClientOption
  24. if options.GlobalPadding {
  25. clientOptions = append(clientOptions, vmess.ClientWithGlobalPadding())
  26. }
  27. if options.AuthenticatedLength {
  28. clientOptions = append(clientOptions, vmess.ClientWithAuthenticatedLength())
  29. }
  30. client, err := vmess.NewClient(options.UUID, options.Security, options.AlterId, clientOptions...)
  31. if err != nil {
  32. return nil, err
  33. }
  34. detour, err := dialer.NewTLS(dialer.NewOutbound(router, options.OutboundDialerOptions), options.Server, common.PtrValueOrDefault(options.TLSOptions))
  35. if err != nil {
  36. return nil, err
  37. }
  38. return &VMess{
  39. myOutboundAdapter{
  40. protocol: C.TypeVMess,
  41. logger: logger,
  42. tag: tag,
  43. network: options.Network.Build(),
  44. },
  45. detour,
  46. client,
  47. options.ServerOptions.Build(),
  48. }, nil
  49. }
  50. func (h *VMess) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
  51. ctx, metadata := adapter.AppendContext(ctx)
  52. metadata.Outbound = h.tag
  53. metadata.Destination = destination
  54. switch network {
  55. case C.NetworkTCP:
  56. h.logger.InfoContext(ctx, "outbound connection to ", destination)
  57. outConn, err := h.dialer.DialContext(ctx, C.NetworkTCP, h.serverAddr)
  58. if err != nil {
  59. return nil, err
  60. }
  61. return h.client.DialEarlyConn(outConn, destination), nil
  62. case C.NetworkUDP:
  63. h.logger.InfoContext(ctx, "outbound packet connection to ", destination)
  64. outConn, err := h.dialer.DialContext(ctx, C.NetworkTCP, h.serverAddr)
  65. if err != nil {
  66. return nil, err
  67. }
  68. return h.client.DialEarlyPacketConn(outConn, destination), nil
  69. default:
  70. panic("unknown network " + network)
  71. }
  72. }
  73. func (h *VMess) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
  74. conn, err := h.DialContext(ctx, C.NetworkUDP, destination)
  75. if err != nil {
  76. return nil, err
  77. }
  78. return conn.(vmess.PacketConn), nil
  79. }
  80. func (h *VMess) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
  81. return NewEarlyConnection(ctx, h, conn, metadata)
  82. }
  83. func (h *VMess) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
  84. return NewPacketConnection(ctx, h, conn, metadata)
  85. }