nps/server/proxy/socks5.go

397 lines
9.0 KiB
Go
Raw Normal View History

2019-02-12 19:54:00 +00:00
package proxy
2018-11-29 11:55:24 +00:00
import (
"encoding/binary"
"errors"
2019-12-01 17:47:22 +00:00
"fmt"
2018-11-29 11:55:24 +00:00
"io"
"net"
"strconv"
2019-08-10 03:15:25 +00:00
"github.com/astaxie/beego/logs"
"github.com/cnlh/nps/lib/common"
"github.com/cnlh/nps/lib/conn"
"github.com/cnlh/nps/lib/file"
2018-11-29 11:55:24 +00:00
)
const (
ipV4 = 1
domainName = 3
ipV6 = 4
2018-11-29 11:55:24 +00:00
connectMethod = 1
bindMethod = 2
associateMethod = 3
// The maximum packet size of any udp Associate packet, based on ethernet's max size,
// minus the IP and UDP headers. IPv4 has a 20 byte header, UDP adds an
// additional 4 bytes. This is a total overhead of 24 bytes. Ethernet's
// max packet size is 1500 bytes, 1500 - 24 = 1476.
maxUDPPacketSize = 1476
)
const (
succeeded uint8 = iota
serverFailure
notAllowed
networkUnreachable
hostUnreachable
connectionRefused
ttlExpired
commandNotSupported
addrTypeNotSupported
)
const (
UserPassAuth = uint8(2)
userAuthVersion = uint8(1)
authSuccess = uint8(0)
authFailure = uint8(1)
)
2018-11-29 11:55:24 +00:00
type Sock5ModeServer struct {
2019-02-23 15:29:48 +00:00
BaseServer
2019-01-05 19:16:46 +00:00
listener net.Listener
2018-11-29 11:55:24 +00:00
}
2019-01-03 16:21:23 +00:00
//req
2018-11-29 11:55:24 +00:00
func (s *Sock5ModeServer) handleRequest(c net.Conn) {
/*
The SOCKS request is formed as follows:
+----+-----+-------+------+----------+----------+
|VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT |
+----+-----+-------+------+----------+----------+
| 1 | 1 | X'00' | 1 | Variable | 2 |
+----+-----+-------+------+----------+----------+
*/
header := make([]byte, 3)
_, err := io.ReadFull(c, header)
if err != nil {
2019-02-23 15:29:48 +00:00
logs.Warn("illegal request", err)
2018-11-29 11:55:24 +00:00
c.Close()
return
}
switch header[1] {
case connectMethod:
s.handleConnect(c)
case bindMethod:
s.handleBind(c)
case associateMethod:
s.handleUDP(c)
default:
s.sendReply(c, commandNotSupported)
c.Close()
}
}
2019-01-03 16:21:23 +00:00
//reply
2018-11-29 11:55:24 +00:00
func (s *Sock5ModeServer) sendReply(c net.Conn, rep uint8) {
reply := []byte{
5,
rep,
0,
1,
}
localAddr := c.LocalAddr().String()
localHost, localPort, _ := net.SplitHostPort(localAddr)
ipBytes := net.ParseIP(localHost).To4()
nPort, _ := strconv.Atoi(localPort)
reply = append(reply, ipBytes...)
portBytes := make([]byte, 2)
binary.BigEndian.PutUint16(portBytes, uint16(nPort))
reply = append(reply, portBytes...)
c.Write(reply)
}
2019-01-03 16:21:23 +00:00
//do conn
func (s *Sock5ModeServer) doConnect(c net.Conn, command uint8) {
2018-11-29 11:55:24 +00:00
addrType := make([]byte, 1)
c.Read(addrType)
var host string
switch addrType[0] {
case ipV4:
ipv4 := make(net.IP, net.IPv4len)
c.Read(ipv4)
host = ipv4.String()
case ipV6:
ipv6 := make(net.IP, net.IPv6len)
c.Read(ipv6)
host = ipv6.String()
case domainName:
var domainLen uint8
binary.Read(c, binary.BigEndian, &domainLen)
domain := make([]byte, domainLen)
c.Read(domain)
host = string(domain)
default:
s.sendReply(c, addrTypeNotSupported)
return
2018-11-29 11:55:24 +00:00
}
var port uint16
binary.Read(c, binary.BigEndian, &port)
// connect to host
addr := net.JoinHostPort(host, strconv.Itoa(int(port)))
var ltype string
if command == associateMethod {
2019-02-09 09:07:47 +00:00
ltype = common.CONN_UDP
} else {
2019-02-09 09:07:47 +00:00
ltype = common.CONN_TCP
}
2019-03-23 14:19:59 +00:00
s.DealClient(conn.NewConn(c), s.task.Client, addr, nil, ltype, func() {
s.sendReply(c, succeeded)
2019-04-08 09:01:08 +00:00
}, s.task.Flow, s.task.Target.LocalProxy)
2019-01-15 12:59:50 +00:00
return
2018-11-29 11:55:24 +00:00
}
2019-01-03 16:21:23 +00:00
//conn
2018-11-29 11:55:24 +00:00
func (s *Sock5ModeServer) handleConnect(c net.Conn) {
s.doConnect(c, connectMethod)
2018-11-29 11:55:24 +00:00
}
2018-12-06 12:45:14 +00:00
2018-11-29 11:55:24 +00:00
// passive mode
func (s *Sock5ModeServer) handleBind(c net.Conn) {
}
2019-12-01 17:47:22 +00:00
func (s *Sock5ModeServer) sendUdpReply(writeConn net.Conn, c net.Conn, rep uint8, serverIp string) {
reply := []byte{
5,
rep,
0,
1,
}
localHost, localPort, _ := net.SplitHostPort(c.LocalAddr().String())
localHost = serverIp
ipBytes := net.ParseIP(localHost).To4()
nPort, _ := strconv.Atoi(localPort)
reply = append(reply, ipBytes...)
portBytes := make([]byte, 2)
binary.BigEndian.PutUint16(portBytes, uint16(nPort))
reply = append(reply, portBytes...)
writeConn.Write(reply)
}
2018-11-29 11:55:24 +00:00
2019-12-01 18:15:13 +00:00
var serveExternalIp string
2018-11-29 11:55:24 +00:00
func (s *Sock5ModeServer) handleUDP(c net.Conn) {
2019-12-01 18:15:13 +00:00
if serveExternalIp == "" {
serveExternalIp = common.GetExternalIp()
}
2019-12-01 17:47:22 +00:00
defer c.Close()
addrType := make([]byte, 1)
c.Read(addrType)
var host string
switch addrType[0] {
case ipV4:
ipv4 := make(net.IP, net.IPv4len)
c.Read(ipv4)
host = ipv4.String()
case ipV6:
ipv6 := make(net.IP, net.IPv6len)
c.Read(ipv6)
host = ipv6.String()
case domainName:
var domainLen uint8
binary.Read(c, binary.BigEndian, &domainLen)
domain := make([]byte, domainLen)
c.Read(domain)
host = string(domain)
default:
s.sendReply(c, addrTypeNotSupported)
return
}
//读取端口
var port uint16
binary.Read(c, binary.BigEndian, &port)
fmt.Println(host, string(port))
replyAddr, err := net.ResolveUDPAddr("udp", s.task.ServerIp+":0")
if err != nil {
logs.Error("build local reply addr error", err)
return
2018-11-29 11:55:24 +00:00
}
2019-12-01 17:47:22 +00:00
reply, err := net.ListenUDP("udp", replyAddr)
if err != nil {
s.sendReply(c, addrTypeNotSupported)
logs.Error("listen local reply udp port error")
return
}
// reply the local addr
2019-12-01 18:15:13 +00:00
s.sendUdpReply(c, reply, succeeded, serveExternalIp)
2019-12-01 17:47:22 +00:00
defer reply.Close()
// new a tunnel to client
link := conn.NewLink("udp", "", s.task.Client.Cnf.Crypt, s.task.Client.Cnf.Compress, c.RemoteAddr().String(), false)
target, err := s.bridge.SendLinkInfo(s.task.Client.Id, link, s.task)
if err != nil {
logs.Warn("get connection from client id %d error %s", s.task.Client.Id, err.Error())
return
}
var clientAddr net.Addr
// copy buffer
go func() {
b := common.BufPoolUdp.Get().([]byte)
defer common.BufPoolUdp.Put(b)
defer c.Close()
for {
n, laddr, err := reply.ReadFrom(b)
if err != nil {
logs.Error("read data from %s err %s", reply.LocalAddr().String(), err.Error())
return
}
if clientAddr == nil {
clientAddr = laddr
}
if _, err := target.Write(b[:n]); err != nil {
logs.Error("write data to client error", err.Error())
return
}
}
}()
2018-11-29 11:55:24 +00:00
2019-12-01 17:47:22 +00:00
go func() {
b := common.BufPoolUdp.Get().([]byte)
defer common.BufPoolUdp.Put(b)
defer c.Close()
for {
n, err := target.Read(b)
if err != nil {
logs.Warn("read data form client error", err.Error())
return
}
if _, err := reply.WriteTo(b[:n], clientAddr); err != nil {
logs.Warn("write data to user ", err.Error())
return
}
}
}()
b := common.BufPoolUdp.Get().([]byte)
defer common.BufPoolUdp.Put(b)
for {
_, err := c.Read(b)
if err != nil {
c.Close()
return
}
}
2018-11-29 11:55:24 +00:00
}
2019-01-03 16:21:23 +00:00
//new conn
2019-01-09 12:33:00 +00:00
func (s *Sock5ModeServer) handleConn(c net.Conn) {
2018-11-29 11:55:24 +00:00
buf := make([]byte, 2)
if _, err := io.ReadFull(c, buf); err != nil {
2019-02-23 15:29:48 +00:00
logs.Warn("negotiation err", err)
2018-11-29 11:55:24 +00:00
c.Close()
return
}
if version := buf[0]; version != 5 {
2019-02-23 15:29:48 +00:00
logs.Warn("only support socks5, request from: ", c.RemoteAddr())
2018-11-29 11:55:24 +00:00
c.Close()
return
}
nMethods := buf[1]
methods := make([]byte, nMethods)
if len, err := c.Read(methods); len != int(nMethods) || err != nil {
2019-02-23 15:29:48 +00:00
logs.Warn("wrong method")
2018-11-29 11:55:24 +00:00
c.Close()
return
}
if (s.task.Client.Cnf.U != "" && s.task.Client.Cnf.P != "") || (s.task.MultiAccount != nil && len(s.task.MultiAccount.AccountMap) > 0) {
buf[1] = UserPassAuth
c.Write(buf)
if err := s.Auth(c); err != nil {
c.Close()
2019-02-23 15:29:48 +00:00
logs.Warn("Validation failed:", err)
return
}
} else {
buf[1] = 0
c.Write(buf)
}
2018-11-29 11:55:24 +00:00
s.handleRequest(c)
}
2019-01-03 16:21:23 +00:00
//socks5 auth
func (s *Sock5ModeServer) Auth(c net.Conn) error {
header := []byte{0, 0}
if _, err := io.ReadAtLeast(c, header, 2); err != nil {
return err
}
if header[0] != userAuthVersion {
return errors.New("验证方式不被支持")
}
userLen := int(header[1])
user := make([]byte, userLen)
if _, err := io.ReadAtLeast(c, user, userLen); err != nil {
return err
}
if _, err := c.Read(header[:1]); err != nil {
return errors.New("密码长度获取错误")
}
passLen := int(header[0])
pass := make([]byte, passLen)
if _, err := io.ReadAtLeast(c, pass, passLen); err != nil {
return err
}
var U, P string
if s.task.MultiAccount != nil {
// enable multi user auth
U = string(user)
var ok bool
P, ok = s.task.MultiAccount.AccountMap[U]
if !ok {
return errors.New("验证不通过")
}
} else {
U = s.task.Client.Cnf.U
P = s.task.Client.Cnf.P
}
if string(user) == U && string(pass) == P {
if _, err := c.Write([]byte{userAuthVersion, authSuccess}); err != nil {
return err
}
return nil
} else {
if _, err := c.Write([]byte{userAuthVersion, authFailure}); err != nil {
return err
}
return errors.New("验证不通过")
}
}
2019-01-03 16:21:23 +00:00
//start
2018-12-11 08:37:12 +00:00
func (s *Sock5ModeServer) Start() error {
return conn.NewTcpListenerAndProcess(s.task.ServerIp+":"+strconv.Itoa(s.task.Port), func(c net.Conn) {
2019-03-23 14:19:59 +00:00
if err := s.CheckFlowAndConnNum(s.task.Client); err != nil {
logs.Warn("client id %d, task id %d, error %s, when socks5 connection", s.task.Client.Id, s.task.Id, err.Error())
c.Close()
return
2018-11-29 11:55:24 +00:00
}
2019-03-23 14:19:59 +00:00
logs.Trace("New socks5 connection,client %d,remote address %s", s.task.Client.Id, c.RemoteAddr())
s.handleConn(c)
2019-03-29 02:41:57 +00:00
s.task.Client.AddConn()
2019-03-23 14:19:59 +00:00
}, &s.listener)
2018-11-29 11:55:24 +00:00
}
2019-01-03 16:21:23 +00:00
//new
2019-04-21 15:03:58 +00:00
func NewSock5ModeServer(bridge NetBridge, task *file.Tunnel) *Sock5ModeServer {
2018-11-29 11:55:24 +00:00
s := new(Sock5ModeServer)
2019-01-05 19:16:46 +00:00
s.bridge = bridge
2019-01-26 09:27:28 +00:00
s.task = task
2018-11-29 11:55:24 +00:00
return s
}
2019-03-23 14:19:59 +00:00
//close
func (s *Sock5ModeServer) Close() error {
return s.listener.Close()
2019-08-10 03:15:25 +00:00
}