direct.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. package inbound
  2. import (
  3. "context"
  4. "net"
  5. "net/netip"
  6. "time"
  7. "github.com/sagernet/sing-box/adapter"
  8. C "github.com/sagernet/sing-box/constant"
  9. "github.com/sagernet/sing-box/log"
  10. "github.com/sagernet/sing-box/option"
  11. "github.com/sagernet/sing/common/buf"
  12. M "github.com/sagernet/sing/common/metadata"
  13. N "github.com/sagernet/sing/common/network"
  14. "github.com/sagernet/sing/common/udpnat"
  15. )
  16. var _ adapter.Inbound = (*Direct)(nil)
  17. type Direct struct {
  18. myInboundAdapter
  19. udpNat *udpnat.Service[netip.AddrPort]
  20. overrideOption int
  21. overrideDestination M.Socksaddr
  22. }
  23. func NewDirect(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.DirectInboundOptions) *Direct {
  24. options.UDPFragmentDefault = true
  25. inbound := &Direct{
  26. myInboundAdapter: myInboundAdapter{
  27. protocol: C.TypeDirect,
  28. network: options.Network.Build(),
  29. ctx: ctx,
  30. router: router,
  31. logger: logger,
  32. tag: tag,
  33. listenOptions: options.ListenOptions,
  34. },
  35. }
  36. if options.OverrideAddress != "" && options.OverridePort != 0 {
  37. inbound.overrideOption = 1
  38. inbound.overrideDestination = M.ParseSocksaddrHostPort(options.OverrideAddress, options.OverridePort)
  39. } else if options.OverrideAddress != "" {
  40. inbound.overrideOption = 2
  41. inbound.overrideDestination = M.ParseSocksaddrHostPort(options.OverrideAddress, options.OverridePort)
  42. } else if options.OverridePort != 0 {
  43. inbound.overrideOption = 3
  44. inbound.overrideDestination = M.Socksaddr{Port: options.OverridePort}
  45. }
  46. var udpTimeout time.Duration
  47. if options.UDPTimeout != 0 {
  48. udpTimeout = time.Duration(options.UDPTimeout)
  49. } else {
  50. udpTimeout = C.UDPTimeout
  51. }
  52. inbound.udpNat = udpnat.New[netip.AddrPort](int64(udpTimeout.Seconds()), adapter.NewUpstreamContextHandler(inbound.newConnection, inbound.newPacketConnection, inbound))
  53. inbound.connHandler = inbound
  54. inbound.packetHandler = inbound
  55. inbound.packetUpstream = inbound.udpNat
  56. return inbound
  57. }
  58. func (d *Direct) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
  59. switch d.overrideOption {
  60. case 1:
  61. metadata.Destination = d.overrideDestination
  62. case 2:
  63. destination := d.overrideDestination
  64. destination.Port = metadata.Destination.Port
  65. metadata.Destination = destination
  66. case 3:
  67. metadata.Destination.Port = d.overrideDestination.Port
  68. }
  69. d.logger.InfoContext(ctx, "inbound connection to ", metadata.Destination)
  70. return d.router.RouteConnection(ctx, conn, metadata)
  71. }
  72. func (d *Direct) NewPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, metadata adapter.InboundContext) error {
  73. switch d.overrideOption {
  74. case 1:
  75. metadata.Destination = d.overrideDestination
  76. case 2:
  77. destination := d.overrideDestination
  78. destination.Port = metadata.Destination.Port
  79. metadata.Destination = destination
  80. case 3:
  81. metadata.Destination.Port = d.overrideDestination.Port
  82. }
  83. d.udpNat.NewContextPacket(ctx, metadata.Source.AddrPort(), buffer, adapter.UpstreamMetadata(metadata), func(natConn N.PacketConn) (context.Context, N.PacketWriter) {
  84. return adapter.WithContext(log.ContextWithNewID(ctx), &metadata), &udpnat.DirectBackWriter{Source: conn, Nat: natConn}
  85. })
  86. return nil
  87. }
  88. func (d *Direct) newConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
  89. return d.router.RouteConnection(ctx, conn, metadata)
  90. }
  91. func (d *Direct) newPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
  92. ctx = log.ContextWithNewID(ctx)
  93. d.logger.InfoContext(ctx, "inbound packet connection from ", metadata.Source)
  94. return d.router.RoutePacketConnection(ctx, conn, metadata)
  95. }