mihomo/proxy/socks/tcp.go

119 lines
2.2 KiB
Go
Raw Normal View History

2018-06-14 01:00:58 +08:00
package socks
2018-06-10 22:50:03 +08:00
import (
"io"
"net"
"strconv"
2018-06-14 01:00:58 +08:00
C "github.com/Dreamacro/clash/constant"
2018-06-10 22:50:03 +08:00
"github.com/Dreamacro/clash/tunnel"
"github.com/riobard/go-shadowsocks2/socks"
log "github.com/sirupsen/logrus"
)
var (
tun = tunnel.GetInstance()
)
2018-07-15 22:23:20 +08:00
func NewSocksProxy(addr string) (*C.ProxySignal, error) {
l, err := net.Listen("tcp", addr)
2018-06-10 22:50:03 +08:00
if err != nil {
2018-07-15 22:23:20 +08:00
return nil, err
2018-06-10 22:50:03 +08:00
}
2018-07-15 22:23:20 +08:00
done := make(chan struct{})
closed := make(chan struct{})
signal := &C.ProxySignal{
Done: done,
Closed: closed,
2018-06-10 22:50:03 +08:00
}
2018-07-15 22:23:20 +08:00
go func() {
log.Infof("SOCKS proxy listening at: %s", addr)
for {
c, err := l.Accept()
if err != nil {
if _, open := <-done; !open {
break
}
continue
}
go handleSocks(c)
}
}()
go func() {
<-done
close(done)
l.Close()
closed <- struct{}{}
}()
return signal, nil
2018-06-10 22:50:03 +08:00
}
func handleSocks(conn net.Conn) {
target, err := socks.Handshake(conn)
if err != nil {
conn.Close()
return
2018-06-10 22:50:03 +08:00
}
conn.(*net.TCPConn).SetKeepAlive(true)
tun.Add(NewSocks(target, conn))
}
type SocksAdapter struct {
conn net.Conn
2018-06-14 01:00:58 +08:00
addr *C.Addr
2018-06-10 22:50:03 +08:00
}
func (s *SocksAdapter) Close() {
s.conn.Close()
}
2018-06-14 01:00:58 +08:00
func (s *SocksAdapter) Addr() *C.Addr {
2018-06-10 22:50:03 +08:00
return s.addr
}
2018-06-14 01:00:58 +08:00
func (s *SocksAdapter) Connect(proxy C.ProxyAdapter) {
go io.Copy(s.conn, proxy.ReadWriter())
io.Copy(proxy.ReadWriter(), s.conn)
}
func parseSocksAddr(target socks.Addr) *C.Addr {
2018-06-10 22:50:03 +08:00
var host, port string
2018-06-11 18:36:39 +08:00
var ip net.IP
2018-06-10 22:50:03 +08:00
switch target[0] {
case socks.AtypDomainName:
host = string(target[2 : 2+target[1]])
port = strconv.Itoa((int(target[2+target[1]]) << 8) | int(target[2+target[1]+1]))
2018-06-11 18:36:39 +08:00
ipAddr, err := net.ResolveIPAddr("ip", host)
if err == nil {
ip = ipAddr.IP
}
2018-06-10 22:50:03 +08:00
case socks.AtypIPv4:
2018-06-11 18:36:39 +08:00
ip = net.IP(target[1 : 1+net.IPv4len])
2018-06-10 22:50:03 +08:00
port = strconv.Itoa((int(target[1+net.IPv4len]) << 8) | int(target[1+net.IPv4len+1]))
case socks.AtypIPv6:
2018-06-11 18:36:39 +08:00
ip = net.IP(target[1 : 1+net.IPv6len])
2018-06-10 22:50:03 +08:00
port = strconv.Itoa((int(target[1+net.IPv6len]) << 8) | int(target[1+net.IPv6len+1]))
}
2018-06-14 01:00:58 +08:00
return &C.Addr{
NetWork: C.TCP,
2018-06-10 22:50:03 +08:00
AddrType: int(target[0]),
Host: host,
2018-06-11 18:36:39 +08:00
IP: &ip,
2018-06-10 22:50:03 +08:00
Port: port,
}
}
func NewSocks(target socks.Addr, conn net.Conn) *SocksAdapter {
return &SocksAdapter{
conn: conn,
addr: parseSocksAddr(target),
}
}