outbound.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. package anytls
  2. import (
  3. "context"
  4. "net"
  5. "os"
  6. "github.com/sagernet/sing-box/adapter"
  7. "github.com/sagernet/sing-box/adapter/outbound"
  8. "github.com/sagernet/sing-box/common/dialer"
  9. "github.com/sagernet/sing-box/common/tls"
  10. C "github.com/sagernet/sing-box/constant"
  11. "github.com/sagernet/sing-box/log"
  12. "github.com/sagernet/sing-box/option"
  13. "github.com/sagernet/sing/common"
  14. M "github.com/sagernet/sing/common/metadata"
  15. N "github.com/sagernet/sing/common/network"
  16. "github.com/sagernet/sing/common/uot"
  17. anytls "github.com/anytls/sing-anytls"
  18. )
  19. func RegisterOutbound(registry *outbound.Registry) {
  20. outbound.Register[option.AnyTLSOutboundOptions](registry, C.TypeAnyTLS, NewOutbound)
  21. }
  22. type Outbound struct {
  23. outbound.Adapter
  24. dialer N.Dialer
  25. server M.Socksaddr
  26. tlsConfig tls.Config
  27. client *anytls.Client
  28. uotClient *uot.Client
  29. logger log.ContextLogger
  30. }
  31. func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.AnyTLSOutboundOptions) (adapter.Outbound, error) {
  32. outbound := &Outbound{
  33. Adapter: outbound.NewAdapterWithDialerOptions(C.TypeAnyTLS, tag, []string{N.NetworkTCP, N.NetworkUDP}, options.DialerOptions),
  34. server: options.ServerOptions.Build(),
  35. logger: logger,
  36. }
  37. if options.TLS == nil || !options.TLS.Enabled {
  38. return nil, C.ErrTLSRequired
  39. }
  40. tlsConfig, err := tls.NewClient(ctx, options.Server, common.PtrValueOrDefault(options.TLS))
  41. if err != nil {
  42. return nil, err
  43. }
  44. outbound.tlsConfig = tlsConfig
  45. outboundDialer, err := dialer.NewWithOptions(dialer.Options{
  46. Context: ctx,
  47. Options: options.DialerOptions,
  48. })
  49. if err != nil {
  50. return nil, err
  51. }
  52. outbound.dialer = outboundDialer
  53. client, err := anytls.NewClient(ctx, anytls.ClientConfig{
  54. Password: options.Password,
  55. IdleSessionCheckInterval: options.IdleSessionCheckInterval.Build(),
  56. IdleSessionTimeout: options.IdleSessionTimeout.Build(),
  57. MinIdleSession: options.MinIdleSession,
  58. DialOut: outbound.dialOut,
  59. Logger: logger,
  60. })
  61. if err != nil {
  62. return nil, err
  63. }
  64. outbound.client = client
  65. outbound.uotClient = &uot.Client{
  66. Dialer: (anytlsDialer)(client.CreateProxy),
  67. Version: uot.Version,
  68. }
  69. return outbound, nil
  70. }
  71. type anytlsDialer func(ctx context.Context, destination M.Socksaddr) (net.Conn, error)
  72. func (d anytlsDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
  73. return d(ctx, destination)
  74. }
  75. func (d anytlsDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
  76. return nil, os.ErrInvalid
  77. }
  78. func (h *Outbound) dialOut(ctx context.Context) (net.Conn, error) {
  79. conn, err := h.dialer.DialContext(ctx, N.NetworkTCP, h.server)
  80. if err != nil {
  81. return nil, err
  82. }
  83. tlsConn, err := tls.ClientHandshake(ctx, conn, h.tlsConfig)
  84. if err != nil {
  85. common.Close(tlsConn, conn)
  86. return nil, err
  87. }
  88. return tlsConn, nil
  89. }
  90. func (h *Outbound) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
  91. ctx, metadata := adapter.ExtendContext(ctx)
  92. metadata.Outbound = h.Tag()
  93. metadata.Destination = destination
  94. switch N.NetworkName(network) {
  95. case N.NetworkTCP:
  96. h.logger.InfoContext(ctx, "outbound connection to ", destination)
  97. return h.client.CreateProxy(ctx, destination)
  98. case N.NetworkUDP:
  99. h.logger.InfoContext(ctx, "outbound UoT packet connection to ", destination)
  100. return h.uotClient.DialContext(ctx, network, destination)
  101. }
  102. return nil, os.ErrInvalid
  103. }
  104. func (h *Outbound) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
  105. ctx, metadata := adapter.ExtendContext(ctx)
  106. metadata.Outbound = h.Tag()
  107. metadata.Destination = destination
  108. h.logger.InfoContext(ctx, "outbound UoT packet connection to ", destination)
  109. return h.uotClient.ListenPacket(ctx, destination)
  110. }
  111. func (h *Outbound) Close() error {
  112. return common.Close(h.client)
  113. }