Network nqis los ntawm FreeRadius ntawm DHCP

Network nqis los ntawm FreeRadius ntawm DHCP
Txoj haujlwm tuaj txog los npaj qhov muab qhov chaw nyob IP rau cov neeg siv khoom. Cov xwm txheej ntawm qhov teeb meem:

  • Peb yuav tsis muab rau koj cais server rau kev tso cai - koj yuav ua 😉
  • Cov neeg thov yuav tsum tau txais kev teeb tsa network ntawm DHCP
  • Lub network yog heterogeneous. Qhov no suav nrog PON cov cuab yeej thiab cov hloov pauv tsis tu ncua nrog kev teeb tsa Option 82 thiab WiFi hauv paus nrog hotspots
  • Yog tias cov ntaub ntawv tsis poob rau hauv ib qho ntawm cov xwm txheej rau kev tshaj tawm IP, koj yuav tsum muab tus IP los ntawm "tus qhua" network

Ntawm qhov zoo: tseem muaj lub server ntawm FreeBSD uas tuaj yeem "ua haujlwm", tab sis nws yog "nyob deb" ;), tsis yog "txoj cai ntawm lub network no".

Kuj tseem muaj cov cuab yeej zoo hu ua Mikrotik. Daim duab network dav dav yog ib yam zoo li no:

Network nqis los ntawm FreeRadius ntawm DHCP

Tom qab qee qhov kev xav, nws tau txiav txim siab siv FreeRadius los teeb tsa lub network rau cov neeg siv khoom. Raws li txoj cai, lub tswv yim yog ib txwm: peb pab DHCP server ntawm Microtick, thiab Radius Client ntawm nws. Peb teeb tsa DHCP server -> Radius Client -> Radius server txuas.

Nws tsis zoo li nyuaj. Tab sis! Dab ntxwg nyoog yog nyob rau hauv cov ntsiab lus. Xws li:

  • Thaum tso cai rau PON OLT siv cov tswv yim no, kev thov raug xa mus rau FreeRadius nrog tus neeg siv-Npe sib npaug rau MAC chaw nyob ntawm lub taub hau, tus neeg sawv cev-Circuit-Id sib npaug rau MAC PON Onu thiab tus password khoob.
  • Thaum tso cai los ntawm cov keyboards nrog kev xaiv 82, FreeRadius tau txais kev thov nrog tus neeg siv-Npe npliag sib npaug rau MAC ntawm tus neeg siv khoom lub cuab yeej thiab sau nrog cov cwj pwm ntxiv Agent-Circuit-Id thiab Agent-Remote-Id uas muaj, feem, dua MAC ntawm lub relay hloov thiab qhov chaw nres nkoj uas cov neeg siv khoom txuas nrog.
  • Qee cov neeg siv nrog WiFI cov ntsiab lus tau tso cai los ntawm PAP-CHAP raws tu qauv
  • Qee cov neeg siv los ntawm WIFI cov ntsiab lus tau tso cai nrog Tus Neeg Siv-Npe sib npaug rau MAC chaw nyob ntawm WIFI point, tsis muaj lo lus zais.

Keeb kwm keeb kwm: dab tsi yog "Option 82" hauv DHCP

Cov no yog cov kev xaiv ntxiv rau DHCP raws tu qauv uas tso cai rau koj hloov cov ntaub ntawv ntxiv, piv txwv li hauv Agent-Circuit-Id thiab Agent-Remote-Id teb. Feem ntau siv los xa cov MAC chaw nyob ntawm qhov hloov pauv thiab qhov chaw nres nkoj uas tus neeg siv khoom txuas nrog. Nyob rau hauv rooj plaub ntawm cov khoom siv PON lossis WIFI lub hauv paus chaw nres tsheb, Agent-Circuit-Id teb tsis muaj cov ntaub ntawv tseem ceeb (tsis muaj qhov chaw nres nkoj). Lub tswv yim dav dav ntawm DHCP kev ua haujlwm hauv qhov no yog raws li hauv qab no:

Network nqis los ntawm FreeRadius ntawm DHCP

