RADIUS Proxy Server Implementation - Help

I want to implement a radius proxy and need some guidance and help in how it can be done using python. Here is the use-case I am trying to solve

Only perform Authentication Requests against two Radius Servers. Want to Intercept Radius requests originating from devices and based on some criteria check forward the Authentication Request to one of the two Radius Servers and send the response back to the devices i.e. VPN, Windows or Linux servers, etc.

Any help is appreciated if there are open-source libraries that I can use to implement this. I tried doing it in java using tinyradius and also looked at freeRadius but no luck so wondering if it can be done through python.

Thanks

Hi @career ,
You should build a packet sniffer.
This is a small example:

import socket

#create an INET, raw socket
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)

# receive a packet
while True:
  print s.recvfrom(65565)

After catch the TCP packet, you forward to other system, like VPN or OS…

Thanks this is what I have, when I send a request through NTRadPing Test Utility it’s all encoded i.e.

(b’\x01(\x000 1644624078\x01\ntestuser\x02\x12d]NjM\xbb\xe4\xf6a\xdc2\xeb]\xbe\x10\xa7’, (‘127.0.0.1’, 54697))

how can I decode this Radius Packet and get the readable values?

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM);
s.bind(("127.0.0.1", 1814));

while True:
  print("####### Server is listening #######")
  data, address = s.recvfrom(65565)
  print("\n\n 2. Server received: ", data, "\n\n")
  #send_data = "Type some text to send => "
  #s.sendto(send_data.encode('utf-8'), address)
  #print("\n\n 1. Server sent : ", send_data,"\n\n")

You can use decode method:

data, address = s.recvfrom(65565).decode('utf-8')

Following works but it really hard to tell what is username, password and other fields that are part of the packet

print("\n\n 2. Server received: ", data.decode(‘ISO-8859-1’).encode(‘utf8’), “\n\n”)

Ok, but it is an other problem…maybe, you post the output of your decoded data, we find a possible solution with re module (regular expression)…

user, password, *other = re.split('\w+\:', data.decode('ISO-8859-1'))

This is the full output. Can’t figure out what are the value of the RADIUS Secret, what is user-name, Password, and Request type as shown in NTRadPing Test Utility.

  1. Server received: b’\x01\n\x001 1644763053\x01\ntestuser\x03\x13\x1f\xc3\x9b\xc2\x905\xc2\x85`a\xc2\x91\xc3\xac\xc2\xa8o}\xc2\x98\xc2\x9b\xc3\x94\xc3\x9b\xc3\x9d’

Sorry, but what you posted is a binary and not a decoded string from the binary type.
You should perform a decoding:

b'\x01\n\x001 1644763053\x01\ntestuser\x03\x13\x1f\xc3\x9b\xc2\x905\xc2\x85`a\xc2\x91\xc3\xac\xc
2\xa8o}\xc2\x98\xc2\x9b\xc3\x94\xc3\x9b\xc3\x9d'.decode()

Thanks but it is the decoded value, please see below

while True:
#data = s.recvfrom(2048)
#print(answer[0].decode(‘ISO-8859-1’).encode(‘utf8’))

print("####### Server is listening #######")
data, address = s.recvfrom(65565)
print("\n\n 2. Server received: ", data.decode(‘ISO-8859-1’).encode(‘utf8’), “\n\n”)
print("\n\n 2. Server received aaddress: ", address, “\n\n”)

send_data = “Type some text to send => "
s.sendto(send_data.encode(‘utf-8’), address)
print(”\n\n 1. Server sent : “, send_data,”\n\n")

Ok, so you do analyze the packet.
This is radius packet format:

Radius Packet Format

Code: This is 1 Octet (1 byte) long and identifies various types of packets. Normally 1 Octet means 1 Byte.

Identifier: This is again 1 Octet long and aids in matching responses with requests.

Length: This is 2 Octets long and specifies the length of the packet including code, identifier, length, and authenticator. (Min packet is 20 Octets and max is 4096 Octets).

Authenticator: This is 16 Octets long and filled up in case of some requests and responses.

List of Attributes: There is a list of 63+ attributes and a Radius attribute will also have a defined format which is described in next chapter.

Final, I found a python package that read (decode) a radius package: pyrad.packet

Hi, I tried decoding the packet coming through the socket using pyrad but no luck anyone, this is what I have. Any help is appreciated. Trying to print all the radius attributes coming through using NTRadping tool

from pyrad.packet import Packet
from pyrad.dictionary import Dictionary
import socket
import struct

from scapy.all import *


UDP_IP = "127.0.0.1"
UDP_PORT = 6495
sock = socket.socket(socket.AF_INET, # Internet
                  socket.SOCK_DGRAM) # UDP
sock.bind((UDP_IP, UDP_PORT))
while True:
    packet, addr = sock.recvfrom(65565)
    msg = struct.unpack('!BBH16s', packet[0:20])
    print ("received message:", packet);
    print ("received msg:", msg);
    
    packet = packet[20:]
    while packet:
        (key, attrlen) = struct.unpack('!BB', packet[0:2])
        value = packet[2:attrlen]
        if key == 26:
            for (key, value) in self._PktDecodeVendorAttribute(value):
                print ("if key:", key);
                print ("if key:", key);
        else:
            print ("else key:", key);
            print ("else value:", value);
        
        packet = packet[attrlen:]
    
    print ("packet msg:", packet);
    
    send_data = "Type some text to send => "
    sock.sendto(send_data.encode('utf-8'), addr);
    print("\n\n 1. Server sent : ", send_data,"\n\n");
received message: b'\x01\x00\x001      1646428153\x01\ntestuser\x03\x13h\xada,\x1ed \x87\xa1\x0fF\tH\xad\xadw\xa0'
received msg: (1, 0, 49, b'      1646428153')
else key: 1
else value: b'testuser'
else key: 3
else value: b'h\xada,\x1ed \x87\xa1\x0fF\tH\xad\xadw\xa0'
packet msg: b''