杰瑞科技汇

FreeRadius与Python如何交互集成?

Of course! Using Python with FreeRADIUS is a powerful combination, allowing you to integrate RADIUS authentication with any Python-based system, like a custom user database, a REST API, or complex business logic.

FreeRadius与Python如何交互集成?-图1
(图片来源网络,侵删)

Here’s a comprehensive guide covering the main ways to interact with FreeRADIUS using Python, from the most common and recommended method to alternatives.


The Main Approaches

There are three primary ways to use Python with FreeRADIUS:

  1. Writing a Custom FreeRADIUS Module (The Best & Most Powerful Method): You write a Python script that FreeRADIUS calls as a module. This gives you full access to the RADIUS request and response lifecycle.
  2. Using a Python RADIUS Client Library: You write a standalone Python application that acts as a RADIUS client, sending authentication requests to a FreeRADIUS server (or any other RADIUS server).
  3. Using a Python RADIUS Server Library: You write a standalone Python application that acts as a RADIUS server, receiving requests from clients. This is less common for production but useful for specific testing or microservice scenarios.

We will focus on the first two, as they are the most common use cases.


Method 1: Writing a Custom FreeRADIUS Module (Recommended)

This is the best way to implement custom authentication or accounting logic directly within FreeRADIUS. You'll create a Python script that FreeRADIUS executes for specific events.

FreeRadius与Python如何交互集成?-图2
(图片来源网络,侵删)

How It Works

FreeRADIUS has a module type called exec. This module can run an external program or script and pass it the request details via environment variables and standard input. The script then writes its response back to standard output.

Step-by-Step Example: Python Authentication Module

Let's create a simple Python script that authenticates a user based on a hardcoded username and password.

Create the Python Authentication Script

Create a file named /etc/freeradius/3.0/mods-config/python/my_auth.py. This script will read the username and password from the environment and respond with Auth-Type := Accept or Auth-Type := Reject.

#!/usr/bin/env python3
import os
import sys
# FreeRADIUS passes the request details as environment variables.
# We need to read them.
USERNAME = os.environ.get('USER_NAME')
PASSWORD = os.environ.get('USER_PASSWORD')
# --- Your custom logic goes here ---
# For this example, we'll hardcode credentials.
VALID_USERNAME = "testuser"
VALID_PASSWORD = "SuperSecretPassword123"
if USERNAME == VALID_USERNAME and PASSWORD == VALID_PASSWORD:
    # Successful authentication
    # The response must be formatted as RADIUS attributes.
    # 'Auth-Type := Accept' tells FreeRADIUS the user is authenticated.
    print("Auth-Type := Accept")
    # You can also add other attributes, e.g., Session-Timeout
    # print("Session-Timeout := 3600")
else:
    # Failed authentication
    # 'Auth-Type := Reject' tells FreeRADIUS the user is not authenticated.
    print("Auth-Type := Reject")
# Exit with code 0 to indicate success. Non-zero can indicate an error.
sys.exit(0)

Make the Script Executable

sudo chmod +x /etc/freeradius/3.0/mods-config/python/my_auth.py

Configure FreeRADIUS to Use the Python Script

Now, you need to tell FreeRADIUS to use this script. Edit the main authorize section in your FreeRADIUS site configuration. The default is usually in /etc/freeradius/3.0/sites-available/default.

Open the file:

sudo nano /etc/freeradius/3.0/sites-available/default

Find the authorize section and add a call to your new module. It's common to place it after files and before eap.

authorize {
    # ... other modules like chap, mschap, etc. ...
    # Read user details from files like /etc/freeradius/3.0/users
    files
    # THIS IS OUR NEW PYTHON MODULE
    # This will call our Python script.
    # It must be placed in the 'authorize' section.
    python my_auth
    # ... other modules like pap, eap, etc. ...
}

Restart FreeRADIUS

Apply the changes by restarting the FreeRADIUS service.

sudo systemctl restart freeradius

Test It

Use the radtest command to send a test RADIUS packet.

  • Successful Test:

    # Format: radtest <username> <password> <freeradius_server_ip> <secret> <port>
    echo "User-Password := 'SuperSecretPassword123'" | radtest testuser whatever 127.0.0.1 testing123 0
  • Failed Test:

    echo "User-Password := 'wrongpassword'" | radtest testuser whatever 127.0.0.1 testing123 0

