123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- package snowflake
- import (
- "errors"
- "fmt"
- "net"
- "net/url"
- "strconv"
- "strings"
- pt "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/goptlib"
- "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/lyrebird/transports/base"
- sf "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/client/lib"
- "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/common/event"
- "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/common/proxy"
- )
- const transportName = "snowflake"
- type sfEventLogger struct {
- onEventCallback func(e base.TransportEvent)
- }
- func (el *sfEventLogger) OnNewSnowflakeEvent(e event.SnowflakeEvent) {
- if el.onEventCallback != nil {
- el.onEventCallback(e)
- }
- }
- type Transport struct{}
- // Name returns the name of the snowflake transport protocol.
- func (t *Transport) Name() string {
- return transportName
- }
- // ClientFactory returns a new snowflakeClientFactory instance.
- func (t *Transport) ClientFactory(stateDir string) (base.ClientFactory, error) {
- cf := &snowflakeClientFactory{transport: t}
- return cf, nil
- }
- // ServerFactory is not implemented for snowflake
- func (t *Transport) ServerFactory(stateDir string, args *pt.Args) (base.ServerFactory, error) {
- return nil, errors.New("ServerFactory not implemented for the snowflake transport")
- }
- type snowflakeClientFactory struct {
- transport base.Transport
- eventLogger *sfEventLogger
- }
- func (cf *snowflakeClientFactory) Transport() base.Transport {
- return cf.transport
- }
- func (cf *snowflakeClientFactory) ParseArgs(args *pt.Args) (interface{}, error) {
- config := sf.ClientConfig{}
- if arg, ok := args.Get("ampcache"); ok {
- config.AmpCacheURL = arg
- }
- if arg, ok := args.Get("sqsqueue"); ok {
- config.SQSQueueURL = arg
- }
- if arg, ok := args.Get("sqscreds"); ok {
- config.SQSCredsStr = arg
- }
- if arg, ok := args.Get("fronts"); ok {
- if arg != "" {
- config.FrontDomains = strings.Split(strings.TrimSpace(arg), ",")
- }
- } else if arg, ok := args.Get("front"); ok {
- config.FrontDomains = strings.Split(strings.TrimSpace(arg), ",")
- }
- if arg, ok := args.Get("ice"); ok {
- config.ICEAddresses = strings.Split(strings.TrimSpace(arg), ",")
- }
- if arg, ok := args.Get("max"); ok {
- max, err := strconv.Atoi(arg)
- if err != nil {
- return nil, fmt.Errorf("Invalid SOCKS arg: max=%s", arg)
- }
- config.Max = max
- }
- if arg, ok := args.Get("url"); ok {
- config.BrokerURL = arg
- }
- if arg, ok := args.Get("utls-nosni"); ok {
- switch strings.ToLower(arg) {
- case "true", "yes":
- config.UTLSRemoveSNI = true
- }
- }
- if arg, ok := args.Get("utls-imitate"); ok {
- config.UTLSClientID = arg
- }
- if arg, ok := args.Get("fingerprint"); ok {
- config.BridgeFingerprint = arg
- }
- if arg, ok := args.Get("proxy"); ok {
- outboundProxy, err := url.Parse(arg)
- if err != nil {
- return nil, fmt.Errorf("Invalid SOCKS arg: proxy=%s", arg)
- }
- if err := proxy.CheckProxyProtocolSupport(outboundProxy); err != nil {
- return nil, fmt.Errorf("proxy is not supported: %s", err.Error())
- }
- client := proxy.NewSocks5UDPClient(outboundProxy)
- conn, err := client.ListenPacket("udp", nil)
- if err != nil {
- return nil, fmt.Errorf("proxy test failure: %s", err.Error())
- }
- conn.Close()
- config.CommunicationProxy = outboundProxy
- }
- return config, nil
- }
- func (cf *snowflakeClientFactory) OnEvent(f func(e base.TransportEvent)) {
- cf.eventLogger = &sfEventLogger{
- onEventCallback: f,
- }
- }
- func (cf *snowflakeClientFactory) Dial(network, address string, dialFn base.DialFunc, args interface{}) (net.Conn, error) {
- config, ok := args.(sf.ClientConfig)
- if !ok {
- return nil, errors.New("invalid type for args")
- }
- transport, err := sf.NewSnowflakeClient(config)
- if err != nil {
- return nil, err
- }
- transport.AddSnowflakeEventListener(cf.eventLogger)
- return transport.Dial()
- }
|