Step-by-step no scheme ua haujlwm zoo li no:

  1. Cov cuab yeej siv ua rau DHCP tshaj tawm kev thov kom tau txais kev teeb tsa network
  2. Cov cuab yeej (piv txwv li, hloov chaw, WiFi lossis PON lub hauv paus chaw nres tsheb) uas cov cuab yeej siv tau txuas ncaj qha "intercepts" pob ntawv no thiab hloov nws, qhia txog kev xaiv ntxiv Option 82 thiab Relay tus neeg sawv cev IP chaw nyob rau hauv nws, thiab xa nws mus ntxiv. lub network.
  3. DHCP server lees txais qhov kev thov, tsim cov lus teb thiab xa mus rau cov khoom siv relay
  4. Lub relay ntaus ntawv xa mus rau cov ntawv teb rau cov neeg siv khoom

Tau kawg, txhua yam tsis ua haujlwm yooj yim; koj yuav tsum teeb tsa koj cov khoom siv network raws li.

Txhim kho FreeRadius

Tau kawg, qhov no tuaj yeem ua tiav nrog FreeRadius teeb tsa, tab sis nws nyuaj thiab tsis meej ... tshwj xeeb tshaj yog thaum koj mus tom qab N lub hlis thiab "txhua yam ua haujlwm." Yog li ntawd, peb txiav txim siab sau peb tus kheej tso cai module rau FreeRadius hauv Python. Peb yuav muab cov ntaub ntawv tso cai los ntawm MySQL database. Tsis muaj qhov taw tes piav qhia nws cov qauv; txawm li cas los xij, txhua tus yuav ua nws "rau lawv tus kheej." Tshwj xeeb, kuv coj cov qauv uas muaj nrog sql module rau FreeRadius, thiab hloov me ntsis los ntawm kev ntxiv mac thiab chaw nres nkoj teb rau txhua tus neeg siv khoom, ntxiv rau tus lej nkag-tus password.

Yog li, ua ntej, nruab FreeRadius:

cd /usr/ports/net/freeradius3
make config
make
install clean

Hauv kev teeb tsa, xaiv rau nruab:

Network nqis los ntawm FreeRadius ntawm DHCP

Peb ua ib qho kev sib txuas rau python module (piv txwv li "tig rau" nws):

ln -s /usr/local/etc/raddb/mods-available/python /usr/local/etc/raddb/mods-enabled

Cia peb nruab ib qho module ntxiv rau python:

pip install mysql-connector

Hauv cov python module teeb tsa rau FreeRadius, koj yuav tsum qhia meej cov kev tshawb nrhiav module hauv python_path sib txawv. Piv txwv li kuv muaj qhov no:

python_path="/usr/local/etc/raddb/mods-config/python:/usr/local/lib/python2.7:/usr/local/lib/python27.zip:/usr/local/lib/python2.7:/usr/local/lib/python2.7/plat-freebsd12:/usr/local/lib/python2.7/lib-tk:/usr/local/lib/python2.7/lib-old:/usr/local/lib/python2.7/lib-dynload:/usr/local/lib/python2.7/site-packages"

Koj tuaj yeem pom cov kev los ntawm kev pib tus neeg txhais lus python thiab nkag mus rau cov lus txib:

root@phaeton:/usr/local/etc/raddb/mods-enabled# python
Python 2.7.15 (default, Dec  8 2018, 01:22:25) 
[GCC 4.2.1 Compatible FreeBSD Clang 6.0.1 (tags/RELEASE_601/final 335540)] on freebsd12
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path
['', '/usr/local/lib/python27.zip', '/usr/local/lib/python2.7', '/usr/local/lib/python2.7/plat-freebsd12', '/usr/local/lib/python2.7/lib-tk', '/usr/local/lib/python2.7/lib-old', '/usr/local/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/site-packages']
>

Yog tias koj tsis ua raws li cov kauj ruam no, ces cov ntawv sau nyob rau hauv python thiab launched los ntawm FreeRadius yuav tsis pom cov modules uas tau teev nyob rau hauv ntshuam. Tsis tas li ntawd, koj yuav tsum uncomment lub zog rau hu rau kev tso cai thiab accounting nyob rau hauv lub module chaw. Piv txwv li, qhov module zoo li no:

