direct.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. package outbound
  2. import (
  3. "context"
  4. "net"
  5. "github.com/sagernet/sing/common/bufio"
  6. M "github.com/sagernet/sing/common/metadata"
  7. N "github.com/sagernet/sing/common/network"
  8. "github.com/sagernet/sing-box/adapter"
  9. "github.com/sagernet/sing-box/common/dialer"
  10. C "github.com/sagernet/sing-box/constant"
  11. "github.com/sagernet/sing-box/log"
  12. "github.com/sagernet/sing-box/option"
  13. )
  14. var _ adapter.Outbound = (*Direct)(nil)
  15. type Direct struct {
  16. myOutboundAdapter
  17. dialer N.Dialer
  18. overrideOption int
  19. overrideDestination M.Socksaddr
  20. }
  21. func NewDirect(router adapter.Router, logger log.Logger, tag string, options option.DirectOutboundOptions) *Direct {
  22. outbound := &Direct{
  23. myOutboundAdapter: myOutboundAdapter{
  24. protocol: C.TypeDirect,
  25. logger: logger,
  26. tag: tag,
  27. network: []string{C.NetworkTCP, C.NetworkUDP},
  28. },
  29. dialer: dialer.New(router, options.DialerOptions),
  30. }
  31. if options.OverrideAddress != "" && options.OverridePort != 0 {
  32. outbound.overrideOption = 1
  33. outbound.overrideDestination = M.ParseSocksaddrHostPort(options.OverrideAddress, options.OverridePort)
  34. } else if options.OverrideAddress != "" {
  35. outbound.overrideOption = 2
  36. outbound.overrideDestination = M.ParseSocksaddrHostPort(options.OverrideAddress, options.OverridePort)
  37. } else if options.OverridePort != 0 {
  38. outbound.overrideOption = 3
  39. outbound.overrideDestination = M.Socksaddr{Port: options.OverridePort}
  40. }
  41. return outbound
  42. }
  43. func (h *Direct) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
  44. ctx, metadata := adapter.AppendContext(ctx)
  45. metadata.Outbound = h.tag
  46. switch h.overrideOption {
  47. case 1:
  48. destination = h.overrideDestination
  49. case 2:
  50. newDestination := h.overrideDestination
  51. newDestination.Port = destination.Port
  52. destination = newDestination
  53. case 3:
  54. destination.Port = h.overrideDestination.Port
  55. }
  56. switch network {
  57. case C.NetworkTCP:
  58. h.logger.WithContext(ctx).Info("outbound connection to ", destination)
  59. case C.NetworkUDP:
  60. h.logger.WithContext(ctx).Info("outbound packet connection to ", destination)
  61. }
  62. return h.dialer.DialContext(ctx, network, destination)
  63. }
  64. func (h *Direct) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
  65. ctx, metadata := adapter.AppendContext(ctx)
  66. metadata.Outbound = h.tag
  67. h.logger.WithContext(ctx).Info("outbound packet connection")
  68. return h.dialer.ListenPacket(ctx, destination)
  69. }
  70. func (h *Direct) NewConnection(ctx context.Context, conn net.Conn, destination M.Socksaddr) error {
  71. outConn, err := h.DialContext(ctx, C.NetworkTCP, destination)
  72. if err != nil {
  73. return err
  74. }
  75. return bufio.CopyConn(ctx, conn, outConn)
  76. }
  77. func (h *Direct) NewPacketConnection(ctx context.Context, conn N.PacketConn, destination M.Socksaddr) error {
  78. outConn, err := h.ListenPacket(ctx, destination)
  79. if err != nil {
  80. return err
  81. }
  82. return bufio.CopyPacketConn(ctx, conn, bufio.NewPacketConn(outConn))
  83. }