From 4cceeda98deb766ef801a6b70ebc3b7a061785b9 Mon Sep 17 00:00:00 2001 From: "rui.zheng" Date: Wed, 20 May 2015 11:01:44 +0800 Subject: [PATCH] add tls authentication --- README.md | 43 ++++++++++++++++++++++++++++++------------- client.go | 23 +++++++++++++++++++++-- main.go | 14 +++++++++----- socks5.go | 25 +++++++++++++++++++++++++ version.go | 2 +- 5 files changed, 86 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index c25891e..57b52b8 100644 --- a/README.md +++ b/README.md @@ -22,12 +22,20 @@ gost - GO Simple Tunnel 二进制文件下载:https://bintray.com/ginuerzh/gost/gost/v1.2/view + +#####v1.3 +* tls加密方式增加密码认证功能 +* 增加版本查看(-v参数) +* -p参数的默认值修改为空 + +二进制文件下载:https://bintray.com/ginuerzh/gost/gost/v1.3/view + ####参数说明 > -L=":8080": listen address > -P="": proxy for forward -> -S="": the server that connecting to +> -S="": the server that connect to > -cert="": cert file for tls @@ -35,7 +43,7 @@ gost - GO Simple Tunnel > -m="": tunnel cipher method -> -p="ginuerzh@gmail.com": tunnel cipher password +> -p="": tunnel cipher password > -sm="rc4-md5": shadowsocks cipher method @@ -45,25 +53,33 @@ gost - GO Simple Tunnel > -ws=false: use websocket for tunnel +> -v=false: print version + ####使用方法 #####服务器端: `gost -L=:8080` -#####服务器端有上层http代理: -`gost -L=:8080 -P=proxy_ip:port` +#####服务器端设置加密: +`gost -L=:8080 -m=aes-256-cfb -p=123456` -#####客户端(默认使用tls加密方法): +#####服务器端有上层http代理: +`gost -L=:8080 -m=aes-256-cfb -p=123456 -P=proxy_ip:port` + +#####客户端: `gost -L=:8899 -S=your_server_ip:8080` +#####客户端设置加密: +`gost -L=:8899 -S=your_server_ip:8080 -m=aes-256-cfb -p=123456` + #####客户端有上层http代理: -`gost -L=:8899 -S=your_server_ip:8080 -P=proxy_ip:port` +`gost -L=:8899 -S=your_server_ip:8080 -m=aes-256-cfb -p=123456 -P=proxy_ip:port` #####使用websocket tunnel * 服务器端 -`gost -L=:8080 -ws` +`gost -L=:8080 -m=aes-256-cfb -p=123456 -ws` * 客户端 -`gost -L=:8899 -S=your_server_ip:8080 -ws` +`gost -L=:8899 -S=your_server_ip:8080 -m=aes-256-cfb -p=123456 -ws` #####作为shadowsocks服务器: gost支持作为shadowsocks服务器运行(-ss参数),这样就可以让android手机通过shadowsocks客户端(影梭)使用代理了。 @@ -80,7 +96,7 @@ gost支持作为shadowsocks服务器运行(-ss参数),这样就可以让androi 无需特殊设置,shadowsocks模式只与客户端有关,与服务端无关。 * 客户端: -`gost -L :8899 -S demo-project-gostwebsocket.c9.io -ws -sm=rc4-md5 -sp=ginuerzh@gmail.com -ss` +`gost -L :8899 -S demo-project-gostwebsocket.c9.io -sm=rc4-md5 -sp=ginuerzh@gmail.com -ss` 在手机的shadowsocks软件中设置好服务器(运行gost电脑的IP),端口(8899),加密方法和密码就可以使用了。 @@ -97,9 +113,9 @@ Client端通过-m参数设置加密方式,默认为不加密(-m参数为空) 如果设置的加密方式不被支持,则默认为不加密。 -当设置的加密方式为tls时,-p参数无效。 +当设置的加密方式为tls时,可通过-p参数设置验证密码(若服务端支持密码验证功能)。 -当设置的加密方式为非tls时,通过-p参数设置加密密码,且不能为空,默认密码为ginuerzh@gmail.com;-p参数必须与Server端的-p参数相同。 +当设置的加密方式为非tls时,通过-p参数设置加密密码,且不能为空;-p参数必须与Server端的-p参数相同。 #####Server @@ -111,6 +127,7 @@ Server端通过-m参数设置加密方式,默认为不加密(-m参数为空) 如果设置了加密方式(-m参数不为空),client端必须使用与Server端相同的加密方式。 -当设置的加密方式为tls时,-p参数无效;-key参数可手动指定公钥文件,-cert参数可手动指定私钥文件,如果未指定,则使用默认的公钥与私钥。 +当设置的加密方式为tls时,-key参数可手动指定公钥文件,-cert参数可手动指定私钥文件,如果未指定,则使用默认的公钥与私钥。 +可通过-p参数设定验证密码(可选),若设置,则客户端必须通过-p参数设置相同的密码。 -当设置的加密方式为非tls时,-key,-cert参数无效;通过-p参数设置加密密码,且不能为空,默认密码为ginuerzh@gmail.com。 +当设置的加密方式为非tls时,-key,-cert参数无效;通过-p参数设置加密密码,且不能为空。 diff --git a/client.go b/client.go index 2ee82fc..b934735 100644 --- a/client.go +++ b/client.go @@ -60,6 +60,9 @@ func clientMethodSelected(method uint8, conn net.Conn) (net.Conn, error) { switch method { case MethodTLS: conn = tls.Client(conn, &tls.Config{InsecureSkipVerify: true}) + if err := cliTLSAuth(conn); err != nil { + return nil, err + } case MethodAES128, MethodAES192, MethodAES256, MethodDES, MethodBF, MethodCAST5, MethodRC4MD5, MethodRC4, MethodTable: cipher, err := shadowsocks.NewCipher(Methods[method], Password) @@ -75,6 +78,22 @@ func clientMethodSelected(method uint8, conn net.Conn) (net.Conn, error) { return conn, nil } +func cliTLSAuth(conn net.Conn) error { + if err := gosocks5.NewUserPassRequest( + gosocks5.UserPassVer, "", Password).Write(conn); err != nil { + return err + } + res, err := gosocks5.ReadUserPassResponse(conn) + if err != nil { + return err + } + if res.Status != gosocks5.Succeeded { + return gosocks5.ErrAuthFailure + } + + return nil +} + func cliHandle(conn net.Conn) { defer conn.Close() /* @@ -284,14 +303,14 @@ func handleHttp(req *http.Request, conn net.Conn, sconn net.Conn) { rep, err := gosocks5.ReadReply(sconn) if err != nil || rep.Rep != gosocks5.Succeeded { conn.Write([]byte("HTTP/1.1 503 Service unavailable\r\n" + - "Proxy-Agent: gost/1.0\r\n\r\n")) + "Proxy-Agent: gost/" + Version + "\r\n\r\n")) return } if req.Method == "CONNECT" { if _, err = conn.Write( []byte("HTTP/1.1 200 Connection established\r\n" + - "Proxy-Agent: gost/2.0\r\n\r\n")); err != nil { + "Proxy-Agent: gost/" + Version + "\r\n\r\n")); err != nil { return } } else { diff --git a/main.go b/main.go index 2525301..43f3e71 100644 --- a/main.go +++ b/main.go @@ -15,22 +15,22 @@ var ( SMethod, SPassword string Method, Password string CertFile, KeyFile string + PrintVersion bool ) func init() { - printVersion() - flag.StringVar(&Proxy, "P", "", "proxy for forward") - flag.StringVar(&Saddr, "S", "", "the server that connecting to") + flag.StringVar(&Saddr, "S", "", "the server that connect to") flag.StringVar(&Laddr, "L", ":8080", "listen address") flag.StringVar(&Method, "m", "", "tunnel cipher method") - flag.StringVar(&Password, "p", "ginuerzh@gmail.com", "tunnel cipher password") + flag.StringVar(&Password, "p", "", "tunnel cipher password") flag.StringVar(&CertFile, "cert", "", "cert file for tls") flag.StringVar(&KeyFile, "key", "", "key file for tls") flag.BoolVar(&Shadows, "ss", false, "run as shadowsocks server") flag.BoolVar(&Websocket, "ws", false, "use websocket for tunnel") flag.StringVar(&SMethod, "sm", "rc4-md5", "shadowsocks cipher method") flag.StringVar(&SPassword, "sp", "ginuerzh@gmail.com", "shadowsocks cipher password") + flag.BoolVar(&PrintVersion, "v", false, "print version") flag.Parse() log.SetFlags(log.LstdFlags | log.Lshortfile) @@ -43,7 +43,11 @@ var ( ) func main() { - //log.Fatal(gost.Run()) + if PrintVersion { + printVersion() + return + } + if len(Saddr) == 0 { var server Server if Websocket { diff --git a/socks5.go b/socks5.go index aae3721..ffc1296 100644 --- a/socks5.go +++ b/socks5.go @@ -125,6 +125,9 @@ func serverMethodSelected(method uint8, conn net.Conn) (net.Conn, error) { return nil, err } conn = tls.Server(conn, &tls.Config{Certificates: []tls.Certificate{cert}}) + if err := svrTLSAuth(conn); err != nil { + return nil, err + } case MethodAES128, MethodAES192, MethodAES256, MethodDES, MethodBF, MethodCAST5, MethodRC4MD5, MethodRC4, MethodTable: cipher, err := shadowsocks.NewCipher(Methods[method], Password) @@ -139,6 +142,28 @@ func serverMethodSelected(method uint8, conn net.Conn) (net.Conn, error) { return conn, nil } +func svrTLSAuth(conn net.Conn) error { + req, err := gosocks5.ReadUserPassRequest(conn) + if err != nil { + return err + } + + if len(Password) > 0 && req.Password != Password { + if err := gosocks5.NewUserPassResponse( + gosocks5.UserPassVer, gosocks5.Failure).Write(conn); err != nil { + return err + } + return gosocks5.ErrAuthFailure + } + + if err := gosocks5.NewUserPassResponse( + gosocks5.UserPassVer, gosocks5.Succeeded).Write(conn); err != nil { + return err + } + + return nil +} + func socks5Handle(conn net.Conn) { defer conn.Close() diff --git a/version.go b/version.go index 1924257..e19ed97 100644 --- a/version.go +++ b/version.go @@ -5,7 +5,7 @@ import ( ) const ( - Version = "1.2" + Version = "1.3" ) func printVersion() {