Skip to content

Commit

Permalink
Merge branch 'release/0.6'
Browse files Browse the repository at this point in the history
  • Loading branch information
cyfdecyf committed Jan 23, 2013
2 parents 3cec162 + 9ebf730 commit bfe063b
Show file tree
Hide file tree
Showing 15 changed files with 610 additions and 237 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
0.6 (2013-01-23)

* Generate ciphers on demand (encryption table cache is removed)
* Support RC4 encryption
41 changes: 22 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,27 @@
# shadowsocks-go #
# shadowsocks-go

Current version: 0.6

shadowsocks-go is a lightweight tunnel proxy which can help you get through firewalls. It is a port of [shadowsocks](https://github.com/clowwindy/shadowsocks).

The protocol is compatible with the origin shadowsocks (if both have been upgraded to the latest version).

# Install #
# Install

Compiled client binaries are provided on [google code](http://code.google.com/p/shadowsocks-go/downloads/list).
Compiled client binaries are provided on [google code](http://code.google.com/p/shadowsocks-go/downloads/list). (Compiled with cgo disabled.)

You can also install from source (assume you have go installed):

On server, run

```
# on server
go get github.com/shadowsocks/shadowsocks-go/cmd/shadowsocks-server
```

On client, run

```
# on client
go get github.com/shadowsocks/shadowsocks-go/cmd/shadowsocks-local
```

# Usage #
It's recommend to disable cgo when compiling shadowsocks-go. This will prevent the go runtime from creating too many threads for dns lookup.

# Usage

Both the server and client program will look for `config.json` in the current directory. You can use `-c` option to specify another configuration file.

Expand All @@ -32,6 +31,7 @@ Configuration file is in json format and has the same syntax with [shadowsocks-n
server your server ip or hostname
server_port server port
local_port local socks5 proxy port
method encryption method, null by default, or use "rc4"
password a password used to encrypt transfer
timeout server option, in seconds
```
Expand All @@ -44,13 +44,13 @@ On client, run `shadowsocks-local`. Change proxy settings of your browser to
SOCKS5 127.0.0.1:local_port
```

## Command line options ##
## Command line options

Command line options can override settings from configuration files.
Command line options can override settings from configuration files. Use `-h` option to see all available options.

```
shadowsocks-local -s server_name -p server_port -l local_port -k password -c config.json
shadowsocks-server -p server_port -k password -t timeout -c config.json
shadowsocks-local -s server_name -p server_port -l local_port -k password -m rc4 -c config.json
shadowsocks-server -p server_port -k password -t timeout -m rc4 -c config.json
```

Use `-d` option to enable debug message.
Expand All @@ -72,13 +72,16 @@ The server can support users with different passwords. Each user will be served

```
port_password specify multiple ports and passwords to support multiple users
cache_enctable store computed encryption table on disk to speedup server startup
```

Here's a sample configuration [`server-multi-port.json`](https://github.com/shadowsocks/shadowsocks-go/blob/master/sample-config/server-multi-port.json). Given `port_password`, server program will ignore `server_port` and `password` options.

Enabling `cache_enctable` is recommended if you have more than 20 different passwords. Unused password will not be deleted, so you may need to delete the file `table.cache` if it grows too big.

### Update port password for a running server ###
### Update port password for a running server

Edit the config file used to start the server, then send `SIGHUP` to the server process.

# Note to OpenVZ users

**Use OpenVZ VM that supports vswap**. Otherwise, the OS will incorrectly account much more memory than actually used. shadowsocks-go on OpenVZ VM with vswap takes about 3MB memory after startup. (Refer to [this issue](https://github.com/shadowsocks/shadowsocks-go/issues/3) for more details.)

If vswap is not an option and memory usage is a problem for you, try [shadowsocks-libuv](https://github.com/dndx/shadowsocks-libuv).
1 change: 1 addition & 0 deletions TODO
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add test script to test both server and client.
171 changes: 171 additions & 0 deletions cmd/shadowsocks-httpget/httpget.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
package main

import (
"flag"
"fmt"
ss "github.com/shadowsocks/shadowsocks-go/shadowsocks"
"io"
"math"
"net"
"net/http"
"net/url"
"os"
"runtime"
"strconv"
"strings"
"time"
)

var config struct {
server string
port int
passwd string
method string
core int
nconn int
nreq int
// nsec int
}

var debug ss.DebugLog

func doOneRequest(client *http.Client, uri string, buf []byte) (err error) {
resp, err := client.Get(uri)
if err != nil {
fmt.Printf("GET %s error: %v\n", uri, err)
return err
}
for err == nil {
_, err = resp.Body.Read(buf)
if debug {
debug.Println(string(buf))
}
}
if err != io.EOF {
fmt.Printf("Read %s response error: %v\n", uri, err)
} else {
err = nil
}
return
}

func get(connid int, uri, serverAddr string, rawAddr []byte, cipher ss.Cipher, done chan []time.Duration) {
reqDone := 0
reqTime := make([]time.Duration, config.nreq, config.nreq)
defer func() {
done <- reqTime[:reqDone]
}()
tr := &http.Transport{
Dial: func(_, _ string) (net.Conn, error) {
return ss.DialWithRawAddr(rawAddr, serverAddr, cipher.Copy())
},
}

buf := make([]byte, 8192)
client := &http.Client{Transport: tr}
for ; reqDone < config.nreq; reqDone++ {
start := time.Now()
if err := doOneRequest(client, uri, buf); err != nil {
return
}
reqTime[reqDone] = time.Now().Sub(start)

if (reqDone+1)%1000 == 0 {
fmt.Printf("conn %d finished %d get requests\n", connid, reqDone+1)
}
}
}

func main() {
flag.StringVar(&config.server, "s", "127.0.0.1", "server:port")
flag.IntVar(&config.port, "p", 0, "server:port")
flag.IntVar(&config.core, "core", 1, "number of CPU cores to use")
flag.StringVar(&config.passwd, "k", "", "password")
flag.StringVar(&config.method, "m", "", "encryption method, use empty string or rc4")
flag.IntVar(&config.nconn, "nc", 1, "number of connection to server")
flag.IntVar(&config.nreq, "nr", 1, "number of request for each connection")
// flag.IntVar(&config.nsec, "ns", 0, "run how many seconds for each connection")
flag.BoolVar((*bool)(&debug), "d", false, "print http response body for debugging")

flag.Parse()

if config.server == "" || config.port == 0 || config.passwd == "" || len(flag.Args()) != 1 {
fmt.Printf("Usage: %s -s <server> -p <port> -k <password> <url>\n", os.Args[0])
os.Exit(1)
}
if err := ss.SetDefaultCipher(config.method); err != nil {
fmt.Println(err)
os.Exit(1)
}

runtime.GOMAXPROCS(config.core)
uri := flag.Arg(0)
if !strings.HasPrefix(uri, "http://") {
uri = "http://" + uri
}

cipher, err := ss.NewCipher(config.passwd)
if err != nil {
fmt.Println("Error creating cipher:", err)
os.Exit(1)
}
serverAddr := net.JoinHostPort(config.server, strconv.Itoa(config.port))

parsedURL, err := url.Parse(uri)
if err != nil {
fmt.Println("Error parsing url:", err)
os.Exit(1)
}
host, _, err := net.SplitHostPort(parsedURL.Host)
if err != nil {
host = net.JoinHostPort(parsedURL.Host, "80")
} else {
host = parsedURL.Host
}
// fmt.Println(host)
rawAddr, err := ss.RawAddr(host)
if err != nil {
panic("Error getting raw address.")
return
}

done := make(chan []time.Duration)
for i := 1; i <= config.nconn; i++ {
go get(i, uri, serverAddr, rawAddr, cipher, done)
}

// collect request finish time
reqTime := make([]int64, config.nconn*config.nreq)
reqDone := 0
for i := 1; i <= config.nconn; i++ {
rt := <-done
for _, t := range rt {
reqTime[reqDone] = int64(t)
reqDone++
}
}

fmt.Println("number of total requests:", config.nconn*config.nreq)
fmt.Println("number of finished requests:", reqDone)
if reqDone == 0 {
return
}

// calculate average an standard deviation
reqTime = reqTime[:reqDone]
var sum int64
for _, d := range reqTime {
sum += d
}
avg := float64(sum) / float64(reqDone)

varSum := float64(0)
for _, d := range reqTime {
di := math.Abs(float64(d) - avg)
di *= di
varSum += di
}
stddev := math.Sqrt(varSum / float64(reqDone))
fmt.Println("\naverage time per request:", time.Duration(avg))
fmt.Println("standard deviation:", time.Duration(stddev))
}
Loading

0 comments on commit bfe063b

Please sign in to comment.