github.com/AntonOrnatskyi/goproxy@v0.0.0-20190205095733-4526a9fa18b4/core/proxy/server/socks5/server.go (about)

     1  package socks5
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"fmt"
     7  	"io"
     8  	"net"
     9  	"strconv"
    10  	"strings"
    11  	"time"
    12  
    13  	socks5c "github.com/AntonOrnatskyi/goproxy/core/lib/socks5"
    14  )
    15  
    16  type BasicAuther interface {
    17  	CheckUserPass(username, password, userIP, localIP, toTarget string) bool
    18  }
    19  type Request struct {
    20  	ver         uint8
    21  	cmd         uint8
    22  	reserve     uint8
    23  	addressType uint8
    24  	dstAddr     string
    25  	dstPort     string
    26  	dstHost     string
    27  	bytes       []byte
    28  	rw          io.ReadWriter
    29  }
    30  
    31  func NewRequest(rw io.ReadWriter, header ...[]byte) (req Request, err interface{}) {
    32  	var b = make([]byte, 1024)
    33  	var n int
    34  	req = Request{rw: rw}
    35  	if header != nil && len(header) == 1 && len(header[0]) > 1 {
    36  		b = header[0]
    37  		n = len(header[0])
    38  	} else {
    39  		n, err = rw.Read(b[:])
    40  		if err != nil {
    41  			err = fmt.Errorf("read req data fail,ERR: %s", err)
    42  			return
    43  		}
    44  	}
    45  	req.ver = uint8(b[0])
    46  	req.cmd = uint8(b[1])
    47  	req.reserve = uint8(b[2])
    48  	req.addressType = uint8(b[3])
    49  	if b[0] != 0x5 {
    50  		err = fmt.Errorf("sosck version supported")
    51  		req.TCPReply(socks5c.REP_REQ_FAIL)
    52  		return
    53  	}
    54  	switch b[3] {
    55  	case 0x01: //IP V4
    56  		req.dstHost = net.IPv4(b[4], b[5], b[6], b[7]).String()
    57  	case 0x03: //域名
    58  		req.dstHost = string(b[5 : n-2]) //b[4]表示域名的长度
    59  	case 0x04: //IP V6
    60  		req.dstHost = net.IP{b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15], b[16], b[17], b[18], b[19]}.String()
    61  	}
    62  	req.dstPort = strconv.Itoa(int(b[n-2])<<8 | int(b[n-1]))
    63  	req.dstAddr = net.JoinHostPort(req.dstHost, req.dstPort)
    64  	req.bytes = b[:n]
    65  	return
    66  }
    67  func (s *Request) Bytes() []byte {
    68  	return s.bytes
    69  }
    70  func (s *Request) Addr() string {
    71  	return s.dstAddr
    72  }
    73  func (s *Request) Host() string {
    74  	return s.dstHost
    75  }
    76  func (s *Request) Port() string {
    77  	return s.dstPort
    78  }
    79  func (s *Request) AType() uint8 {
    80  	return s.addressType
    81  }
    82  func (s *Request) CMD() uint8 {
    83  	return s.cmd
    84  }
    85  
    86  func (s *Request) TCPReply(rep uint8) (err error) {
    87  	_, err = s.rw.Write(s.NewReply(rep, "0.0.0.0:0"))
    88  	return
    89  }
    90  func (s *Request) UDPReply(rep uint8, addr string) (err error) {
    91  	_, err = s.rw.Write(s.NewReply(rep, addr))
    92  	return
    93  }
    94  func (s *Request) NewReply(rep uint8, addr string) []byte {
    95  	var response bytes.Buffer
    96  	host, port, _ := net.SplitHostPort(addr)
    97  	ip := net.ParseIP(host)
    98  	ipb := ip.To4()
    99  	atyp := socks5c.ATYP_IPV4
   100  	ipv6 := ip.To16()
   101  	zeroiIPv6 := fmt.Sprintf("%d%d%d%d%d%d%d%d%d%d%d%d",
   102  		ipv6[0], ipv6[1], ipv6[2], ipv6[3],
   103  		ipv6[4], ipv6[5], ipv6[6], ipv6[7],
   104  		ipv6[8], ipv6[9], ipv6[10], ipv6[11],
   105  	)
   106  	if ipb == nil && ipv6 != nil && "0000000000255255" != zeroiIPv6 {
   107  		atyp = socks5c.ATYP_IPV6
   108  		ipb = ip.To16()
   109  	}
   110  	porti, _ := strconv.Atoi(port)
   111  	portb := make([]byte, 2)
   112  	binary.BigEndian.PutUint16(portb, uint16(porti))
   113  	// log.Printf("atyp : %v", atyp)
   114  	// log.Printf("ip : %v", []byte(ip))
   115  	response.WriteByte(socks5c.VERSION_V5)
   116  	response.WriteByte(rep)
   117  	response.WriteByte(socks5c.RSV)
   118  	response.WriteByte(atyp)
   119  	response.Write(ipb)
   120  	response.Write(portb)
   121  	return response.Bytes()
   122  }
   123  
   124  type MethodsRequest struct {
   125  	ver          uint8
   126  	methodsCount uint8
   127  	methods      []uint8
   128  	bytes        []byte
   129  	rw           *io.ReadWriter
   130  }
   131  
   132  func NewMethodsRequest(r io.ReadWriter, header ...[]byte) (s MethodsRequest, err interface{}) {
   133  	defer func() {
   134  		if err == nil {
   135  			err = recover()
   136  		}
   137  	}()
   138  	s = MethodsRequest{}
   139  	s.rw = &r
   140  	var buf = make([]byte, 300)
   141  	var n int
   142  	if header != nil && len(header) == 1 && len(header[0]) > 1 {
   143  		buf = header[0]
   144  		n = len(header[0])
   145  	} else {
   146  		n, err = r.Read(buf)
   147  		if err != nil {
   148  			return
   149  		}
   150  	}
   151  	if buf[0] != 0x05 {
   152  		err = fmt.Errorf("socks version not supported")
   153  		return
   154  	}
   155  	if n != int(buf[1])+int(2) {
   156  		err = fmt.Errorf("socks methods data length error")
   157  		return
   158  	}
   159  	s.ver = buf[0]
   160  	s.methodsCount = buf[1]
   161  	s.methods = buf[2:n]
   162  	s.bytes = buf[:n]
   163  	return
   164  }
   165  func (s *MethodsRequest) Version() uint8 {
   166  	return s.ver
   167  }
   168  func (s *MethodsRequest) MethodsCount() uint8 {
   169  	return s.methodsCount
   170  }
   171  func (s *MethodsRequest) Methods() []uint8 {
   172  	return s.methods
   173  }
   174  func (s *MethodsRequest) Select(method uint8) bool {
   175  	for _, m := range s.methods {
   176  		if m == method {
   177  			return true
   178  		}
   179  	}
   180  	return false
   181  }
   182  func (s *MethodsRequest) Reply(method uint8) (err error) {
   183  	_, err = (*s.rw).Write([]byte{byte(socks5c.VERSION_V5), byte(method)})
   184  	return
   185  }
   186  func (s *MethodsRequest) Bytes() []byte {
   187  	return s.bytes
   188  }
   189  
   190  type ServerConn struct {
   191  	target   string
   192  	user     string
   193  	password string
   194  	conn     *net.Conn
   195  	timeout  time.Duration
   196  	auth     *BasicAuther
   197  	header   []byte
   198  	ver      uint8
   199  	//method
   200  	methodsCount uint8
   201  	methods      []uint8
   202  	method       uint8
   203  	//request
   204  	cmd         uint8
   205  	reserve     uint8
   206  	addressType uint8
   207  	dstAddr     string
   208  	dstPort     string
   209  	dstHost     string
   210  	udpAddress  string
   211  }
   212  
   213  func NewServerConn(conn *net.Conn, timeout time.Duration, auth *BasicAuther, udpAddress string, header []byte) *ServerConn {
   214  	if udpAddress == "" {
   215  		udpAddress = "0.0.0.0:16666"
   216  	}
   217  	s := &ServerConn{
   218  		conn:       conn,
   219  		timeout:    timeout,
   220  		auth:       auth,
   221  		header:     header,
   222  		ver:        socks5c.VERSION_V5,
   223  		udpAddress: udpAddress,
   224  	}
   225  	return s
   226  
   227  }
   228  func (s *ServerConn) Close() {
   229  	(*s.conn).Close()
   230  }
   231  func (s *ServerConn) AuthData() socks5c.UsernamePassword {
   232  	return socks5c.UsernamePassword{s.user, s.password}
   233  }
   234  func (s *ServerConn) Method() uint8 {
   235  	return s.method
   236  }
   237  func (s *ServerConn) Target() string {
   238  	return s.target
   239  }
   240  func (s *ServerConn) Handshake() (err error) {
   241  	remoteAddr := (*s.conn).RemoteAddr()
   242  	localAddr := (*s.conn).LocalAddr()
   243  	//协商开始
   244  	//method select request
   245  	var methodReq MethodsRequest
   246  	(*s.conn).SetReadDeadline(time.Now().Add(s.timeout))
   247  
   248  	methodReq, e := NewMethodsRequest((*s.conn), s.header)
   249  	(*s.conn).SetReadDeadline(time.Time{})
   250  	if e != nil {
   251  		(*s.conn).SetReadDeadline(time.Now().Add(s.timeout))
   252  		methodReq.Reply(socks5c.Method_NONE_ACCEPTABLE)
   253  		(*s.conn).SetReadDeadline(time.Time{})
   254  		err = fmt.Errorf("new methods request fail,ERR: %s", e)
   255  		return
   256  	}
   257  	//log.Printf("%v,s.auth == %v && methodReq.Select(Method_NO_AUTH) %v", methodReq.methods, s.auth, methodReq.Select(Method_NO_AUTH))
   258  	if s.auth == nil && methodReq.Select(socks5c.Method_NO_AUTH) && !methodReq.Select(socks5c.Method_USER_PASS) {
   259  		// if !methodReq.Select(Method_NO_AUTH) {
   260  		// 	(*s.conn).SetReadDeadline(time.Now().Add(time.Second * s.timeout))
   261  		// 	methodReq.Reply(Method_NONE_ACCEPTABLE)
   262  		// 	(*s.conn).SetReadDeadline(time.Time{})
   263  		// 	err = fmt.Errorf("none method found : Method_NO_AUTH")
   264  		// 	return
   265  		// }
   266  		s.method = socks5c.Method_NO_AUTH
   267  		//method select reply
   268  		(*s.conn).SetReadDeadline(time.Now().Add(s.timeout))
   269  		err = methodReq.Reply(socks5c.Method_NO_AUTH)
   270  		(*s.conn).SetReadDeadline(time.Time{})
   271  		if err != nil {
   272  			err = fmt.Errorf("reply answer data fail,ERR: %s", err)
   273  			return
   274  		}
   275  		// err = fmt.Errorf("% x", methodReq.Bytes())
   276  	} else {
   277  		//auth
   278  		if !methodReq.Select(socks5c.Method_USER_PASS) {
   279  			(*s.conn).SetReadDeadline(time.Now().Add(s.timeout))
   280  			methodReq.Reply(socks5c.Method_NONE_ACCEPTABLE)
   281  			(*s.conn).SetReadDeadline(time.Time{})
   282  			err = fmt.Errorf("none method found : Method_USER_PASS")
   283  			return
   284  		}
   285  		s.method = socks5c.Method_USER_PASS
   286  		//method reply need auth
   287  		(*s.conn).SetReadDeadline(time.Now().Add(s.timeout))
   288  		err = methodReq.Reply(socks5c.Method_USER_PASS)
   289  		(*s.conn).SetReadDeadline(time.Time{})
   290  		if err != nil {
   291  			err = fmt.Errorf("reply answer data fail,ERR: %s", err)
   292  			return
   293  		}
   294  		//read auth
   295  		buf := make([]byte, 500)
   296  		var n int
   297  		(*s.conn).SetReadDeadline(time.Now().Add(s.timeout))
   298  		n, err = (*s.conn).Read(buf)
   299  		(*s.conn).SetReadDeadline(time.Time{})
   300  		if err != nil {
   301  			err = fmt.Errorf("read auth info fail,ERR: %s", err)
   302  			return
   303  		}
   304  		r := buf[:n]
   305  		s.user = string(r[2 : r[1]+2])
   306  		s.password = string(r[2+r[1]+1:])
   307  		//err = fmt.Errorf("user:%s,pass:%s", user, pass)
   308  		//auth
   309  		_userAddr := strings.Split(remoteAddr.String(), ":")
   310  		_localAddr := strings.Split(localAddr.String(), ":")
   311  		if s.auth == nil || (*s.auth).CheckUserPass(s.user, s.password, _userAddr[0], _localAddr[0], "") {
   312  			(*s.conn).SetDeadline(time.Now().Add(s.timeout))
   313  			_, err = (*s.conn).Write([]byte{0x01, 0x00})
   314  			(*s.conn).SetDeadline(time.Time{})
   315  			if err != nil {
   316  				err = fmt.Errorf("answer auth success to %s fail,ERR: %s", remoteAddr, err)
   317  				return
   318  			}
   319  		} else {
   320  			(*s.conn).SetDeadline(time.Now().Add(s.timeout))
   321  			_, err = (*s.conn).Write([]byte{0x01, 0x01})
   322  			(*s.conn).SetDeadline(time.Time{})
   323  			if err != nil {
   324  				err = fmt.Errorf("answer auth fail to %s fail,ERR: %s", remoteAddr, err)
   325  				return
   326  			}
   327  			err = fmt.Errorf("auth fail from %s", remoteAddr)
   328  			return
   329  		}
   330  	}
   331  	//request detail
   332  	(*s.conn).SetReadDeadline(time.Now().Add(s.timeout))
   333  	request, e := NewRequest(*s.conn)
   334  	(*s.conn).SetReadDeadline(time.Time{})
   335  	if e != nil {
   336  		err = fmt.Errorf("read request data fail,ERR: %s", e)
   337  		return
   338  	}
   339  	//协商结束
   340  
   341  	switch request.CMD() {
   342  	case socks5c.CMD_BIND:
   343  		err = request.TCPReply(socks5c.REP_UNKNOWN)
   344  		if err != nil {
   345  			err = fmt.Errorf("TCPReply REP_UNKNOWN to %s fail,ERR: %s", remoteAddr, err)
   346  			return
   347  		}
   348  		err = fmt.Errorf("cmd bind not supported, form: %s", remoteAddr)
   349  		return
   350  	case socks5c.CMD_CONNECT:
   351  		err = request.TCPReply(socks5c.REP_SUCCESS)
   352  		if err != nil {
   353  			err = fmt.Errorf("TCPReply REP_SUCCESS to %s fail,ERR: %s", remoteAddr, err)
   354  			return
   355  		}
   356  	case socks5c.CMD_ASSOCIATE:
   357  		err = request.UDPReply(socks5c.REP_SUCCESS, s.udpAddress)
   358  		if err != nil {
   359  			err = fmt.Errorf("UDPReply REP_SUCCESS to %s fail,ERR: %s", remoteAddr, err)
   360  			return
   361  		}
   362  	}
   363  
   364  	//fill socks info
   365  	s.target = request.Addr()
   366  	s.methodsCount = methodReq.MethodsCount()
   367  	s.methods = methodReq.Methods()
   368  	s.cmd = request.CMD()
   369  	s.reserve = request.reserve
   370  	s.addressType = request.addressType
   371  	s.dstAddr = request.dstAddr
   372  	s.dstHost = request.dstHost
   373  	s.dstPort = request.dstPort
   374  	return
   375  }