python {
    python_path="/usr/local/etc/raddb/mods-config/python:/usr/local/lib/python2.7:/usr/local/lib/python2.7/site-packages:/usr/local/lib/python27.zip:/usr/local/lib/python2.7:/usr/local/lib/python2.7/plat-freebsd12:/usr/local/lib/python2.7/lib-tk:/usr/local/lib/python2.7/lib-old:/usr/local/lib/python2.7/lib-dynload:/usr/local/lib/python2.7/site-packages"
    module = work
    mod_instantiate = ${.module}
    mod_detach = ${.module}

    mod_authorize = ${.module}
    func_authorize = authorize

    mod_authenticate = ${.module}
    func_authenticate = authenticate

    mod_preacct = ${.module}
    func_preacct = preacct

    mod_accounting = ${.module}
    func_accounting = accounting

    mod_checksimul = ${.module}
    mod_pre_proxy = ${.module}
    mod_post_proxy = ${.module}
    mod_post_auth = ${.module}
    mod_recv_coa = ${.module}
    mod_send_coa = ${.module}

}

Cov ntawv work.py (thiab tag nrho lwm cov) yuav tsum muab tso rau hauv /usr/local/etc/raddb/mods-config/python Kuv muaj peb tsab ntawv tag nrho.

ua haujlwm.py:

