go-socket5-proxy/socket5/request.go

152 lines
3.3 KiB
Go

package socket5
import (
"io"
"net"
)
type ClientRequestMessage struct {
CMD Command
Address string
Port uint16
AddressType Command
}
type Command = byte
const (
IPV4_LENGHT = 4
IPV6_LENGHT = 6
PORT_LENGHT = 2
)
const (
CmdConnect Command = 0x01
CmdBind Command = 0x02
CmdUDP Command = 0x03
)
type AddressType = byte
const (
TypeIPV4 AddressType = 0x01
TypeDoMain AddressType = 0x03
TypeIPV6 AddressType = 0x04
)
func NewClientRequestMessage(conn net.Conn) (*ClientRequestMessage, error) {
// 版本 命令 reseved 地址类型
buf := make([]byte, 4)
if _, err := io.ReadFull(conn, buf); err != nil {
return nil, err
}
version, command, reserved, addType := buf[0], buf[1], buf[2], buf[3]
if version != SOCKET_5_VERSION {
return nil, ERROR_SOCKET_VERSION_SUPPORTED
}
if command != CmdConnect && command != CmdBind && command != CmdUDP {
return nil, ERROR_COMMAND_NOT_SUPPORTED
}
if reserved != ReservedFild {
return nil, ERROR_SOCKET_VERSION_SUPPORTED
}
if addType == TypeIPV4 || addType == TypeDoMain {
var message ClientRequestMessage
message.CMD = command
message.AddressType = addType
//fmt.Printf("请求地址类型为:%v\n", addType)
switch addType {
case TypeIPV6:
buf = make([]byte, IPV6_LENGHT)
if _, err := io.ReadFull(conn, buf); err != nil {
return nil, err
}
ip := net.ParseIP(string(buf))
message.Address = ip.String()
//fmt.Println("TypeIPV6 地址为:" + ip.String())
case TypeIPV4:
buf = make([]byte, IPV4_LENGHT)
if _, err := io.ReadFull(conn, buf); err != nil {
return nil, err
}
ip := net.IP(buf)
message.Address = ip.String()
//fmt.Println("TypeIPV4 地址为:" + ip.String())
case TypeDoMain:
if _, err := io.ReadFull(conn, buf[:1]); err != nil {
return nil, err
}
domain_length := buf[0]
if domain_length > IPV4_LENGHT {
buf = make([]byte, domain_length)
}
if _, err := io.ReadFull(conn, buf[:domain_length]); err != nil {
message.Address = string(buf[:domain_length])
}
//fmt.Println("TypeDoMain 地址为:" + message.Address)
}
//读取 端口
if _, err := io.ReadFull(conn, buf[:PORT_LENGHT]); err != nil {
return nil, err
}
message.Port = (uint16(buf[0]) << 8) + uint16(buf[1])
return &message, nil
} else {
return nil, ERRADDRESS_TYPE_NOT_SUPPORTED
}
}
type ReplyType = byte
const (
ReplySuccess ReplyType = iota
ReplyServerFailure
ReplyConnectionNotAllowed
ReplyNetworkUnreachable
ReplyHostUnreachable
ReplyConnectionRefused
ReplyTTLExpired
ReplyCommandNotSupported
ReplyAddressTypeNotSupported
)
func WriteRequestSuccessMessage(conn net.Conn, ip net.IP, port uint16) error {
addressType := TypeIPV4
if len(ip) == IPV6_LENGHT {
addressType = TypeIPV6
}
// Write version, reply success, reserved, address type
_, err := conn.Write([]byte{SOCKET_5_VERSION, ReplySuccess, ReservedFild, addressType})
if err != nil {
return err
}
// write bind IP(IPV4/IPV6)
if _, err := conn.Write(ip); err != nil {
return err
}
// write bind port
buf := make([]byte, 2)
buf[0] = byte(port >> 8)
buf[1] = byte(port - uint16(buf[0]))
_, err = conn.Write(buf)
return err
}
func WriteRequestFailureMessage(conn net.Conn, replyType ReplyType) error {
_, err := conn.Write([]byte{SOCKET_5_VERSION, replyType, ReservedFild, TypeIPV4, 0, 0, 0, 0, 0, 0})
return err
}