Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

As mentioned in the General information page, the NASes available do not support sending RADIUS accounting packets, they are only able to authenticate users against the response from a RADIUS server. This solution uses 802.1X to authenticate users and let them into the wireless network, and then Shorewall to perform the logging/accounting work. FreeRADIUS, along with a couple of scripts, logs the MAC address of all devices that connect along with the username they authenticated as, this information '@@@1' can information can be used to match information in Shorewall's logs to a user session. For improved security the firewall policy will be to disallow all connections except those originating from known IP addresses of known wifi clients. A script, shwl_add.sh, gets run by FreeRADIUS upon successful authentication of a supplicant, which runs an ARP scan to find the IP address of the device with the MAC address specified by FreeRADIUS, it then adds the IP address to shorewall's "whitelist", logs the event along with some useful information to a MySQL database and writes the current timestamp to a text file. In Access-Accept packets the Session-Timeout and Termination-Action attributes are sent, informing the NAS that after the specified amount of time the supplicant needs to repeat the authentication process or be disconnected. When the supplicant repeats authentication the mentioned script detects that the supplicant is already known and simply logs the event to MySQL and updates the timestamp in the text file. Another script, shwl_del.sh, is run by crontab at a regular interval, which goes through all the IP addresses present in shorewall's "whitelist" and checks the timestamp of the corresponding supplicant's last authentication to FreeRADIUS in the corresponding text file. If more than the specified amount of time has passed, this script assumes that the supplicant has disconnected from the wifi network and removes its IP from shorewall's "whitelist", logs the event to MySQL, and deletes the related text files.

...

A package containing the mentioned scripts, as well as the empty MySQL schema for the database used by some of them, is attached to this wiki the Installation page.

Scripts

Common MySQL database schema

...

The supplicant MAC address is used in the script, the remaining values are simply logged into the MySQL database. Some sanity check is performed on the username before the script continues. The supplicant MAC address is processed so as to obtain it in both of the following formats regardless of the format the NAS specified it in: filename friendly version: 0123456789ab, normal version: 01:23:45:67:89:ab. The supported input formats are: 01-23-45-67-89-ab, 01:23:45:67:89:ab, 0123456789ab, all case in-sensitive'@@@1'. The script then checks if a file named as the filename friendly version of the supplicant MAC address already exists (referred to by the script as an IP file). If it does not, the script '@@@1assumes' runs an ARP scan on the configured network interface and in the resulting table, looks for the IP address matching the specified supplicant MAC address. In case no such device is found, it repeats the scan a configurable amount of times at a configurable interval before giving up. Once a matching IP is found some a basic amount of sanity check is performed on the scan results (e.g. to detect multiple MACs being used by the found IP '@@@1', or such), and then the event is logged into '@@@1' MySQL with "connect" mentioned in the 'event' column, the found IP is added to the configured shorewall dynamic zone, and a file named as the filename friendly version of the supplicant MAC address is created containing the device's IP, and a file named as the device's IP (referred to by the script as a timestamp file) is created containing the present timestamp. In case adding the IP address to the shorewall dynamic zone is not successful, the script waits a configurable amount of time, and then attempts a second time, after which it gives up (it was observed that it might happen that FreeRADIUS starts earlier in the boot process than Shorewall, and if this script is started during that timeframe the shorewall add command fails). In case the IP file is already present, the script simply logs the event to MySQL with "re-auth" mentioned in the 'event' column and re-writes the timestamp file with the present timestamp. In case an error is encountered, the script logs the error to MySQL mentioning "err-add-N" (where N is the error number) in the 'event' column, populating the remaining columns with their respective information as may be available at the time of the error, and exits immediately, returning the error number as exit code. In case access is available to the script's stdout and stderr, a description of the error message is also printed (and the script is quite verbose about what's happening), in case not, it is possible to look in the script's code for calls to the shwl_add_error_message_close() function, identify the call where the error number in question is passed to the function, and the error description can be found in the same function call. The configurable options can be found at the top of the script. The username is logged into the 'device_username' column, the IP address found during the scan is logged in the 'device_ip' column, the above mentioned normal version of the supplicant MAC address is logged in the 'device_mac' column, and the remaining RADIUS attributes are logged in the columns with the respective names.

...

This script makes use of two MySQL databases, the one with containing the above mentioned 'event_log' table '@@@1' for table for logging errors, and FreeRADIUS's database for updating passwords.

This script checks first whether it is running as root (the PAM stack does not necessarily run as root, but as the user as which the service that invoked it is running). If it is, it proceeds to encrypt the user's password (${PAM_AUTHTOK}) as an NT hash and update it in the 'value' column of the configured table in FreeRADIUS's MySQL database for the entry where the value of the 'username' column matches the user's username (${PAM_USER}). Due to the nature of the SQL query used, there needs to already be an entry in the table containing the matching username in the 'username' column (for functionality it should actually also already '@@@1' contain the appropriate values for the remaining columns, except the 'value' column). If it is not running as root, it uses . If it is not running as root, it uses a workaround to escalate its privileges. It uses the available credentials to SSH into localhost as the user in question, causing the SSH daemon to run a new instance of the PAM stack to verify the user's credentials (and sshd runs the PAM stack as root) and thus a new instance of the script, as root. Before doing so the script makes sure that the PAM stack has not already now been invoked by sshd, in order to avoid, in case sshd should ever decide to run the PAM stack as a non-root user, that an infinite loop occurs spawning endless processes of this script, sshd, PAM, etc.

In case an error is encountered, the script logs the error to the above mentioned '@@@1' the configured table in MySQL, in the 'event_log' table in MySQL , mentioning "err-pmu-N" (where N is the error number) in the 'event' column, populating the 'device_username' column with the user's username, leaving the other columns empty, and exits immediately, returning the error number as exit code. The error is logged to MySQL only if the script is running as root. In case access is available to the script's stdout and stderr, a description of the error message is also printed (and the script is quite verbose about what's happening if cfg_verbose is set to 1), in case not, it is possible to look in the script's code for calls to the pam_to_mysql_update_error_message_close() function, identify the call where the error number in question is passed to the function, and the error description can be found in the same function call. The configurable options can be found at the top of the script.

In the intended PAM/libpam-script configuration, in the case of the This script has been tested with the 'passwd' system utility and the GNOME User Accounts applet, for the PAM password stack. It has been tested with 'su', GNOME desktop and sshd for the PAM auth stack.

In the intended PAM/libpam-script configuration, in the case of the script running SSH to start a second instance as root, in the case the second instance (running as root) fails and returns an error exit code, libpam-script will report failure to the PAM stack, causing the authentication to fail, thus the SSH login to fail, and the ssh command that was launched in the first instance of the script, resulting finally in the first instance of the script to also fail, the first instance of libpam-script, and thus the first PAM stack. Setting cfg_verbose=1 will cause the script's verbose output to appear on screen in cases where a service invoking the PAM stack allows, e.g. when running the 'su' command. During PAM password stack execution, the libpam-script module also shows a prompt "Current password:", which is visible when using command line utilities such as 'passwd', and is irrelevant to our purpose, this can be safely ignored and it is sufficient to press enter.

Sources

...

https://wiki.freeradius.org/guide/Basic-configuration-HOWTO

...