func sendSocks5ResponseRejected(w io.Writer, reason byte) error {
	return sendSocks5Response(w, reason)
}
Send a SOCKS5 response with the provided failure reason.
package socks
import (
	"bufio"
	"fmt"
	"io"
	"net"
	"time"
)
const (
	socks4Version = 0x04
	socks5Version = 0x05
	socksAuthNoneRequired        = 0x00
	socksAuthUsernamePassword    = 0x02
	socksAuthNoAcceptableMethods = 0xff
	socksCmdConnect = 0x01
	socksCmdBind    = 0x02
	socksCmdUDP     = 0x03
	socksReserved   = 0x00
	socksAtypeV4         = 0x01
	socksAtypeDomainName = 0x03
	socksAtypeV6         = 0x04
	socksAuthRFC1929Ver     = 0x01
	socksAuthRFC1929Success = 0x00
	socksAuthRFC1929Fail    = 0x01
	socksRepSucceeded = 0x00
	SocksRepGeneralFailure = 0x01
	SocksRepConnectionNotAllowed = 0x02
	SocksRepNetworkUnreachable = 0x03
	SocksRepHostUnreachable = 0x04
	SocksRepConnectionRefused = 0x05
	SocksRepTTLExpired = 0x06
	SocksRepCommandNotSupported = 0x07
	SocksRepAddressNotSupported = 0x08
	socks4ResponseVersion = 0x00
	socks4RequestGranted  = 0x5a
	socks4RequestRejected = 0x5b
)
const socksRequestTimeout = 5 * time.Second
type SocksRequest struct {
	Target string
	Username string
	Password string
	Args Args
}
type SocksConn struct {
	net.Conn
	Req          SocksRequest
	socksVersion byte
}
func (conn *SocksConn) Version() string {
	if conn.socksVersion == socks4Version {
		return "socks4"
	} else if conn.socksVersion == socks5Version {
		return "socks5"
	}
	return "unknown"
}
func (conn *SocksConn) Grant(addr *net.TCPAddr) error {
	if conn.socksVersion == socks4Version {
		return sendSocks4aResponseGranted(conn, addr)
	}
	return sendSocks5ResponseGranted(conn)
}
func (conn *SocksConn) Reject() error {
	if conn.socksVersion == socks4Version {
		return sendSocks4aResponseRejected(conn)
	}
	return sendSocks5ResponseRejected(conn, SocksRepGeneralFailure)
}
func (conn *SocksConn) RejectReason(reason byte) error {
	if conn.socksVersion == socks4Version {
		return sendSocks4aResponseRejected(conn)
	}
	return sendSocks5ResponseRejected(conn, reason)
}
type SocksListener struct {
	net.Listener
}
func ListenSocks(network, laddr string) (*SocksListener, error) {
	ln, err := net.Listen(network, laddr)
	if err != nil {
		return nil, err
	}
	return NewSocksListener(ln), nil
}
func NewSocksListener(ln net.Listener) *SocksListener {
	return &SocksListener{ln}
}
func (ln *SocksListener) Accept() (net.Conn, error) {
	return ln.AcceptSocks()
}
func NewSocksConn(c net.Conn) (*SocksConn, *bufio.Reader, error) {
	conn := new(SocksConn)
	conn.Conn = c
	bio := bufio.NewReader(c)
	if version, err := socksPeekByte(bio); err != nil {
		err = newTemporaryNetError("AcceptSocks: socksPeekByte() failed: %s", err.Error())
		return nil, bio, err
	} else if version == socks4Version {
		conn.socksVersion = socks4Version
		conn.Req, err = readSocks4aConnect(bio)
		if err != nil {
			return nil, nil, err
		}
	} else if version == socks5Version {
		conn.socksVersion = socks5Version
		rw := bufio.NewReadWriter(bio, bufio.NewWriter(conn))
		conn.Req, err = socks5Handshake(rw)
		if err != nil {
			return nil, nil, err
		}
	} else {
		err = newTemporaryNetError("AcceptSocks: Illegal SOCKS version: 0x%02x", version)
		return nil, bio, err
	}
	conn.SetDeadline(time.Time{})
	return conn, bio, nil
}
func (ln *SocksListener) AcceptSocks() (*SocksConn, error) {
	c, err := ln.Listener.Accept()
	if err != nil {
		return nil, err
	}
	conn := new(SocksConn)
	conn.Conn = c
	err = conn.SetDeadline(time.Now().Add(socksRequestTimeout))
	if err != nil {
		conn.Close()
		err = newTemporaryNetError("AcceptSocks: conn.SetDeadline() #1 failed: %s", err.Error())
		return nil, err
	}
	rw := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
	if version, err := socksPeekByte(rw.Reader); err != nil {
		conn.Close()
		err = newTemporaryNetError("AcceptSocks: socksPeekByte() failed: %s", err.Error())
		return nil, err
	} else if version == socks4Version {
		conn.socksVersion = socks4Version
		conn.Req, err = readSocks4aConnect(rw.Reader)
		if err != nil {
			conn.Close()
			return nil, err
		}
	} else if version == socks5Version {
		conn.socksVersion = socks5Version
		conn.Req, err = socks5Handshake(rw)
		if err != nil {
			conn.Close()
			return nil, err
		}
	} else {
		conn.Close()
		err = newTemporaryNetError("AcceptSocks: Illegal SOCKS version: 0x%02x", version)
		return nil, err
	}
	err = conn.SetDeadline(time.Time{})
	if err != nil {
		conn.Close()
		err = newTemporaryNetError("AcceptSocks: conn.SetDeadline() #2 failed: %s", err.Error())
		return nil, err
	}
	return conn, nil
}
func (ln *SocksListener) Version() string {
	return "socks5"
}
func socks5Handshake(rw *bufio.ReadWriter) (req SocksRequest, err error) {
	var method byte
	if method, err = socks5NegotiateAuth(rw); err != nil {
		return
	}
	if err = socks5Authenticate(rw, method, &req); err != nil {
		return
	}
	err = socks5ReadCommand(rw, &req)
	return
}
func socks5NegotiateAuth(rw *bufio.ReadWriter) (method byte, err error) {
	if err = socksReadByteVerify(rw.Reader, "version", socks5Version); err != nil {
		err = newTemporaryNetError("socks5NegotiateAuth: %s", err.Error())
		return
	}
	var nmethods byte
	if nmethods, err = socksReadByte(rw.Reader); err != nil {
		err = newTemporaryNetError("socks5NegotiateAuth: Failed to read nmethods byte: %s", err.Error())
		return
	}
	var methods []byte
	if methods, err = socksReadBytes(rw.Reader, int(nmethods)); err != nil {
		err = newTemporaryNetError("socks5NegotiateAuth: Failed to read methods bytes: %s", err.Error())
		return
	}
	method = socksAuthNoAcceptableMethods
	for _, m := range methods {
		switch m {
		case socksAuthNoneRequired:
			if method == socksAuthNoAcceptableMethods {
				method = m
			}
		case socksAuthUsernamePassword:
			method = m
		}
	}
	var msg [2]byte
	msg[0] = socks5Version
	msg[1] = method
	if _, err = rw.Writer.Write(msg[:]); err != nil {
		err = newTemporaryNetError("socks5NegotiateAuth: Failed to write negotiated method: %s", err.Error())
		return
	}
	if err = socksFlushBuffers(rw); err != nil {
		err = newTemporaryNetError("socks5NegotiateAuth: Failed to flush buffers: %s", err.Error())
		return
	}
	return
}
func socks5Authenticate(rw *bufio.ReadWriter, method byte, req *SocksRequest) (err error) {
	switch method {
	case socksAuthNoneRequired:
	case socksAuthUsernamePassword:
		if err = socks5AuthRFC1929(rw, req); err != nil {
			return
		}
	case socksAuthNoAcceptableMethods:
		err = newTemporaryNetError("socks5Authenticate: SOCKS method select had no compatible methods")
		return
	default:
		err = newTemporaryNetError("socks5Authenticate: SOCKS method select picked a unsupported method 0x%02x", method)
		return
	}
	if err = socksFlushBuffers(rw); err != nil {
		err = newTemporaryNetError("socks5Authenticate: Failed to flush buffers: %s", err)
		return
	}
	return
}
func socks5AuthRFC1929(rw *bufio.ReadWriter, req *SocksRequest) (err error) {
	sendErrResp := func() {
		resp := []byte{socksAuthRFC1929Ver, socksAuthRFC1929Fail}
		rw.Write(resp[:])
		socksFlushBuffers(rw)
	}
	if err = socksReadByteVerify(rw.Reader, "auth version", socksAuthRFC1929Ver); err != nil {
		sendErrResp()
		err = newTemporaryNetError("socks5AuthRFC1929: %s", err)
		return
	}
	var ulen byte
	if ulen, err = socksReadByte(rw.Reader); err != nil {
		err = newTemporaryNetError("socks5AuthRFC1929: Failed to read username length: %s", err)
		return
	}
	if ulen < 1 {
		sendErrResp()
		err = newTemporaryNetError("socks5AuthRFC1929: username with 0 length")
		return
	}
	var uname []byte
	if uname, err = socksReadBytes(rw.Reader, int(ulen)); err != nil {
		err = newTemporaryNetError("socks5AuthRFC1929: Failed to read username: %s", err)
		return
	}
	req.Username = string(uname)
	var plen byte
	if plen, err = socksReadByte(rw.Reader); err != nil {
		err = newTemporaryNetError("socks5AuthRFC1929: Failed to read password length: %s", err)
		return
	}
	if plen < 1 {
		sendErrResp()
		err = newTemporaryNetError("socks5AuthRFC1929: password with 0 length")
		return
	}
	var passwd []byte
	if passwd, err = socksReadBytes(rw.Reader, int(plen)); err != nil {
		err = newTemporaryNetError("socks5AuthRFC1929: Failed to read password: %s", err)
		return
	}
	if !(plen == 1 && passwd[0] == 0x00) {
		req.Password = string(passwd)
	}
	if req.Args, err = parseClientParameters(req.Username + req.Password); err != nil {
		sendErrResp()
		err = newTemporaryNetError("socks5AuthRFC1929: failed to parse client parameters: %s", err)
		return
	}
	resp := []byte{socksAuthRFC1929Ver, socksAuthRFC1929Success}
	if _, err = rw.Write(resp[:]); err != nil {
		err = newTemporaryNetError("socks5AuthRFC1929: failed to write success response: %s", err)
		return
	}
	return
}
func socks5ReadCommand(rw *bufio.ReadWriter, req *SocksRequest) (err error) {
	sendErrResp := func(reason byte) {
		sendSocks5ResponseRejected(rw, reason)
		socksFlushBuffers(rw)
	}
	if err = socksReadByteVerify(rw.Reader, "version", socks5Version); err != nil {
		sendErrResp(SocksRepGeneralFailure)
		err = newTemporaryNetError("socks5ReadCommand: %s", err)
		return
	}
	if err = socksReadByteVerify(rw.Reader, "command", socksCmdConnect); err != nil {
		sendErrResp(SocksRepCommandNotSupported)
		err = newTemporaryNetError("socks5ReadCommand: %s", err)
		return
	}
	if err = socksReadByteVerify(rw.Reader, "reserved", socksReserved); err != nil {
		sendErrResp(SocksRepGeneralFailure)
		err = newTemporaryNetError("socks5ReadCommand: %s", err)
		return
	}
	var atype byte
	if atype, err = socksReadByte(rw.Reader); err != nil {
		err = newTemporaryNetError("socks5ReadCommand: Failed to read address type: %s", err)
		return
	}
	var host string
	switch atype {
	case socksAtypeV4:
		var addr []byte
		if addr, err = socksReadBytes(rw.Reader, net.IPv4len); err != nil {
			err = newTemporaryNetError("socks5ReadCommand: Failed to read IPv4 address: %s", err)
			return
		}
		host = net.IPv4(addr[0], addr[1], addr[2], addr[3]).String()
	case socksAtypeDomainName:
		var alen byte
		if alen, err = socksReadByte(rw.Reader); err != nil {
			err = newTemporaryNetError("socks5ReadCommand: Failed to read domain name length: %s", err)
			return
		}
		if alen == 0 {
			err = newTemporaryNetError("socks5ReadCommand: SOCKS request had domain name with 0 length")
			return
		}
		var addr []byte
		if addr, err = socksReadBytes(rw.Reader, int(alen)); err != nil {
			err = newTemporaryNetError("socks5ReadCommand: Failed to read domain name: %s", err)
			return
		}
		host = string(addr)
	case socksAtypeV6:
		var rawAddr []byte
		if rawAddr, err = socksReadBytes(rw.Reader, net.IPv6len); err != nil {
			err = newTemporaryNetError("socks5ReadCommand: Failed to read IPv6 address: %s", err)
			return
		}
		addr := make(net.IP, net.IPv6len)
		copy(addr[:], rawAddr[:])
		host = fmt.Sprintf("[%s]", addr.String())
	default:
		sendErrResp(SocksRepAddressNotSupported)
		err = newTemporaryNetError("socks5ReadCommand: SOCKS request had unsupported address type 0x%02x", atype)
		return
	}
	var rawPort []byte
	if rawPort, err = socksReadBytes(rw.Reader, 2); err != nil {
		err = newTemporaryNetError("socks5ReadCommand: Failed to read port number: %s", err)
		return
	}
	port := int(rawPort[0])<<8 | int(rawPort[1])<<0
	if err = socksFlushBuffers(rw); err != nil {
		err = newTemporaryNetError("socks5ReadCommand: Failed to flush buffers: %s", err)
		return
	}
	req.Target = fmt.Sprintf("%s:%d", host, port)
	return
}
func sendSocks5Response(w io.Writer, code byte) error {
	resp := make([]byte, 4+4+2)
	resp[0] = socks5Version
	resp[1] = code
	resp[2] = socksReserved
	resp[3] = socksAtypeV4
	if _, err := w.Write(resp[:]); err != nil {
		err = newTemporaryNetError("sendSocks5Response: Failed write response: %s", err)
		return err
	}
	return nil
}
func sendSocks5ResponseGranted(w io.Writer) error {
	return sendSocks5Response(w, socksRepSucceeded)
}