Fix for IKEv2 VPN on Fortigate (bug in 5.0.0 MPPE support)

The Duo Auth Proxy 5.0.0 is now able to re-encrypt MPPE keys as associated with RADIUS-encapsulated EAP messages e.g. EAP-MSCHAPv2 as commonly used to authenticate IKEv2 VPNs, awesome! However in 5.0.0 there is a bug whereby the Message-Authenticator attribute is copied rather than being re-generated.

After pointing my Fortigate to a Duo Auth Proxy between it and FreeRADIUS, PAP authentication works fine (e.g. SSL VPN) but IKEv2 is unhappy.

Enable debugging on the Fortigate

diagnose debug application ike -1
diagnose debug application fnbamd -1
diagnose debug enable

And note the smoking gun

[1763] fnbamd_radius_auth_validate_pkt-Invalid digest
[1364] fnbamd_auth_handle_radius_result-Error validating radius rsp
[2708] handle_auth_rsp-Error (5) for req 2087461305

A packet capture on the Duo Auth Proxy server shows that the Message-Authenticator attribute is just being copied. Time to dig into the source.

duoauthproxy/lib/radius/server.py

    def create_accept_packet(
...
        # If there are any MPPE attributes in the radius_attrs, they will have
        # been decrypted for us by the radius client module. Re-encrypt them
        # with the authenticator and secret shared between the server module
        # and the appliance
        if any(a in base.MS_MPPE_RESPONSE_ATTRS for a in radius_attrs):
            send_key = radius_attrs["MS-MPPE-Send-Key"][0]
            recv_key = radius_attrs["MS-MPPE-Recv-Key"][0]

            # _create_response_packet put the unencrypted keys on the packet
            # since it copies over all radius_attrs. Remove them and add the
            # encrypted values
            del response_packet["MS-MPPE-Send-Key"]
            del response_packet["MS-MPPE-Recv-Key"]
            mppe.add_mppe(
                response_packet,
                send_key,
                recv_key,
                response_packet.secret,
                response_packet.authenticator,
            )

        return response_packet

Hmm, this looks relevant. What if I try to re-generate the Message-Authenticator attribute after Duo’s finished mangling the message.

            del response_packet["Message-Authenticator"]
            response_packet.add_message_authenticator()

        return response_packet

Voila! Now the proxied RADIUS message can be authenticated by the Fortigate and IKEv2 VPNs work regardless of which auth method is used.

Hopefully this can be incorporated into 5.0.1 and released soon :slight_smile:

-Ryan

Please update to v5.0.1 to see if the Message-Authenticator fix resolves your issue.

(No, we didn’t create a v5.0.1 release overnight after your post. :slight_smile: )

v5.0.1 works, thanks!