radius挑戰認證+對接華為防火牆實現SSLvpn 雙因子認證1


近日公司有個需求,需要對使用vpn的用戶進行二次認證,要求使用動態碼進行驗證,我再網上搜了很多資料都沒有找到合適的解決方案。

使用第三方設備吧,費用太貴,不是很值得。 正好博客園有位大佬之前趟過坑,文章給了我思路。他的博文地址是:

https://www.cnblogs.com/luckpiky/p/11441916.html

廢話不多說,上我修改過的代碼。

環境說明:

py3.8   數據庫mysql (存radius第一次認證的密碼),安裝pyrad插件

修改過的
 1  # -*- coding: UTF-8 -*-
 2  2 from pyrad import *
 3  3 import socket
 4  4 import pyrad.host
 5  5 import random
 6  6 import pymysql
 7  7 
 8  8 BUFSIZE = 1024
 9  9 KEY = b"test123456789"
10 10 CHALLENGE = "666" #挑戰碼初始為666
11 11 
12 12 class RadiusServer(pyrad.host.Host):
13 13     def __init__(self):
14 14         dict = pyrad.dictionary.Dictionary("dictionary") #從通用的字典使用
15 15         pyrad.host.Host.__init__(self, dict=dict)
16 16 
17 17     def get_challenge(self): #產生一個4字節的隨機挑戰碼
18 18         challenge = ""  #初始化挑戰碼
19 19         challenge = challenge + str(chr(random.randint(65,90)))
20 20         challenge = challenge + str(chr(random.randint(65,90)))
21 21         challenge = challenge + str(chr(random.randint(65,90)))
22 22         challenge = challenge + str(chr(random.randint(65,90)))
23 23         return challenge
24 24     def check_pass(self, radpkt): 
25 25         global CHALLENGE
26 26         print("檢查用戶名稱")
27 27         conn=pymysql.connect(
28 28             host='x.x.x.x',     #數據庫的ip地址
29 29             port=3306,          #數據庫端口
30 30             user='root',        #數據庫用戶名
31 31             password='12345678',#數據庫密碼
32 32             db='test',          #數據庫表名
33 33             charset='utf8'      #數據庫編碼
34 34         )
35 35          # 拿到游標
36 36         cursor=conn.cursor()
37 37         user=radpkt["User-Name"][0]
38 38         print(user)
39 39         password=radpkt["User-Password"][0]
40 40         print(password)
41 41          # 執行sql語句 
42 42         sql='select * from test where user = "%s" '% (user)
43 44         res=cursor.execute(sql)
44 46         pwd=cursor.fetchall()
45 48         cursor.close()
46 49         conn.close()
47 50 
48 52         if radpkt.PwCrypt(CHALLENGE) == radpkt["User-Password"][0]:
49 53             radpkt.code = packet.AccessAccept
50 54             CHALLENGE = self.get_challenge() #挑戰碼使用過后就更換掉
51 55             print("AccessAccept")
52 56         elif radpkt.PwCrypt(pwd[0][1]) == radpkt["User-Password"][0]:
53 57             radpkt.code = packet.AccessChallenge
54 58             CHALLENGE = self.get_challenge()
55 59             radpkt.AddAttribute("Reply-Message","Enter Token Code") 
56 60             radpkt.AddAttribute("State",b'0x123231')#隨機生成一個state,此處簡單寫的,可以仿照挑戰碼寫一個類似的
57 61             print("AccessChallenge, please input", CHALLENGE)
58 62         else:
59 63             radpkt.code = packet.AccessReject
60 64             print("AccessReject")
61 65 
62 66     def get_pkt(self, pkt):
63 67         get_pw = None
64 68         get_name = None
65 69         radpkt = self.CreateAuthPacket(packet=pkt) #解析請求報文
66 70         #radpkt.code = packet.AccessChallenge
67 71         radpkt.secret = KEY
68 72 
69 73         print("輸出相關參數")
70 74         for key in radpkt.keys():        
71 75             print(key, radpkt[key])
72 76             if key == "User-Password":
73 77                 get_pw = 1
74 78             if key == "User-Name":
75 79                 get_name = 1
76 80         
77 81         if 1 == get_pw and 1 == get_name:
78 82             self.check_pass(radpkt)
79 83              
80 84         return radpkt.ReplyPacket()
81 85      
82 87 ip_port = ('', 1812)
83 88 server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  # udp協議
84 89 server.bind(ip_port)
85 90 
86 91 
87 92 while True:
88 93     data,client_addr = server.recvfrom(BUFSIZE)
89 94     srv = RadiusServer()
90 95     reply = srv.get_pkt(data)
91 96     server.sendto(reply, client_addr)

驗證過程。打開ssl vpn的登錄頁面 使用數據庫表的用戶名和密碼登錄

python服務端 動態碼

輸入動態碼

登錄成功0

寫在后面:

當然這樣僅僅是雙因子認證成功而已,我們可以在結合企業微信或者釘釘機器人之類的工具,把生成的動態碼 即時的發給vpn的使用者。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM