# Authenticating distributed Ruby

**URL:** <https://www.ruby-forum.com/t/authenticating-distributed-ruby/74021>\
**Category:** Ruby\
**Created:** [February 27, 2006, 6:05am UTC](https://www.ruby-forum.com/t/authenticating-distributed-ruby/74021 "2006-02-27T06:05:17Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![trejkaz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/8797f3/32.png) [@trejkaz](https://www.ruby-forum.com/u/trejkaz)\
**Post date:** [February 27, 2006, 6:05am UTC](https://www.ruby-forum.com/t/authenticating-distributed-ruby/74021/1 "2006-02-27T06:05:17Z")

</div>

Hi all.

I’ve been playing with DRb a fair bit lately, am planning to use it as  
part of a Rails-to-XMPP integration project. XMPP is relatively costly  
to authenticate with, and one of the ways around that is to login only  
once and then have every Rails instance talk via DRb to that single  
instance. And of course the other benefit of having the clients online  
24/7 is that it would allow me to affect the state of my application  
and give live feedback via XMPP messages and commands.

Of course, DRb in itself provides no real security. But because of the  
nature of some of the applications I want to make possible, I do want  
to provide some basic protection against some of the more obvious kinds  
of attacks which occur.

The first aspect of this is encrypting the traffic which I can use SSL  
for. Although I’m not particularly keen on having to generate a  
certificate just to run this lightweight server… some lighter  
encryption would be preferable but I’ll take what’s available. Once I  
have SSL up, at least I can assume that people won’t be able to spy on  
the messages which are being sent back and forth.

The next aspect is some kind of basic authentication. Really, what I  
want is just a secret key that the client has to pass in in order to  
get access to my remote objects. But, I don’t want to have to add that  
secret key to every method.

One idea I came up with, which is simple but probably not very good:

class Chest  
def initialize(treasure, key)  
@treasure = treasure  
@key = key  
end

```
def unlock(key)
  if @key == key
    return @treasure
  else
    return nil # I suppose an exception would be better.
  end
end

```

end

Then I serve the Chest instance up as the remote object, and this way  
the “real” server (the treasure) doesn’t have to have the password  
added to all its methods, but I get an icky feeling that it opens the  
door to someone somehow “remembering” the remote reference to the  
treasure and getting a direct reference to it somehow after the  
password is changed.

How do people usually do this sort of thing? Is there a  
generally-accepted norm?

TX

---

<div class="post-metadata">

**Author:** ![trejkaz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/8797f3/32.png) [@trejkaz](https://www.ruby-forum.com/u/trejkaz)\
**Post date:** [February 27, 2006, 2:10pm UTC](https://www.ruby-forum.com/t/authenticating-distributed-ruby/74021/2 "2006-02-27T14:10:54Z")

</div>

On Mon, Feb 27, 2006 at 02:03:35PM +0900, Trejkaz wrote:  
[…]  
} Of course, DRb in itself provides no real security. But because of  
the  
} nature of some of the applications I want to make possible, I do want  
} to provide some basic protection against some of the more obvious  
kinds  
} of attacks which occur.  
}  
} The first aspect of this is encrypting the traffic which I can use SSL  
} for. Although I’m not particularly keen on having to generate a  
} certificate just to run this lightweight server… some lighter  
} encryption would be preferable but I’ll take what’s available. Once I  
} have SSL up, at least I can assume that people won’t be able to spy on  
} the messages which are being sent back and forth.  
}  
} The next aspect is some kind of basic authentication. Really, what I  
} want is just a secret key that the client has to pass in in order to  
} get access to my remote objects. But, I don’t want to have to add  
that  
} secret key to every method.  
[…]  
} How do people usually do this sort of thing? Is there a  
} generally-accepted norm?

You are working too hard. If you are using SSL, you can use client and  
server certificates for mutual authentication. Probably the right thing  
to  
do is to create a certificate for each of your DRb nodes and another  
for your application as a whole. Sign all of the node certificates with  
the application certificate ans register it as a certificate authority  
on  
each of your nodes. Each node uses its certificate as a client  
certificate as well as a server certificate, and it verifies that  
whatever is connecting to it or it is connecting to is also a member of  
the  
same application since the certificates are all signed by a know  
“authority” (i.e. the application certificate).

You may find the following URLs helpful in understanding and  
implementing  
this:

