outbound.go 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. package shadowtls
  2. import (
  3. "context"
  4. "crypto/tls"
  5. "github.com/sagernet/sing-shadowtls"
  6. "github.com/xtls/xray-core/common"
  7. "github.com/xtls/xray-core/common/net"
  8. "github.com/xtls/xray-core/common/session"
  9. "github.com/xtls/xray-core/common/singbridge"
  10. "github.com/xtls/xray-core/transport"
  11. "github.com/xtls/xray-core/transport/internet"
  12. )
  13. func init() {
  14. common.Must(common.RegisterConfig((*ClientConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
  15. return NewClient(ctx, config.(*ClientConfig))
  16. }))
  17. }
  18. type Outbound struct {
  19. ctx context.Context
  20. clientConfig shadowtls.ClientConfig
  21. }
  22. func NewClient(ctx context.Context, config *ClientConfig) (*Outbound, error) {
  23. return &Outbound{
  24. ctx: ctx,
  25. clientConfig: shadowtls.ClientConfig{
  26. Version: int(config.Version),
  27. Password: config.Password,
  28. Server: singbridge.ToSocksaddr(net.Destination{
  29. Address: config.Address.AsAddress(),
  30. Port: net.Port(config.Port),
  31. }),
  32. Logger: singbridge.NewLogger(newError),
  33. },
  34. }, nil
  35. }
  36. func (o *Outbound) Process(ctx context.Context, link *transport.Link, dialer internet.Dialer) error {
  37. var inboundConn net.Conn
  38. inbound := session.InboundFromContext(ctx)
  39. if inbound != nil {
  40. inboundConn = inbound.Conn
  41. }
  42. outbound := session.OutboundFromContext(ctx)
  43. if outbound == nil || !outbound.Target.IsValid() {
  44. return newError("target not specified")
  45. }
  46. destination := outbound.Target
  47. if destination.Network != net.Network_TCP {
  48. return newError("only TCP is supported")
  49. }
  50. newError("tunneling request to ", destination, " via ", o.clientConfig.Server).WriteToLog(session.ExportIDToError(ctx))
  51. var client *shadowtls.Client
  52. clientConfig := o.clientConfig
  53. if clientConfig.Version == 3 {
  54. clientConfig.Dialer = singbridge.NewTLSDialer(dialer, func(conn net.Conn, config *tls.Config) net.Conn {
  55. client.SetTLSConfig(config)
  56. return conn
  57. })
  58. } else {
  59. clientConfig.Dialer = singbridge.NewDialer(dialer)
  60. }
  61. var err error
  62. client, err = shadowtls.NewClient(clientConfig)
  63. if err != nil {
  64. return newError("failed to create client").Base(err)
  65. }
  66. conn, err := client.DialContext(ctx)
  67. if err != nil {
  68. return newError("failed to connect to server").Base(err)
  69. }
  70. return singbridge.CopyConn(ctx, inboundConn, link, conn)
  71. }