outbound.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  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. RemoteIsDomain: options.ServerIsDomain(),
  49. })
  50. if err != nil {
  51. return nil, err
  52. }
  53. outbound.dialer = outboundDialer
  54. client, err := anytls.NewClient(ctx, anytls.ClientConfig{
  55. Password: options.Password,
  56. IdleSessionCheckInterval: options.IdleSessionCheckInterval.Build(),
  57. IdleSessionTimeout: options.IdleSessionTimeout.Build(),
  58. MinIdleSession: options.MinIdleSession,
  59. DialOut: outbound.dialOut,
  60. Logger: logger,
  61. })
  62. if err != nil {
  63. return nil, err
  64. }
  65. outbound.client = client
  66. outbound.uotClient = &uot.Client{
  67. Dialer: (anytlsDialer)(client.CreateProxy),
  68. Version: uot.Version,
  69. }
  70. return outbound, nil
  71. }
  72. type anytlsDialer func(ctx context.Context, destination M.Socksaddr) (net.Conn, error)
  73. func (d anytlsDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
  74. return d(ctx, destination)
  75. }
  76. func (d anytlsDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
  77. return nil, os.ErrInvalid
  78. }
  79. func (h *Outbound) dialOut(ctx context.Context) (net.Conn, error) {
  80. conn, err := h.dialer.DialContext(ctx, N.NetworkTCP, h.server)
  81. if err != nil {
  82. return nil, err
  83. }
  84. tlsConn, err := tls.ClientHandshake(ctx, conn, h.tlsConfig)
  85. if err != nil {
  86. common.Close(tlsConn, conn)
  87. return nil, err
  88. }
  89. return tlsConn, nil
  90. }
  91. func (h *Outbound) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
  92. ctx, metadata := adapter.ExtendContext(ctx)
  93. metadata.Outbound = h.Tag()
  94. metadata.Destination = destination
  95. switch N.NetworkName(network) {
  96. case N.NetworkTCP:
  97. h.logger.InfoContext(ctx, "outbound connection to ", destination)
  98. return h.client.CreateProxy(ctx, destination)
  99. case N.NetworkUDP:
  100. h.logger.InfoContext(ctx, "outbound UoT packet connection to ", destination)
  101. return h.uotClient.DialContext(ctx, network, destination)
  102. }
  103. return nil, os.ErrInvalid
  104. }
  105. func (h *Outbound) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
  106. ctx, metadata := adapter.ExtendContext(ctx)
  107. metadata.Outbound = h.Tag()
  108. metadata.Destination = destination
  109. h.logger.InfoContext(ctx, "outbound UoT packet connection to ", destination)
  110. return h.uotClient.ListenPacket(ctx, destination)
  111. }
  112. func (h *Outbound) Close() error {
  113. return common.Close(h.client)
  114. }