radius挑战认证

匿名 (未验证) 提交于 2019-12-02 23:57:01

做基于radius的双因子认证,但未找到一个方便测试的radius服务器,网上找了freeradius,折腾了很久没有搞定,想了想是否可以自己写一个,只要有一个radius的雏形,发一个challenge应该是比较简单的。

pyrad

找到了pyrad,这个是提供一个radius的基本操作的库,提供了客户端和服务端的库,试了一下服务端,windows上起不来,于是只能从头写。
基本思路是自己创建一个udp socket,进行监听,收到报文后,使用pyrad进行解析,然后做身份验证的处理,再用pyrad创建回应消息。
代码如下:

from pyrad import * import socket import pyrad.host import random  BUFSIZE = 1024 KEY = b"testing123" CHALLENGE = "test2"  class RadiusServer(pyrad.host.Host):     def __init__(self):         dict = pyrad.dictionary.Dictionary("dictionary.rfc2865") #从freeradius中搞一个通用的字典使用         pyrad.host.Host.__init__(self, dict=dict)      def get_challenge(self): #产生一个4字节的随机挑战码         challenge = ""         challenge = challenge + str(chr(random.randint(65,90)))         challenge = challenge + str(chr(random.randint(65,90)))         challenge = challenge + str(chr(random.randint(65,90)))         challenge = challenge + str(chr(random.randint(65,90)))         return challenge      def check_pass(self, radpkt): #检查用户名密码,这里简单处理一下,如果密码是test则发起挑战,如果输入正确的挑战码,回应正确,否则失败         global CHALLENGE         print("check user")         if radpkt.PwCrypt(CHALLENGE) == radpkt["User-Password"][0]:             radpkt.code = packet.AccessAccept             CHALLENGE = self.get_challenge() #挑战码使用过后就更换掉             print("AccessAccept")         elif radpkt.PwCrypt("test") == radpkt["User-Password"][0]:             radpkt.code = packet.AccessChallenge             CHALLENGE = self.get_challenge()             radpkt.AddAttribute("Reply-Message", CHALLENGE) #把挑战码发给客户端             print("AccessChallenge, please input", CHALLENGE)         else:             radpkt.code = packet.AccessReject             print("AccessReject")      def get_pkt(self, pkt):         get_pw = None         get_name = None         radpkt = self.CreateAuthPacket(packet=pkt) #解析请求报文         print("code:", radpkt.code)         print("authenticator:", radpkt.authenticator)         print("id:", radpkt.id)         #radpkt.code = packet.AccessChallenge         radpkt.secret = KEY          for key in radpkt.keys():             print(key, radpkt[key])             if key == "User-Password":                 get_pw = 1             if key == "User-Name":                 get_name = 1                  if 1 == get_pw and 1 == get_name:             self.check_pass(radpkt)          return radpkt.ReplyPacket()  ip_port = ('', 1812) server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  # udp协议 server.bind(ip_port)   while True:     data,client_addr = server.recvfrom(BUFSIZE)     srv = RadiusServer()     reply = srv.get_pkt(data)     server.sendto(reply, client_addr)

测试,采用freeradius中自带的ratest进行测试。

使用第一次验证用的密码进行请求:   C:\FreeRADIUS.net\bin>radclient.exe -d ..\etc\raddb -f radtest.txt -x -s 127.1 auth testing123 Sending Access-Request of id 172 to 127.0.0.1 port 1812         User-Name = "admin"         User-Password = "test"         NAS-IP-Address = 127.0.0.1         NAS-Port = 123 rad_recv: Access-Challenge packet from host 127.0.0.1:1812, id=172, length=63         User-Name = "admin"         User-Password = "test"         NAS-IP-Address = 127.0.0.1         NAS-Port = 123         Reply-Message = "PFJT"             Total approved auths:  1              Total denied auths:  0                Total lost auths:  0 PS C:\FreeRADIUS.net\bin> .\radtest.bat  收到了应答,里面带了挑战码  #使用挑战码去请求:   C:\FreeRADIUS.net\bin>radclient.exe -d ..\etc\raddb -f radtest.txt -x -s 127.1 auth testing123 Sending Access-Request of id 0 to 127.0.0.1 port 1812         User-Name = "admin"         User-Password = "PFJT"         NAS-IP-Address = 127.0.0.1         NAS-Port = 123 rad_recv: Access-Accept packet from host 127.0.0.1:1812, id=0, length=57         User-Name = "admin"         User-Password = "PFJT"         NAS-IP-Address = 127.0.0.1         NAS-Port = 123             Total approved auths:  1              Total denied auths:  0                Total lost auths:  0 PS C:\FreeRADIUS.net\bin> .\radtest.bat   第二次使用挑战码请求,挑战码已经失效,应该请求失败: C:\FreeRADIUS.net\bin>radclient.exe -d ..\etc\raddb -f radtest.txt -x -s 127.1 auth testing123 Sending Access-Request of id 196 to 127.0.0.1 port 1812         User-Name = "admin"         User-Password = "PFJT"         NAS-IP-Address = 127.0.0.1         NAS-Port = 123 rad_recv: Access-Reject packet from host 127.0.0.1:1812, id=196, length=57         User-Name = "admin"         User-Password = "PFJT"         NAS-IP-Address = 127.0.0.1         NAS-Port = 123             Total approved auths:  0              Total denied auths:  1                Total lost auths:  0