#!/usr/local/bin/python
# coding=utf-8
import radiusd
import func
import sys
from pprint import pprint
mysql_host="localhost"
mysql_username="укацук"
mysql_password="ыукаыукаыук"
mysql_base="ыукаыкуаыу"
def instantiate(p):
print ("*** instantiate ***")
print (p)
# return 0 for success or -1 for failure
def authenticate(p):
print ("*** Аутенфикация!!***")
print (p)
def authorize(p):
radiusd.radlog(radiusd.L_INFO, '*** radlog call in authorize ***')    
conn=func.GetConnectionMysql(mysql_host, mysql_username, mysql_password, mysql_base);
param=func.ConvertArrayToNames(p);
pprint(param)
print ("*** Авторизация ***")
reply = ()
conf = ()
cnt=0
username="";mac="";
# сначала проверяем "как положено", по связке логин/пароль
if ("User-Name" in param) and ("User-Password" in param) :
print ("Вариант авторизации (1): есть логин-пароль")
pprint(param["User-Name"])
pprint(param["User-Password"])
pprint(conn)
print(sys.version_info)
print (radiusd.config)
sql="select radreply.attribute,radreply.value from radcheck inner join radreply on radreply.username=radcheck.username where radcheck.username=%s and radcheck.value=%s"
print(sql)
cursor = conn.cursor(dictionary=True,buffered=True)
cursor.execute(sql,[param["User-Name"], param["User-Password"]]);
row = cursor.fetchone()	
while row is not None:    
cnt=cnt+1
username=row["username"]
reply = reply+((str(row["attribute"]),str(row["value"])), )
row = cursor.fetchone()	          
# вариант, что User-Name - это МАС адрес БС,пароля и порта нет                
if ("User-Name" in param)  and ("User-Password" in param) and (cnt==0):
if param["User-Password"] =='':
if ":" in param["User-Name"]:
pprint(param["User-Name"])            
print ("Вариант авторизации (2): User-Name - это MAC адрес базовой станции, порта и пароля нет")
sql="select radreply.username,radreply.attribute,radreply.value from radcheck inner join radreply on radreply.username=radcheck.username where REPLACE(radcheck.mac,':','') = REPLACE(REPLACE('"+str(param["User-Name"])+"','0x',''),':','') and radcheck.sw_port=''"
print (sql)
cursor = conn.cursor(dictionary=True,buffered=True)
cursor.execute(sql);
row = cursor.fetchone()	
while row is not None:                  
cnt=cnt+1
username=row["username"]
mac=param["User-Name"]
reply = reply+((str(row["attribute"]),str(row["value"])), )
row = cursor.fetchone()	          
if ("Agent-Remote-Id" in param)  and ("User-Password" in param) and (cnt==0):
if param["User-Password"] =='':
pprint(param["Agent-Remote-Id"])            
print ("Вариант авторизации (2.5): Agent-Remote-Id - это MAC адрес PON оборудования")
sql="select radreply.username,radreply.attribute,radreply.value from radcheck inner join radreply on radreply.username=radcheck.username where REPLACE(radcheck.mac,':','') = REPLACE(REPLACE('"+str(param["Agent-Remote-Id"])+"','0x',''),':','') and radcheck.sw_port=''"
print (sql)
cursor = conn.cursor(dictionary=True,buffered=True)
cursor.execute(sql);
row = cursor.fetchone()	
while row is not None:                  
cnt=cnt+1
username=row["username"]
mac=param["User-Name"]
reply = reply+((str(row["attribute"]),str(row["value"])), )
row = cursor.fetchone()	          
#Вариант, что Agent-Remote-Id - это МАС адрес БС,пароля и порта нет и предыдущие варианты поиска IP результата не дали                
if ("Agent-Remote-Id" in param)  and ("User-Password" not in param) and (cnt==0):
pprint(param["Agent-Remote-Id"])            
print ("Вариант авторизации (3): Agent-Remote-Id - МАС базовой станции/пон. Порта в биллинге нет")
sql="select radreply.username,radreply.attribute,radreply.value from radcheck inner join radreply on radreply.username=radcheck.username where REPLACE(radcheck.mac,':','') = REPLACE(REPLACE('"+str(param["Agent-Remote-Id"])+"','0x',''),':','') and radcheck.sw_port=''"
print(sql)
cursor = conn.cursor(dictionary=True,buffered=True)
cursor.execute(sql);
row = cursor.fetchone()	
while row is not None:    
cnt=cnt+1
mac=param["Agent-Remote-Id"]
username=row["username"]
reply = reply+((str(row["attribute"]),str(row["value"])), )
row = cursor.fetchone()	          
#Вариант, что предыдущие попытки результата не дали, но есть Agent-Remote-Id и Agent-Circuit-Id
if ("Agent-Remote-Id" in param)  and ("Agent-Circuit-Id" in param) and (cnt==0):
pprint(param["Agent-Remote-Id"])            
pprint(param["Agent-Circuit-Id"])            
print ("Вариант авторизации (4): авторизация по Agent-Remote-Id и Agent-Circuit-Id, в биллинге есть порт/мак")
sql="select radreply.username,radreply.attribute,radreply.value from radcheck inner join radreply on radreply.username=radcheck.username where upper(radcheck.sw_mac)=upper(REPLACE('"+str(param["Agent-Remote-Id"])+"','0x','')) and upper(radcheck.sw_port)=upper(RIGHT('"+str(param["Agent-Circuit-Id"])+"',2)) and radcheck.sw_port<>''"
print(sql)
cursor = conn.cursor(dictionary=True,buffered=True)
cursor.execute(sql);
row = cursor.fetchone()	
while row is not None:    
cnt=cnt+1
mac=param["Agent-Remote-Id"]
username=row["username"]
reply = reply+((str(row["attribute"]),str(row["value"])), )
row = cursor.fetchone()	          
# если так до сих пор IP не получен, то выдаю иего из гостевой сети..
if cnt==0:      
print ("Ни один из вариантов авторизации не сработал, получаю IP из гостевой сети..")
ip=func.GetGuestNet(conn)      
if ip!="": 
cnt=cnt+1;
reply = reply+(("Framed-IP-Address",str(ip)), )
# если совсем всё плохо, то Reject
if cnt==0:
conf = ( ("Auth-Type", "Reject"), ) 
else:
#если авторизация успешная (есть такой абонент), то запишем историю авторизации
if username!="":
func.InsertToHistory(conn,username,mac, reply);
conf = ( ("Auth-Type", "Accept"), )             
pprint (reply)
conn=None;
return radiusd.RLM_MODULE_OK, reply, conf
def preacct(p):
print ("*** preacct ***")
print (p)
return radiusd.RLM_MODULE_OK
def accounting(p):
print ("*** Аккаунтинг ***")
radiusd.radlog(radiusd.L_INFO, '*** radlog call in accounting (0) ***')  
print (p)
conn=func.GetConnectionMysql(mysql_host, mysql_username, mysql_password, mysql_base);
param=func.ConvertArrayToNames(p);
pprint(param)  
print("Удалим старые сессии (более 20 минут нет аккаунтинга)");
sql="delete from radacct where TIMESTAMPDIFF(minute,acctupdatetime,now())>20"
cursor = conn.cursor(dictionary=True,buffered=True)
cursor.execute(sql);
conn.commit()
print("Обновим/добавим информацию о сессии")
if (("Acct-Unique-Session-Id" in param) and ("User-Name" in param) and ("Framed-IP-Address" in param)):
sql='insert into radacct (radacctid,acctuniqueid,username,framedipaddress,acctstarttime) values (null,"'+str(param['Acct-Unique-Session-Id'])+'","'+str(param['User-Name'])+'","'+str(param['Framed-IP-Address'])+'",now()) ON DUPLICATE KEY update acctupdatetime=now()'
print(sql)
cursor = conn.cursor(dictionary=True,buffered=True)
cursor.execute(sql)
conn.commit()
conn=None;
return radiusd.RLM_MODULE_OK
def pre_proxy(p):
print ("*** pre_proxy ***")
print (p)
return radiusd.RLM_MODULE_OK
def post_proxy(p):
print ("*** post_proxy ***")
print (p)
return radiusd.RLM_MODULE_OK
def post_auth(p):
print ("*** post_auth ***")
print (p)
return radiusd.RLM_MODULE_OK
def recv_coa(p):
print ("*** recv_coa ***")
print (p)
return radiusd.RLM_MODULE_OK
def send_coa(p):
print ("*** send_coa ***")
print (p)
return radiusd.RLM_MODULE_OK
def detach():
print ("*** На этом всё детишечки ***")
return radiusd.RLM_MODULE_OK

