Once in a while people come and ask for FreeIPA servers to work in multi-homed environments. A multi-homed environment in this context is a deployment where the same server is accessible through multiple network interfaces which connect together networks which are not routable to each other. This is typical for administrative and operational networks but there are other types of environments which employ disconnected networks for their operations. FreeIPA server right now has a single host name that resolves to the same IP address in all networks and if one cannot reach the server through that IP address, access to IPA server would not be possible. This typically assumes use of unicast networking as well.

A solution many people look for is to be able to access IPA servers by their interface-specific addresses. Since all secure communication over HTTPS and other protocols (LDAP, Kerberos, etc.) uses name-based resolution in the first place, use of different host names is implied. For example, if FreeIPA is deployed at DNS domain example.test, it would be using Kerberos realm EXAMPLE.TEST and then the original IPA server would be deployed at a host named ipa.example.test (the server host name is not that important here, rather the fact that is is an individual host name). Let’s look at possible communications with this server in a non-multihomed environment first.

Single-homed environment

An IPA client uses HTTPS to communicate with IPA management API, SSSD on the IPA client would use LDAP(S) and Kerberos protocols. In both HTTPS and LDAP(S) cases TLS negotiation would force checking server TLS certificate correctness. A hostname of the host we connect to (ipa.example.test) would have to be present as a dNS SAN record in the TLS certificate presented by the IPA server.

In Kerberos protocol case a different mechanism is used. Yet, Kerberos KDC must know the name of the service principal that a client is asking a service ticket for. If the client wants to acquire a service ticket to ldap/ipa.example.test@EXAMPLE.TEST, this service principal must exist in the Kerberos database that KDC is looking up at.

Multi-homed environment

There are multiple ways of exposing a single hostname in multi-homed environment but they generally involve use of DNS views specific to the individual networking. In such cases DNS serves visible to clients in one network would resolve ipa.example.test to an IP address in that specific network. FreeIPA DNS integration does not support DNS views; this means any of DNS manipulations would have to be done externally to FreeIPA. This is, of course possible, but it really is not then different from a single-homed environment from FreeIPA perspective.

Thus, we would have to have not a single ipa.example.test hostname but for each independent network’s address present on the IPA server a different host name must be present. Let’s assume these are ipa1.example.test and ipa2.example.test. Had we not done this split and simply added multiple addresses for the same ipa.example.test name, clients might resolve the name to an IP address which they could not reach through their own networking routing.

Requirements

Immediately we get a set of requirements here:

  • TLS certificates issued by IPA CA for HTTPS and LDAP(S) use on IPA server must include dNS SAN records for each hostname represented by the multi-homed server.

  • Kerberos principals for at least LDAP (ldap/), HTTP (HTTP/), and the system (host/) service principals must have aliases for all multi-homed hostnames.

The latter requirement means that if ipa1.example.test is the primary name, then ldap/ipa1.example.test should have an alias of ldap/ipa2.example.test, HTTP/ipa1.example.test should have an alias of HTTP/ipa2.example.test, and host/ipa1.example.test should have an alias of host/ipa2.example.test.

The same would apply to any other service hosted on IPA server: SMB (cifs/..) or DNS services would need those aliases as well. However, this is not enough.

Implementation considerations

Hostname aliases

FreeIPA does additional checks when issuing certificiates prior to passing the request to the Dogtag CA that is integrated into FreeIPA. For hosts and services on those hosts we also check whether a requestor is granted to issue these certificates. In FreeIPA terms, a host ipa1.example.test would be allowed to issue certificates with dNS SAN record of ipa2.example.test if a host object of ipa1.example.test manages the host object ipa2.example.test in FreeIPA.

Here lies our first problem. A host object in FreeIPA represents the host principal in Kerberos, host/ipa1.example.test. If we created two host objects, ipa1.example.test and ipa2.example.test, then they cannot be aliases to each other on Kerberos level because they’d be two completely different objects from FreeIPA perspective.