再改进一下,回应的报文中少点请求的属性。

from pyrad import * import socket import pyrad.host import random  BUFSIZE = 1024 KEY = b"testing123" CHALLENGE = "test2"  class RadiusServer(pyrad.host.Host):     def __init__(self):         dict = pyrad.dictionary.Dictionary("dictionary.rfc2865") #从freeradius中搞一个通用的字典使用         pyrad.host.Host.__init__(self, dict=dict)      def get_challenge(self): #产生一个4字节的随机挑战码         challenge = ""         challenge = challenge + str(chr(random.randint(65,90)))         challenge = challenge + str(chr(random.randint(65,90)))         challenge = challenge + str(chr(random.randint(65,90)))         challenge = challenge + str(chr(random.randint(65,90)))         return challenge      def check_pass(self, radpkt, get_pw): #检查用户名密码,这里简单处理一下,如果密码是test则发起挑战,如果输入正确的挑战码,回应正确,否则失败         global CHALLENGE         print("check user")         pwd = ""                  if 1 == get_pw:             pwd = radpkt["User-Password"][0]                              if radpkt.PwCrypt(CHALLENGE) == pwd:                 radpkt.code = packet.AccessAccept                 CHALLENGE = self.get_challenge() #挑战码使用过后就更换掉                 print("AccessAccept")             elif radpkt.PwCrypt("test") == pwd:                 radpkt.code = packet.AccessChallenge                 CHALLENGE = self.get_challenge()                 radpkt.AddAttribute("Reply-Message", CHALLENGE) #把挑战码发给客户端                 print("AccessChallenge, please input", CHALLENGE)             else:                 radpkt.code = packet.AccessReject                 print("AccessReject")                          def get_pkt(self, pkt):         get_pw = None         get_name = None         radpkt = self.CreateAuthPacket(packet=pkt) #解析请求报文         print("code:", radpkt.code)         print("authenticator:", radpkt.authenticator)         print("id:", radpkt.id)         #radpkt.code = packet.AccessChallenge         radpkt.secret = KEY          for key in radpkt.keys():             print(key, radpkt[key])             if key == "User-Password":                 get_pw = 1             if key == "User-Name":                 get_name = 1                  if 1 == get_pw and 1 == get_name:             self.check_pass(radpkt, get_pw)                      reply = radpkt.CreateReply()                  for key in radpkt.keys():             if key == "User-Name":                 reply.AddAttribute("User-Name", radpkt["User-Name"][0])              if key == "Reply-Message":                 reply.AddAttribute("Reply-Message", radpkt["Reply-Message"][0])              if key == "NAS-IP-Address":                 reply.AddAttribute("NAS-IP-Address", radpkt["NAS-IP-Address"][0])              #reply.source = radpkt.source             reply.code = radpkt.code          return reply.ReplyPacket()  ip_port = ('', 1812) server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  # udp协议 server.bind(ip_port)   while True:     data,client_addr = server.recvfrom(BUFSIZE)     srv = RadiusServer()     reply = srv.get_pkt(data)     server.sendto(reply, client_addr)

测试:

PS C:\FreeRADIUS.net\bin> .\radclient.exe -d ..\etc\raddb -f radtest.txt -x -s 127.0.0.1 auth testing123 Sending Access-Request of id 48 to 127.0.0.1 port 1812         User-Name = "admin"         User-Password = "test"         NAS-IP-Address = 127.0.0.1         NAS-Port = 123 rad_recv: Access-Challenge packet from host 127.0.0.1:1812, id=48, length=39         User-Name = "admin"         NAS-IP-Address = 127.0.0.1         Reply-Message = "UTJG"             Total approved auths:  1              Total denied auths:  0                Total lost auths:  0 PS C:\FreeRADIUS.net\bin> .\radclient.exe -d ..\etc\raddb -f radtest.txt -x -s 127.0.0.1 auth testing123 Sending Access-Request of id 228 to 127.0.0.1 port 1812         User-Name = "admin"         User-Password = "UTJG"         NAS-IP-Address = 127.0.0.1         NAS-Port = 123 rad_recv: Access-Accept packet from host 127.0.0.1:1812, id=228, length=33         User-Name = "admin"         NAS-IP-Address = 127.0.0.1             Total approved auths:  1              Total denied auths:  0                Total lost auths:  0
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!