New: custom socks5 proxy support
This commit is contained in:
parent
35e572406b
commit
2b87b907ae
6 changed files with 105 additions and 8 deletions
|
@ -78,6 +78,9 @@ external-controller = 127.0.0.1:8080
|
|||
ss1 = ss, server1, port, AEAD_CHACHA20_POLY1305, password
|
||||
ss2 = ss, server2, port, AEAD_CHACHA20_POLY1305, password
|
||||
|
||||
# name = socks5, server, port
|
||||
socks = socks5, server1, port
|
||||
|
||||
[Proxy Group]
|
||||
# url-test select which proxy will be used by benchmarking speed to a URL.
|
||||
# name = url-test, [proxies], url, interval(second)
|
||||
|
|
91
adapters/remote/socks5.go
Normal file
91
adapters/remote/socks5.go
Normal file
|
@ -0,0 +1,91 @@
|
|||
package adapters
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
|
||||
"github.com/riobard/go-shadowsocks2/socks"
|
||||
)
|
||||
|
||||
// Socks5Adapter is a shadowsocks adapter
|
||||
type Socks5Adapter struct {
|
||||
conn net.Conn
|
||||
}
|
||||
|
||||
// Close is used to close connection
|
||||
func (ss *Socks5Adapter) Close() {
|
||||
ss.conn.Close()
|
||||
}
|
||||
|
||||
func (ss *Socks5Adapter) Conn() net.Conn {
|
||||
return ss.conn
|
||||
}
|
||||
|
||||
type Socks5 struct {
|
||||
addr string
|
||||
name string
|
||||
}
|
||||
|
||||
func (ss *Socks5) Name() string {
|
||||
return ss.name
|
||||
}
|
||||
|
||||
func (ss *Socks5) Type() C.AdapterType {
|
||||
return C.Socks5
|
||||
}
|
||||
|
||||
func (ss *Socks5) Generator(addr *C.Addr) (adapter C.ProxyAdapter, err error) {
|
||||
c, err := net.Dial("tcp", ss.addr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error", ss.addr)
|
||||
}
|
||||
c.(*net.TCPConn).SetKeepAlive(true)
|
||||
|
||||
if err := ss.sharkHand(addr, c); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Socks5Adapter{conn: c}, nil
|
||||
}
|
||||
|
||||
func (ss *Socks5) sharkHand(addr *C.Addr, rw io.ReadWriter) error {
|
||||
buf := make([]byte, socks.MaxAddrLen)
|
||||
|
||||
// VER, CMD, RSV
|
||||
_, err := rw.Write([]byte{5, 1, 0})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := io.ReadFull(rw, buf[:2]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if buf[0] != 5 {
|
||||
return errors.New("SOCKS version error")
|
||||
} else if buf[1] != 0 {
|
||||
return errors.New("SOCKS need auth")
|
||||
}
|
||||
|
||||
// VER, CMD, RSV, ADDR
|
||||
if _, err := rw.Write(bytes.Join([][]byte{[]byte{5, 1, 0}, serializesSocksAddr(addr)}, []byte(""))); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := io.ReadFull(rw, buf[:10]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewSocks5(name, addr string) *Socks5 {
|
||||
return &Socks5{
|
||||
addr: addr,
|
||||
name: name,
|
||||
}
|
||||
}
|
|
@ -228,6 +228,14 @@ func (c *Config) parseProxies(cfg *ini.File) error {
|
|||
return err
|
||||
}
|
||||
proxies[key.Name()] = ss
|
||||
// socks5, server, port
|
||||
case "socks5":
|
||||
if len(proxy) < 3 {
|
||||
continue
|
||||
}
|
||||
addr := fmt.Sprintf("%s:%s", proxy[1], proxy[2])
|
||||
socks5 := adapters.NewSocks5(key.Name(), addr)
|
||||
proxies[key.Name()] = socks5
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -325,19 +333,16 @@ func (c *Config) handleResponseMessage() {
|
|||
log.Errorf("Listening HTTP proxy at %s error", c.general.Port)
|
||||
c.general.Port = 0
|
||||
}
|
||||
break
|
||||
case "socks-addr":
|
||||
if event.Payload.(bool) == false {
|
||||
log.Errorf("Listening SOCKS proxy at %s error", c.general.SocksPort)
|
||||
c.general.SocksPort = 0
|
||||
}
|
||||
break
|
||||
case "redir-addr":
|
||||
if event.Payload.(bool) == false {
|
||||
log.Errorf("Listening Redir proxy at %s error", c.general.RedirPort)
|
||||
c.general.RedirPort = 0
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ const (
|
|||
Reject
|
||||
Selector
|
||||
Shadowsocks
|
||||
Socks5
|
||||
URLTest
|
||||
)
|
||||
|
||||
|
@ -42,6 +43,8 @@ func (at AdapterType) String() string {
|
|||
return "Selector"
|
||||
case Shadowsocks:
|
||||
return "Shadowsocks"
|
||||
case Socks5:
|
||||
return "Socks5"
|
||||
case URLTest:
|
||||
return "URLTest"
|
||||
default:
|
||||
|
|
|
@ -84,17 +84,14 @@ func (l *Listener) process(signal chan<- struct{}) {
|
|||
addr := event.Payload.(string)
|
||||
err := l.updateHTTP(addr)
|
||||
reportCH <- &config.Event{Type: "http-addr", Payload: err == nil}
|
||||
break
|
||||
case "socks-addr":
|
||||
addr := event.Payload.(string)
|
||||
err := l.updateSocks(addr)
|
||||
reportCH <- &config.Event{Type: "socks-addr", Payload: err == nil}
|
||||
break
|
||||
case "redir-addr":
|
||||
addr := event.Payload.(string)
|
||||
err := l.updateRedir(addr)
|
||||
reportCH <- &config.Event{Type: "redir-addr", Payload: err == nil}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -106,10 +106,8 @@ func (t *Tunnel) handleConn(localConn C.ServerAdapter) {
|
|||
switch adapter := localConn.(type) {
|
||||
case *LocalAdapter.HttpAdapter:
|
||||
t.handleHTTP(adapter, remoConn)
|
||||
break
|
||||
case *LocalAdapter.SocksAdapter:
|
||||
t.handleSOCKS(adapter, remoConn)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue