github.com/AntonOrnatskyi/goproxy@v0.0.0-20190205095733-4526a9fa18b4/utils/socks/structs.go (about)

     1  package socks
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"errors"
     7  	"fmt"
     8  	"io"
     9  	"net"
    10  	"strconv"
    11  )
    12  
    13  type Request struct {
    14  	ver         uint8
    15  	cmd         uint8
    16  	reserve     uint8
    17  	addressType uint8
    18  	dstAddr     string
    19  	dstPort     string
    20  	dstHost     string
    21  	bytes       []byte
    22  	rw          io.ReadWriter
    23  }
    24  
    25  func NewRequest(rw io.ReadWriter, header ...[]byte) (req Request, err interface{}) {
    26  	var b = make([]byte, 1024)
    27  	var n int
    28  	req = Request{rw: rw}
    29  	if header != nil && len(header) == 1 && len(header[0]) > 1 {
    30  		b = header[0]
    31  		n = len(header[0])
    32  	} else {
    33  		n, err = rw.Read(b[:])
    34  		if err != nil {
    35  			err = fmt.Errorf("read req data fail,ERR: %s", err)
    36  			return
    37  		}
    38  	}
    39  	req.ver = uint8(b[0])
    40  	req.cmd = uint8(b[1])
    41  	req.reserve = uint8(b[2])
    42  	req.addressType = uint8(b[3])
    43  	if b[0] != 0x5 {
    44  		err = fmt.Errorf("sosck version supported")
    45  		req.TCPReply(REP_REQ_FAIL)
    46  		return
    47  	}
    48  	switch b[3] {
    49  	case 0x01: //IP V4
    50  		req.dstHost = net.IPv4(b[4], b[5], b[6], b[7]).String()
    51  	case 0x03: //域名
    52  		req.dstHost = string(b[5 : n-2]) //b[4]表示域名的长度
    53  	case 0x04: //IP V6
    54  		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()
    55  	}
    56  	req.dstPort = strconv.Itoa(int(b[n-2])<<8 | int(b[n-1]))
    57  	req.dstAddr = net.JoinHostPort(req.dstHost, req.dstPort)
    58  	req.bytes = b[:n]
    59  	return
    60  }
    61  func (s *Request) Bytes() []byte {
    62  	return s.bytes
    63  }
    64  func (s *Request) Addr() string {
    65  	return s.dstAddr
    66  }
    67  func (s *Request) Host() string {
    68  	return s.dstHost
    69  }
    70  func (s *Request) Port() string {
    71  	return s.dstPort
    72  }
    73  func (s *Request) AType() uint8 {
    74  	return s.addressType
    75  }
    76  func (s *Request) CMD() uint8 {
    77  	return s.cmd
    78  }
    79  
    80  func (s *Request) TCPReply(rep uint8) (err error) {
    81  	_, err = s.rw.Write(s.NewReply(rep, "0.0.0.0:0"))
    82  	return
    83  }
    84  func (s *Request) UDPReply(rep uint8, addr string) (err error) {
    85  	_, err = s.rw.Write(s.NewReply(rep, addr))
    86  	return
    87  }
    88  func (s *Request) NewReply(rep uint8, addr string) []byte {
    89  	var response bytes.Buffer
    90  	host, port, _ := net.SplitHostPort(addr)
    91  	ip := net.ParseIP(host)
    92  	ipb := ip.To4()
    93  	atyp := ATYP_IPV4
    94  	ipv6 := ip.To16()
    95  	zeroiIPv6 := fmt.Sprintf("%d%d%d%d%d%d%d%d%d%d%d%d",
    96  		ipv6[0], ipv6[1], ipv6[2], ipv6[3],
    97  		ipv6[4], ipv6[5], ipv6[6], ipv6[7],
    98  		ipv6[8], ipv6[9], ipv6[10], ipv6[11],
    99  	)
   100  	if ipb == nil && ipv6 != nil && "0000000000255255" != zeroiIPv6 {
   101  		atyp = ATYP_IPV6
   102  		ipb = ip.To16()
   103  	}
   104  	porti, _ := strconv.Atoi(port)
   105  	portb := make([]byte, 2)
   106  	binary.BigEndian.PutUint16(portb, uint16(porti))
   107  	// log.Printf("atyp : %v", atyp)
   108  	// log.Printf("ip : %v", []byte(ip))
   109  	response.WriteByte(VERSION_V5)
   110  	response.WriteByte(rep)
   111  	response.WriteByte(RSV)
   112  	response.WriteByte(atyp)
   113  	response.Write(ipb)
   114  	response.Write(portb)
   115  	return response.Bytes()
   116  }
   117  
   118  type MethodsRequest struct {
   119  	ver          uint8
   120  	methodsCount uint8
   121  	methods      []uint8
   122  	bytes        []byte
   123  	rw           *io.ReadWriter
   124  }
   125  
   126  func NewMethodsRequest(r io.ReadWriter, header ...[]byte) (s MethodsRequest, err interface{}) {
   127  	defer func() {
   128  		if err == nil {
   129  			err = recover()
   130  		}
   131  	}()
   132  	s = MethodsRequest{}
   133  	s.rw = &r
   134  	var buf = make([]byte, 300)
   135  	var n int
   136  	if header != nil && len(header) == 1 && len(header[0]) > 1 {
   137  		buf = header[0]
   138  		n = len(header[0])
   139  	} else {
   140  		n, err = r.Read(buf)
   141  		if err != nil {
   142  			return
   143  		}
   144  	}
   145  	if buf[0] != 0x05 {
   146  		err = fmt.Errorf("socks version not supported")
   147  		return
   148  	}
   149  	if n != int(buf[1])+int(2) {
   150  		err = fmt.Errorf("socks methods data length error")
   151  		return
   152  	}
   153  	s.ver = buf[0]
   154  	s.methodsCount = buf[1]
   155  	s.methods = buf[2:n]
   156  	s.bytes = buf[:n]
   157  	return
   158  }
   159  func (s *MethodsRequest) Version() uint8 {
   160  	return s.ver
   161  }
   162  func (s *MethodsRequest) MethodsCount() uint8 {
   163  	return s.methodsCount
   164  }
   165  func (s *MethodsRequest) Methods() []uint8 {
   166  	return s.methods
   167  }
   168  func (s *MethodsRequest) Select(method uint8) bool {
   169  	for _, m := range s.methods {
   170  		if m == method {
   171  			return true
   172  		}
   173  	}
   174  	return false
   175  }
   176  func (s *MethodsRequest) Reply(method uint8) (err error) {
   177  	_, err = (*s.rw).Write([]byte{byte(VERSION_V5), byte(method)})
   178  	return
   179  }
   180  func (s *MethodsRequest) Bytes() []byte {
   181  	return s.bytes
   182  }
   183  
   184  func ParseUDPPacket(b []byte) (p UDPPacket, err error) {
   185  	p = UDPPacket{}
   186  	p.frag = uint8(b[2])
   187  	p.bytes = b
   188  	if p.frag != 0 {
   189  		err = fmt.Errorf("FRAG only support for 0 , %v ,%v", p.frag, b[:4])
   190  		return
   191  	}
   192  	portIndex := 0
   193  	p.atype = b[3]
   194  	switch p.atype {
   195  	case ATYP_IPV4: //IP V4
   196  		p.dstHost = net.IPv4(b[4], b[5], b[6], b[7]).String()
   197  		portIndex = 8
   198  	case ATYP_DOMAIN: //域名
   199  		domainLen := uint8(b[4])
   200  		p.dstHost = string(b[5 : 5+domainLen]) //b[4]表示域名的长度
   201  		portIndex = int(5 + domainLen)
   202  	case ATYP_IPV6: //IP V6
   203  		p.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()
   204  		portIndex = 20
   205  	}
   206  	p.dstPort = strconv.Itoa(int(b[portIndex])<<8 | int(b[portIndex+1]))
   207  	p.data = b[portIndex+2:]
   208  	p.header = b[:portIndex+2]
   209  	return
   210  }
   211  
   212  type UDPPacket struct {
   213  	rsv     uint16
   214  	frag    uint8
   215  	atype   uint8
   216  	dstHost string
   217  	dstPort string
   218  	data    []byte
   219  	header  []byte
   220  	bytes   []byte
   221  }
   222  
   223  func (s *UDPPacket) Header() []byte {
   224  	return s.header
   225  }
   226  func (s *UDPPacket) NewReply(data []byte) []byte {
   227  	var buf bytes.Buffer
   228  	buf.Write(s.header)
   229  	buf.Write(data)
   230  	return buf.Bytes()
   231  }
   232  func (s *UDPPacket) Host() string {
   233  	return s.dstHost
   234  }
   235  
   236  func (s *UDPPacket) Port() string {
   237  	return s.dstPort
   238  }
   239  func (s *UDPPacket) Data() []byte {
   240  	return s.data
   241  }
   242  
   243  type PacketUDP struct {
   244  	rsv     uint16
   245  	frag    uint8
   246  	atype   uint8
   247  	dstHost string
   248  	dstPort string
   249  	data    []byte
   250  }
   251  
   252  func NewPacketUDP() (p PacketUDP) {
   253  	return PacketUDP{}
   254  }
   255  func (p *PacketUDP) Build(destAddr string, data []byte) (err error) {
   256  	host, port, err := net.SplitHostPort(destAddr)
   257  	if err != nil {
   258  		return
   259  	}
   260  	p.rsv = 0
   261  	p.frag = 0
   262  	p.dstHost = host
   263  	p.dstPort = port
   264  	p.atype = ATYP_IPV4
   265  	if ip := net.ParseIP(host); ip != nil {
   266  		if ip4 := ip.To4(); ip4 != nil {
   267  			p.atype = ATYP_IPV4
   268  			ip = ip4
   269  		} else {
   270  			p.atype = ATYP_IPV6
   271  		}
   272  	} else {
   273  		if len(host) > 255 {
   274  			err = errors.New("proxy: destination host name too long: " + host)
   275  			return
   276  		}
   277  		p.atype = ATYP_DOMAIN
   278  	}
   279  	p.data = data
   280  
   281  	return
   282  }
   283  func (p *PacketUDP) Parse(b []byte) (err error) {
   284  	if len(b) < 9 {
   285  		return fmt.Errorf("too short packet")
   286  	}
   287  	p.frag = uint8(b[2])
   288  	if p.frag != 0 {
   289  		err = fmt.Errorf("FRAG only support for 0 , %v ,%v", p.frag, b[:4])
   290  		return
   291  	}
   292  	portIndex := 0
   293  	p.atype = b[3]
   294  	switch p.atype {
   295  	case ATYP_IPV4: //IP V4
   296  		if len(b) < 11 {
   297  			return fmt.Errorf("too short packet")
   298  		}
   299  		p.dstHost = net.IPv4(b[4], b[5], b[6], b[7]).String()
   300  		portIndex = 8
   301  	case ATYP_DOMAIN: //域名
   302  		domainLen := uint8(b[4])
   303  		if len(b) < int(domainLen)+7 {
   304  			return fmt.Errorf("too short packet")
   305  		}
   306  		p.dstHost = string(b[5 : 5+domainLen]) //b[4]表示域名的长度
   307  		portIndex = int(5 + domainLen)
   308  	case ATYP_IPV6: //IP V6
   309  		if len(b) < 22 {
   310  			return fmt.Errorf("too short packet")
   311  		}
   312  		p.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()
   313  		portIndex = 20
   314  	}
   315  	p.dstPort = strconv.Itoa(int(b[portIndex])<<8 | int(b[portIndex+1]))
   316  	p.data = b[portIndex+2:]
   317  	return
   318  }
   319  func (p *PacketUDP) Header() []byte {
   320  	header := new(bytes.Buffer)
   321  	header.Write([]byte{0x00, 0x00, p.frag, p.atype})
   322  	if p.atype == ATYP_IPV4 {
   323  		ip := net.ParseIP(p.dstHost)
   324  		header.Write(ip.To4())
   325  	} else if p.atype == ATYP_IPV6 {
   326  		ip := net.ParseIP(p.dstHost)
   327  		header.Write(ip.To16())
   328  	} else if p.atype == ATYP_DOMAIN {
   329  		hBytes := []byte(p.dstHost)
   330  		header.WriteByte(byte(len(hBytes)))
   331  		header.Write(hBytes)
   332  	}
   333  	port, _ := strconv.ParseUint(p.dstPort, 10, 64)
   334  	portBytes := new(bytes.Buffer)
   335  	binary.Write(portBytes, binary.BigEndian, port)
   336  	header.Write(portBytes.Bytes()[portBytes.Len()-2:])
   337  	return header.Bytes()
   338  }
   339  func (p *PacketUDP) Bytes() []byte {
   340  	packBytes := new(bytes.Buffer)
   341  	packBytes.Write(p.Header())
   342  	packBytes.Write(p.data)
   343  	return packBytes.Bytes()
   344  }
   345  func (p *PacketUDP) Host() string {
   346  	return p.dstHost
   347  }
   348  func (p *PacketUDP) Addr() string {
   349  	return net.JoinHostPort(p.dstHost, p.dstPort)
   350  }
   351  func (p *PacketUDP) Port() string {
   352  	return p.dstPort
   353  }
   354  func (p *PacketUDP) Data() []byte {
   355  	return p.data
   356  }