snowflake.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. package snowflake
  2. import (
  3. "errors"
  4. "fmt"
  5. "net"
  6. "net/url"
  7. "strconv"
  8. "strings"
  9. pt "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/goptlib"
  10. "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/lyrebird/transports/base"
  11. sf "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/client/lib"
  12. "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/common/event"
  13. "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/common/proxy"
  14. )
  15. const transportName = "snowflake"
  16. type sfEventLogger struct {
  17. onEventCallback func(e base.TransportEvent)
  18. }
  19. func (el *sfEventLogger) OnNewSnowflakeEvent(e event.SnowflakeEvent) {
  20. if el.onEventCallback != nil {
  21. el.onEventCallback(e)
  22. }
  23. }
  24. type Transport struct{}
  25. // Name returns the name of the snowflake transport protocol.
  26. func (t *Transport) Name() string {
  27. return transportName
  28. }
  29. // ClientFactory returns a new snowflakeClientFactory instance.
  30. func (t *Transport) ClientFactory(stateDir string) (base.ClientFactory, error) {
  31. cf := &snowflakeClientFactory{transport: t}
  32. return cf, nil
  33. }
  34. // ServerFactory is not implemented for snowflake
  35. func (t *Transport) ServerFactory(stateDir string, args *pt.Args) (base.ServerFactory, error) {
  36. return nil, errors.New("ServerFactory not implemented for the snowflake transport")
  37. }
  38. type snowflakeClientFactory struct {
  39. transport base.Transport
  40. eventLogger *sfEventLogger
  41. }
  42. func (cf *snowflakeClientFactory) Transport() base.Transport {
  43. return cf.transport
  44. }
  45. func (cf *snowflakeClientFactory) ParseArgs(args *pt.Args) (interface{}, error) {
  46. config := sf.ClientConfig{}
  47. if arg, ok := args.Get("ampcache"); ok {
  48. config.AmpCacheURL = arg
  49. }
  50. if arg, ok := args.Get("sqsqueue"); ok {
  51. config.SQSQueueURL = arg
  52. }
  53. if arg, ok := args.Get("sqscreds"); ok {
  54. config.SQSCredsStr = arg
  55. }
  56. if arg, ok := args.Get("fronts"); ok {
  57. if arg != "" {
  58. config.FrontDomains = strings.Split(strings.TrimSpace(arg), ",")
  59. }
  60. } else if arg, ok := args.Get("front"); ok {
  61. config.FrontDomains = strings.Split(strings.TrimSpace(arg), ",")
  62. }
  63. if arg, ok := args.Get("ice"); ok {
  64. config.ICEAddresses = strings.Split(strings.TrimSpace(arg), ",")
  65. }
  66. if arg, ok := args.Get("max"); ok {
  67. max, err := strconv.Atoi(arg)
  68. if err != nil {
  69. return nil, fmt.Errorf("Invalid SOCKS arg: max=%s", arg)
  70. }
  71. config.Max = max
  72. }
  73. if arg, ok := args.Get("url"); ok {
  74. config.BrokerURL = arg
  75. }
  76. if arg, ok := args.Get("utls-nosni"); ok {
  77. switch strings.ToLower(arg) {
  78. case "true", "yes":
  79. config.UTLSRemoveSNI = true
  80. }
  81. }
  82. if arg, ok := args.Get("utls-imitate"); ok {
  83. config.UTLSClientID = arg
  84. }
  85. if arg, ok := args.Get("fingerprint"); ok {
  86. config.BridgeFingerprint = arg
  87. }
  88. if arg, ok := args.Get("proxy"); ok {
  89. outboundProxy, err := url.Parse(arg)
  90. if err != nil {
  91. return nil, fmt.Errorf("Invalid SOCKS arg: proxy=%s", arg)
  92. }
  93. if err := proxy.CheckProxyProtocolSupport(outboundProxy); err != nil {
  94. return nil, fmt.Errorf("proxy is not supported: %s", err.Error())
  95. }
  96. client := proxy.NewSocks5UDPClient(outboundProxy)
  97. conn, err := client.ListenPacket("udp", nil)
  98. if err != nil {
  99. return nil, fmt.Errorf("proxy test failure: %s", err.Error())
  100. }
  101. conn.Close()
  102. config.CommunicationProxy = outboundProxy
  103. }
  104. return config, nil
  105. }
  106. func (cf *snowflakeClientFactory) OnEvent(f func(e base.TransportEvent)) {
  107. cf.eventLogger = &sfEventLogger{
  108. onEventCallback: f,
  109. }
  110. }
  111. func (cf *snowflakeClientFactory) Dial(network, address string, dialFn base.DialFunc, args interface{}) (net.Conn, error) {
  112. config, ok := args.(sf.ClientConfig)
  113. if !ok {
  114. return nil, errors.New("invalid type for args")
  115. }
  116. transport, err := sf.NewSnowflakeClient(config)
  117. if err != nil {
  118. return nil, err
  119. }
  120. transport.AddSnowflakeEventListener(cf.eventLogger)
  121. return transport.Dial()
  122. }