1. 程式人生 > >0816關於MySQL的審計 init-connect+binlog實現用戶操作追蹤

0816關於MySQL的審計 init-connect+binlog實現用戶操作追蹤

database 復用 time utf ant 很大的 uri sin 超級用戶

轉自:http://blog.sina.com.cn/s/blog_605f5b4f01013xkv.html

mysql 用init-connect+binlog實現用戶操作追蹤 做access 的ip的log 記錄


在MYSQL中,每個連接都會先執行init-connect,進行連接的初始化。我們可以在這裏獲取用戶的登錄名稱和thread的ID值。然後配合binlog,就可以追蹤到每個操作語句的操作時間,操作人等。實現審計。 實驗過程:
1:創建登錄日誌庫,登錄日誌表
  1. CREATE DATABASE `accesslog`;
  2. USE `accesslog`;
  3. CREATE TABLE `accesslog`
  4. (
  5. `id` int(11) NOT NULL AUTO_INCREMENT,
  6. `thread_id` int(11) DEFAULT NULL, #線程ID,這個值很重要
  7. `log_time` timestamp NOT NULL DEF AULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, #登錄時間
  8. `localname` varchar(30) DEFAULT NULL, #登錄名稱帶IP
  9. `matchname` varchar(30) DEFAULT NULL, #登錄用戶,user的全稱
  10. PRIMARY KEY (`id`)
  11. ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
2:在配置文件中配置init-connect參數。登錄時插入日誌表。如果這個參數是個錯誤的SQL語句,登錄就會失敗。
Linux 下的配置文件為 my.cnf,windows下位my.ini
  1. init-connect=‘insert into accesslog.accesslog values(null,connection_id(),now(),user(),current_user());‘ -- 註意修改對應SQL
重啟service mysqld 以使其配置文件生效


3:創建普通用戶,不能有super權限。init-connect對具有super權限的用戶不起作用。同時此用戶必須至少要有對accesslog.accesslog表的INSERT權限,如果沒有,登錄後的任何操作都會導致MYSQL登錄失敗。
  1. grant insert,select,update on *.* to [email protected]; #帶INSERT權限
  2. grant select,update on *.* to [email protected]; #不帶INSERT權限
4:SESSION1登錄,並查看日誌
  1. mysql> select * FROM accesslog.accesslog;
  2. +----+-----------+---------------------+-----------------+-----------------+
  3. | id | thread_id | log_time | localname | matchname |
  4. +----+-----------+---------------------+-----------------+-----------------+
  5. | 1 | 65 | 2011-03-11 19:18:25 | [email protected] | [email protected] |
  6. +----+-----------+---------------------+-----------------+-----------------+
  7. 1 row in set (0.00 sec)
  8. mysql> show processlist;# 當前運行的threadId
  9. +----+-------+----------------+------+---------+------+-------+------------------+
  10. | Id | User | Host | db | Command | Time | State | Info |
  11. +----+-------+----------------+------+---------+------+-------+------------------+
  12. | 65 | user1 | localhost:1339 | NULL | Query | 0 | NULL | show processlist |
  13. +----+-------+----------------+------+---------+------+-------+------------------+
  14. 1 row in set (0.00 sec)
  15. mysql>
5:再用user2登錄
  1. D:\mysql6\bin>mysql -uuser2 -p
  2. Enter password:
  3. Welcome to the MySQL monitor. Commands end with ; or \g.
  4. Your MySQL connection id is 76
  5. Server version: 5.1.45-community-log
  6. Type ‘help;‘ or ‘\h‘ for help. Type ‘\c‘ to clear the current input statement.
  7. mysql> select * FROM accesslog.accesslog;
  8. ERROR 2006 (HY000): MySQL server has gone away
  9. No connection. Trying to reconnect...
  10. Connection id: 77
  11. Current database: *** NONE ***
  12. ERROR 2013 (HY000): Lost connection to MySQL server during query
  13. mysql> select * FROM accesslog.accesslog;
  14. ERROR 2006 (HY000): MySQL server has gone away
  15. No connection. Trying to reconnect...
  16. Connection id: 78
  17. Current database: *** NONE ***
看下錯誤日誌
如果沒有對log-bin指定log文件,默認在 /var/lib/mysql目錄下以mysqld-bin.00000X等作為名稱。而 mysqld-bin.index則記錄了所有的log的文件名稱
使用時則使用mysqlbinlog /var/lib/mysql|grep -B "表名"等來追蹤database的操作。

  1. 110311 19:23:47 [Warning] Aborted connection 77 to db: ‘unconnected‘ user: ‘user2‘ host: ‘localhost‘ (init_connect command failed)
  2. 110311 19:23:47 [Warning] INSERT command denied to user [email protected] for table ‘accesslog‘
  3. 110311 19:23:53 [Warning] Aborted connection 78 to db: ‘unconnected‘ user: ‘user2‘ host: ‘localhost‘ (init_connect command failed)
  4. 110311 19:23:53 [Warning] INSERT command denied to user [email protected] for table ‘accesslog‘
6:下面以USER1登錄,並做一個INSERT操作,查看日誌文件。
  1. mysql> insert into t3 values(10,10,‘2011-10-10 00:00:00‘);
  2. Query OK, 1 row affected (0.00 sec)
  3. mysql> show processlist;
  4. +----+-------+----------------+-----------+---------+------+-------+------------------+
  5. | Id | User | Host | db | Command | Time | State | Info |
  6. +----+-------+----------------+-----------+---------+------+-------+------------------+
  7. | 69 | user1 | localhost:1439 | accesslog | Query | 0 | NULL | show processlist |
  8. +----+-------+----------------+-----------+---------+------+-------+------------------+
  9. 1 row in set (0.00 sec)
  10. mysql> select * from accesslog.accesslog;
  11. +----+-----------+---------------------+-----------------+-----------------+
  12. | id | thread_id | log_time | localname | matchname |
  13. +----+-----------+---------------------+-----------------+-----------------+
  14. | 1 | 65 | 2011-03-11 19:18:25 | [email protected] | [email protected] |
  15. | 2 | 91 | 2011-03-11 19:28:33 | [email protected] | [email protected] |
  16. | 3 | 2 | 2011-03-11 19:31:49 | [email protected] | [email protected] |
  17. | 4 | 2 | 2000-10-10 10:10:10 | [email protected] | [email protected] |
  18. | 5 | 21 | 2000-10-10 11:11:11 | [email protected] | root@% |
  19. | 6 | 69 | 2011-03-12 21:35:43 | [email protected] | [email protected] |
  20. +----+-----------+---------------------+-----------------+-----------------+
  21. 6 rows in set (0.01 sec)
查看日誌文件的內容
  1. # at 340
  2. #110312 21:36:01 server id 1 end_log_pos 453 Query thread_id=69 exec_time=0 error_code=0
  3. use text;
  4. SET TIMESTAMP=1299936961;
  5. insert into t3 values(10,10,‘2011-10-10 00:00:00‘)
  6. ;
  7. # at 453
thread_id=69
在日誌表裏記錄的和日誌文件裏面記錄的相同。可以通過這個thread_id來追蹤到是誰,什麽時間,做了什麽操作。

3. Q&A

Q:使用init-connect會影響服務器性能嗎?

A:理論上,只會在用戶每次連接時往數據庫裏插入一條記錄,不會對數據庫產生很大影響。除非連接頻率非常高(當然,這個時候需要註意的就是如何進行連接復用和控制,而非是不是要用這種方法的問題了)

Q:access-log表如何維護?

A: 由於是一個log系統,推薦使用archive存儲引擎,有利於數據厄壓縮存放。如果數據庫連接數量很大的話,建議一定時間做一次數據導出,然後清表。

Q:表有其他用途麽?

A:有!access-log表當然不只用於審計,當然也可以用於對於數據庫連接的情況進行數據分析,例如每日連接數分布圖等等,只有想不到沒有做不到。

Q:會有遺漏的記錄嗎?

A:會的,init-connect 是不會在super用戶登錄時執行的。所以access-log裏不會有數據庫超級用戶的記錄,這也是為什麽我們不主張多個超級用戶,並且多人使用的原因

-- 這個跟權限有關

0816關於MySQL的審計 init-connect+binlog實現用戶操作追蹤