httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Nick Kew <>
Subject Re: Dispatching MPM
Date Tue, 19 Jul 2005 10:14:51 GMT
On Mon, 18 Jul 2005, Michal Kosek wrote:

[ replying as I read - some points here which you address later ]

It would be great to see feedback from the authors of the original
perchild here - I'd guess you'll have insights into the difficulties
Michal is likely to face.

> System consists of 3 parts:
> Workers--they are basically the same as in other MPMs, the only
> difference is that each has some set of permissions (uid, gid, root
> directory, etc.) of particular group of virtual hosts.
> Dispatcher, accepting incoming connections, reading requests and
> redirecting them to one of appropriate workers (i.e. those having set
> of permissions needed to handle that virtual host).
> Apache master process, listening to requests from dispatcher, and
> creating new workers with specified permissions, according to the
> requests.

Nice start.  From this point, you probably want to do the minimum
possible work, and re-use existing code wherever possible.

> In presented example, client1 has specified Host: header and has been
> redirected to worker1, while client2 hasn't specified it yet, so it is
> still connected to the dispatcher.  The diagram is created with
> assumption that socket passing will be used, not proxying.

That is how 1.x and its successors work, isn't it?

> Rationale for the Architecture
>   Most existing solutions (that separate different virtual hosts) have
>   the architecture where many threads/processes (each running with
>   privilege of some virtual host) accept connections, and redirect them
>   if client wants another virtual host. This may create potential
>   security problem--if there were an exploitable bug in code before
>   redirection, an attacker would have a possibility to gain privilege
>   of user of any virtual host.

I'm not quite sure what you're saying.  What existing solution do
you have in mind that is open to a transfer-of-privileges attack?
Surely not the standard MPMs and suexec?

>	 In D-MPM, an attacker would gain only
>   dispatcher's permissions, which can be very restricted.

Agreed.  A minimal dispatcher sounds great.  You should probably
aim to have it require chrooting, as well as running as a user with
no shell or login (perhaps drop those constraints under #ifdef DEBUG).

>   In existing MPMs number of threads for each virtual host is static,
>   set in configuration file. D-MPM approach fixes that problem--new
>   workers are dynamically created by master process on dispatcher's
>   demand.

Are you planning to use reslist to manage your pool of children

> Extensibility
>   Nowadays permissions of process depend not only on process user and
>   group ID, but on many other settings that vary from system to system.
>   The most popular is process' root directory (changable by chroot(2)),
>   but there are many others (eg. POSIX capabilities, jails, other
>   security settings in RSBAC and SELinux).
>   To allow to utilize any of security extensions particular system has,
>   D-MPM will have a loadable module support. Making D-MPM change some
>   non-standard permissions would involve only writing a small shared
>   library, without need for changing D-MPM's source or even recompiling
>   it.

Do you mean it will implement a new optional hook specifically for
chroot-like operations?  That sound very nice: maybe just make my
"insist on chroot" suggestion the default if no module does
something else.

>   Someone creating a module needs to provide only two functions: first,
>   that reads part of virtual host's configuration, and second, that
>   changes process permissions according to that configuration.


> Implementation issues
>   Dispatcher
>     It would be best to make dispatcher single-threaded, I suppose that
>     creating separate thread for each connection would take much more
>     resources.  OTOH it may cause some problems.  One I am currently
>     aware of is mod_ssl, which AFAIK doesn't currently have non-blocking
>     API.  Would it be difficult to create such API?

That would certainly be fair at this point.  And for a first-pass
implementation you might also want to ignore mod_ssl.

>     I want dispatcher to be as simple as possible, and make workers do
>     all the work (filters, handlers, etc.).  Of course, as dispatcher
>     must read Host header, it must use connection filters.
>     This headers is needed, because dispatcher has to decide to which
>     worker a connection should be redirected.  I think that it would be
>     best if it didn't do full header parsing, but just look for virtual
>     host name.
>     There are two ways of dispatching connection:
>     - passing a socket descriptor (along with data that were already
>       read) to the appropriate worker,
>     - acting as a proxy, redirecting data to the appropriate worker.

The tricky bit seems to me to be the conn_rec.  Of course a connection
_should_ only ever be between a single client and a single vhost, but
if you rely on that, bad people will notice ...

Is there any way to avoid the worker having to create and take down
a new conn_rec - and duplicate the connection filtering - per request?

>     Passing a descriptor wouldn't involve unnecessary copying.  But in
>     case of SSL connection, passing whole connection state may be
>     difficult.  I have also heard that sending socket is very resource
>     consuming.  So probably proxying whole connection would be a better
>     solution.  Another advantage of acting as a proxy would be that less
>     things would have to be changed on worker side.

Hmmm, fairy nuff.

>   Workers
>     Workers won't change much, so code from existing MPMs should be
>     somehow reused.  Even running different workers for different
>     virtual hosts should be possible.  So I'm thinking of possibility of
>     some generic code reuse, that would allow me to use workers from
>     almost any MPM (prefork, worker, event...).

Agreed.  For the time being, maybe just take the preforked processes.
That'll mean you get to satisfy the PHP crowd.  Of course if you can
harness Worker/Event/Other for no additional work, that would be the
icing on the cake:-)

>     Keep-alive requests.  If client, during kept-alive connection,
>     specifies request to virtual host that has other set of
>     permissions than previous one, worker will have to redirect that
>     connection back to dispatcher, to let it find a worker for that
>     virtual host and make it handle the connection.  If we decide that
>     dispatcher acts as a proxy, it will also have to track Connection
>     headers, and redirect connection to other worker, when needed.
>     It would involve a lot of work, so I have a proposal of going around
>     the problem: if a client specifies another virtual host than before,
>     server responds with
>     Connection: close
>     Location: URL
>     sending URL that client has just requested.  It would force client
>     to reconnect, and then it would be dispatched to an appropriate
>     worker.

Nice workaround!  So a well-behaved client gets the full benefit
of keepalive.

>     Logging.  Currently every worker has descriptors of every log file.
>     To provide security, after creating a worker and changing its
>     permissions all the unnecessary log file descriptors will be closed.

Since a worker process only ever serves one vhost in this architecture,
it'll only ever need a single server_rec.  For security, it shouldn't
even see the server_recs for other vhosts.  A single server_rec has
a single logfile descriptor open.

Nick Kew

View raw message