direct.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  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. inbound := &Direct{
  24. myInboundAdapter: myInboundAdapter{
  25. protocol: C.TypeDirect,
  26. network: options.Network.Build(),
  27. ctx: ctx,
  28. router: router,
  29. logger: logger,
  30. tag: tag,
  31. listenOptions: options.ListenOptions,
  32. },
  33. }
  34. if options.OverrideAddress != "" && options.OverridePort != 0 {
  35. inbound.overrideOption = 1
  36. inbound.overrideDestination = M.ParseSocksaddrHostPort(options.OverrideAddress, options.OverridePort)
  37. } else if options.OverrideAddress != "" {
  38. inbound.overrideOption = 2
  39. inbound.overrideDestination = M.ParseSocksaddrHostPort(options.OverrideAddress, options.OverridePort)
  40. } else if options.OverridePort != 0 {
  41. inbound.overrideOption = 3
  42. inbound.overrideDestination = M.Socksaddr{Port: options.OverridePort}
  43. }
  44. var udpTimeout int64
  45. if options.UDPTimeout != 0 {
  46. udpTimeout = options.UDPTimeout
  47. } else {
  48. udpTimeout = int64(C.UDPTimeout.Seconds())
  49. }
  50. inbound.udpNat = udpnat.New[netip.AddrPort](udpTimeout, adapter.NewUpstreamContextHandler(inbound.newConnection, inbound.newPacketConnection, inbound))
  51. inbound.connHandler = inbound
  52. inbound.packetHandler = inbound
  53. inbound.packetUpstream = inbound.udpNat
  54. return inbound
  55. }
  56. func (d *Direct) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
  57. switch d.overrideOption {
  58. case 1:
  59. metadata.Destination = d.overrideDestination
  60. case 2:
  61. destination := d.overrideDestination
  62. destination.Port = metadata.Destination.Port
  63. metadata.Destination = destination
  64. case 3:
  65. metadata.Destination.Port = d.overrideDestination.Port
  66. }
  67. d.logger.InfoContext(ctx, "inbound connection to ", metadata.Destination)
  68. return d.router.RouteConnection(ctx, conn, metadata)
  69. }
  70. func (d *Direct) NewPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, metadata adapter.InboundContext) error {
  71. switch d.overrideOption {
  72. case 1:
  73. metadata.Destination = d.overrideDestination
  74. case 2:
  75. destination := d.overrideDestination
  76. destination.Port = metadata.Destination.Port
  77. metadata.Destination = destination
  78. case 3:
  79. metadata.Destination.Port = d.overrideDestination.Port
  80. }
  81. d.udpNat.NewContextPacket(ctx, metadata.Source.AddrPort(), buffer, adapter.UpstreamMetadata(metadata), func(natConn N.PacketConn) (context.Context, N.PacketWriter) {
  82. return adapter.WithContext(log.ContextWithNewID(ctx), &metadata), &udpnat.DirectBackWriter{Source: conn, Nat: natConn}
  83. })
  84. return nil
  85. }
  86. func (d *Direct) newConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
  87. return d.router.RouteConnection(ctx, conn, metadata)
  88. }
  89. func (d *Direct) newPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
  90. ctx = log.ContextWithNewID(ctx)
  91. d.logger.InfoContext(ctx, "inbound packet connection from ", metadata.Source)
  92. return d.router.RoutePacketConnection(ctx, conn, metadata)
  93. }