github.com/ipfans/trojan-go@v0.11.0/url/option.go (about)

     1  package url
     2  
     3  import (
     4  	"encoding/json"
     5  	"flag"
     6  	"net"
     7  	"strconv"
     8  	"strings"
     9  
    10  	"github.com/ipfans/trojan-go/common"
    11  	"github.com/ipfans/trojan-go/log"
    12  	"github.com/ipfans/trojan-go/option"
    13  	"github.com/ipfans/trojan-go/proxy"
    14  )
    15  
    16  const Name = "URL"
    17  
    18  type Websocket struct {
    19  	Enabled bool   `json:"enabled"`
    20  	Host    string `json:"host"`
    21  	Path    string `json:"path"`
    22  }
    23  
    24  type TLS struct {
    25  	SNI string `json:"sni"`
    26  }
    27  
    28  type Shadowsocks struct {
    29  	Enabled  bool   `json:"enabled"`
    30  	Method   string `json:"method"`
    31  	Password string `json:"password"`
    32  }
    33  
    34  type Mux struct {
    35  	Enabled bool `json:"enabled"`
    36  }
    37  
    38  type API struct {
    39  	Enabled bool   `json:"enabled"`
    40  	APIHost string `json:"api_addr"`
    41  	APIPort int    `json:"api_port"`
    42  }
    43  
    44  type UrlConfig struct {
    45  	RunType     string   `json:"run_type"`
    46  	LocalAddr   string   `json:"local_addr"`
    47  	LocalPort   int      `json:"local_port"`
    48  	RemoteAddr  string   `json:"remote_addr"`
    49  	RemotePort  int      `json:"remote_port"`
    50  	Password    []string `json:"password"`
    51  	Websocket   `json:"websocket"`
    52  	Shadowsocks `json:"shadowsocks"`
    53  	TLS         `json:"ssl"`
    54  	Mux         `json:"mux"`
    55  	API         `json:"api"`
    56  }
    57  
    58  type url struct {
    59  	url    *string
    60  	option *string
    61  }
    62  
    63  func (u *url) Name() string {
    64  	return Name
    65  }
    66  
    67  func (u *url) Handle() error {
    68  	if u.url == nil || *u.url == "" {
    69  		return common.NewError("")
    70  	}
    71  	info, err := NewShareInfoFromURL(*u.url)
    72  	if err != nil {
    73  		log.Fatal(err)
    74  	}
    75  	wsEnabled := false
    76  	if info.Type == ShareInfoTypeWebSocket {
    77  		wsEnabled = true
    78  	}
    79  	ssEnabled := false
    80  	ssPassword := ""
    81  	ssMethod := ""
    82  	if strings.HasPrefix(info.Encryption, "ss;") {
    83  		ssEnabled = true
    84  		ssConfig := strings.Split(info.Encryption[3:], ":")
    85  		if len(ssConfig) != 2 {
    86  			log.Fatalf("invalid shadowsocks config: %s", info.Encryption)
    87  		}
    88  		ssMethod = ssConfig[0]
    89  		ssPassword = ssConfig[1]
    90  	}
    91  	muxEnabled := false
    92  	listenHost := "127.0.0.1"
    93  	listenPort := 1080
    94  
    95  	apiEnabled := false
    96  	apiHost := "127.0.0.1"
    97  	apiPort := 10000
    98  
    99  	options := strings.Split(*u.option, ";")
   100  	for _, o := range options {
   101  		key := ""
   102  		val := ""
   103  		l := strings.Split(o, "=")
   104  		if len(l) != 2 {
   105  			log.Fatal("option format error, no \"key=value\" pair found:", o)
   106  		}
   107  		key = l[0]
   108  		val = l[1]
   109  		switch key {
   110  		case "mux":
   111  			muxEnabled, err = strconv.ParseBool(val)
   112  			if err != nil {
   113  				log.Fatal(err)
   114  			}
   115  		case "listen":
   116  			h, p, err := net.SplitHostPort(val)
   117  			if err != nil {
   118  				log.Fatal(err)
   119  			}
   120  			listenHost = h
   121  			lp, err := strconv.Atoi(p)
   122  			if err != nil {
   123  				log.Fatal(err)
   124  			}
   125  			listenPort = lp
   126  		case "api":
   127  			apiEnabled = true
   128  			h, p, err := net.SplitHostPort(val)
   129  			if err != nil {
   130  				log.Fatal(err)
   131  			}
   132  			apiHost = h
   133  			lp, err := strconv.Atoi(p)
   134  			if err != nil {
   135  				log.Fatal(err)
   136  			}
   137  			apiPort = lp
   138  		default:
   139  			log.Fatal("invalid option", o)
   140  		}
   141  	}
   142  	config := UrlConfig{
   143  		RunType:    "client",
   144  		LocalAddr:  listenHost,
   145  		LocalPort:  listenPort,
   146  		RemoteAddr: info.TrojanHost,
   147  		RemotePort: int(info.Port),
   148  		Password:   []string{info.TrojanPassword},
   149  		TLS: TLS{
   150  			SNI: info.SNI,
   151  		},
   152  		Websocket: Websocket{
   153  			Enabled: wsEnabled,
   154  			Path:    info.Path,
   155  			Host:    info.Host,
   156  		},
   157  		Mux: Mux{
   158  			Enabled: muxEnabled,
   159  		},
   160  		Shadowsocks: Shadowsocks{
   161  			Enabled:  ssEnabled,
   162  			Password: ssPassword,
   163  			Method:   ssMethod,
   164  		},
   165  		API: API{
   166  			Enabled: apiEnabled,
   167  			APIHost: apiHost,
   168  			APIPort: apiPort,
   169  		},
   170  	}
   171  	data, err := json.Marshal(&config)
   172  	if err != nil {
   173  		log.Fatal(err)
   174  	}
   175  	log.Debug(string(data))
   176  	client, err := proxy.NewProxyFromConfigData(data, true)
   177  	if err != nil {
   178  		log.Fatal(err)
   179  	}
   180  	return client.Run()
   181  }
   182  
   183  func (u *url) Priority() int {
   184  	return 10
   185  }
   186  
   187  func init() {
   188  	option.RegisterHandler(&url{
   189  		url:    flag.String("url", "", "Setup trojan-go client with a url link"),
   190  		option: flag.String("url-option", "mux=true;listen=127.0.0.1:1080", "URL mode options"),
   191  	})
   192  }