I don't quite understand the statement that mod_auth_external doesn't
work for digest authentication, only basic authentication. I must not
understand something. I need to set up the more secure digest auth
(not using SSL, so basic auth is a basic no-no). My password DB
contains Digest encrypted passwords, why would I take the encrypted
USRNAME:REALM send by the browser and be able to authenticate the
user? I'm sure I just don't understand something simple. I was able to
do exactly this using squid proxy without any problem.
I'm concerned about performance of authentication on a loaded proxy
server. I've inferred from a few sources that each request calls
authentication, and it also sounds like (from the docs here) that each
authentication lauches a new authentication process. I just want to
verify that, if there are 100 concurrent requests/sec this could be
bad (1000 would be terrible).
It seems like it would be easy enough to cache authentications or keep
open a connection to a single external auth application using the
internal function call available. I just want to be sure that I should
be following this path in this case (or can someone let me know what I
don't know yet).
Thanks!
David
On Fri, 2010-03-26 at 07:12 -0700, David Parks wrote:
> Hi, can I ask a few questions before jumping head first into using
> mod_auth_external?
>
> I don't quite understand the statement that mod_auth_external doesn't
> work for digest authentication, only basic authentication. I must not
> understand something. I need to set up the more secure digest auth
> (not using SSL, so basic auth is a basic no-no). My password DB
> contains Digest encrypted passwords, why would I take the encrypted
> USRNAME:REALM send by the browser and be able to authenticate the
> user? I'm sure I just don't understand something simple. I was able to
> do exactly this using squid proxy without any problem.
It would certainly be possible to make mod_authnz_external work with
Digest authentication. It add a fair amount of code to the size of the
module, and I don't think it would be used by a lot of people. In most
cases if someone is setting up a password DB using digest encrypted
passwords, then they are clearly designing the database to use with
Apache. If they are sensible then they will put it in a flat file
formatted to work with mod_authn_file, or a has file formatted to work
with mod_authn_dbm or a SQL table so they can use mod_authn_dbd. Any of
these would be much faster and much easier to set up than
mod_authnz_external.
Mod_authnz_external is generally most useful when you are authenticating
out of a database that is not designed for web authentication. Either
they are oddly formatted so that a normal apache module can't access
them, or they are not readable to Apache, so you need an external suid
authenticator to read them. But databases not designed for web
authentication are hardly ever going to have passwords encrypted the
right way to work with digest authentication.
The only case I can think of where it might actually make sense to use
mod_authnz_external with digest authentication is if you want your
digest password database to be unreadable to Apache for security
reasons. Then an external authenticator that runs suid to another user
that can read the password database would be a good solution. Doing it
that way is pretty paranoid, but paranoia is not a bad attribute when
designing security.
I'm not much inclined to implement digest authentication within
mod_authnz_external, but if someone else implemented the patches I'd
incorporate them in the release, in part because if they are willing to
go to that trouble then presumably they actually have a use for it, and
if they do then I probably wrong about it being mostly useless.
> I'm concerned about performance of authentication on a loaded proxy
> server. I've inferred from a few sources that each request calls
> authentication, and it also sounds like (from the docs here) that each
> authentication lauches a new authentication process. I just want to
> verify that, if there are 100 concurrent requests/sec this could be
> bad (1000 would be terrible).
Yup. That is a definite problem. If I was building a really high
traffic site, I would certainly avoid mod_authnz_external.
> It seems like it would be easy enough to cache authentications or keep
> open a connection to a single external auth application using the
> internal function call available. I just want to be sure that I should
> be following this path in this case (or can someone let me know what I
> don't know yet).
Caching authentications is a good idea, and I've thought some about it.
But I really think there ought to be a separate module that caches
authentications. It would be set up as the first authenticator, so on
each authentication mod_auth_cache would be the first called. It would
check it's cache and validate the request if it found a match.
Otherwise it would pass on it and let the other authentication modules
check it. If another module accepts it, it should have a hook into
apache so that it notices this fact and adds the authentication to its
cache. None of that is hard to do. But then there are trickier things.
Since there are usual multiple apache processes running on a server,
you'd probably do best if the cache were in shared memory so all shared
a cache. Then you need to figure out your cache expiration policies.
You'll probably want to make that configurable. It's going to end up
being a sophisticated module that takes a lot of debugging and fine
tuning to work right, and I'm not actually using basic authentication
(or mod_authnz_external) on any site I manage these days, so I'm really
not the person to build this. Building it into mod_authnz_external
would be no easier than making a separate module. It's easy to do
badly, hard to do well.
The same applies to keeping open a connection to the authenticator. If
a lot of requests come in fast, then you have to feed them one at a time
through one (or more?) authenticators, instead of running them in
parallel. If done wrong, this could become a bottleneck. What if the
external authenticator unexpectedly dies? Do we need logic to restart
it? This could certainly be done, and I've got ideas on how to do it,
but to really make it work well is going to take a lot of very careful
design. I think I actually put hooks in the current mod_authnz_external
that enable it to start an external process as a detached daemon, but I
never went very far with that project because doing it well would be
pretty hard, and I'd really want to test it out on a busy production
system, which I haven't actually got right now.
So I'm mostly in a maintenance mode with mod_authnz_external at this
point. I'll fix any bugs reported, update it as Apache's API evolves,
and incorporate sensible patches that people submit, but I'm not going
to go out and do ambitious development on it unless I get a client who
really needs that.
I'm happy to encourage people wanting to do more ambitious development,
but actually I think both caching and daemon authentication would
probably make more sense a separate modules rather than elaborations of
mod_authnz_external.
- Jan
> Thanks!
> David
>
Just to give you the background I'm coming from - I tried to configure
squid proxy, but found that I could not disable a previously
authenticated user on demand (at least not efficiently). Their
external authentication approach is actually very similar to
mod_auth_external, and supports digest authentication. They do 1 of 2
things to speed access to the external auth app, either: 1) launch X
processes and round robin between them, or 2) pass multiple requests
to one or more external apps with an ID # to identify the responses
(for example, with pipes it would send "52:user:encrypted_pass" and
the app needs to respond to STDOUT with "52:OK" or "52:ERR", where 52
is the ID of the request - I simplify the process a tiny bit for
conversation). It's just a thought for you.
My purpose in contemplating an external auth app is so that I can
properly control when a user should no longer have authenticated
access (in my case I will monitor log files externally and cancel a
users access when they exceed a usage quota, I then need to block
access after the user has authenticated).
I also don't know how efficient a DB is with many authentications. If
I wrote my own app I would simply store successful authenticated user
names in an in-memory table, and provide a way to clear users that
should be blocked. My thought was that I could provide both speed
(with my own simple in-memory cache), and the required functionality
(blocking previously authenticated users).
I will look into the other authentication schemes and see if I can get
one to perform in the way I need (I can indeed control the DB design),
and hopefully find one with the efficiency required by a proxy server
where connections are numerous but actual workload is minimal.
Thanks again for your help!!
Thank you for the incredibly detailed response, it's immensely
helpful.
Just to give you the background I'm coming from - I tried to configure
squid proxy, but found that I could not disable a previously
authenticated user on demand (at least not efficiently). Their
external authentication approach is actually very similar to
mod_auth_external, and supports digest authentication. They do 1 of 2
things to speed access to the external auth app, either: 1) launch X
processes and round robin between them, or 2) pass multiple requests
to one or more external apps with an ID # to identify the responses
(for example, with pipes it would send "52:user:encrypted_pass" and
the app needs to respond to STDOUT with "52:OK" or "52:ERR", where 52
is the ID of the request - I simplify the process a tiny bit for
conversation). It's just a thought for you.
My purpose in contemplating an external auth app is so that I can
properly control when a user should no longer have authenticated
access (in my case I will monitor log files externally and cancel a
users access when they exceed a usage quota, I then need to block
access after the user has authenticated).
I also don't know how efficient a DB is with many authentications. If
I wrote my own app I would simply store successful authenticated user
names in an in-memory table, and provide a way to clear users that
should be blocked. My thought was that I could provide both speed
(with my own simple in-memory cache), and the required functionality
(blocking previously authenticated users).
I will look into the other authentication schemes and see if I can get
one to perform in the way I need (I can indeed control the DB design),
and hopefully find one with the efficiency required by a proxy server
where connections are numerous but actual workload is minimal.
Thanks again for your help!!
David