outbound.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. package shadowsocks
  2. import (
  3. "context"
  4. "net"
  5. "github.com/sagernet/sing-box/adapter"
  6. "github.com/sagernet/sing-box/common/dialer"
  7. "github.com/sagernet/sing-box/common/tunnel"
  8. "github.com/sagernet/sing-box/config"
  9. C "github.com/sagernet/sing-box/constant"
  10. "github.com/sagernet/sing-box/log"
  11. "github.com/sagernet/sing-shadowsocks"
  12. "github.com/sagernet/sing-shadowsocks/shadowimpl"
  13. "github.com/sagernet/sing/common/bufio"
  14. E "github.com/sagernet/sing/common/exceptions"
  15. M "github.com/sagernet/sing/common/metadata"
  16. N "github.com/sagernet/sing/common/network"
  17. )
  18. var _ adapter.Outbound = (*Outbound)(nil)
  19. type Outbound struct {
  20. tag string
  21. logger log.Logger
  22. dialer N.Dialer
  23. method shadowsocks.Method
  24. serverAddr M.Socksaddr
  25. }
  26. func NewOutbound(tag string, router adapter.Router, logger log.Logger, options *config.ShadowsocksOutboundOptions) (outbound *Outbound, err error) {
  27. outbound = &Outbound{
  28. tag: tag,
  29. logger: logger,
  30. dialer: dialer.NewDialer(router, options.DialerOptions),
  31. }
  32. outbound.method, err = shadowimpl.FetchMethod(options.Method, options.Password)
  33. if err != nil {
  34. return
  35. }
  36. if options.Server == "" {
  37. err = E.New("missing server address")
  38. return
  39. } else if options.ServerPort == 0 {
  40. err = E.New("missing server port")
  41. return
  42. }
  43. outbound.serverAddr = M.ParseSocksaddrHostPort(options.Server, options.ServerPort)
  44. return
  45. }
  46. func (o *Outbound) Type() string {
  47. return C.TypeShadowsocks
  48. }
  49. func (o *Outbound) Tag() string {
  50. return o.tag
  51. }
  52. func (o *Outbound) NewConnection(ctx context.Context, conn net.Conn, destination M.Socksaddr) error {
  53. serverConn, err := o.DialContext(ctx, "tcp", destination)
  54. if err != nil {
  55. return err
  56. }
  57. return tunnel.CopyEarlyConn(ctx, conn, serverConn)
  58. }
  59. func (o *Outbound) NewPacketConnection(ctx context.Context, conn N.PacketConn, destination M.Socksaddr) error {
  60. serverConn, err := o.ListenPacket(ctx)
  61. if err != nil {
  62. return err
  63. }
  64. return bufio.CopyPacketConn(ctx, conn, bufio.NewPacketConn(serverConn))
  65. }
  66. func (o *Outbound) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
  67. switch network {
  68. case C.NetworkTCP:
  69. o.logger.WithContext(ctx).Debug("outbound connection to ", destination)
  70. outConn, err := o.dialer.DialContext(ctx, "tcp", o.serverAddr)
  71. if err != nil {
  72. return nil, err
  73. }
  74. return o.method.DialEarlyConn(outConn, destination), nil
  75. case C.NetworkUDP:
  76. o.logger.WithContext(ctx).Debug("outbound packet connection to ", destination)
  77. outConn, err := o.dialer.DialContext(ctx, "udp", o.serverAddr)
  78. if err != nil {
  79. return nil, err
  80. }
  81. return &bufio.BindPacketConn{PacketConn: o.method.DialPacketConn(outConn), Addr: destination}, nil
  82. default:
  83. panic("unknown network " + network)
  84. }
  85. }
  86. func (o *Outbound) ListenPacket(ctx context.Context) (net.PacketConn, error) {
  87. o.logger.WithContext(ctx).Debug("outbound packet connection to ", o.serverAddr)
  88. outConn, err := o.dialer.ListenPacket(ctx)
  89. if err != nil {
  90. return nil, err
  91. }
  92. return o.method.DialPacketConn(&bufio.BindPacketConn{PacketConn: outConn, Addr: o.serverAddr.UDPAddr()}), nil
  93. }