This package contains a WSGI module for proxying KDC requests over HTTP by following the MS-KKDCP protocol. It aims to be simple to deploy, with minimal configuration.
The kdcproxy module follows the standard WSGI protocol for deploying Python web applications. This makes configuration simple. Simply load up your favorite WSGI-enabled web server and point it to the module. For example, if you wish to use mod_wsgi, try something like this::
WSGIDaemonProcess kdcproxy processes=2 threads=15 maximum-requests=1000 \
display-name=%{GROUP}
WSGIImportScript /usr/lib/python3.6/site-packages/kdcproxy/__init__.py \
process-group=kdcproxy application-group=kdcproxy
WSGIScriptAlias /KdcProxy /usr/lib/python3.6/site-packages/kdcproxy/__init__.py
WSGIScriptReloading Off
<Location "/KdcProxy">
Satisfy Any
Order Deny,Allow
Allow from all
WSGIProcessGroup kdcproxy
WSGIApplicationGroup kdcproxy
</Location>
MS-KKDCP suggests /KdcProxy as end point. For more information, see the documentation of your WSGI server.
When kdcproxy receives a request, it needs to know where to proxy it to. This is the purpose of configuration: discovering where to send kerberos requests.
One important note: where the underlying configuration does not specify TCP or
UDP, both will be attempted. TCP will be attempted before UDP, hence setting
udp_preference_limit = 1 is not required for kdcproxy itself (though krb5
may still need it). This permits the use of longer timeouts and prevents
possible lockouts when the KDC packets contain OTP token codes (which should
preferably be sent to only one server).
The location of kdcproxy's main configuration file is specified by the
KDCPROXY_CONFIG environment variable. If not set, the default locations are
/usr/local/etc/kdcproxy.conf or /etc/kdcproxy.conf. This configuration
file takes precedence over all other configuration modules. This file is an
ini-style configuration with a special [global] section, wildcard realm
sections, and exact realm sections.
Exact realm sections are named after the realms that kdcproxy is expected to
receive requests for. Wildcard realm sections differ from exact realm sections
by being prefixed by a '*' character. Such sections will match with realms
having either all or their final labels in common with the section. As an
example, [*EXAMPLE.COM] will match with EXAMPLE.COM, SUB.EXAMPLE.COM,
and SUB.SUB.EXAMPLE.COM, but not MYEXAMPLE.COM.
The following parameters can be set on any of these sections, with exact realm parameters having higher precedence, followed by wildcard realm parameters, and then global parameters:
use_dns (boolean): Allows querying DNS SRV records (aka. DNS discovery) to find KDCs associated with the requested realm in case they are not explicitly set in the configuration (main one, or configuration module-provided). By default (or if explicitly enabled globally), this mechanism is activated only for realms explicitly declared in the main (an empty section named after the realm, or a matching wildcard realm section is enough) or module-provided configuration. To allow use of DNS discovery for any requested realm, see the dns_realm_discovery parameter.
silence_port_warn (boolean): When DNS SRV records are used to discover KDC
addresses, kdcproxy will write a warning in the logs in case a non-standard
port is found in the DNS response. Setting this parameter to true will
silence such warnings.
The following parameters are specific to the [global] section:
configs (string): Allows you to load other configuration modules for finding configuration in other places. The configuration modules specified in here will have priority in the order listed. For instance, if you wished to read configuration from MIT libkrb5, you would set the following:
[global]
configs = mit
dns_realm_discovery (boolean): When use_dns is not disabled globally, kdcproxy is allowed to query SRV records to find KDCs of the realms declared in its configuration only. This protects kdcproxy from attacks based on server-side request forgery (CVE-2025-59088). Allowing DNS discovery for unknown realms too is possible by also setting dns_realm_discovery to true, yet heavily discouraged:
[global]
dns_realm_discovery = true
Exact realm sections have 2 specific parameters: kerberos and kpasswd. These specify the locations of the remote servers for Kerberos ticket requests, and kpasswd requests, respectively. For example:
[EXAMPLE.COM]
kerberos = kerberos+tcp://kdc.example.com:88
kpasswd = kpasswd+tcp://kpasswd.example.com:464
The realm configuration parameters may list multiple servers separated by a space. The order the realms are specified in will be respected by kdcproxy when forwarding requests. The port number is optional. Possible schemes are:
- kerberos://
- kerberos+tcp://
- kerberos+udp://
- kpasswd://
- kpasswd+tcp://
- kpasswd+udp://
If you load the mit config module in the main configuration file, kdcproxy will also read the config using libkrb5 (usually /etc/krb5.conf). If this module is used, kdcproxy will respect the realm configuration from the [realms] section.
For more information, see the documentation for MIT's krb5.conf.
kdcproxy reads its configurtion files when package is imported and a global WSGI application object is instantiated. For now kdcproxy does neither monitor its configuration files for changes nor supports runtime updates. You have to restart the WSGI process to make modification available. With Apache HTTP and mod_wsgi, a reload of the server also restarts all WSGI daemons.
HTTPS proxy support is available since Kerberos 5 release 1.13. Some
vendors have backported the feature to older versions of krb5, too. In order
to use a HTTPS proxy, simply point the kdc and kpasswd options to the proxy URL like
explained in HTTPS proxy configuration guide. Your /etc/krb5.conf may
look like this::
[libdefaults]
default_realm = EXAMPLE.COM
[realms]
EXAMPLE.COM = {
http_anchors = FILE:/etc/krb5/cacert.pem
kdc = https://kerberos.example.com/KdcProxy
kpasswd_server = https://kerberos.example.com/KdcProxy
}
To debug the feature, set the environment variable KRB5_TRACE to
/dev/stdout. When the feature is correctly configured, you should see
two POST requests in the access log of the WSGI server and a line containing
Sending HTTPS request in the debug output of kinit::
$ env KRB5_TRACE=/dev/stdout kinit user
[1037] 1431509096.26305: Getting initial credentials for [email protected]
[1037] 1431509096.26669: Sending request (169 bytes) to EXAMPLE.COM
[1037] 1431509096.26939: Resolving hostname kerberos.example.com
[1037] 1431509096.34377: TLS certificate name matched "kerberos.example.com"
[1037] 1431509096.38791: Sending HTTPS request to https 128.66.0.1:443
[1037] 1431509096.46387: Received answer (344 bytes) from https 128.66.0.1:443
[1037] 1431509096.46411: Terminating TCP connection to https 128.66.0.1:443
...
If kinit still connects to port 88/TCP or port 88/UDP, then System Security
Services Daemon's Kerberos locator plugin might override the settings in
/etc/krb5.conf. With the environment variable SSSD_KRB5_LOCATOR_DEBUG=1,
kinit and sssd_krb5_locator_plugin print out additional debug information. To
disable the KDC locator feature, edit /etc/sssd/sssd.conf and set
krb5_use_kdcinfo to False:
[domain/example.com]
krb5_use_kdcinfo = False
Don't forget to restart SSSD!