Feature: add Mixed(http+socks5) proxy listening (#685)

This commit is contained in:
bytew021
2020-05-12 11:29:53 +08:00
committed by GitHub
parent 3638b077cd
commit 3a27cfc4a1
9 changed files with 186 additions and 5 deletions

41
proxy/mixed/conn.go Normal file
View File

@ -0,0 +1,41 @@
package mixed
import (
"bufio"
"net"
)
type BufferedConn struct {
r *bufio.Reader
net.Conn
}
func NewBufferedConn(c net.Conn) *BufferedConn {
return &BufferedConn{bufio.NewReader(c), c}
}
// Reader returns the internal bufio.Reader.
func (c *BufferedConn) Reader() *bufio.Reader {
return c.r
}
// Peek returns the next n bytes without advancing the reader.
func (c *BufferedConn) Peek(n int) ([]byte, error) {
return c.r.Peek(n)
}
func (c *BufferedConn) Read(p []byte) (int, error) {
return c.r.Read(p)
}
func (c *BufferedConn) ReadByte() (byte, error) {
return c.r.ReadByte()
}
func (c *BufferedConn) UnreadByte() error {
return c.r.UnreadByte()
}
func (c *BufferedConn) Buffered() int {
return c.r.Buffered()
}

69
proxy/mixed/mixed.go Normal file
View File

@ -0,0 +1,69 @@
package mixed
import (
"net"
"time"
"github.com/Dreamacro/clash/common/cache"
"github.com/Dreamacro/clash/component/socks5"
"github.com/Dreamacro/clash/log"
"github.com/Dreamacro/clash/proxy/http"
"github.com/Dreamacro/clash/proxy/socks"
)
type MixedListener struct {
net.Listener
address string
closed bool
cache *cache.Cache
}
func NewMixedProxy(addr string) (*MixedListener, error) {
l, err := net.Listen("tcp", addr)
if err != nil {
return nil, err
}
ml := &MixedListener{l, addr, false, cache.New(30 * time.Second)}
go func() {
log.Infoln("Mixed(http+socks5) proxy listening at: %s", addr)
for {
c, err := ml.Accept()
if err != nil {
if ml.closed {
break
}
continue
}
go handleConn(c, ml.cache)
}
}()
return ml, nil
}
func (l *MixedListener) Close() {
l.closed = true
l.Listener.Close()
}
func (l *MixedListener) Address() string {
return l.address
}
func handleConn(conn net.Conn, cache *cache.Cache) {
bufConn := NewBufferedConn(conn)
head, err := bufConn.Peek(1)
if err != nil {
return
}
if head[0] == socks5.Version {
socks.HandleSocks(bufConn)
return
}
http.HandleConn(bufConn, cache)
}