There’s normally hardly any point using PEAP if you’re already using EAP-TLS for network client authentication over RADIUS. The vast majority of the EAP conversation is encrypted with EAP-TLS anyway. The general consensus seems to be that it’s a waste of time adding the complexity of the PEAP layer too, just to hide the client certificate.

For this reason, examples of how to actually do it in FreeRADIUS are few and far between. In fact, they seem to be rather non-existant. The easy answer via a simple Google search is that you just probably can’t do it. However, there’s now a reason to consider this slightly unusual method, which is that FreeRADIUS now has support for Microsoft Statement of Health (SoH). This is a method where an agent, built in to Windows from XP SP3 and above, can supply a report about the anti-virus software and firewall, etc, upon connection to the network. It’s one component that can be used as part of Network Access Control in deciding whether to permit a client to connect.

Unfortunately for those that want to use TLS and certificates for network authentication, SoH fits into the PEAP layer. Which neatly brings us back to ‘how do I do PEAP/EAP-TLS?’

It turns out that with a recent FreeRADIUS this will now work, and it’s not actually that hard. As always, the key is knowing what to put where. The main configuration, as expected, goes in eap.conf. It needs to look something like this:

eap {
    default_eap_type = peap
    timer_expire     = 60
    ignore_unknown_eap_types = no
    cisco_accounting_username_bug = no

    tls {
        private_key_file = ${raddbdir}/certs/radius.key
        certificate_file = ${raddbdir}/certs/radius.pem
        # Don't add CA_file here unless you also
        # want to allow plain EAP-TLS.

        dh_file = ${raddbdir}/certs/dh
        random_file = /dev/urandom
        # must be around 50 or more bytes greater than
        # fragment_size in innereap below:
        fragment_size = 1200
        check_crl = no
        cipher_list = "DEFAULT"
    }

    peap {
        default_eap_type = tls
        copy_request_to_tunnel = yes
        use_tunneled_reply = yes
        proxy_tunneled_request_as_eap = no
        virtual_server = "inner-tunnel"

        # SoH configuration goes here
        # soh = yes
        # soh_virtual_server = "soh-server"
    }
}

eap innereap {
    default_eap_type = tls
    timer_expire     = 60
    ignore_unknown_eap_types = no
    cisco_accounting_username_bug = no

    tls {
        check_cert_issuer = "/DC=com/DC=example/CN=Test CA"
        private_key_file = ${raddbdir}/certs/radius.key
        certificate_file = ${raddbdir}/certs/radius.pem
        CA_file = ${raddbdir}/certs/ca.pem

        dh_file = ${raddbdir}/certs/dh
        random_file = /dev/urandom
        fragment_size = 1024
        check_crl = no
        cipher_list = "DEFAULT"

        # OCSP configuration goes here
        #ocsp {
        #        enable = yes
        #        override_cert_url = yes
        #        url = "http://ocsp-responder.example.com/ocsp/"
        #}
    }
}

The main server configuration needs to call ‘eap’ as usual. A very basic config might contain:

authorize {
    eap {
        ok = return
    }
}
authenticate {
    eap
}
preacct {
}
accounting {
}
session {
}
post-auth {
}
pre-proxy {
}
post-proxy {
}

However, the inner-tunnel server that is used by PEAP needs to call the second “innereap” instantiation of the eap module. Again, a very basic config might be:

server inner-tunnel {
    authorize {
        innereap
    }
    authenticate {
        innereap
    }
    session {
    }
    post-auth {
    }
    pre-proxy {
    }
    post-proxy {
    }
} # inner-tunnel server block

The key to all this seems to be the fragment_size setting. The TLS component for EAP-TLS must have a smaller fragment_size than the TLS component for PEAP. Experimentation indicated that it should probably at least be 50 bytes smaller, so using the values in eap.conf above is probably safe — your mileage may vary. This difference also seems to be the reason why you can’t just use the same eap instantiation for both the outer and inner servers, as otherwise the configuration could be identical.

(Note: Please don’t put these examples into production as they are — I can’t guarantee they are secure, they’re just examples from the way I got this to work. You should base your server on the default FreeRADIUS configuration until you really know what you are doing.)

After this is working, which hopefully it should do fairly easily, you can start to add the extras, such as SoH (see FreeRADIUS SoH.txt documentation) or client certificate checking with OCSP.

3 Thoughts on “FreeRADIUS with PEAP/EAP-TLS for Microsoft SoH”

  • First of all – great article. I’ve been struggling for days to get this to work, and then found your blog here – lifesaving stuff as I need to replace and already existing 2k8 NPS server that’s showing it’s limitations with something a bit more capable.
    Anyway, whilst this seems to work and clients connect, I’m a little bothered about the fact that I get multiple WARNING : eap session for state … did not finish, please read wiki page re certificate compatibility. Using exactly the same certificates and these work with plain EAP-TLS ok. Is this something you came across? If so, is there an easy fix?
    Thanks
    Andy Franks

  • Is this up-to-date for FreeRadius 3.0?

    I’ve followed all the configurations in here by making changes to:

    eap.conf
    inner-eap.conf
    inner-tunnel.conf

    However no even using just PEAP as an outer method (no inner method) fails as well.

    Any suggestions?

    • Yes, this is fine for FreeRADIUS 3.0. Possibly not 3.1 or 4 with Windows clients, but you shouldn’t be using them in production as they’re development branches anyway.

      If PEAP on its own isn’t working, then you need to start by getting that fixed first. Try from the default config, which generally works for everything, and change one thing at a time.

      If you can’t work it out then your best option is to post full debug output (right from the first banner and including a broken authentication) to the freeradius-users list, and we’ll have a look there.

Leave a Reply to Josh Cancel reply

Your email address will not be published. Required fields are marked *