outbound.go 3.8 KB

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