Network marongero kubva kuFreeRadius kuburikidza neDHCP

Network marongero kubva kuFreeRadius kuburikidza neDHCP
Basa rakasvika kuronga kuburitswa kweIP kero kune vanyoreri. Mamiriro edambudziko:

  • Hatikupe sevha yakaparadzana yemvumo - iwe uchaita 😉
  • Vanyoreri vanofanirwa kugamuchira zvigadziriso zvetiweki kuburikidza neDHCP
  • Iyo network ine zvakasiyana. Izvi zvinosanganisira PON midziyo uye anogara achichinja ane yakagadziriswa Option 82 uye WiFi mabhesi ane hotspots.
  • Kana iyo data isingawire pasi pechero mamiriro ekuburitsa IP, iwe unofanirwa kuburitsa IP kubva kune "muenzi" network.

Kudivi rakanaka: kuchine sevha paFreeBSD inogona "kushanda", asi iri "kure";), kwete "kurudyi pane iyi network".

Kune zvakare chishandiso chinoshamisa chinonzi Mikrotik. Iyo general network diagraph chinhu chakadai:

Network marongero kubva kuFreeRadius kuburikidza neDHCP

Mushure meimwe pfungwa, zvakasarudzwa kushandisa FreeRadius kuburitsa network network kune vanyoreri. Muchidimbu, chirongwa chacho chinowanzo: tinogonesa sevha yeDHCP paMicrotick, uye Radius Client pairi. Isu tinogadzirisa sevha yeDHCP -> Radius Client -> Radius server yekubatanidza.

Zvinoita sezvisina kuoma. Asi! Dhiyabhorosi ari muhuwandu. Zvinonzi:

  • Pakupa mvumo yePON OLT uchishandisa chirongwa ichi, chikumbiro chinotumirwa kuFreeRadius neMushandisi-Zita rakaenzana nekero yeMAC yemusoro, Agent-Circuit-Id yakaenzana neMAC PON Onu uye password isina chinhu.
  • Kana ichibvumidza kubva kuchinjika nesarudzo 82, FreeRadius inogamuchira chikumbiro chine isina Mushandisi-Zita rakaenzana neMAC yechishandiso chemunyoreri uye yakazadzwa nehumwe hunhu Agent-Circuit-Id uye Agent-Remote-Id ine, zvichiteerana, zvakare MAC ye. iyo relay switch uye chiteshi icho munyoreri akabatana.
  • Vamwe vanyoreri vane mapoinzi eWiFI vanotenderwa kuburikidza nePAP-CHAP protocol
  • Vamwe vanyoreri kubva kuWIFI mapoinzi vanobvumidzwa neMushandisi-Zita rakaenzana neMAC kero yeWIFI point, isina password.

Nhoroondo yekare: chii chinonzi "Sarudzo 82" muDHCP

Idzi ndidzo dzimwe sarudzo dzeDHCP protocol dzinokutendera kuti utumire rumwe ruzivo, semuenzaniso munzvimbo dzeAgent-Circuit-Id uye Agent-Remote-Id. Inowanzo shandiswa kufambisa iyo MAC kero yerelay switch uye chiteshi chakabatana nemunyoreri. Panyaya yePON midziyo kana WIFI base zviteshi, iyo Agent-Circuit-Id ndima haina ruzivo runobatsira (hapana kunyoresa chiteshi). Iyo general scheme yeDHCP kushanda mune iyi kesi ndeiyi inotevera:

Network marongero kubva kuFreeRadius kuburikidza neDHCP

Nhanho nhanho chirongwa ichi chinoshanda seizvi:

  1. Mushandisi wemidziyo inoita chikumbiro cheDHCP kutepfenyura kuti uwane marongero etiweki
  2. Chishandiso (semuenzaniso, switch, WiFi kana PON base chiteshi) iyo yekunyorera yakabatana zvakananga "inobata" pakiti iyi uye ichichinja, ichiunza imwe sarudzo Option 82 uye Relay mumiriri IP kero mairi, uye oiendesa mberi pamusoro. network.
  3. Sevha yeDHCP inogamuchira chikumbiro, inogadzira mhinduro uye inotumira kune relay device
  4. Chishandiso chekutumira chinoendesa mberi pakiti yekupindura kune mudziyo wekunyorera