func.py:

#!/usr/bin/python2.7
# coding=utf-8
import mysql.connector
from mysql.connector import Error
# Функция возвращает соединение с MySQL
def GetConnectionMysql(mysql_host, mysql_username, mysql_password, mysql_base):    
try:
conn = mysql.connector.connect(host=mysql_host,database=mysql_base,user=mysql_username,password=mysql_password)
if conn.is_connected(): print('---cоединение с БД '+mysql_base+' установлено')
except Error as e:
print("Ошибка: ",e);
exit(1);       
return conn
def ConvertArrayToNames(p):
mass={};
for z in p:
mass[z[0]]=z[1]
return mass
# Функция записывает историю соединения по известным данным
def InsertToHistory(conn,username,mac, reply):
print("--записываю для истории")
repl=ConvertArrayToNames(reply)
if "Framed-IP-Address" in repl:
sql='insert into radpostauth (username,reply,authdate,ip,mac,session_id,comment) values ("'+username+'","Access-Accept",now(),"'+str(repl["Framed-IP-Address"])+'","'+str(mac)+'","","")'
print(sql)
cursor = conn.cursor(dictionary=True,buffered=True)          
cursor.execute(sql);
conn.commit()
# Функция выдает последний по дате выдачи IP адрес из гостевой сети        
def GetGuestNet(conn):
ip="";id=0
sql="select * from guestnet order by dt limit 1"
print (sql)
cursor = conn.cursor(dictionary=True,buffered=True)          
cursor.execute(sql);
row = cursor.fetchone()	
while row is not None:    
ip=row["ip"]
id=row["id"]
row = cursor.fetchone()	          
if id>0:
sql="update guestnet set dt=now() where id="+str(id)
print (sql)
cursor = conn.cursor(dictionary=True,buffered=True)          
cursor.execute(sql);
conn.commit()
return ip         

radiusd.py:

#!/usr/bin/python2.7
# coding=utf-8
# from modules.h
RLM_MODULE_REJECT = 0
RLM_MODULE_FAIL = 1
RLM_MODULE_OK = 2
RLM_MODULE_HANDLED = 3
RLM_MODULE_INVALID = 4
RLM_MODULE_USERLOCK = 5
RLM_MODULE_NOTFOUND = 6
RLM_MODULE_NOOP = 7
RLM_MODULE_UPDATED = 8
RLM_MODULE_NUMCODES = 9
# from log.h
L_AUTH = 2
L_INFO = 3
L_ERR = 4
L_WARN = 5
L_PROXY = 6
L_ACCT = 7
L_DBG = 16
L_DBG_WARN = 17
L_DBG_ERR = 18
L_DBG_WARN_REQ = 19
L_DBG_ERR_REQ = 20
# log function
def radlog(level, msg):
import sys
sys.stdout.write(msg + 'n')
level = level

