func NewRequest(bufConn io.Reader) (*Request, error) {
	header := []byte{0, 0, 0}
	if _, err := io.ReadAtLeast(bufConn, header, 3); err != nil {
		return nil, fmt.Errorf("Failed to get command version: %v", err)
	}
	if header[0] != socks5Version {
		return nil, fmt.Errorf("Unsupported command version: %v", header[0])
	}
	dest, err := readAddrSpec(bufConn)
	if err != nil {
		return nil, err
	}
	request := &Request{
		Version:  socks5Version,
		Command:  header[1],
		DestAddr: dest,
		bufConn:  bufConn,
	}
	return request, nil
}
NewRequest creates a new Request from the tcp connection
package socks5
import (
	"fmt"
	"io"
	"net"
	"strconv"
	"strings"
	"golang.org/x/net/context"
)
const (
	ConnectCommand   = uint8(1)
	BindCommand      = uint8(2)
	AssociateCommand = uint8(3)
	ipv4Address      = uint8(1)
	fqdnAddress      = uint8(3)
	ipv6Address      = uint8(4)
)
const (
	successReply uint8 = iota
	serverFailure
	ruleFailure
	networkUnreachable
	hostUnreachable
	connectionRefused
	ttlExpired
	commandNotSupported
	addrTypeNotSupported
)
var (
	unrecognizedAddrType = fmt.Errorf("Unrecognized address type")
)
type AddressRewriter interface {
	Rewrite(ctx context.Context, request *Request) (context.Context, *AddrSpec)
}
type AddrSpec struct {
	FQDN string
	IP   net.IP
	Port int
}
func (a *AddrSpec) String() string {
	if a.FQDN != "" {
		return fmt.Sprintf("%s (%s):%d", a.FQDN, a.IP, a.Port)
	}
	return fmt.Sprintf("%s:%d", a.IP, a.Port)
}
func (a AddrSpec) Address() string {
	if 0 != len(a.IP) {
		return net.JoinHostPort(a.IP.String(), strconv.Itoa(a.Port))
	}
	return net.JoinHostPort(a.FQDN, strconv.Itoa(a.Port))
}
type Request struct {
	Version uint8
	Command uint8
	AuthContext *AuthContext
	RemoteAddr *AddrSpec
	DestAddr *AddrSpec
	realDestAddr *AddrSpec
	bufConn      io.Reader
}
type conn interface {
	Write([]byte) (int, error)
	RemoteAddr() net.Addr
}