tproxy.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. package inbound
  2. import (
  3. "context"
  4. "net"
  5. "net/netip"
  6. "github.com/sagernet/sing-box/adapter"
  7. "github.com/sagernet/sing-box/common/redir"
  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"
  12. "github.com/sagernet/sing/common/buf"
  13. E "github.com/sagernet/sing/common/exceptions"
  14. M "github.com/sagernet/sing/common/metadata"
  15. N "github.com/sagernet/sing/common/network"
  16. "github.com/sagernet/sing/common/udpnat"
  17. )
  18. type TProxy struct {
  19. myInboundAdapter
  20. udpNat *udpnat.Service[netip.AddrPort]
  21. }
  22. func NewTProxy(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.TProxyInboundOptions) *TProxy {
  23. tproxy := &TProxy{
  24. myInboundAdapter: myInboundAdapter{
  25. protocol: C.TypeTProxy,
  26. network: options.Network.Build(),
  27. ctx: ctx,
  28. router: router,
  29. logger: logger,
  30. tag: tag,
  31. listenOptions: options.ListenOptions,
  32. },
  33. }
  34. var udpTimeout int64
  35. if options.UDPTimeout != 0 {
  36. udpTimeout = options.UDPTimeout
  37. } else {
  38. udpTimeout = int64(C.UDPTimeout.Seconds())
  39. }
  40. tproxy.connHandler = tproxy
  41. tproxy.oobPacketHandler = tproxy
  42. tproxy.udpNat = udpnat.New[netip.AddrPort](udpTimeout, tproxy.upstreamContextHandler())
  43. tproxy.packetUpstream = tproxy.udpNat
  44. return tproxy
  45. }
  46. func (t *TProxy) Start() error {
  47. err := t.myInboundAdapter.Start()
  48. if err != nil {
  49. return err
  50. }
  51. if t.tcpListener != nil {
  52. tcpFd, err := common.GetFileDescriptor(t.tcpListener)
  53. if err != nil {
  54. return err
  55. }
  56. err = redir.TProxy(tcpFd, M.SocksaddrFromNet(t.tcpListener.Addr()).Addr.Is6())
  57. if err != nil {
  58. return E.Cause(err, "configure tproxy TCP listener")
  59. }
  60. }
  61. if t.udpConn != nil {
  62. udpFd, err := common.GetFileDescriptor(t.udpConn)
  63. if err != nil {
  64. return err
  65. }
  66. err = redir.TProxy(udpFd, M.SocksaddrFromNet(t.udpConn.LocalAddr()).Addr.Is6())
  67. if err != nil {
  68. return E.Cause(err, "configure tproxy UDP listener")
  69. }
  70. }
  71. return nil
  72. }
  73. func (t *TProxy) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
  74. metadata.Destination = M.SocksaddrFromNet(conn.LocalAddr())
  75. return t.newConnection(ctx, conn, metadata)
  76. }
  77. func (t *TProxy) NewPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, oob []byte, metadata adapter.InboundContext) error {
  78. destination, err := redir.GetOriginalDestinationFromOOB(oob)
  79. if err != nil {
  80. return E.Cause(err, "get tproxy destination")
  81. }
  82. metadata.Destination = M.SocksaddrFromNetIP(destination)
  83. t.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), &tproxyPacketWriter{natConn}
  85. })
  86. return nil
  87. }
  88. type tproxyPacketWriter struct {
  89. source N.PacketConn
  90. }
  91. func (w *tproxyPacketWriter) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error {
  92. defer buffer.Release()
  93. udpConn, err := redir.DialUDP(destination.UDPAddr(), M.SocksaddrFromNet(w.source.LocalAddr()).UDPAddr())
  94. if err != nil {
  95. return E.Cause(err, "tproxy udp write back")
  96. }
  97. defer udpConn.Close()
  98. return common.Error(udpConn.Write(buffer.Bytes()))
  99. }