clash/proxy/socks/tcp.go

99 lines
1.9 KiB
Go
Raw Normal View History

2018-06-13 17:00:58 +00:00
package socks
2018-06-10 14:50:03 +00:00
import (
"fmt"
"io"
"net"
"strconv"
2018-06-13 17:00:58 +00:00
C "github.com/Dreamacro/clash/constant"
2018-06-10 14:50:03 +00:00
"github.com/Dreamacro/clash/tunnel"
"github.com/riobard/go-shadowsocks2/socks"
log "github.com/sirupsen/logrus"
)
var (
tun = tunnel.GetInstance()
)
func NewSocksProxy(port string) {
l, err := net.Listen("tcp", fmt.Sprintf(":%s", port))
defer l.Close()
if err != nil {
return
}
log.Infof("SOCKS proxy :%s", port)
for {
c, err := l.Accept()
if err != nil {
continue
}
go handleSocks(c)
}
}
func handleSocks(conn net.Conn) {
target, err := socks.Handshake(conn)
if err != nil {
conn.Close()
return
2018-06-10 14:50:03 +00:00
}
conn.(*net.TCPConn).SetKeepAlive(true)
tun.Add(NewSocks(target, conn))
}
type SocksAdapter struct {
conn net.Conn
2018-06-13 17:00:58 +00:00
addr *C.Addr
2018-06-10 14:50:03 +00:00
}
func (s *SocksAdapter) Close() {
s.conn.Close()
}
2018-06-13 17:00:58 +00:00
func (s *SocksAdapter) Addr() *C.Addr {
2018-06-10 14:50:03 +00:00
return s.addr
}
2018-06-13 17:00:58 +00: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 14:50:03 +00:00
var host, port string
2018-06-11 10:36:39 +00:00
var ip net.IP
2018-06-10 14:50:03 +00: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 10:36:39 +00:00
ipAddr, err := net.ResolveIPAddr("ip", host)
if err == nil {
ip = ipAddr.IP
}
2018-06-10 14:50:03 +00:00
case socks.AtypIPv4:
2018-06-11 10:36:39 +00:00
ip = net.IP(target[1 : 1+net.IPv4len])
2018-06-10 14:50:03 +00:00
port = strconv.Itoa((int(target[1+net.IPv4len]) << 8) | int(target[1+net.IPv4len+1]))
case socks.AtypIPv6:
2018-06-11 10:36:39 +00:00
ip = net.IP(target[1 : 1+net.IPv6len])
2018-06-10 14:50:03 +00:00
port = strconv.Itoa((int(target[1+net.IPv6len]) << 8) | int(target[1+net.IPv6len+1]))
}
2018-06-13 17:00:58 +00:00
return &C.Addr{
NetWork: C.TCP,
2018-06-10 14:50:03 +00:00
AddrType: int(target[0]),
Host: host,
2018-06-11 10:36:39 +00:00
IP: &ip,
2018-06-10 14:50:03 +00:00
Port: port,
}
}
func NewSocks(target socks.Addr, conn net.Conn) *SocksAdapter {
return &SocksAdapter{
conn: conn,
addr: parseSocksAddr(target),
}
}