# -*- text -*- # # $Id$ # # Calculate dynamic PSKs # # This module needs the following attributes as input: # # * control:Pre-Shared-Key - the PSK for the user # * User-Name - the supplicant MAC in hex format, e.g. "abcdef012345" # * Called-Station-MAC - the AP MAC in binary # this attribute is set by the "rewrite_called_station_id" policy. # * FreeRADIUS-802.1X-Anonce - from the AP # * FreeRADIUS-802.1X-EAPoL-Key-Msg - from the AP # # Note that you MUST run the "rewrite_called_station_id" policy before calling this module. # # That policy MUST also create the Called-Station-MAC attribute. # # Then place the following configuration into the "authorize" section: # # authorize { # ... # rewrite_called_station_id # # update control { # &PSK-Identity := "bob" # &Pre-Shared-Key := "this-is-super-secret" # } # dpsk # # } # # And update the "authenticate" section to list the "dpsk" module: # # authenticate { # ... # dpsk # ... # } # # The module will return "fail" if the PSK is not correct. It will return "ok" # if the PSK is correct. # # It also updates &reply:Pre-Shared-Key with the found key, along with # &reply:PSK-Identity with the found identity. # # We STRONGLY RECOMMEND THAT NO ONE USE THIS MODULE. # # While it works, it needs to use a brute-force method to match MAC # to PSK. That process is extremely slow, and scales very poorly. # # i.e. if you have 10 PSKs, it's not too bad. If you have 10,000 # PSKs, then the module can comsume 100% of CPU trying to # brute-force every PSK. # # This is a limitation of how DPSK works. There is no way to make it # better. The only thing we've done is to add a cache which can help # to minimize the amount of brute-force attempts. # # # The modules configuration. # dpsk { # # The maximum number of entries to cache. # # The cache is keyed by (supplicant MAC + SSID) # # The cache entry is the PSK-Identity and Pre-Sharedd-Key, # and/or the PMK which are used to verify the information in # the Access-Request. # cache_size = 1024 # # The lifetime of an entry in the cache. # cache_lifetime = 86400 # # PSKs can also be stored in a CSV file. The format of the file is: # # identity,psk,mac # # If there are commas in a field, then the field can be # double quoted: "psk". # # The mac field is optional. If it exists, then that PSK # will be used. It is highly recommended that the MAC *not* be placed # into the CSV file. Instead, the MAC and PSK should be placed into a # database. The server can then be configured to look up the MAC in the # database, which returns the PSK. That way this module will only ever # check one PSK, which is fast. # # i.e. the CSV file should only contain the small number of PSKs where # you do not yet know the MAC. As soon as you know the MAC, you should # put the MAC and PSK into a database, and then remove the MAC and PSK # from the CSV file. # # NOTE: the file is opened and read from top to bottom for every # new request which comes in. This process can be very slow! # # However, opening the file for every new request means that the # server does not have to be reloaded when the file changes. Instead, # the file can be generated, and then moved into place atomically: # # create csv file > psk.csv.new # mv psk.csv.new psk.csv # # Any process which writes a new "psk.csv" file MUST NOT # write to the file directly, as that will cause the dpsk # module to read partial entries and fail. Instead, use "mv" # to atomically overwrite the old file with a new one. # # Both "cache_size" and "filename" can be configured at the # same time, which is recommended. When an entry in the file # is found, the identity, PSK, and MAC are saved in the cache. # # If a cache entry is found, then the filename is NOT read. # # The resulting combination of features means that the module # should be as fast as possible, given the limitations of DPSK. # # NOTE: Tests show that the module can do ~100K PSK / DPSK # checks per second. This means that if you have 10,000 # users and 10 packets a second, the system will be 100% busy # checking PSKs. # # As a result, the DPSK functionality is scales poorly. It # should be used only with a small number of PSKs (100s # perhaps), and only at low packet rates. If the server is # getting 1000 packets per second, then it can only handle # 100 PSKs before running out of CPU. # # Using the cache will help substantially. But the cache is # only in memory, which means that all cache entries are lost # when the server restarts. As a result, the combination of # number of PSKs and packet rates should be kept as low as # possible. # # filename = "${modconfdir}/${..:name}/psk.csv" }