socks5/util.go

93 lines
1.9 KiB
Go
Raw Normal View History

2021-07-09 16:50:43 +00:00
package socks5
import (
"encoding/binary"
"io"
"net"
"strconv"
)
// NewEmptyAddrReply returns reply with empty address and port
func NewEmptyAddrReply(status ReplyStatus, atyp ATYP) *Reply {
if atyp == ATYPIPv6 {
return NewReply(status, ATYPIPv6, []byte(net.IPv6zero), []byte{0x00, 0x00})
}
return NewReply(status, ATYPIPv4, []byte{0x00, 0x00, 0x00, 0x00}, []byte{0x00, 0x00})
}
// ReadAddress reads address from reader
func ReadAddress(r io.Reader, atyp ATYP) ([]byte, error) {
var addr []byte
//nolint:exhaustive
switch atyp {
case ATYPIPv4:
addr = make([]byte, 4)
if _, err := io.ReadFull(r, addr); err != nil {
return nil, err
}
case ATYPIPv6:
addr = make([]byte, 16)
if _, err := io.ReadFull(r, addr); err != nil {
return nil, err
}
case ATYPFQDN:
domainLen := make([]byte, 1)
if _, err := io.ReadFull(r, domainLen); err != nil {
return nil, err
}
if domainLen[0] == 0 {
return nil, ErrBadRequest
}
addr = make([]byte, int(domainLen[0]))
if _, err := io.ReadFull(r, addr); err != nil {
return nil, err
}
addr = append(domainLen, addr...) //nolint:makezero
default:
return nil, ErrBadRequest
}
return addr, nil
}
// ParseAddress parses address from string
func ParseAddress(address string) (ATYP, []byte, []byte, error) {
host, port, err := net.SplitHostPort(address)
if err != nil {
return 0x00, []byte{}, []byte{}, err
}
var (
atyp ATYP
addr []byte
)
ip := net.ParseIP(host)
if ip4 := ip.To4(); ip4 != nil {
atyp = ATYPIPv4
addr = []byte(ip4)
} else if ip6 := ip.To16(); ip6 != nil {
atyp = ATYPIPv6
addr = []byte(ip6)
} else {
atyp = ATYPFQDN
addr = []byte{byte(len(host))}
addr = append(addr, []byte(host)...)
}
portInt, err := strconv.Atoi(port)
if err != nil {
return 0x00, []byte{}, []byte{}, err
}
portBytes := make([]byte, 2)
binary.BigEndian.PutUint16(portBytes, uint16(portInt))
return atyp, addr, portBytes, nil
}