walkor / workerman

An asynchronous event driven PHP socket framework. Supports HTTP, Websocket, SSL and other custom protocols.
http://www.workerman.net
MIT License
11.03k stars 2.25k forks source link

Using this as Radius Server #999

Closed rjjrbatarao closed 5 months ago

rjjrbatarao commented 5 months ago

Thank you for this wonderful library, im currently using this as a pure php radius server :), still were fixing some minor issues check this link radius image image

walkor commented 5 months ago

I'm glad you like it.

rjjrbatarao commented 5 months ago

I'll update here if the code ready for everyone i've already implemented accounting as well as the change of authorization, timers for the daily, weekly and monthly is still on going :) all concepts from freeradius are being implemented, its amazing what workerman can do :)

rjjrbatarao commented 5 months ago

Below is my benchmark using golang radius golang_radius_c10000_p100 This is my benchmark for workerman radius php_radius_c10000_p100 ALthough workerman radius is consistent at 7000 packet/s still not as fast as the golang radius which tops at 17000 packet/s is this the limitation of workerman udp or maybe it has to parse the packet which consumes speed I dont know how can I improve this to match golang speeds. Maybe async udp server could help? do you have any insights to this? both were tested with radperf with radperf -c 10000, -p 100, -s -f radperf.data 192.168.10.199 auth secret sending 100 packets in parallel for 10k times

<?php

use Workerman\Worker;
use Boo\Radius\Packet;
use Boo\Radius\PacketType;
use Boo\Radius\PacketEncoder;

require_once __DIR__ . '/vendor/autoload.php';

// #### create socket and listen radius 1812 port ####
$udp_authentication_worker = new Worker('udp://0.0.0.0:1812');

// 4 processes
$udp_authentication_worker->count = 6;

// Emitted when new connection come
$udp_authentication_worker->onConnect = function ($connection) {
    var_dump("New authentication Connection\n");
};
// Emitted when data received
$udp_authentication_worker->onMessage = function ($connection, $data) {
    $encoder = new PacketEncoder();
    $packet = $encoder->decode($data, 'secret');
    //var_dump("Authentication->");
    //var_dump(json_encode($packet->getAttributes(), JSON_INVALID_UTF8_IGNORE));
    // Do some logic on the response PacketType to accept or reject based on the decoded username and password on this case it just accepts everything
    $response = $encoder->encode(new Packet(
        PacketType::ACCESS_ACCEPT(),
        'secret',
        [
            'Session-Timeout' => 60 * 5,
            'Acct-Interim-Interval' => 60,
        ],
        $packet->getAuthenticator(),
        $packet->getIdentifier()
    ));

    $connection->send($response);
};

// Emitted when connection is closed
$udp_authentication_worker->onClose = function ($connection) {
    var_dump("authentication Connection closed\n");
};

Worker::runAll();
rjjrbatarao commented 5 months ago

7000 packet/s is already impressive given that freeRadius could get lower benchmark than this as low as 200 packet/s if using sql. I'll keep on poking some settings or add database queries and rerun my benchmark again to see some difference

walkor commented 5 months ago

Workerman only supports one process on Windows servers, which cannot fully utilize its performance. If you want better performance, you need to use a Linux system. If your business does not involve external IO operations such as a database, the number of processes can be set equal to the number of CPU cores. Otherwise, the number of processes should be set to around four times the number of CPU cores.

walkor commented 5 months ago

Also, printing data to the terminal is a time-consuming operation, it is best to delete the relevant code

var_dump("New authentication Connection\n");
var_dump("authentication Connection closed\n");
rjjrbatarao commented 5 months ago

@walkor I see thank you that sorts it out, im using it on my windows nonetheless it still good, I'll definetely deploy it on a linux machine