You should see Access-Accept for the successful test and Access-Reject for the failed one in the FreeRADIUS log (/var/log/freeradius/radius.log).

Passing More Complex Data

For more advanced use cases (like accounting or handling arbitrary attributes), you can use the rlm_python module, which is a more integrated C module that can load Python code directly. It's more complex to set up but offers better performance and more control. However, for most use cases, the exec method shown above is simpler and more than sufficient.


Method 2: Using a Python RADIUS Client Library

This approach is useful when you have a Python application (e.g., a web app, a script) that needs to authenticate a user against a RADIUS server.

Popular Python Libraries

  • pyrad: The most popular and feature-rich library. It's a pure Python implementation.
  • radiator-python-api: A wrapper around the Radiator engine, a powerful commercial RADIUS server. Less common for simple clients.

Step-by-Step Example: pyrad Client

Install the pyrad Library

pip install pyrad

Write a Python Client Script

Create a Python script (e.g., radius_client.py) to send an Access-Request.

from pyrad.client import Client
from pyrad.dictionary import Dictionary
from pyrad.packet import AccessRequest
# --- Configuration ---
SERVER = "127.0.0.1"  # IP of your FreeRADIUS server
SECRET = b"testing123"  # The 'secret' from clients.conf
USERNAME = "testuser"
PASSWORD = "SuperSecretPassword123"
DICTIONARY = "/etc/freeradius/3.0/dictionary" # Path to the FreeRADIUS dictionary
# --- Create a client instance ---
# The dictionary tells the client how to build RADIUS packets.
client = Client(server=SERVER, authport=1812, secret=SECRET, dict=Dictionary(DICTIONARY))
# --- Create an Access-Request packet ---
# The 'coa' port is 3799, auth is 1812, acct is 1813.
request = AccessRequest(code=AccessRequest, User_Name=USERNAME, User_Password=PASSWORD)
# --- Send the packet and wait for a response ---
try:
    reply = client.SendPacket(request)
    print(f"Received reply code: {reply.code}")
    if reply.code == AccessAccept:
        print("Authentication SUCCESS!")
        # You can access attributes from the reply
        if 'Session-Timeout' in reply:
            print(f"Session Timeout: {reply['Session-Timeout'][0]}")
    elif reply.code == AccessReject:
        print("Authentication FAILED.")
    else:
        print("An unexpected response was received.")
except Exception as e:
    print(f"An error occurred: {e}")

Run the Script

Execute your Python script. It will connect to the FreeRADIUS server and print the result.

python3 radius_client.py
# Expected Output:
# Received reply code: 2
# Authentication SUCCESS!

Key Concepts & Best Practices

  • Security: The RADIUS secret is critical. It must be kept confidential and match on both the client and server. Never hardcode it directly in your Python code if the script is exposed. Use environment variables or a secrets management system.
  • Dictionaries: RADIUS uses dictionaries to define attribute names and their data types (e.g., User-Name is a string, Session-Timeout is an integer). When using a client library, you need to point it to the correct dictionary file (usually provided by the RADIUS server) so it can build valid packets.
  • Error Handling: Network connections can fail. The RADIUS server can be down. Your Python code should handle these exceptions gracefully.
  • Performance: If you're writing a custom FreeRADIUS module, be aware that forking a new Python process for every request (as the exec method does) can have performance overhead. For very high-throughput systems, investigate rlm_python or consider writing the module in C. For most applications, the exec method is perfectly fine.

Summary: Which Method to Choose?

Scenario Recommended Method Why?
I need to integrate FreeRADIUS with my Python app's database. Custom FreeRADIUS Module (exec) Keeps the logic inside the RADIUS server, which is designed for high-performance network I/O.
I am building a web app that needs to verify MFA. Python RADIUS Client (pyrad) Your web app acts as the client, delegating the authentication check to the central RADIUS server.
I need to implement complex accounting logic in Python. Custom FreeRADIUS Module (exec or rlm_python) The Accounting-Request packet must be processed by the RADIUS server, so a module is the only way.
I need to test my RADIUS setup from a script. Python RADIUS Client (pyrad) Perfect for automation and testing without needing to install radtest or other CLI tools.
分享:
扫描分享到社交APP
上一篇
下一篇