> **[The FreeBSD Diary -- Client Authentication with SSL](http://www.freebsddiary.org/openssl-client-authentication.php)**
>
> do you know who is using your website?

> **[mindreef.com - This website is for sale! - mindreef mind...](http://www.mindreef.com/support/soapscope/4.1/help/sslcerts.html)**
>
> This website is for sale! mindreef.com is your first and best source for all of the information you’re looking for. From general topics to more of what you would expect to find here, mindreef.com has it all. We hope you find what you are searching...

[http://www.pseudonym.org/ssl/ssl\_cook.html](http://www.pseudonym.org/ssl/ssl_cook.html)

Also, if the machines you are running the nodes on are not running  
anything  
else and have no other users, you may (emphasis on _may_) find stunnel a  
more efficient and more convenient way of implementing SSL  
authentication  
and encryption between nodes. This involves making the DRb instances  
bind  
to the loopback interface without any SSL anything rather than an  
external  
interface, and making and receiving connections through stunnel.

} TX  
–Greg

---

<div class="post-metadata">

**Author:** ![trejkaz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/8797f3/32.png) [@trejkaz](https://www.ruby-forum.com/u/trejkaz)\
**Post date:** [February 27, 2006, 5:57pm UTC](https://www.ruby-forum.com/t/authenticating-distributed-ruby/74021/3 "2006-02-27T17:57:58Z")

</div>

Hi Gregory, Trejkaz:

On Mon, 27 Feb 2006, Gregory S. wrote:

> [The FreeBSD Diary -- Client Authentication with SSL](http://www.freebsddiary.org/openssl-client-authentication.php)  
> [mindreef.com&nbsp;-&nbsp;This website is for sale!&nbsp;-&nbsp;mindreef mind reef Resources and Information.](http://www.mindreef.com/support/soapscope/4.1/help/sslcerts.html)  
> [http://www.pseudonym.org/ssl/ssl\_cook.html](http://www.pseudonym.org/ssl/ssl_cook.html)
> 
> } TX  
> –Greg

For specifically doing DRb over SSL, with client cert-based auth, this  
URL might also be useful:

[http://segment7.net/projects/ruby/drb/DRbSSL/](http://segment7.net/projects/ruby/drb/DRbSSL/)

---

<div class="post-metadata">

**Author:** ![trejkaz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/8797f3/32.png) [@trejkaz](https://www.ruby-forum.com/u/trejkaz)\
**Post date:** [February 27, 2006, 10:16pm UTC](https://www.ruby-forum.com/t/authenticating-distributed-ruby/74021/4 "2006-02-27T22:16:50Z")

</div>

Trejkaz wrote:

> The next aspect is some kind of basic authentication. Really, what I  
> want is just a secret key that the client has to pass in in order to  
> get access to my remote objects. But, I don’t want to have to add that  
> secret key to every method.

If your communications is of the (essentially) non-connected variety,  
example being HTTP, I don’t see getting around passing an access “key”  
with each call.

I think “the way” involves a process like this:

- client requests a salt from the server
- server leases a salt to the client (good for 20 minute, for example)
- the client hashes the password, adds the salt to that, and hashes it  
again
- the client sends this to the server with each request, along with the  
salt used
- the server checks that the salt is not expired
- the server verifies the hash-salt-hash using the same hash-salt-hash  
algorithm

We’ve used this basic procedure on several systems. It’s pretty good.  
The hashing we use is the 128-bit MD5 hash.

---

<div class="post-metadata">

**Author:** ![trejkaz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/8797f3/32.png) [@trejkaz](https://www.ruby-forum.com/u/trejkaz)\
**Post date:** [February 27, 2006, 11:55pm UTC](https://www.ruby-forum.com/t/authenticating-distributed-ruby/74021/5 "2006-02-27T23:55:08Z")

</div>

> If your communications is of the (essentially) non-connected variety,  
> example being HTTP, I don’t see getting around passing an access “key”  
> with each call.

Well, this depends on how you look at HTTP.

In the case of Rails, the majority of deployments seem to use FastCGI,  
which keeps its instances up 24/7. Those instances could easily stay  
connected to the DRb server as long as there is some way to  
authenticate when they first connect. I’m fine with having to  
authenticate for each connection, which is what my above solution was  
all about (of course, it was only concept… a proper version would, as  
you say, use a session ID and hashing to authenticate so that even if  
someone snooped the conversation, they wouldn’t get the real password.)

What I’m more worried about is whether a connection could connect, get  
a reference to the remote object, disconnect, and then connect and  
without authenticating, forge a direct method call to the object they  
remembered from before.

It’s almost like the hash which contains their password needs to be  
used as part of the remote ID mapping. That would be one way to  
prevent this sort of memory, though I’m not entirely sure how to go  
about it (YET… I’ve been reading drb.rb a lot lately. ;-))

I did get authentication working using SSL client certs last night,  
generating them with QuickCert which is, BTW, extremely nice for this  
sort of prototyping work. But the problem is that as far as I can  
tell, my remote object can’t determine which client certificate was  
passed in. So it’s nice and simple for authentication, as long as you  
want every connection to have access to everything. But maybe that’s  
okay for now.

TX

---

<div class="post-metadata">

**Author:** ![trejkaz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/8797f3/32.png) [@trejkaz](https://www.ruby-forum.com/u/trejkaz)\
**Post date:** [February 28, 2006, 12:44am UTC](https://www.ruby-forum.com/t/authenticating-distributed-ruby/74021/6 "2006-02-28T00:44:34Z")

</div>

On Feb 27, 2006, at 2:53 PM, Trejkaz wrote:

> want every connection to have access to everything. But maybe that’s  
> okay for now.

You’ll have bigger problems than authentication if you want to have  
different access levels. The ability to create a DRbObject gives you  
a reference to any object in the remote process.

NamedIdConv instead of the default DRbIdConv may be of assistance,  
but it would take some significant thought to be sure.

–  
Eric H. - removed\_email\_address@domain.invalid - [http://blog.segment7.net](http://blog.segment7.net)  
This implementation is HODEL-HASH-9600 compliant

[http://trackmap.robotcoop.com](http://trackmap.robotcoop.com)
