中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么通過MySQL-Proxy實現數據庫的認證、授權與審計

發布時間:2021-12-18 15:32:13 來源:億速云 閱讀:198 作者:柒染 欄目:數據安全

怎么通過MySQL-Proxy實現數據庫的認證、授權與審計,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

0x00 前言

總來的話數據庫里面的賬號就會越來越多,賬號授權也是一個蛋疼的工作。特別是還會有“mysql從刪庫到跑路”的問題,員工離職刪除賬號也會十分的麻煩。對于財大氣粗的財閥來說這個問題很好解決,買一套設備就好了,但是對于創業公司要力爭做到“零元黨”,不然也沒辦法完全體現出自己的價值。

0x01 調研

最初的想法是對開源mysql的代理工具做一次二次開發,于是乎開始搜集類似工具的資料。無意中發現mysql-proxy居然預留了6個鉤子允許用戶通過Lua腳本去調用他們,也就是說我們可以自行編寫Lua腳本來掌握“用戶的命運”。

connect_server()                  當代理服務器接受到客戶端連接請求時會調用該函數

read_handshake()               當mysql服務器返回握手相應時會被調用

read_auth()                         當客戶端發送認證信息時會被調用

read_auth_result(aut)           當mysql返回認證結果時會被調用

read_query(packet)             當客戶端提交一個sql語句時會被調用

read_query_result(inj)          當mysql返回查詢結果時會被調用

顯然,通過上述的read_auth和read_query兩個鉤子函數,我們可以實現對mysql數據庫的認證、授權和審計的工作。

0x02 設計

我們的目標是認證、授權和審計,那么read_auth函數可以實現認證和授權,read_query可以實現審計的功能。read_query比較容易實現,只需要get到用戶發來的sql語句寫到消息隊列里就好了,我這里就簡單地寫到redis的list中。

read_auth函數就要相對復雜些,不僅需要對用戶提交的一次性password進行校驗,還需要讀取授權信息,讓用戶登錄到mysql的時候華麗的變身成為我們指定的身份。

怎么通過MySQL-Proxy實現數據庫的認證、授權與審計

1.用戶訪問Openresty,后端的lua腳本會調用公司內部使用的im軟件的消息接口,將生成的一次性口令發送給用戶。與此同時,也會將該口令寫入redis。

2.用戶使用mysql客戶端連接指定的mysql-proxy,此時進入read_auth鉤子函數,先對用戶提交的口令進行確認。然后會去redis請求當前數據庫對應developer、master、owner三個role的授權名單,查看三個名單中是否含有當前用戶,如果有則將用戶以其對應的role跳轉到數據庫上。

3.當認證授權成功結束后,用戶通過上一步授權的role來訪問后端mysql,并且執行的所有sql語句都會進入read_query鉤子函數被記錄到redis的隊列中。

0x03 代碼

 local password =assert(require("mysql.password"))