Perhaps, we can avoid creating two different host objects? DNS records for hosts are different from the host objects themselves, we only need to have different IP addresses for the hostnames represented by these host entries, not the host entries themselves. May be we could mark one hostname an alias of the other host object?

On Kerberos level FreeIPA does have Kebreros principal name aliasing already. However, it does not exist for hosts as this task has never appeared in past. We would need to add a way to add multiple names to the host object. One way to achieve that is to rely on the fact that fqdn LDAP attribute is multi-valued. Unfortunately, it is also enforced to be a primary key in IPA API – while the underlying LDAP attribute is a multi-valued one, IPA API will enforce its single value:

$ ipa host-mod ipa1.example.test --addattr fqdn=ipa2.example.test
ipa: ERROR: fqdn: Only one value allowed.

This happens because in IPA API any parameter which could be a multi-valued one should explicitly set multivalue=True in its definition. We probably would need to change the multi-valued state for fqdn parameter:

...
        Str('fqdn', hostname_validator,
            cli_name='hostname',
            label=_('Host name'),
            primary_key=True,
            normalizer=normalize_hostname,
>>>>>>      multivalue=True,
        ),
...

and review countless places where its single value is assumed through the code, like in the resolve_fqdn() helper below. LDAP does not guarantee a particular order of returned values for the multi-valued attributes. From LDAP protocol point of view they all equal, there is no particular order.

def resolve_fqdn(name):
    hostentry = api.Command['host_show'](name)['result']
    return hostentry['fqdn'][0]

An alternative would be to introduce a separate attribute purely for the hostname alias management. We don’t need to use it anywhere else at Kerberos level because there we use Kerberos-specific attributes to handle Kerberos principal names and aliases.

LDAP Access Controls

A big part of the FreeIPA access control mechanism relies on 389-ds LDAP server access control interface. Permissions and roles in FreeIPA effectively define a set of ACIs for 389-ds to check access rights. IPA servers verified to be present in certain resource groups (like cn=masters,cn=ipa,cn=etc,$BASEDN). For host aliases this means they should be present in the same groups to be able to operate as their own entities when checking permissions. This is important for internal logic in IPA LDAP plugins and in KDC driver. For the cases when authentication would be done via GSSAPI a resulting Kerberos principal will be normalized to he primary name of the system anyway.

Certificate issuance

Issuing a certificate is a whole separate topic which still awaits its write up. An abridged version of it can be found in my freeipa-users@ mailing list response from May 2022. I need to turn that into a proper document one day.

From the perspective of aliases, we would need to teach the certificate request processing code to look at the host and service aliases when validating SAN records.

Installer integration

There are two approaches to setting up this multi-homed environment. We can provide all information upfront or we can add a tool that adds individual aliases after deployment. This would mean to (re-)generate certificates, create host aliases and services, create configuration snippets and other details which are required to handle multiple host names for the same host from different networks.

The after-deployment case would cause re-issuance of certificates. For external CA providers it could be handled with existing tool that allows to replace existing TLS certificates with externally provided ones. We need to create a checker to verify that all required dNS SAN names were added and are available. In general, troubleshooting this environment would be non-trivial so a special module for ipa-healthcheck definitely would help.

Final thoughts

Multi-homed environments are hard to automate as many assumptions aren’t actually known to us. They are partly implicit to system and network administrator’s work and cannot be derived merely from the system state. It means administrators would need to aid IPA installers with an information. At this point, it is unclear how to structure this information and which of it going to be useful enough. In contemporary Linux environments you might have DNS resolution depend on a specific network interface thanks to systemd-resolved or VPN connection properties. We might not have that information for introspection in advance. While automatically issuing certificates with required names to cover multi-homed setup is not going to be easy, writing down requirements for external CAs and verifying those certificates before applying them at the second stage of external CA enrollment would further complicate things.

All these problems could be solved, of course. Prioritization of this work against other, more urging tasks, is what we need to figure first…