add new cipher method tls-auth
This commit is contained in:
parent
0d98dd3d6c
commit
573d31ae23
19
README.md
19
README.md
@ -16,6 +16,12 @@ gost - GO Simple Tunnel
|
||||
Google讨论组: https://groups.google.com/d/forum/go-gost
|
||||
|
||||
#### 版本更新
|
||||
##### v1.6
|
||||
* 增加tls-auth加密方式,此方式必须设置认证密码(-p参数),原tls加密方式与v1.3版以前兼容
|
||||
|
||||
###### Bug fix:
|
||||
* 修正当不设置上层代理时,连接出错问题
|
||||
|
||||
##### v1.5
|
||||
* 支持设置上层socks5代理(注: http tunnel不支持)
|
||||
* 支持上层代理用户名密码验证
|
||||
@ -110,7 +116,7 @@ gost支持作为shadowsocks服务器运行(-ss参数),这样就可以让androi
|
||||
|
||||
#### tunnel加密说明
|
||||
##### 目前支持的加密方法
|
||||
tls, aes-128-cfb, aes-192-cfb, aes-256-cfb, des-cfb, bf-cfb, cast5-cfb, rc4-md5, rc4, table
|
||||
tls, tls-auth, aes-128-cfb, aes-192-cfb, aes-256-cfb, des-cfb, bf-cfb, cast5-cfb, rc4-md5, rc4, table
|
||||
|
||||
##### Client
|
||||
|
||||
@ -118,7 +124,7 @@ Client端通过-m参数设置加密方式,默认为不加密(-m参数为空)
|
||||
|
||||
如果设置的加密方式不被支持,则默认为不加密。
|
||||
|
||||
当设置的加密方式为tls时,可通过-p参数设置验证密码(若服务端支持密码验证功能)。
|
||||
当设置的加密方式为tls时,-p参数无效。
|
||||
|
||||
当设置的加密方式为非tls时,通过-p参数设置加密密码,且不能为空;-p参数必须与Server端的-p参数相同。
|
||||
|
||||
@ -132,7 +138,10 @@ Server端通过-m参数设置加密方式,默认为不加密(-m参数为空)
|
||||
|
||||
如果设置了加密方式(-m参数不为空),client端必须使用与Server端相同的加密方式。
|
||||
|
||||
当设置的加密方式为tls时,-key参数可手动指定公钥文件,-cert参数可手动指定私钥文件,如果未指定,则使用默认的公钥与私钥。
|
||||
可通过-p参数设定验证密码(可选),若设置,则客户端必须通过-p参数设置相同的密码。
|
||||
当设置的加密方式为tls,tls-auth时,-key参数可手动指定公钥文件,-cert参数可手动指定私钥文件,如果未指定,则使用默认的公钥与私钥。
|
||||
|
||||
当设置的加密方式为tls时,-p参数无效;为tls-auth时,通过-p参数设置认证密码,且不能为空。
|
||||
|
||||
当设置的加密方式为非tls,tls-auth时,-key,-cert参数无效;通过-p参数设置加密密码,且不能为空。
|
||||
|
||||
|
||||
当设置的加密方式为非tls时,-key,-cert参数无效;通过-p参数设置加密密码,且不能为空。
|
||||
|
86
client.go
86
client.go
@ -58,10 +58,12 @@ func listenAndServe(addr string, handler func(net.Conn)) error {
|
||||
|
||||
func clientMethodSelected(method uint8, conn net.Conn) (net.Conn, error) {
|
||||
switch method {
|
||||
case MethodTLS:
|
||||
case MethodTLS, MethodTLSAuth:
|
||||
conn = tls.Client(conn, &tls.Config{InsecureSkipVerify: true})
|
||||
if err := cliTLSAuth(conn); err != nil {
|
||||
return nil, err
|
||||
if method == MethodTLSAuth {
|
||||
if err := cliTLSAuth(conn); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
case MethodAES128, MethodAES192, MethodAES256,
|
||||
MethodDES, MethodBF, MethodCAST5, MethodRC4MD5, MethodRC4, MethodTable:
|
||||
@ -79,6 +81,10 @@ func clientMethodSelected(method uint8, conn net.Conn) (net.Conn, error) {
|
||||
}
|
||||
|
||||
func cliTLSAuth(conn net.Conn) error {
|
||||
if len(Password) == 0 {
|
||||
return ErrEmptyPassword
|
||||
}
|
||||
|
||||
if err := gosocks5.NewUserPassRequest(
|
||||
gosocks5.UserPassVer, "", Password).Write(conn); err != nil {
|
||||
return err
|
||||
@ -94,19 +100,7 @@ func cliTLSAuth(conn net.Conn) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func cliHandle(conn net.Conn) {
|
||||
defer conn.Close()
|
||||
/*
|
||||
fmt.Println("new session", atomic.AddInt64(&sessionCount, 1))
|
||||
defer func() {
|
||||
fmt.Println("session end", atomic.AddInt64(&sessionCount, -1))
|
||||
}()
|
||||
*/
|
||||
|
||||
//log.Println("connect:", Saddr, Proxy)
|
||||
var c net.Conn
|
||||
var err error
|
||||
|
||||
func makeTunnel() (c net.Conn, err error) {
|
||||
if UseWebsocket || !UseHttp {
|
||||
c, err = connect(Saddr)
|
||||
} else {
|
||||
@ -117,40 +111,44 @@ func cliHandle(conn net.Conn) {
|
||||
c, err = dial(addr)
|
||||
}
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
if UseWebsocket {
|
||||
ws, resp, err := websocket.NewClient(c, &url.URL{Host: Saddr}, nil, 8192, 8192)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
c.Close()
|
||||
return nil, err
|
||||
}
|
||||
resp.Body.Close()
|
||||
|
||||
c = NewWSConn(ws)
|
||||
} else if UseHttp {
|
||||
httpcli := NewHttpClientConn(c)
|
||||
if err := httpcli.Handshake(); err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
if err = httpcli.Handshake(); err != nil {
|
||||
c.Close()
|
||||
return nil, err
|
||||
}
|
||||
c = httpcli
|
||||
defer httpcli.Close()
|
||||
//defer httpcli.Close()
|
||||
}
|
||||
|
||||
sc := gosocks5.ClientConn(c, clientConfig)
|
||||
if err := sc.Handleshake(); err != nil {
|
||||
return
|
||||
if err = sc.Handleshake(); err != nil {
|
||||
c.Close()
|
||||
return nil, err
|
||||
}
|
||||
c = sc
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func cliHandle(conn net.Conn) {
|
||||
defer conn.Close()
|
||||
|
||||
if Shadows {
|
||||
cipher, _ := shadowsocks.NewCipher(SMethod, SPassword)
|
||||
conn = shadowsocks.NewConn(conn, cipher)
|
||||
handleShadow(conn, c)
|
||||
handleShadow(conn)
|
||||
return
|
||||
}
|
||||
|
||||
@ -174,7 +172,7 @@ func cliHandle(conn net.Conn) {
|
||||
return
|
||||
}
|
||||
|
||||
handleSocks5(conn, c)
|
||||
handleSocks5(conn)
|
||||
return
|
||||
}
|
||||
|
||||
@ -196,15 +194,22 @@ func cliHandle(conn net.Conn) {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
handleHttp(req, conn, c)
|
||||
handleHttp(req, conn)
|
||||
}
|
||||
|
||||
func handleSocks5(conn net.Conn, sconn net.Conn) {
|
||||
func handleSocks5(conn net.Conn) {
|
||||
req, err := gosocks5.ReadRequest(conn)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
//log.Println(req)
|
||||
sconn, err := makeTunnel()
|
||||
if err != nil {
|
||||
gosocks5.NewReply(gosocks5.Failure, nil).Write(conn)
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
switch req.Cmd {
|
||||
case gosocks5.CmdConnect, gosocks5.CmdBind:
|
||||
@ -295,7 +300,7 @@ func cliTunnelUDP(uconn *net.UDPConn, sconn net.Conn) {
|
||||
}
|
||||
}
|
||||
|
||||
func handleHttp(req *http.Request, conn net.Conn, sconn net.Conn) {
|
||||
func handleHttp(req *http.Request, conn net.Conn) {
|
||||
var host string
|
||||
var port uint16
|
||||
|
||||
@ -313,6 +318,15 @@ func handleHttp(req *http.Request, conn net.Conn, sconn net.Conn) {
|
||||
Port: port,
|
||||
}
|
||||
r := gosocks5.NewRequest(gosocks5.CmdConnect, addr)
|
||||
|
||||
sconn, err := makeTunnel()
|
||||
if err != nil {
|
||||
conn.Write([]byte("HTTP/1.1 503 Service unavailable\r\n" +
|
||||
"Proxy-Agent: gost/" + Version + "\r\n\r\n"))
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := r.Write(sconn); err != nil {
|
||||
return
|
||||
}
|
||||
@ -340,13 +354,19 @@ func handleHttp(req *http.Request, conn net.Conn, sconn net.Conn) {
|
||||
}
|
||||
}
|
||||
|
||||
func handleShadow(conn, sconn net.Conn) {
|
||||
func handleShadow(conn net.Conn) {
|
||||
addr, extra, err := getShadowRequest(conn)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
sconn, err := makeTunnel()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
req := gosocks5.NewRequest(gosocks5.CmdConnect, addr)
|
||||
if err := req.Write(sconn); err != nil {
|
||||
log.Println(err)
|
||||
|
2
http.go
2
http.go
@ -219,7 +219,7 @@ func (s *HttpServer) s2c(w http.ResponseWriter, r *http.Request) {
|
||||
s.conns[token] = conn
|
||||
defer delete(s.conns, token)
|
||||
|
||||
socks5Handle(gosocks5.ServerConn(conn, serverConfig))
|
||||
serveSocks5(gosocks5.ServerConn(conn, serverConfig))
|
||||
}
|
||||
|
||||
func (s *HttpServer) c2s(w http.ResponseWriter, r *http.Request) {
|
||||
|
26
main.go
26
main.go
@ -6,7 +6,6 @@ import (
|
||||
//"github.com/ginuerzh/gosocks5"
|
||||
"log"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -18,10 +17,8 @@ var (
|
||||
Method, Password string
|
||||
CertFile, KeyFile string
|
||||
PrintVersion bool
|
||||
Filter string
|
||||
|
||||
proxyURL *url.URL
|
||||
filters []string
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -37,14 +34,12 @@ func init() {
|
||||
flag.BoolVar(&UseHttp, "http", false, "use http tunnel")
|
||||
flag.StringVar(&SMethod, "sm", "rc4-md5", "shadowsocks cipher method")
|
||||
flag.StringVar(&SPassword, "sp", "ginuerzh@gmail.com", "shadowsocks cipher password")
|
||||
flag.StringVar(&Filter, "f", "", "comma separated host/url wildcard not go through tunnel")
|
||||
flag.BoolVar(&PrintVersion, "v", false, "print version")
|
||||
flag.Parse()
|
||||
|
||||
log.SetFlags(log.LstdFlags | log.Lshortfile)
|
||||
|
||||
proxyURL, _ = parseURL(Proxy)
|
||||
filters = parseFilter(Filter)
|
||||
}
|
||||
|
||||
var (
|
||||
@ -74,24 +69,3 @@ func main() {
|
||||
|
||||
log.Fatal(listenAndServe(Laddr, cliHandle))
|
||||
}
|
||||
|
||||
func parseURL(rawurl string) (*url.URL, error) {
|
||||
if len(rawurl) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
if !strings.HasPrefix(rawurl, "http://") &&
|
||||
!strings.HasPrefix(rawurl, "socks://") {
|
||||
rawurl = "http://" + rawurl
|
||||
}
|
||||
return url.Parse(rawurl)
|
||||
}
|
||||
|
||||
func parseFilter(rawfilter string) (filters []string) {
|
||||
for _, s := range strings.Split(rawfilter, ",") {
|
||||
s = strings.TrimSpace(s)
|
||||
if len(s) > 0 {
|
||||
filters = append(filters)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
18
socks5.go
18
socks5.go
@ -89,7 +89,7 @@ func (s *Socks5Server) ListenAndServe() error {
|
||||
}
|
||||
//log.Println("accept", conn.RemoteAddr())
|
||||
|
||||
go socks5Handle(gosocks5.ServerConn(conn, serverConfig))
|
||||
go serveSocks5(gosocks5.ServerConn(conn, serverConfig))
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,7 +111,7 @@ func serverSelectMethod(methods ...uint8) uint8 {
|
||||
|
||||
func serverMethodSelected(method uint8, conn net.Conn) (net.Conn, error) {
|
||||
switch method {
|
||||
case MethodTLS:
|
||||
case MethodTLS, MethodTLSAuth:
|
||||
var cert tls.Certificate
|
||||
var err error
|
||||
|
||||
@ -125,8 +125,10 @@ 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
|
||||
if method == MethodTLSAuth {
|
||||
if err := svrTLSAuth(conn); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
case MethodAES128, MethodAES192, MethodAES256,
|
||||
MethodDES, MethodBF, MethodCAST5, MethodRC4MD5, MethodRC4, MethodTable:
|
||||
@ -143,12 +145,16 @@ func serverMethodSelected(method uint8, conn net.Conn) (net.Conn, error) {
|
||||
}
|
||||
|
||||
func svrTLSAuth(conn net.Conn) error {
|
||||
if len(Password) == 0 {
|
||||
return ErrEmptyPassword
|
||||
}
|
||||
|
||||
req, err := gosocks5.ReadUserPassRequest(conn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(Password) > 0 && req.Password != Password {
|
||||
if req.Password != Password {
|
||||
if err := gosocks5.NewUserPassResponse(
|
||||
gosocks5.UserPassVer, gosocks5.Failure).Write(conn); err != nil {
|
||||
return err
|
||||
@ -164,7 +170,7 @@ func svrTLSAuth(conn net.Conn) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func socks5Handle(conn net.Conn) {
|
||||
func serveSocks5(conn net.Conn) {
|
||||
defer conn.Close()
|
||||
|
||||
req, err := gosocks5.ReadRequest(conn)
|
||||
|
15
util.go
15
util.go
@ -26,8 +26,11 @@ const (
|
||||
MethodRC4MD5
|
||||
MethodRC4
|
||||
MethodTable
|
||||
MethodTLSAuth
|
||||
)
|
||||
|
||||
var ErrEmptyPassword = errors.New("empty key")
|
||||
|
||||
var Methods = map[uint8]string{
|
||||
gosocks5.MethodNoAuth: "", // 0x00
|
||||
MethodTLS: "tls", // 0x80
|
||||
@ -40,6 +43,18 @@ var Methods = map[uint8]string{
|
||||
MethodRC4MD5: "rc4-md5", // 8x87
|
||||
MethodRC4: "rc4", // 0x88
|
||||
MethodTable: "table", // 0x89
|
||||
MethodTLSAuth: "tls-auth", // 0x90
|
||||
}
|
||||
|
||||
func parseURL(rawurl string) (*url.URL, error) {
|
||||
if len(rawurl) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
if !strings.HasPrefix(rawurl, "http://") &&
|
||||
!strings.HasPrefix(rawurl, "socks://") {
|
||||
rawurl = "http://" + rawurl
|
||||
}
|
||||
return url.Parse(rawurl)
|
||||
}
|
||||
|
||||
func ToSocksAddr(addr net.Addr) *gosocks5.Addr {
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
Version = "1.5"
|
||||
Version = "1.6"
|
||||
)
|
||||
|
||||
func printVersion() {
|
||||
|
Loading…
Reference in New Issue
Block a user