|
|
@@ -537,3 +537,46 @@ func ClientHandshake(request *protocol.RequestHeader, reader io.Reader, writer i
|
|
|
|
|
|
return nil, nil
|
|
|
}
|
|
|
+
|
|
|
+func ClientHandshake4(request *protocol.RequestHeader, reader io.Reader, writer io.Writer) error {
|
|
|
+ b := buf.New()
|
|
|
+ defer b.Release()
|
|
|
+
|
|
|
+ common.Must2(b.Write([]byte{socks4Version, cmdTCPConnect}))
|
|
|
+ portBytes := b.Extend(2)
|
|
|
+ binary.BigEndian.PutUint16(portBytes, request.Port.Value())
|
|
|
+ switch request.Address.Family() {
|
|
|
+ case net.AddressFamilyIPv4:
|
|
|
+ common.Must2(b.Write(request.Address.IP()))
|
|
|
+ case net.AddressFamilyDomain:
|
|
|
+ common.Must2(b.Write([]byte{0x00, 0x00, 0x00, 0x01}))
|
|
|
+ case net.AddressFamilyIPv6:
|
|
|
+ return newError("ipv6 is not supported in socks4")
|
|
|
+ default:
|
|
|
+ panic("Unknown family type.")
|
|
|
+ }
|
|
|
+ if request.User != nil {
|
|
|
+ account := request.User.Account.(*Account)
|
|
|
+ common.Must2(b.WriteString(account.Username))
|
|
|
+ }
|
|
|
+ common.Must(b.WriteByte(0x00))
|
|
|
+ if request.Address.Family() == net.AddressFamilyDomain {
|
|
|
+ common.Must2(b.WriteString(request.Address.Domain()))
|
|
|
+ common.Must(b.WriteByte(0x00))
|
|
|
+ }
|
|
|
+ if err := buf.WriteAllBytes(writer, b.Bytes()); err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
+ b.Clear()
|
|
|
+ if _, err := b.ReadFullFrom(reader, 8); err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ if b.Byte(0) != 0x00 {
|
|
|
+ return newError("unexpected version of the reply code: ", b.Byte(0))
|
|
|
+ }
|
|
|
+ if b.Byte(1) != socks4RequestGranted {
|
|
|
+ return newError("server rejects request: ", b.Byte(1))
|
|
|
+ }
|
|
|
+ return nil
|
|
|
+}
|