|
|
@@ -34,6 +34,12 @@ const (
|
|
|
statusCmdNotSupport = 0x07
|
|
|
)
|
|
|
|
|
|
+var addrParser = protocol.NewAddressParser(
|
|
|
+ protocol.AddressFamilyByte(0x01, net.AddressFamilyIPv4),
|
|
|
+ protocol.AddressFamilyByte(0x04, net.AddressFamilyIPv6),
|
|
|
+ protocol.AddressFamilyByte(0x03, net.AddressFamilyDomain),
|
|
|
+)
|
|
|
+
|
|
|
type ServerSession struct {
|
|
|
config *ServerConfig
|
|
|
port net.Port
|
|
|
@@ -122,7 +128,7 @@ func (s *ServerSession) Handshake(reader io.Reader, writer io.Writer) (*protocol
|
|
|
return nil, newError("failed to write auth response").Base(err)
|
|
|
}
|
|
|
}
|
|
|
- if err := buffer.Reset(buf.ReadFullFrom(reader, 4)); err != nil {
|
|
|
+ if err := buffer.Reset(buf.ReadFullFrom(reader, 3)); err != nil {
|
|
|
return nil, newError("failed to read request").Base(err)
|
|
|
}
|
|
|
|
|
|
@@ -139,13 +145,11 @@ func (s *ServerSession) Handshake(reader io.Reader, writer io.Writer) (*protocol
|
|
|
request.Command = protocol.RequestCommandUDP
|
|
|
}
|
|
|
|
|
|
- addrType := buffer.Byte(3)
|
|
|
-
|
|
|
buffer.Clear()
|
|
|
|
|
|
request.Version = socks5Version
|
|
|
|
|
|
- addr, port, err := ReadAddress(buffer, addrType, reader)
|
|
|
+ addr, port, err := addrParser.ReadAddressPort(buffer, reader)
|
|
|
if err != nil {
|
|
|
return nil, newError("failed to read address").Base(err)
|
|
|
}
|
|
|
@@ -229,30 +233,10 @@ func writeSocks5AuthenticationResponse(writer io.Writer, version byte, auth byte
|
|
|
return err
|
|
|
}
|
|
|
|
|
|
-// AppendAddress appends Socks address into the given buffer.
|
|
|
-func AppendAddress(buffer *buf.Buffer, address net.Address, port net.Port) error {
|
|
|
- switch address.Family() {
|
|
|
- case net.AddressFamilyIPv4:
|
|
|
- buffer.AppendBytes(addrTypeIPv4)
|
|
|
- buffer.Append(address.IP())
|
|
|
- case net.AddressFamilyIPv6:
|
|
|
- buffer.AppendBytes(addrTypeIPv6)
|
|
|
- buffer.Append(address.IP())
|
|
|
- case net.AddressFamilyDomain:
|
|
|
- if protocol.IsDomainTooLong(address.Domain()) {
|
|
|
- return newError("Super long domain is not supported in Socks protocol: ", address.Domain())
|
|
|
- }
|
|
|
- buffer.AppendBytes(addrTypeDomain, byte(len(address.Domain())))
|
|
|
- common.Must(buffer.AppendSupplier(serial.WriteString(address.Domain())))
|
|
|
- }
|
|
|
- common.Must(buffer.AppendSupplier(serial.WriteUint16(port.Value())))
|
|
|
- return nil
|
|
|
-}
|
|
|
-
|
|
|
func writeSocks5Response(writer io.Writer, errCode byte, address net.Address, port net.Port) error {
|
|
|
buffer := buf.NewLocal(64)
|
|
|
buffer.AppendBytes(socks5Version, errCode, 0x00 /* reserved */)
|
|
|
- if err := AppendAddress(buffer, address, port); err != nil {
|
|
|
+ if err := addrParser.WriteAddressPort(buffer, address, port); err != nil {
|
|
|
return err
|
|
|
}
|
|
|
|
|
|
@@ -269,9 +253,9 @@ func writeSocks4Response(writer io.Writer, errCode byte, address net.Address, po
|
|
|
return err
|
|
|
}
|
|
|
|
|
|
-func DecodeUDPPacket(packet []byte) (*protocol.RequestHeader, []byte, error) {
|
|
|
- if len(packet) < 5 {
|
|
|
- return nil, nil, newError("insufficient length of packet.")
|
|
|
+func DecodeUDPPacket(packet *buf.Buffer) (*protocol.RequestHeader, error) {
|
|
|
+ if packet.Len() < 5 {
|
|
|
+ return nil, newError("insufficient length of packet.")
|
|
|
}
|
|
|
request := &protocol.RequestHeader{
|
|
|
Version: socks5Version,
|
|
|
@@ -279,50 +263,25 @@ func DecodeUDPPacket(packet []byte) (*protocol.RequestHeader, []byte, error) {
|
|
|
}
|
|
|
|
|
|
// packet[0] and packet[1] are reserved
|
|
|
- if packet[2] != 0 /* fragments */ {
|
|
|
- return nil, nil, newError("discarding fragmented payload.")
|
|
|
+ if packet.Byte(2) != 0 /* fragments */ {
|
|
|
+ return nil, newError("discarding fragmented payload.")
|
|
|
}
|
|
|
|
|
|
- addrType := packet[3]
|
|
|
- var dataBegin int
|
|
|
+ packet.SliceFrom(3)
|
|
|
|
|
|
- switch addrType {
|
|
|
- case addrTypeIPv4:
|
|
|
- if len(packet) < 10 {
|
|
|
- return nil, nil, newError("insufficient length of packet")
|
|
|
- }
|
|
|
- ip := packet[4:8]
|
|
|
- request.Port = net.PortFromBytes(packet[8:10])
|
|
|
- request.Address = net.IPAddress(ip)
|
|
|
- dataBegin = 10
|
|
|
- case addrTypeIPv6:
|
|
|
- if len(packet) < 22 {
|
|
|
- return nil, nil, newError("insufficient length of packet")
|
|
|
- }
|
|
|
- ip := packet[4:20]
|
|
|
- request.Port = net.PortFromBytes(packet[20:22])
|
|
|
- request.Address = net.IPAddress(ip)
|
|
|
- dataBegin = 22
|
|
|
- case addrTypeDomain:
|
|
|
- domainLength := int(packet[4])
|
|
|
- if len(packet) < 5+domainLength+2 {
|
|
|
- return nil, nil, newError("insufficient length of packet")
|
|
|
- }
|
|
|
- domain := string(packet[5 : 5+domainLength])
|
|
|
- request.Port = net.PortFromBytes(packet[5+domainLength : 5+domainLength+2])
|
|
|
- request.Address = net.ParseAddress(domain)
|
|
|
- dataBegin = 5 + domainLength + 2
|
|
|
- default:
|
|
|
- return nil, nil, newError("unknown address type ", addrType)
|
|
|
+ addr, port, err := addrParser.ReadAddressPort(nil, packet)
|
|
|
+ if err != nil {
|
|
|
+ return nil, newError("failed to read UDP header").Base(err)
|
|
|
}
|
|
|
-
|
|
|
- return request, packet[dataBegin:], nil
|
|
|
+ request.Address = addr
|
|
|
+ request.Port = port
|
|
|
+ return request, nil
|
|
|
}
|
|
|
|
|
|
func EncodeUDPPacket(request *protocol.RequestHeader, data []byte) (*buf.Buffer, error) {
|
|
|
b := buf.New()
|
|
|
b.AppendBytes(0, 0, 0 /* Fragment */)
|
|
|
- if err := AppendAddress(b, request.Address, request.Port); err != nil {
|
|
|
+ if err := addrParser.WriteAddressPort(b, request.Address, request.Port); err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
b.Append(data)
|
|
|
@@ -342,12 +301,9 @@ func (r *UDPReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
|
|
if err := b.AppendSupplier(buf.ReadFrom(r.reader)); err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
- _, data, err := DecodeUDPPacket(b.Bytes())
|
|
|
- if err != nil {
|
|
|
+ if _, err := DecodeUDPPacket(b); err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
- b.Clear()
|
|
|
- b.Append(data)
|
|
|
return buf.NewMultiBufferValue(b), nil
|
|
|
}
|
|
|
|
|
|
@@ -376,40 +332,6 @@ func (w *UDPWriter) Write(b []byte) (int, error) {
|
|
|
return len(b), nil
|
|
|
}
|
|
|
|
|
|
-func ReadAddress(b *buf.Buffer, addrType byte, reader io.Reader) (net.Address, net.Port, error) {
|
|
|
- var address net.Address
|
|
|
- switch addrType {
|
|
|
- case addrTypeIPv4:
|
|
|
- if err := b.AppendSupplier(buf.ReadFullFrom(reader, 4)); err != nil {
|
|
|
- return nil, 0, err
|
|
|
- }
|
|
|
- address = net.IPAddress(b.BytesFrom(-4))
|
|
|
- case addrTypeIPv6:
|
|
|
- if err := b.AppendSupplier(buf.ReadFullFrom(reader, 16)); err != nil {
|
|
|
- return nil, 0, err
|
|
|
- }
|
|
|
- address = net.IPAddress(b.BytesFrom(-16))
|
|
|
- case addrTypeDomain:
|
|
|
- if err := b.AppendSupplier(buf.ReadFullFrom(reader, 1)); err != nil {
|
|
|
- return nil, 0, err
|
|
|
- }
|
|
|
- domainLength := int(b.Byte(b.Len() - 1))
|
|
|
- if err := b.AppendSupplier(buf.ReadFullFrom(reader, domainLength)); err != nil {
|
|
|
- return nil, 0, err
|
|
|
- }
|
|
|
- address = net.DomainAddress(string(b.BytesFrom(-domainLength)))
|
|
|
- default:
|
|
|
- return nil, 0, newError("unknown address type: ", addrType)
|
|
|
- }
|
|
|
-
|
|
|
- if err := b.AppendSupplier(buf.ReadFullFrom(reader, 2)); err != nil {
|
|
|
- return nil, 0, err
|
|
|
- }
|
|
|
- port := net.PortFromBytes(b.BytesFrom(-2))
|
|
|
-
|
|
|
- return address, port, nil
|
|
|
-}
|
|
|
-
|
|
|
func ClientHandshake(request *protocol.RequestHeader, reader io.Reader, writer io.Writer) (*protocol.RequestHeader, error) {
|
|
|
authByte := byte(authNotRequired)
|
|
|
if request.User != nil {
|
|
|
@@ -462,7 +384,7 @@ func ClientHandshake(request *protocol.RequestHeader, reader io.Reader, writer i
|
|
|
command = byte(cmdUDPPort)
|
|
|
}
|
|
|
b.AppendBytes(socks5Version, command, 0x00 /* reserved */)
|
|
|
- if err := AppendAddress(b, request.Address, request.Port); err != nil {
|
|
|
+ if err := addrParser.WriteAddressPort(b, request.Address, request.Port); err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
|
|
|
@@ -471,7 +393,7 @@ func ClientHandshake(request *protocol.RequestHeader, reader io.Reader, writer i
|
|
|
}
|
|
|
|
|
|
b.Clear()
|
|
|
- if err := b.AppendSupplier(buf.ReadFullFrom(reader, 4)); err != nil {
|
|
|
+ if err := b.AppendSupplier(buf.ReadFullFrom(reader, 3)); err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
|
|
|
@@ -480,11 +402,9 @@ func ClientHandshake(request *protocol.RequestHeader, reader io.Reader, writer i
|
|
|
return nil, newError("server rejects request: ", resp)
|
|
|
}
|
|
|
|
|
|
- addrType := b.Byte(3)
|
|
|
-
|
|
|
b.Clear()
|
|
|
|
|
|
- address, port, err := ReadAddress(b, addrType, reader)
|
|
|
+ address, port, err := addrParser.ReadAddressPort(b, reader)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|