direct.go 3.6 KB

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