Raws li koj tuaj yeem pom los ntawm cov cai, peb tab tom sim txheeb xyuas tus neeg siv khoom siv txhua txoj hauv kev los ntawm nws tus neeg siv npe MAC chaw nyob lossis Option 82 ua ke, thiab yog tias qhov no tsis ua haujlwm, ces peb muab qhov chaw nyob IP qub uas tau siv los ntawm "tus qhua. "kev network. Txhua yam uas tseem tshuav yog txhawm rau teeb tsa lub neej ntawd tsab ntawv nyob rau hauv cov chaw-enabled nplaub tshev, kom cov haujlwm tsim nyog los ntawm cov ntawv python yuav twitch ntawm lub sijhawm teem tseg. Qhov tseeb, nws txaus los nqa cov ntaub ntawv mus rau hauv daim ntawv:

ua ntej

server default {
listen {
type = auth
ipaddr = *
port = 0
limit {
max_connections = 16
lifetime = 0
idle_timeout = 30
}
}
listen {
ipaddr = *
port = 0
type = acct
limit {
}
}
listen {
type = auth
port = 0
limit {
max_connections = 1600
lifetime = 0
idle_timeout = 30
}
}
listen {
ipv6addr = ::
port = 0
type = acct
limit {
}
}
authorize {
python
filter_username
preprocess
expiration
logintime
}
authenticate {
Auth-Type PAP {
pap
python
}
Auth-Type CHAP {
chap
python
}
Auth-Type MS-CHAP {
mschap
python
}
eap
}
preacct {
preprocess
acct_unique
suffix
files
}
accounting {
python
exec
attr_filter.accounting_response
}
session {
}
post-auth {
update {
&reply: += &session-state:
}
exec
remove_reply_message_if_eap
Post-Auth-Type REJECT {
attr_filter.access_reject
eap
remove_reply_message_if_eap
}
Post-Auth-Type Challenge {
}
}
pre-proxy {
}
post-proxy {
eap
}
}

Cia peb sim khiav nws thiab saib dab tsi tuaj rau hauv lub cav debug:

/usr/local/etc/rc.d/radiusd debug

Dab tsi ntxiv. Thaum teeb tsa FreeRadius, nws yooj yim los ntsuas nws txoj haujlwm siv radclient utility. Piv txwv li kev tso cai:

echo "User-Name=4C:5E:0C:2E:7F:15,Agent-Remote-Id=0x9845623a8c98,Agent-Circuit-Id=0x00010006" | radclient -x  127.0.0.1:1812 auth testing123

Los yog account:

echo "User-Name=4C:5E:0C:2E:7F:15,Agent-Remote-Id=0x00030f26054a,Agent-Circuit-Id=0x00010002" | radclient -x  127.0.0.1:1813 acct testing123

Kuv xav ceeb toom rau koj tias nws tsis tuaj yeem siv lub tswv yim thiab cov ntawv sau "tsis muaj kev hloov pauv" ntawm "kev lag luam" nplai. Yam tsawg kawg pom tau:

  • nws muaj peev xwm "cua" qhov chaw nyob MAC. Nws yog txaus rau cov neeg rau npe rau lwm tus MAC thiab yuav muaj teeb meem
  • lub logic ntawm kev tawm cov qhua network yog dhau qhov kev thuam. Tsis muaj ib daim tshev "tej zaum twb muaj cov neeg siv khoom nrog tib tus IP chaw nyob?"

Qhov no tsuas yog "cov kua nplaum-cutter" tsim los ua haujlwm tshwj xeeb hauv kuv cov xwm txheej, tsis muaj dab tsi ntxiv. Tsis txhob txiav txim nruj 😉

Tau qhov twg los: www.hab.com

Ntxiv ib saib