local proto =assert(require("mysql.proto"))
assert(require("redis"))
--字符串切割
function string:split(sep) 
local sep, fields = sep or ":", {} 
local pattern = string.format("([^%s]+)", sep) 
self:gsub(pattern, function (c) fields[#fields + 1] = c end) 
return fields 
end 
function read_query( packet )
if packet:byte() == proxy.COM_QUERY then
local con = proxy.connection
local redis = Redis.connect('your_redis_ip',6379)
--獲取ip對應的域名
redis:select('3')
local domain = redis:get(con.server.dst.name:split(':')[1])
--將執行的sql語句放入redis隊列中
redis:select('2')
redis:lpush('mysql_command_queue',os.date("%Y-%m-%d%H:%M:%S",os.time())
.. " " .. con.client.src.address .. "" .. con.client.username .. " " ..
domain .. " [" ..packet:sub(2) .. "]")
if packet:sub(2) == "SELECT 1" then
proxy.queries:append(1, packet)
end
end
end
function read_auth()
local names = {}
--developer、master、owner三個角色權限逐級增大
local roles = {[1] = 'developer',[2] = 'master',[3] = 'owner'}
local con = proxy.connection
local s = con.server
local role = ''
--認證
local redis = Redis.connect('your_redis_ip', 6379)
local pass = redis:get(con.client.username)
ifpassword.scramble(s.scramble_buffer, password.hash(pass)) ~=con.client.scrambled_password then
--認證失敗返回錯誤信息
proxy.response.type = proxy.MYSQLD_PACKET_ERR
proxy.response.errmsg ="Password error!"
return proxy.PROXY_SEND_RESULT
end
redis:del(con.client.username)
--獲取ip對應的域名
redis:select('3')
local domain = redis:get(con.server.dst.name:split(':')[1])
redis:select('1')
--獲取用戶對于當前數據庫的role
for i,v inipairs(roles) do
--查詢“domain:role”返回相應的名單并將名單切割為table
names = redis:get(domain .. ":" .. v):split(',')
for k,name in ipairs(names) do
if name == con.client.username then
role = v
break
end
end
end
--無授權信息返回錯誤信息
if role == '' then
proxy.response.type = proxy.MYSQLD_PACKET_ERR
proxy.response.errmsg = "Unauthorized access!"
return proxy.PROXY_SEND_RESULT
end
--最新mysql-proxy加入的新屬性
local protocol_41_default_capabilities = 8 + 512 + 32768
proxy.queries:append(1, 
proto.to_response_packet({ 
username = role,  
response = password.scramble(s.scramble_buffer, password.hash(“your_role_password”)),
--最新mysql-proxy加入的新屬性
server_capabilities=protocol_41_default_capabilities
}) 
)
return proxy.PROXY_SEND_QUERY
end

0x04 效果

[root@ip-172-31-24-123 ~]# mysql -u test -h your_mysql-proxy_ip -P your_mysql-proxy_port-pEnter password:Welcome to the MySQL monitor.  Commands end with ; or \g.Your MySQL connection id is 30341Server version: 5.7.12 MySQL CommunityServer (GPL)Copyright (c) 2000, 2018, Oracle and/or itsaffiliates. All rights reserved.Oracle is a registered trademark of OracleCorporation and/or itsaffiliates. Other names may be trademarksof their respectiveowners.Type 'help;' or '\h' for help. Type '\c' toclear the current input statement.mysql> select user();+-------------------------+| user()                  |+-------------------------+| developer@your_ip|+-------------------------+1 row in set (0.01 sec)

顯然,使用用戶名test登錄mysql-proxy,最終跳轉到mysql上時用戶已經變為developer。

0x05 總結

用于非業務場景連接數據庫,比如開發運維人員在公司連接數據庫。

管理腳本需要監控每個mysql-proxy進程的狀態,負責他們的啟動和停止,以及將他們的域名解析為ip存入redis中。

授權腳本讀取一個yaml文件,將文件中的授權規則同步到redis中。

每個數據庫中都只需要新建developer、master、owner三個賬號,yaml配置文件中的內容決定用戶使用以上哪種role登錄到mysql。

mysql-proxy需要使用源碼編譯安裝。

啟動mysql-proxy的命令為: 

mysql-proxy/bin/mysql-proxy--proxy-address=mysql-proxy_ip:mysql-proxy_port --proxy-backend-addresses=mysql_ip:mysql_port--max-open-files=1024 --user=root --log-file=/var/log/mysql-proxy--log-level=debug --proxy-lua-script=your_lua_file &

關于怎么通過MySQL-Proxy實現數據庫的認證、授權與審計問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

同心县| 武冈市| 洛隆县| 清新县| 中西区| 东宁县| 金门县| 五大连池市| 屏东市| 镇坪县| 望谟县| 基隆市| 台江县| 东源县| 得荣县| 淄博市| 北宁市| 策勒县| 章丘市| 兰西县| 罗平县| 灯塔市| 衡阳市| 遵义县| 沛县| 林口县| 南木林县| 如皋市| 金寨县| 柳州市| 平昌县| 江川县| 克拉玛依市| 河南省| 阿巴嘎旗| 澳门| 温宿县| 甘德县| 大悟县| 霸州市| 千阳县|