Releases: graygnuorg/pound
Version 4.16
A bug fixing release. Noteworthy changes:
-
Fix backend probing when compiled without support for dynamic backends.
-
Reject requests with oversized chunk bodies.
-
Handle errors that occur during evaluation of conditionals.
Version 4.15
Noteworthy changes in this release
-
New configuration statement:
IgnoreSRVWeight
Instructs pound to ignore weight value of an
SRV
record when generating new backend from it. Priority of the generated backend will be copied from its matrix backend. -
New configuration statement:
OverrideTTL
When used with dynamic backends, instructs pound to use its argument rather than the
TTL
value returned inDNS
response, to calculate the expiration time of the new backend. -
Load balancing code revisited
Removed arbitrary limit on backend priority value. The allowed range is now 1..65535.
Remove priority mapping forSRV
-generated backends.SRV
weights are assigned to backend priorities verbatim. -
Fix access to freed memory in session handling code.
- Improve testsuite
- Check for missing
perl
modules and skip tests if needed. - DNS-based tests are disabled by default, due to their experimental nature. Use
--enable-dns-tests
to enable them. - The
poundharness.pl
script runs a self-test when invoked with the--fakedns
option, to avoid spurious test failures.
Version 4.14
Dynamic backends
Dynamic backends are created and updated on the fly based on the information from DNS. To declare backend as dynamic, use a symbolic host name in its Address
statement and add the Resolve
statement with one of the following values:
-
first
Resolve the symbolic host name and use first IP from the DNS response as the address of the created dynamic backend. Thus, at most one dynamic backend will be created. -
all
Resolve the symbolic host name and create one backend for each address from the DNS response. This enables load balancing between created backends. Each backend will be assigned the same priority. -
srv
Obtain SRV records for the host name and use them to generate regular backends. Each record produces new dynamic backend ofResolve all
type, which creates regular backends as described above. The weight field of the SRV record is mapped to the priority field of each generated backend. The SRV priority field determines the balancing group (see below) where the backend will be hosted.
By default, both IPv4 and IPv6 addresses are looked for. You can select the specific address family using the Family
statement. Its allowed values are:
any
Use all address families available. This is the default.inet
Use only IPv4 addresses.inet6
Use only IPv6 addresses.
For example:
Backend
Address "be0.example.net"
Port 8080
Resolve first
Family inet
End
Dynamic backends will be updated periodically, when the TTL of the corresponding DNS records expires. If the hostname cannot be resolved or a DNS failure occurs, next update will be scheduled in 600 seconds after the failure. This interval can be configured using the RetryInterval
statement in the Backend
section, or globally, in the Resolver
section.
The Resolver
section allows you to control how DNS lookups are performed. It can contain the following directives:
-
CNAMEChain
integer
Maximum allowed length of a CNAME chain. CNAME chains are formed by DNS CNAME records pointing to another CNAME. Although prohibited by the RFC, such usage occurs sometimes in the wild. By default, pound does not accept CNAME chains. If you work with a nameserver that uses them, set this statement to a small integer value, defining maximum number of CNAMEs in the chain that pound will accept. The value of 2 or 3 should suffice in most cases. -
ConfigFile
string
Name of the resolver configuration file. Defaults to/etc/resolv.conf
. -
ConfigText
This is a compound statement:ConfigText ... End
The material between
ConfigText
andEnd
is read verbatim and used as the content of the resolver configuration file.If both
ConfigFile
andConfigText
are used, the last statement used wins. -
Debug
boolean
Whether to enable DNS debugging info. -
RetryInterval
integer
Interval in seconds, after which to retry failed DNS queries or queries that returned no RRs. This value is used unless the backend defines its own retry interval value.
Dynamic backends can be controlled using poundctl
. For example, consider the following output from poundctl list
:
1. Listener http://192.0.2.1:80 enabled
0. Service active (5)
0. matrix "be0.example.com" 2 0 active
1. backend http 198.51.100.15:8081 5 alive active
2. backend http 203.0.113.121:8081 5 alive active
3. backend http 192.0.2.203:8081 5 alive active
The backend 0 ("matrix") refers to the Backend
statement in the configuration file that produced the other three dynamic backends. Disabling it (poundctl disable /1/0/0
) causes the dynamic ones to be removed. Enabling it will create them again. In a pinch, this can be used to force backend re-creation prior to TTL expiration.
Compiling
To enable dynamic backend support, you will need the adns library. On debian-based systems, it is installed by the following command
apt-get install libadns1-dev
If all preconditions necessary for enabling dynamic backends are met, the output from configure will end with the following status line:
Dynamic backends .............................. yes
*******************************************************************
When compiled with the dynamic backend support, the output of pound -V
will contain the following line in the Built-in defaults
section:
Dynamic backends: enabled
Backend groups
Backend groups are a new pound feature, that extends the idea of regular and emergency backends used in previous versions. Any number of backend groups can be associated with a service. Each group is assigned an integer number (weight). The groups are ordered by weight (in ascending order) and are tried in that order when looking for a backend to serve the request. The look up starts with the first group. The balancing algorithm configured for the service is applied. If no backend can be selected, next group will be tried, and so on.
In the static configuration, regular backends are hosted in backend group of weight 0 and emergency (high availability) backends are stored in group of weight 65535. One consequence of this is that any number of Emergency
backend declarations are now allowed in a service. More backend groups can be allocated when using dynamic backends of srv
resolve type (see above).
Emergency backends
Any number of emergency backends can be defined. Usual request balancing algorithm applies when selecting an emergency backend.
All statements valid within a Backend
section are also valid within an emergency backend declaration.
Listener address configuration
Both Address
and Port
statements are now optional. If Address
is omitted, pound will listen on all available interfaces. If Port
is omitted (and not listening on a UNIX socket), default port number for this kind of listener will be used: 80, for ListenHTTP
, and 443, for ListenHTTPS
.
New request matching conditional: ClientCert
The syntax is:
ClientCert "FILENAME"
The conditional evaluates to true if the client presented the certificate matching that from the given file (PEM format).
It cannot be used in standalone services (i.e. services that are defined in global scope). It also cannot be used if the ListenHTTPS
section that hosts the service has the ClientCert
statement of its own.
Remote access to the management interface
A new backend type Control
is introduced to make it possible to access the management interface remotely. The example below shows how to configure pound to expose the management interface on http://192.0.2.1:3434
:
ListenHTTP
Address 192.0.2.1
Port 3434
Service
ACL "secure"
Control
End
End
poundctl
Changes in poundctl functionality reflect those in the management interface. First of all, the -s
option accepts URL as its argument:
poundctl -s https://user:password@hostname:8080/path
Additionally, the following new options are implemented:
-
-C
FILE
Load CA certificates from FILE. If FILE is a directory, all PEM files will be loaded from it. -
-K
FILE
Load client certificate and key fromFILE
. During TLS handshake, send them to the peer for authentication. -
-k
Insecure mode: disable peer verification. -
-S
NAME
Take settings for server NAME from the poundctl configuration file (see below).
.poundctl
The file .poundctl
in user home directory provides configuration settings for the poundctl
command. Syntactically, it is similar to pound.cfg
. Upon startup, poundctl
first checks if ~/.poundctl
exists and reads it if so. If the program cannot determine the URL of the control socket from it (possibly using the argument to the -S
option, if given), it scans the pound configuration file (if it exists), looking for Control
statement. Finally, if neither method determines the URL, poundctl requires the user to supply the -s
option.
The default name and location of the poundctl configuration file can be changed using the environment variable POUNDCTL_CONF
. Setting it to empty string disables the configuration mechanism altogether.
configure
Removed historic --with-owner
and --with-group
options.
Version 4.13
Support for pcre and pcre2 rewritten
The pcre2posix
(or pcreposix) layer is no longer used. Instead, pound uses the native API of the corresponding library. This provides for the additional speed-up and (in case of pcre2) avoids coredumps under high load.
Use of POSIX and Perl-compatible regular expressions
In contrast to previous versions, both types of regular expressions can be used simultaneously in the configuration file. The flavour of the regex to use can be specified either individually with each request matching statement (such as URL
, Header
, etc.), or globally.
To set it globally, use the RegexType
statement. The type of regular expression set by it will be used in all matching statements that appear below that statement, unless they declare regex type explicitly. It remains in effect until next RegexType
statement or end of file is encountered, whichever occurs first. For example, to use PCRE by default, add the following statement somewhere near the beginning of your pound.cfg
file:
RegexType pcre
To change the default back to POSIX regexps, do
RegexType posix
Regular expression type can also be specified with each matching statement individually. For example, the -pcre
option indicates that Perl-compatible regular expression is given as argument, e.g.:
Host -pcre -icase "(?<!www\\.)example.org"
Similarly, the -posix
option indicates that POSIX extended regular expression is used. Use these options to override the default for a single statement.
New matching option: -contain
The -contain
option enables substring match. E.g. the following will match if URL contains the word "user" (case-insensitive):
URL -contain -icase "user"
New configuration statement: LogTag
Sets a string to tag syslog messages with. By default, the name used to start the program is assumed.
Bugfixes
- Fix infinite recursion on reporting an out of memory condition.
- Fix deadlock in session expiration handling.
- Fix RewriteLocation functionality.
v4.12
Manual in texinfo format included
Change in the order of applying rewrites to responses
When rewriting a response, rules defined in the service section are applied first, followed by the ones defined in the listener.
When rewriting incoming requests, the order is opposite: first the rules in the listener, then the ones in the service.
Fixes in handling of Transfer-Encoding
- Requests with unrecognized
Transfer-Encoding
are rejected - Requests containing both
Transfer-Encoding
andContent-Length
are rejected
Deprecated configuration statements
Pound issues a warning for each deprecated statement used in the configuration file. The warning message contains a suggestion on what to use instead of the offending statement. You are advised to replace each occurrence of deprecated statements in accordance with these suggestions, since such statements will be removed in future releases.
If it is not feasible to do so for a while, you can suppress these messages by using the -W no-warn-deprecated
command line option.
ServerName
directive is allowed in the Emergency
section
New configuration statement: ErrorFile
ErrorFile NNN "FILENAME"
This statement defines content of the response page returned with the HTTP status NNN from the file FILENAME. It obsoletes the Err400
- Err503
statements used in previous versions. These statements are still supported for backward compatibility, although their use is discouraged.
New configuration statement: MaxURI
This statement sets the maximum allowed length of the request URI. It can be used in ListenHTTP
and ListenHTTPS
sections.
Bugfixes
- Don't try to access the include directory, unless needed by configuration.
- Fix handling of session deletion/addition on request from
poundctl
.
Version 4.11
Combining multi-value headers
HTTP protocol allows for certain headers to appear in the message multiple times. Namely, multiple headers with the same header name are permitted if that header field is defined as a comma-separated list. The standard specifies that such fields can be combined in a single header: value
pair, by appending each subsequent field value to the previous one, each separated by a comma.
Pound is able to perform such combining on incoming requests as well as on responses. To enable this feature, declare names of headers that can be combined using the CombineHeader
statement, e.g.:
CombineHeaders
"Accept"
"Allow"
"Forwarded"
End
Pound distribution includes file mvh.inc
which declares all multiple-value headers in a form suitable for inclusion to the main
pound configuration file. This file is installed in the package data directory, which is normally /usr/local/share/pound
or
/usr/share/pound
, depending on the installation prefix used.
SNI in HTTPS backends
New directive ServerName
is provided for use in Backend
section after the HTTPS
statement. This directive sets the host name to be used in server name identification (SNI). Its argument is a quoted string specifying the host name. This directive also rewrites the Host:
header accordingly. Example usage:
Backend
HTTPS
Address 192.0.2.1
Port 443
ServerName "www.example.org"
End
Cert
statement in ListenHTTPS
section
Argument to the Cert
statement in ListenHTTPS
section can be the name of a directory containing certificate files. All files from that directory will be loaded.
Version 4.10
Global Backend
definitions
A Backend
statement is allowed to appear in global scope. In this case it must be followed by a symbolic name, as in:
Backend "name"
...
End
The "name" must uniquely identify this backend among other backends defined in global scope.
Global backend definitions can be used in services using the UseBackend
statement:
UseBackend "name"
A single globally defined backend can be used in multiple services. Its actual global definition may appear before as well as after the service or services it is used in.
The named form of Backend
statement is also allowed for use in Service
sections. In this case it acts as UseBackend
statement, except that statements between Backend
and End
modify parameters of the backend for use in this particular service. Only two statements are allowed in such named form: Priority
and Disabled
. The following example attaches the globally defined backend "assets" to the service and modifies its priority:
Backend "assets"
Priority 8
End
Response header modification
The Rewrite
statement accepts optional argument specifying whether it applies to the incoming request, or to the response. The following statement applies to requests and is exactly equivalent to Rewrite
without argument:
Rewrite request
...
End
In contrast, the following statement:
Rewrite response
...
End
applies to responses (as received from regular backends or generated by error backends). In this form, the set of statements that can appear inside the section (denoted by ellipsis above) is limited to the following: Not
, Match
, Header
, StringMatch
, SetHeader
, and DeleteHeader
. For example:
Rewrite response
Match
Header "Content-Type: text/(.*)"
End
SetHeader "X-Text-Type: $1"
End
The same applies to Else
branches.
Basic authentication
New request matching statement BasicAuth
is implemented. Its syntax is:
BasicAuth "FILE"
It evaluates to true, if the incoming request contains Authorization:
header with scheme Basic
, such that the user name and password obtained from it match a line in the given disk file. FILE must be a plain-text file created with htpasswd or similar utility, i.e. each non-empty line of it must contain username and password hash separated by a colon. Password hash can be one of:
- Password in plain text.
- Hash created by the system crypt(3) function.
- Password hashed using SHA1 algorithm and encoded in base64. This hash must be prefixed by
{SHA}
- Apache-style "APR1" hash.
Combined with the response rewriting technique described above, this can be used to implement basic HTTP authentication in pound as shown in the example below:
Service "auth"
Not BasicAuth "/etc/pound/htpass"
Rewrite response
SetHeader "WWW-Authenticate: Basic realm=\"Restricted access\""
End
Error 401
End
Unless file name starts with a slash, it is taken relative to the IncludeDir
directory. The file is cached in memory on the first authorization attempt, so that further authorizations do not result in disk i/o operations. It will be rescanned if pound notices that the file's modification time has changed.
Bugfixes
- The Host statement assumes exact match by default.
- Fix detection of duplicate Transfer-Encoding headers.
Version 4.9
HTTP request logging
In addition to six built-in log formats, you can define your own named formats and use them in LogLevel
directive. Log formats are defined using the following statement:
LogFormat "name" "FormatString"
The "name" argument specifies a string uniquely identifying this format. "FormatString" is the format specification. It is
modelled after Apache's LogFormat
string. For example, the built-in format 3 is defined as:
"%a - %u %t \"%r\" %s %b \"%{Referer}i\" \"%{User-Agent}i\""
The LogLevel
directive has been extended to take symbolic format name as argument. For example:
LogLevel "my_format"
The traditional built-in formats are assigned the following symbolic names:
0
- "null"1
- "regular"2
- "extended"3
- "vhost_combined"4
- "combined"5
- "detailed"
So, instead of
LogLevel 3
one may write
LogLevel "vhost_combined"
New statements: ForwardedHeader
and TrustedIP
These statements control how the %a
log format conversion specifier determines the originator IP address:
-
ForwardedHeader
"name"Defines the name of HTTP header that carries the list of proxies the request has passed through. It is used to report the originator IP address when logging.
The default value is "X-Forwarded-For". This statement can be used in global, listener, and service scope.
-
TrustedIP
Defines a list of trusted proxy IP addresses, which is used to determine the originator IP. This is a special form of the
ACL
statement and, as the latter, it can appear in two forms: directive and section.In directive form, it takes a single argument referring to a named access control list, which must have been defined previously using the
ACL
statement.In section form, it is followed by a list of one or more CIDRs each appearing on a separate line. The
End
directive on a separate line terminates the statement.This statement can be used in global, listener, and service scope.
New service statement: LogSuppress
Suppresses HTTP logs for requests that resulted in response status codes from a particular group or groups. The statement takes one or more arguments specifying status code groups to suppress log messages for:
-
info
or1
1xx status codes
-
success
or2
2xx status codes
-
redirect
or3
3xx status codes
-
clterr
or4
4xx status codes
-
srverr
or5
5xx status codes
-
all
all status codes
Suggested usage is for special services that are likely to process large numbers of similar requests, such as Openmetrics services. For example:
Service "metrics"
URL "/metrics"
Metrics
LogSuppress success
End
New request matching directive: StringMatch
The syntax is:
StringMatch "SUBJECT" [OPTIONS] "PATTERN"
OPTIONS are usual matcher options. The directive matches if SUBJECT, after backreference expansion and accessor interpretation, matches PATTERN.
This directive allows you to build complex service selection criteria. For example:
Service
Host "^foobar\.(.+)$"
StringMatch "$1" -file "domain.list"
...
End
The service above will be used for requests whose Host
header value is "foobar." followed by a domain name from the file "domain.list".
New request accessors: host
and port
The %[host]
accessor returns the hostname part of the Host
header value. The %[port]
accessor returns port number with leading column character. If no explicit port number is given in the Host
value, %[port]
returns empty string.
Bugfixes
- Fix the
QueryParam
statement. - Improve testsuite and documentation.
Version 4.8
Support for libpcre2-posix
The configure
script checks for both libpcreposix2
and legacy libpcreposix
. Version 2 is preferred, if available. To force compiling with the older libpcreposix
, use --enable-pcreposix=pcre1
.
Bugfixes
- Fix coredump on
-c -v
poundctl
: ignore empty lines inpound.cfg
v4.7
Default include directory
Configuration directives that take filenames as their argument search for files in the include directory (unless the filename is absolute). Initial value of the include directory is set to the system configuration directory, as configured at compile time. It can be changed:
- From the command line, using the
-Winclude-dir=DIR
or-Wno-include-dir
options.
The latter form resets it to the current working directory. - From the configuration file, using the
IncludeDir
configuration statement.
The Include
directive
The Include
directive can appear not only at the topmost level, but also in any sections (ListenHTTP
, Service
, ACL
, etc.). In short - anyplace where a statement is allowed.
Reading patterns from file
All request matching directives (Header
, Host
, URL
, etc.) take an additional option -file
. When this option is specified, the argument to the directive is treated as the name of a file to read patterns from. If the filename is relative, it is looked up in the include directory (see above). For example:
Service
Host -file "pound/webhosts"
...
End
Patterns are read from the file line by line, empty lines and comments are ignored.
Early pthread_cancel
probe
Pound calls pthread_cancel
(3p) during its shutdown sequence. In GNU libc, a call to this function involves loading the libgcc_s.so.1
shared library. In previous versions of pound, this would fail if pound
was running in chrooted environment (RootJail
), unless that library had previously been copied to the chroot directory. The following diagnostics would be printed
libgcc_s.so.1 must be installed for pthread_cancel to work
and the program would abort. That means that normal pound shutdown sequence would not be performed properly. Starting with this version, pound will create and cancel a dummy thread right before doing chroot. This ensures that libgcc_s.so.1
is loaded early, so that pthread_cancel
will run successfully even when chrooted later.
This early probe is enabled if pound is linked with GNU libc. The --enable-pthread-cancel-probe
configure option is available to forcefully enable or disable it, if the need be.
PID file and control socket are properly removed when in RootJail mode.
This doesn't cover the case where the privileges of the user the program runs at (as set by the User
and Group
configuration statements) forbid to remove the file.
Control socket ownership and mode
The Control
configuration directive has two forms: inline and section. The inline form is the same as in previous versions. The Control
section allows you to manage file mode and ownership of the socket file. Its syntax is:
Control
Socket "FILE"
Mode OCTAL
ChangeOwner BOOL
End
The Socket
statement sets the name of the UNIX socket file. This is the only mandatory statement in the Control
section. The Mode
statement sets the mode of the socket file (default is 600). Finally, if ChangeOwner
is true
, the ownership of the socket file will be changed to the user defined by the User
and/or Group
statements in global scope.