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 }