direct.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. package outbound
  2. import (
  3. "context"
  4. "net"
  5. "net/netip"
  6. "github.com/sagernet/sing-box/adapter"
  7. "github.com/sagernet/sing-box/common/dialer"
  8. C "github.com/sagernet/sing-box/constant"
  9. "github.com/sagernet/sing-box/log"
  10. "github.com/sagernet/sing-box/option"
  11. E "github.com/sagernet/sing/common/exceptions"
  12. M "github.com/sagernet/sing/common/metadata"
  13. N "github.com/sagernet/sing/common/network"
  14. "github.com/pires/go-proxyproto"
  15. )
  16. var _ adapter.Outbound = (*Direct)(nil)
  17. type Direct struct {
  18. myOutboundAdapter
  19. dialer N.Dialer
  20. overrideOption int
  21. overrideDestination M.Socksaddr
  22. proxyProto uint8
  23. }
  24. func NewDirect(router adapter.Router, logger log.ContextLogger, tag string, options option.DirectOutboundOptions) (*Direct, error) {
  25. outbound := &Direct{
  26. myOutboundAdapter: myOutboundAdapter{
  27. protocol: C.TypeDirect,
  28. network: []string{N.NetworkTCP, N.NetworkUDP},
  29. router: router,
  30. logger: logger,
  31. tag: tag,
  32. },
  33. dialer: dialer.NewOutbound(router, options.OutboundDialerOptions),
  34. proxyProto: options.ProxyProtocol,
  35. }
  36. if options.ProxyProtocol > 2 {
  37. return nil, E.New("invalid proxy protocol option: ", options.ProxyProtocol)
  38. }
  39. if options.OverrideAddress != "" && options.OverridePort != 0 {
  40. outbound.overrideOption = 1
  41. outbound.overrideDestination = M.ParseSocksaddrHostPort(options.OverrideAddress, options.OverridePort)
  42. } else if options.OverrideAddress != "" {
  43. outbound.overrideOption = 2
  44. outbound.overrideDestination = M.ParseSocksaddrHostPort(options.OverrideAddress, options.OverridePort)
  45. } else if options.OverridePort != 0 {
  46. outbound.overrideOption = 3
  47. outbound.overrideDestination = M.Socksaddr{Port: options.OverridePort}
  48. }
  49. return outbound, nil
  50. }
  51. func (h *Direct) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
  52. ctx, metadata := adapter.AppendContext(ctx)
  53. originDestination := metadata.Destination
  54. metadata.Outbound = h.tag
  55. metadata.Destination = destination
  56. switch h.overrideOption {
  57. case 1:
  58. destination = h.overrideDestination
  59. case 2:
  60. newDestination := h.overrideDestination
  61. newDestination.Port = destination.Port
  62. destination = newDestination
  63. case 3:
  64. destination.Port = h.overrideDestination.Port
  65. }
  66. network = N.NetworkName(network)
  67. switch network {
  68. case N.NetworkTCP:
  69. h.logger.InfoContext(ctx, "outbound connection to ", destination)
  70. case N.NetworkUDP:
  71. h.logger.InfoContext(ctx, "outbound packet connection to ", destination)
  72. }
  73. conn, err := h.dialer.DialContext(ctx, network, destination)
  74. if err != nil {
  75. return nil, err
  76. }
  77. if h.proxyProto > 0 {
  78. source := metadata.Source
  79. if !source.IsValid() {
  80. source = M.SocksaddrFromNet(conn.LocalAddr())
  81. }
  82. if originDestination.Addr.Is6() {
  83. source = M.SocksaddrFrom(netip.AddrFrom16(source.Addr.As16()), source.Port)
  84. }
  85. header := proxyproto.HeaderProxyFromAddrs(h.proxyProto, source.TCPAddr(), originDestination.TCPAddr())
  86. _, err = header.WriteTo(conn)
  87. if err != nil {
  88. conn.Close()
  89. return nil, E.Cause(err, "write proxy protocol header")
  90. }
  91. }
  92. return conn, nil
  93. }
  94. func (h *Direct) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
  95. ctx, metadata := adapter.AppendContext(ctx)
  96. metadata.Outbound = h.tag
  97. metadata.Destination = destination
  98. h.logger.InfoContext(ctx, "outbound packet connection")
  99. return h.dialer.ListenPacket(ctx, destination)
  100. }
  101. func (h *Direct) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
  102. return NewConnection(ctx, h, conn, metadata)
  103. }
  104. func (h *Direct) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
  105. return NewPacketConnection(ctx, h, conn, metadata)
  106. }