ss client now support OTA

This commit is contained in:
rui.zheng 2017-01-14 13:41:49 +08:00
parent e476a9f700
commit 148d114c73
2 changed files with 38 additions and 28 deletions

45
conn.go
View File

@ -2,18 +2,18 @@ package gost
import ( import (
"bufio" "bufio"
"bytes"
"crypto/tls" "crypto/tls"
"encoding/base64" "encoding/base64"
"errors" "errors"
"github.com/ginuerzh/gosocks5" "github.com/ginuerzh/gosocks5"
"github.com/golang/glog" "github.com/golang/glog"
"github.com/shadowsocks/shadowsocks-go/shadowsocks" ss "github.com/shadowsocks/shadowsocks-go/shadowsocks"
"net" "net"
"net/http" "net/http"
"net/http/httputil" "net/http/httputil"
"net/url" "net/url"
"strconv" "strconv"
"strings"
"sync" "sync"
"time" "time"
) )
@ -115,15 +115,7 @@ func (c *ProxyConn) handshake() error {
} }
c.conn = conn c.conn = conn
case "ss": // shadowsocks case "ss": // shadowsocks
if len(c.Node.Users) > 0 { // nothing to do
method := c.Node.Users[0].Username()
password, _ := c.Node.Users[0].Password()
cipher, err := shadowsocks.NewCipher(method, password)
if err != nil {
return err
}
c.conn = &shadowConn{conn: shadowsocks.NewConn(c.conn, cipher)}
}
case "http", "http2": case "http", "http2":
fallthrough fallthrough
default: default:
@ -138,26 +130,31 @@ func (c *ProxyConn) handshake() error {
func (c *ProxyConn) Connect(addr string) error { func (c *ProxyConn) Connect(addr string) error {
switch c.Node.Protocol { switch c.Node.Protocol {
case "ss": // shadowsocks case "ss": // shadowsocks
host, port, err := net.SplitHostPort(addr) rawaddr, err := ss.RawAddr(addr)
if err != nil { if err != nil {
return err return err
} }
p, _ := strconv.Atoi(port)
req := gosocks5.NewRequest(gosocks5.CmdConnect, &gosocks5.Addr{ var method, password string
Type: gosocks5.AddrDomain, if len(c.Node.Users) > 0 {
Host: host, method = c.Node.Users[0].Username()
Port: uint16(p), password, _ = c.Node.Users[0].Password()
})
buf := bytes.Buffer{}
if err := req.Write(&buf); err != nil {
return err
} }
b := buf.Bytes() if c.Node.getBool("ota") && !strings.HasSuffix(method, "-auth") {
if _, err := c.Write(b[3:]); err != nil { method += "-auth"
}
cipher, err := ss.NewCipher(method, password)
if err != nil {
return err return err
} }
glog.V(LDEBUG).Infoln("[ss]", req) ssc, err := ss.DialWithRawAddrConn(rawaddr, c.conn, cipher)
if err != nil {
return err
}
c.conn = &shadowConn{conn: ssc}
return nil
case "socks", "socks5": case "socks", "socks5":
host, port, err := net.SplitHostPort(addr) host, port, err := net.SplitHostPort(addr)
if err != nil { if err != nil {

View File

@ -10,6 +10,7 @@ import (
"net" "net"
"net/http" "net/http"
"strconv" "strconv"
"strings"
) )
type ProxyServer struct { type ProxyServer struct {
@ -18,6 +19,7 @@ type ProxyServer struct {
TLSConfig *tls.Config TLSConfig *tls.Config
selector *serverSelector selector *serverSelector
cipher *ss.Cipher cipher *ss.Cipher
ota bool
} }
func NewProxyServer(node ProxyNode, chain *ProxyChain, config *tls.Config) *ProxyServer { func NewProxyServer(node ProxyNode, chain *ProxyChain, config *tls.Config) *ProxyServer {
@ -29,10 +31,20 @@ func NewProxyServer(node ProxyNode, chain *ProxyChain, config *tls.Config) *Prox
} }
var cipher *ss.Cipher var cipher *ss.Cipher
if node.Protocol == "ss" && node.Users != nil { var ota bool
if node.Protocol == "ss" {
var err error var err error
method := node.Users[0].Username() var method, password string
password, _ := node.Users[0].Password()
if len(node.Users) > 0 {
method = node.Users[0].Username()
password, _ = node.Users[0].Password()
}
ota = node.getBool("ota")
if strings.HasSuffix(method, "-auth") {
ota = true
method = strings.TrimSuffix(method, "-auth")
}
cipher, err = ss.NewCipher(method, password) cipher, err = ss.NewCipher(method, password)
if err != nil { if err != nil {
glog.Fatal(err) glog.Fatal(err)
@ -54,6 +66,7 @@ func NewProxyServer(node ProxyNode, chain *ProxyChain, config *tls.Config) *Prox
tlsConfig: config, tlsConfig: config,
}, },
cipher: cipher, cipher: cipher,
ota: ota,
} }
} }
@ -134,7 +147,7 @@ func (s *ProxyServer) handleConn(conn net.Conn) {
switch s.Node.Protocol { switch s.Node.Protocol {
case "ss": // shadowsocks case "ss": // shadowsocks
server := NewShadowServer(ss.NewConn(conn, s.cipher.Copy()), s) server := NewShadowServer(ss.NewConn(conn, s.cipher.Copy()), s)
server.OTA = s.Node.getBool("ota") server.OTA = s.ota
server.Serve() server.Serve()
return return
case "http": case "http":