Ehe, zvese hazvishande zviri nyore; iwe unofanirwa kugadzirisa yako network zvishandiso zvinoenderana.

Kuisa FreeRadius

Zvechokwadi, izvi zvinogona kuwanikwa neFreeRadius configuration settings, asi zvakaoma uye hazvina kujeka ... kunyanya paunoenda ikoko mushure meN mwedzi uye "zvose zvinoshanda." Naizvozvo, isu takasarudza kunyora yedu yekubvumidza module yeFreeRadius muPython. Isu tichatora mvumo data kubva kuMySQL dhatabhesi. Hapana chikonzero chekutsanangura chimiro chayo; zvakadaro, munhu wese achazvigadzira "zvavo." Kunyanya, ini ndakatora chimiro chinopihwa ne sql module yeFreeRadius, uye zvishoma yakachichinja nekuwedzera mac uye chiteshi chengarava kune mumwe nemumwe munyoreri, kuwedzera kune login-password.

Saka, kutanga, isa FreeRadius:

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

Muzvirongwa, sarudza kuisa:

Network marongero kubva kuFreeRadius kuburikidza neDHCP

Isu tinogadzira symlink kune python module (kureva "batidza" iyo):

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

Ngatiise imwe module yepython:

pip install mysql-connector

Mune iyo python module marongero eFreeRadius, iwe unofanirwa kutsanangura iyo module yekutsvaga nzira mune python_path kusiyanisa. Somuenzaniso, ndine izvi:

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"

Iwe unogona kutsvaga nzira nekutanga muturikiri wepython uye nekuisa mirairo:

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']
>

Kana iwe ukasatora danho iri, ipapo zvinyorwa zvakanyorwa mu python uye zvakatangwa neFreeRadius hazvizowane ma module akanyorwa mukupinza. Uye zvakare, iwe unofanirwa kusunungura mabasa ekufona mvumo uye accounting mumamodule marongero. Semuenzaniso, iyi module inoita seizvi:

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}

}

The work.py script (uye mamwe ose) inofanira kuiswa mukati /usr/local/etc/raddb/mods-config/python Ndine zvinyorwa zvitatu zvakazara.

work.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

Sezvauri kuona kubva kukodhi, isu tiri kuyedza kuona munyoreri tichishandisa nzira dzese dziripo neanonyoresa akero MAC kero kana Option 82 musanganiswa, uye kana izvi zvikasashanda, isu tinoburitsa yekare kero yeIP yakamboshandiswa kubva kune "muenzi. ” network. Chinosara ndechekugadzirisa script yakasarudzika mumasaiti-inogonesa folda, kuitira kuti mabasa anodiwa kubva kune python script anozununguka panguva dzakatarwa. Muchokwadi, zvakakwana kuunza faira kune fomu:

Default

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
}
}

Ngatiedzei kuimhanyisa uye tione zvinouya mudebug log:

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

Chii chimwe. Kana uchimisa FreeRadius, zviri nyore kuyedza mashandiro ayo uchishandisa radclient utility. Semuenzaniso mvumo:

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

Kana 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

Ndinoda kukunyevera kuti hazvibviri zvachose kushandisa chirongwa chakadaro uye zvinyorwa "pasina shanduko" pachiyero che "industrial". Zvirinani zvinoonekwa:

  • zvinokwanisika "kunyepera" iyo MAC kero. Zvakakwana kuti munyoreri anyore MAC yemumwe munhu uye pachava nematambudziko
  • pfungwa yekuburitsa manetwork evaenzi inodarika kushoropodzwa. Iko hakuna kana cheki "pamwe kune vatove nevatengi vane imwe IP kero?"

Iyi ingori "cookie-cutter solution" yakagadzirirwa kushanda chaizvo mumamiriro angu, hapana chimwe. Usatonge zvakasimba 😉

Source: www.habr.com

Voeg