You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Rici Lake <ri...@ricilake.net> on 2004/12/13 22:04:07 UTC

Proposal: mod_acceptfilter

With reference to [Re: svn commit: r111596]

The following proposal attempts to provide a simple way of configuring
a server which supports multiple protocols (http, ftp, nntp) while
allowing the administrator and/or packager to configure OS kernel-
implemented accept filters, as provided by FreeBSD and to a lesser
extent by Linux. (And probably other OS's.)

On 13-Dec-04, at 11:00 AM, Paul Querna wrote:
>
> I just tested it here, and it Fails on FreeBSD if accf_http is loaded 
> in the kernel.
>
> Perhaps both the accept filter and defer accept code belongs somewhere 
> in modules/http/* ?

It seems to me that accept filters need to be configured for specific
protocols and in a way consistent with the specific operating system.

After an interesting discussion on IRC, I volunteered to write up the
following proposal (which I take full responsibility for; I don't
claim that it represents any consensus).

The essential point here is that accept filters need to be established
before the call to accept(). Consequently, the setting will be specific
to the listener. In the current architecture, the protocol module is not
invoked until too late to make this determination. It therefore seems
reasonable to provide a separate module, mod_acceptfilter, which handles
the configuration of accept filters.

However, protocol modules will need to indicate which protocol they
handle. This could be done by a callback which registers the protocol[s]
which they handle, or it could be done by using the name of the protocol
module directly as a key. I personally prefer the former solution, but
the second one might be possible for legacy-compatibility.

The proposal is then:

1. Core directives

1.a: The Listen directive is extended to allow the optional 
specification
      of a protocol:

   Listen [transport/][ip:]port [protocol]

where
   transport is either a domain specification from protocols(5),
     like "tcp" or "udp", or it might even (in some future time)
     be a specification like "namedpipe" (although the use of
     transports which do not identify themselves with ip numbers
     implies significant changes). (This is not core to the proposal.)

   port is either a number or a service from services(5)

   protocol is either the name of a protocol registered by a protocol
     module or the name of the protocol module itself.

   If protocol is omitted, then if a service name is provided and a
   protocol module has registered that name, then that name is used
   to bind the protocol module to the listener. Otherwise, "http" is
   assumed.

1,b: The assignment of protocols to listeners can be overridden in a
   <VirtualHost> section by means of the new "Protocol" directive:

   Protocol <registered-protocol or module-name>

   The argument is interpreted as above.

1.c: protocol modules register themselves as providing a protocol
   by providing a hook to ap_register_protocol; this is called with
   the name of a protocol, and the module either returns OK or DECLINED.

2. mod_acceptfilter

This new module would implement two directives;

   DefaultAcceptFilter (<protocol> | "*") (<os-dependent identifier>+ | 
"none")

   AcceptFilter (<os-dependent identifier>+ | "none")

The first of these is only available in the main configuration section; 
the
second only in <VirtualHost> sections. Although this specification 
makes it
possible to use the same directive name for both options, I personally 
believe
that that particular form of parsimony is confusing for people writing
configuration files.

If there is an AcceptFilter directive within the <VirtualHost> section
applicable to a particular ip:port, that directive will apply. 
Otherwise,
if there is a DefaultAcceptFilter for the protocol bound to the 
<VirtualHost>
section, that directive will apply. Otherwise, "none" is assumed.

mod_acceptfilter will then use the first AcceptFilter in the list which 
is
available, using an interface provided by APR. If no accept filter is
available, "none" will be used (that is, no accept filter will be placed
on the connection.) This is not to be considered an error.

The intent is to allow Apache packagers for specific OS distributions to
create reasonable default accept filter configurations for the 
particular of
the particular OS. The FreeBSD mechanism, for example, is extensible 
through
kernel modules. So, a FreeBSD packager who had also implemented
an accf_ldap filter could provide the directive:

   DefaultAcceptFilter ldap accf_ldap accf_data

If some protocol module had registered as providing the ldap protocol,
mod_acceptfilter would attempt to enable accf_ldap on listeners assigned
to the ldap protocol; failing that, it would attempt to enable 
accf_data.
In the event that the config file was being used on, for example, Linux,
APR might be able to substitute the Linux equivalent of accf_data.

Regardless of the DefaultAcceptFilter specifications, an Apache
administrator with specific needs could simply place an AcceptFilter
directive in a particular virtual host.

---------------------

Config file example:

# This is trying to illustrate a complex configuration
# in the hopes that it illustrates that the proposal
# is understandable in complex configurations

# These directives are probably in some .conf file
# from the packager

DefaultAcceptFilter http accf_http accf_data
DefaultAcceptFilter nntp none
DefaultAcceptFilter smtp none
DefaultAcceptFilter ldap accf_ldap accf_http


# Ports we're listening to:

Listen http
Listen https
Listen 8080 http
# http is the default, so the above was for documentation.
Listen 8443
Listen 192.168.1.1:9091 ldap
Listen *:ldap

# The usual http configurations
NameVirtualHost *:http
NameVirtualHost *:8080
<VirtualHost *:http *:8080>
#...
</VirtualHost>

<VirtualHost *:https>
   # No SSLEngine On directive is necessary, since the protocol
   # is already bound to the port
   DocumentRoot /var/www/secure
   SSLCertificate ...
   #...
</VirtualHost>

# For some reason we want to only use https on port 8443 on
# our external interface

<VirtualHost 1.2.3.4:8443>
   # Note: The following replaces "SSLEngine On"
   Protocol https
   # SSL/vhost configuration goes here
</VirtualHost>

# Other ips on port 8443
<VirtualHost _default_:8443>
   DocumentRoot /var/www/local8443
   #...
</VirtualHost

# Disable the accept filter on local connections.
<VirtualHost 192.168.1.1:9091>
   AcceptFilter none
   # No protocol enable is required because this port is bound
   # to the ldap protocol provider.
   # ...
</VirtualHost>