diff --git a/README.md b/README.md index 680f161b..b84f2b23 100644 --- a/README.md +++ b/README.md @@ -22,26 +22,16 @@ go get -u -v github.com/shadowsocks/go-shadowsocks2 ## Basic Usage -### Key generation - -A random key is almost always better than a password. You can generate a base64url-encoded 16-byte random key with - -```sh -go-shadowsocks2 -keygen 16 -``` - ### Server -Start a server listening on port 8848 using `aes-128-gcm` AEAD cipher with a base64url-encoded 16-byte key. - +Start a server listening on port 8488 using `aes-128-gcm` AEAD cipher with password `your-password`. ```sh -go-shadowsocks2 -s :8488 -cipher aes-128-gcm -key k5yEIX5ciUDpkpdtvZm7zQ== -verbose +go-shadowsocks2 -s ss://aes-128-gcm:your-password@:8488 -verbose ``` - ### Client Start a client connecting to the above server. The client listens on port 1080 for incoming SOCKS5 @@ -49,15 +39,37 @@ connections, and tunnels UDP packets received on port 1080 and port 1081 to 8.8. respectively. ```sh -go-shadowsocks2 -c [server_address]:8488 -cipher aes-128-gcm -key k5yEIX5ciUDpkpdtvZm7zQ== \ +go-shadowsocks2 -c ss://aes-128-gcm:your-password@[server_address]:8488 \ -socks :1080 -udptun :1080=8.8.8.8:53,:1081=8.8.4.4:53 -verbose ``` +Replace `[server_address]` with the server's public address. ## Advanced Usage +### Use random keys instead of passwords + +A random key is almost always better than a password. Generate a base64url-encoded 16-byte random key + +```sh +go-shadowsocks2 -keygen 16 +``` + +Start a server listening on port 8848 using `aes-128-gcm` AEAD cipher with the key generated above. + +```sh +go-shadowsocks2 -s :8488 -cipher aes-128-gcm -key k5yEIX5ciUDpkpdtvZm7zQ== -verbose +``` + +And the corresponding client to connect to it. + +```sh +go-shadowsocks2 -c [server_address]:8488 -cipher aes-128-gcm -key k5yEIX5ciUDpkpdtvZm7zQ== -verbose +``` + + ### Netfilter TCP redirect (Linux only) The client offers `-redir` and `-redir6` (for IPv6) options to handle TCP connections diff --git a/main.go b/main.go index 7a7ae91f..ec6efbb9 100644 --- a/main.go +++ b/main.go @@ -7,6 +7,7 @@ import ( "fmt" "io" "log" + "net/url" "os" "os/signal" "strings" @@ -48,8 +49,8 @@ func main() { flag.StringVar(&flags.Key, "key", "", "base64url-encoded key (derive from password if empty)") flag.IntVar(&flags.Keygen, "keygen", 0, "generate a base64url-encoded random key of given length in byte") flag.StringVar(&flags.Password, "password", "", "password") - flag.StringVar(&flags.Server, "s", "", "server listen address") - flag.StringVar(&flags.Client, "c", "", "client connect address") + flag.StringVar(&flags.Server, "s", "", "server listen address or url") + flag.StringVar(&flags.Client, "c", "", "client connect address or url") flag.StringVar(&flags.Socks, "socks", ":1080", "(client-only) SOCKS listen address") flag.StringVar(&flags.RedirTCP, "redir", "", "(client-only) redirect TCP from this address") flag.StringVar(&flags.RedirTCP6, "redir6", "", "(client-only) redirect TCP IPv6 from this address") @@ -79,42 +80,81 @@ func main() { key = k } - ciph, err := core.PickCipher(flags.Cipher, key, flags.Password) - if err != nil { - log.Fatal(err) - } - if flags.Client != "" { // client mode + addr := flags.Client + cipher := flags.Cipher + password := flags.Password + + if strings.HasPrefix(addr, "ss://") { + u, err := url.Parse(addr) + if err != nil { + log.Fatal(err) + } + + addr = u.Host + if u.User != nil { + cipher = u.User.Username() + password, _ = u.User.Password() + } + } + + ciph, err := core.PickCipher(cipher, key, password) + if err != nil { + log.Fatal(err) + } + if flags.UDPTun != "" { for _, tun := range strings.Split(flags.UDPTun, ",") { p := strings.Split(tun, "=") - go udpLocal(p[0], flags.Client, p[1], ciph) + go udpLocal(p[0], addr, p[1], ciph) } } if flags.TCPTun != "" { for _, tun := range strings.Split(flags.TCPTun, ",") { p := strings.Split(tun, "=") - go tcpTun(p[0], flags.Client, p[1], ciph) + go tcpTun(p[0], addr, p[1], ciph) } } if flags.Socks != "" { - go socksLocal(flags.Socks, flags.Client, ciph) + go socksLocal(flags.Socks, addr, ciph) } if flags.RedirTCP != "" { - go redirLocal(flags.RedirTCP, flags.Client, ciph) + go redirLocal(flags.RedirTCP, addr, ciph) } if flags.RedirTCP6 != "" { - go redir6Local(flags.RedirTCP6, flags.Client, ciph) + go redir6Local(flags.RedirTCP6, addr, ciph) } } if flags.Server != "" { // server mode - go udpRemote(flags.Server, ciph) - go tcpRemote(flags.Server, ciph) + addr := flags.Server + cipher := flags.Cipher + password := flags.Password + + if strings.HasPrefix(addr, "ss://") { + u, err := url.Parse(addr) + if err != nil { + log.Fatal(err) + } + + addr = u.Host + if u.User != nil { + cipher = u.User.Username() + password, _ = u.User.Password() + } + } + + ciph, err := core.PickCipher(cipher, key, password) + if err != nil { + log.Fatal(err) + } + + go udpRemote(addr, ciph) + go tcpRemote(addr, ciph) } sigCh := make(chan os.Signal, 1)