136 lines
2.8 KiB
Go
136 lines
2.8 KiB
Go
package socks5
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"errors"
|
|
"net"
|
|
"strconv"
|
|
)
|
|
|
|
// ParseAddress format address x.x.x.x:xx to raw address.
|
|
// addr contains domain length
|
|
func ParseAddress(address string) (a byte, addr []byte, port []byte, err error) {
|
|
var h, p string
|
|
h, p, err = net.SplitHostPort(address)
|
|
if err != nil {
|
|
return
|
|
}
|
|
ip := net.ParseIP(h)
|
|
if ip4 := ip.To4(); ip4 != nil {
|
|
a = ATYPIPv4
|
|
addr = []byte(ip4)
|
|
} else if ip6 := ip.To16(); ip6 != nil {
|
|
a = ATYPIPv6
|
|
addr = []byte(ip6)
|
|
} else {
|
|
a = ATYPDomain
|
|
addr = []byte{byte(len(h))}
|
|
addr = append(addr, []byte(h)...)
|
|
}
|
|
i, _ := strconv.Atoi(p)
|
|
port = make([]byte, 2)
|
|
binary.BigEndian.PutUint16(port, uint16(i))
|
|
return
|
|
}
|
|
|
|
// bytes to address
|
|
// addr contains domain length
|
|
func ParseBytesAddress(b []byte) (a byte, addr []byte, port []byte, err error) {
|
|
if len(b) < 1 {
|
|
err = errors.New("Invalid address")
|
|
return
|
|
}
|
|
a = b[0]
|
|
if a == ATYPIPv4 {
|
|
if len(b) < 1+4+2 {
|
|
err = errors.New("Invalid address")
|
|
return
|
|
}
|
|
addr = b[1 : 1+4]
|
|
port = b[1+4 : 1+4+2]
|
|
return
|
|
}
|
|
if a == ATYPIPv6 {
|
|
if len(b) < 1+16+2 {
|
|
err = errors.New("Invalid address")
|
|
return
|
|
}
|
|
addr = b[1 : 1+16]
|
|
port = b[1+16 : 1+16+2]
|
|
return
|
|
}
|
|
if a == ATYPDomain {
|
|
if len(b) < 1+1 {
|
|
err = errors.New("Invalid address")
|
|
return
|
|
}
|
|
l := int(b[1])
|
|
if len(b) < 1+1+l+2 {
|
|
err = errors.New("Invalid address")
|
|
return
|
|
}
|
|
addr = b[1 : 1+1+l]
|
|
port = b[1+1+l : 1+1+l+2]
|
|
return
|
|
}
|
|
err = errors.New("Invalid address")
|
|
return
|
|
}
|
|
|
|
// ToAddress format raw address to x.x.x.x:xx
|
|
// addr contains domain length
|
|
func ToAddress(a byte, addr []byte, port []byte) string {
|
|
var h, p string
|
|
if a == ATYPIPv4 || a == ATYPIPv6 {
|
|
h = net.IP(addr).String()
|
|
}
|
|
if a == ATYPDomain {
|
|
if len(addr) < 1 {
|
|
return ""
|
|
}
|
|
if len(addr) < int(addr[0])+1 {
|
|
return ""
|
|
}
|
|
h = string(addr[1:])
|
|
}
|
|
p = strconv.Itoa(int(binary.BigEndian.Uint16(port)))
|
|
return net.JoinHostPort(h, p)
|
|
}
|
|
|
|
// Address return request address like ip:xx
|
|
func (r *Request) Address() string {
|
|
var s string
|
|
if r.Atyp == ATYPDomain {
|
|
s = bytes.NewBuffer(r.DstAddr[1:]).String()
|
|
} else {
|
|
s = net.IP(r.DstAddr).String()
|
|
}
|
|
p := strconv.Itoa(int(binary.BigEndian.Uint16(r.DstPort)))
|
|
return net.JoinHostPort(s, p)
|
|
}
|
|
|
|
// Address return request address like ip:xx
|
|
func (r *Reply) Address() string {
|
|
var s string
|
|
if r.Atyp == ATYPDomain {
|
|
s = bytes.NewBuffer(r.BndAddr[1:]).String()
|
|
} else {
|
|
s = net.IP(r.BndAddr).String()
|
|
}
|
|
p := strconv.Itoa(int(binary.BigEndian.Uint16(r.BndPort)))
|
|
return net.JoinHostPort(s, p)
|
|
}
|
|
|
|
// Address return datagram address like ip:xx
|
|
func (d *Datagram) Address() string {
|
|
var s string
|
|
if d.Atyp == ATYPDomain {
|
|
s = bytes.NewBuffer(d.DstAddr[1:]).String()
|
|
} else {
|
|
s = net.IP(d.DstAddr).String()
|
|
}
|
|
p := strconv.Itoa(int(binary.BigEndian.Uint16(d.DstPort)))
|
|
return net.JoinHostPort(s, p)
|
|
}
|