Feature: SOCKS5 authentication support (#34)

* Feature: socks5 auth support

* Chore: make code unified

* Fix: auth buffer length
This commit is contained in:
gVisor bot 2018-11-09 17:36:30 +08:00
parent 563708708e
commit 172553566f

View file

@ -31,6 +31,8 @@ func (ss *Socks5Adapter) Conn() net.Conn {
type Socks5 struct { type Socks5 struct {
addr string addr string
name string name string
user string
pass string
tls bool tls bool
skipCertVerify bool skipCertVerify bool
tlsConfig *tls.Config tlsConfig *tls.Config
@ -40,6 +42,8 @@ type Socks5Option struct {
Name string `proxy:"name"` Name string `proxy:"name"`
Server string `proxy:"server"` Server string `proxy:"server"`
Port int `proxy:"port"` Port int `proxy:"port"`
UserName string `proxy:"username,omitempty"`
Password string `proxy:"password,omitempty"`
TLS bool `proxy:"tls,omitempty"` TLS bool `proxy:"tls,omitempty"`
SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"` SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"`
} }
@ -73,19 +77,47 @@ func (ss *Socks5) Generator(metadata *C.Metadata) (adapter C.ProxyAdapter, err e
func (ss *Socks5) shakeHand(metadata *C.Metadata, rw io.ReadWriter) error { func (ss *Socks5) shakeHand(metadata *C.Metadata, rw io.ReadWriter) error {
buf := make([]byte, socks.MaxAddrLen) buf := make([]byte, socks.MaxAddrLen)
var err error
// VER, CMD, RSV // VER, NMETHODS, METHODS
_, err := rw.Write([]byte{5, 1, 0}) if len(ss.user) > 0 {
_, err = rw.Write([]byte{5, 1, 2})
} else {
_, err = rw.Write([]byte{5, 1, 0})
}
if err != nil { if err != nil {
return err return err
} }
// VER, METHOD
if _, err := io.ReadFull(rw, buf[:2]); err != nil { if _, err := io.ReadFull(rw, buf[:2]); err != nil {
return err return err
} }
if buf[0] != 5 { if buf[0] != 5 {
return errors.New("SOCKS version error") return errors.New("SOCKS version error")
}
if buf[1] == 2 {
// password protocol version
authMsg := &bytes.Buffer{}
authMsg.WriteByte(1)
authMsg.WriteByte(uint8(len(ss.user)))
authMsg.WriteString(ss.user)
authMsg.WriteByte(uint8(len(ss.pass)))
authMsg.WriteString(ss.pass)
if _, err := rw.Write(authMsg.Bytes()); err != nil {
return err
}
if _, err := io.ReadFull(rw, buf[:2]); err != nil {
return err
}
if buf[1] != 0 {
return errors.New("rejected username/password")
}
} else if buf[1] != 0 { } else if buf[1] != 0 {
return errors.New("SOCKS need auth") return errors.New("SOCKS need auth")
} }
@ -117,6 +149,8 @@ func NewSocks5(option Socks5Option) *Socks5 {
return &Socks5{ return &Socks5{
addr: net.JoinHostPort(option.Server, strconv.Itoa(option.Port)), addr: net.JoinHostPort(option.Server, strconv.Itoa(option.Port)),
name: option.Name, name: option.Name,
user: option.UserName,
pass: option.Password,
tls: option.TLS, tls: option.TLS,
skipCertVerify: option.SkipCertVerify, skipCertVerify: option.SkipCertVerify,
tlsConfig: tlsConfig, tlsConfig: tlsConfig,