在前面兩篇文章中詳細介紹了pptp ***的安裝與使用,以及如何配置用戶認證存入mysql數據庫。本文將在前面兩篇文章的基礎上介紹如何對用戶的流量作限制,同時限制相同帳號的用戶,同一時刻的在線數爲1。html
前文傳送門地址:mysql
PPTP-×××部署與簡單使用 http://ylw6006.blog.51cto.com/470441/1794577sql
PPTP-×××使用mysql進行用戶登陸認證 http://ylw6006.blog.51cto.com/470441/1795201數據庫
1、向mysql庫表中插入基礎數據網絡
mysql> use radius mysql> INSERT INTO radgroupreply (groupname,attribute,op,VALUE) VALUES ('user','Auth-Type',':=','Local'); mysql> INSERT INTO radgroupreply (groupname,attribute,op,VALUE) VALUES ('user','Service-Type',':=','Framed-User'); mysql> INSERT INTO radgroupreply (groupname,attribute,op,VALUE) VALUES ('user','Framed-IP-Address',':=','255.255.255.255'); mysql> INSERT INTO radgroupreply (groupname,attribute,op,VALUE) VALUES ('user','Framed-IP-Netmask',':=','255.255.255.0'); mysql> INSERT INTO radgroupreply (groupname,attribute,op,VALUE) VALUES ('user','Acct-Interim-Interval',':=','600'); mysql> INSERT INTO radgroupreply (groupname,attribute,op,VALUE) VALUES ('user','Max-Monthly-Traffic',':=','20480'); mysql> INSERT INTO radgroupcheck (groupname,attribute,op,VALUE) VALUES ('user','Simultaneous-Use',':=','1');
acct-interim-interval是計算流量的間隔(600秒),意味着每隔10分鐘記錄當前流量;session
Max-Monthly-Traffic是每個月最大流量,這裏是20G(單位是M);socket
radgroupcheck表的Simultaneous-Use表示單個用戶的同時鏈接數目;
ide
這裏要格外注意的是,許多網絡上的文章介紹Max-Monthly-Traffic單位爲字節,數值爲5368709102,換算一下大概5G左右,而若是咱們也精確到字節,數值設爲20G,也就是21474836480,則用戶撥入進行身份驗證的時候將會報錯。於是這次咱們將流量限制的精度單位修改成M。詳細可參考以下連接介紹:http://www.xj123.info/2856.html
oop
2、修改配置文件post
1、修改/etc/raddb/sites-enabled/default文件,添加流量限制的reject條件
# vi /etc/raddb/sites-enabled/default #找到authorize一節插入以下內容: update request { Group-Name := "%{sql:SELECT groupname FROM radusergroup WHERE username='%{User-Name}' ORDER BY priority}" } if ("%{sql: SELECT SUM(acctinputoctets+acctoutputoctets) div 1048576 FROM radacct WHERE username='%{User-Name}' AND date_format(acctstarttime, '%Y-%m-%d') >= date_format(now(),'%Y-%m-01') AND date_format(acctstoptime, '%Y-%m-%d') <= last_day(now());}" >= "%{sql: SELECT value FROM radgroupreply WHERE groupname='%{Group-Name}' AND attribute='Max-Monthly-Traffic';}") { reject }
2、因爲使用了非內置的attribute Max-Monthly-Traffic,因此須要在/etc/raddb/dictionary裏面定義
# tail -1 /etc/raddb/dictionary ATTRIBUTE Max-Monthly-Traffic 3003 integer
3、修改/etc/raddb/sql/mysql/dialup.conf文件,開啓在線用戶數檢查
# vi /etc/raddb/sql/mysql/dialup.conf sql_user_name = "%{%{Stripped-User-Name}:-%{%{User-Name}:-DEFAULT}}" #sql_user_name = "%{User-Name}" #註釋掉這行 # Uncomment simul_count_query to enable simultaneous use checking simul_count_query = "SELECT COUNT(*) \ FROM ${acct_table1} \ WHERE username = '%{SQL-User-Name}' \ AND acctstoptime IS NULL" simul_verify_query = "SELECT radacctid, acctsessionid, username, \ nasipaddress, nasportid, framedipaddress, \ callingstationid, framedprotocol \ FROM ${acct_table1} \ WHERE username = '%{SQL-User-Name}' \ AND acctstoptime IS NULL"
3、重啓服務
# /etc/init.d/radiusd stop
# /etc/init.d/pptpd restart
4、測試
1、將rediusd服務運行在debug模式下,進行撥號測試,主要測試流量控制!
#radiusd -X
經過上面能夠看到當前的用戶流量消耗爲2M,限制流量的值爲20480M。
於是在/etc/raddb/sites-enabled/default文件,判斷流量限制的reject條件的結果爲false,用戶能夠經過驗證,完成撥號!下面是詳細的撥號日誌:
rad_recv: Access-Request packet from host 127.0.0.1 port 49226, id=94, length=150 Service-Type = Framed-User Framed-Protocol = PPP User-Name = "ptest1" MS-CHAP-Challenge = 0x6716c32940f1c84ad213d2d52df1712d MS-CHAP2-Response = 0x2400c77c090296803fb3c0822b8c679547f000000000000000001eb41fe8e518c1f756fb5d9d5904ddb8dc1fe271e98aa055 Calling-Station-Id = "27.151.123.121" NAS-IP-Address = 127.0.0.1 NAS-Port = 0 # Executing section authorize from file /etc/raddb/sites-enabled/default +group authorize { ++update request { sql_xlat expand: %{Stripped-User-Name} -> ... expanding second conditional expand: %{User-Name} -> ptest1 expand: %{%{User-Name}:-DEFAULT} -> ptest1 expand: %{%{Stripped-User-Name}:-%{%{User-Name}:-DEFAULT}} -> ptest1 sql_set_user escaped user --> 'ptest1' expand: SELECT groupname FROM radusergroup WHERE username='%{User-Name}' ORDER BY priority -> SELECT groupname FROM radusergroup WHERE username='ptest1' ORDER BY priority rlm_sql (sql): Reserving sql socket id: 30 sql_xlat finished rlm_sql (sql): Released sql socket id: 30 expand: %{sql:SELECT groupname FROM radusergroup WHERE username='%{User-Name}' ORDER BY priority} -> user ++} # update request = noop ++? if ("%{sql: SELECT SUM(acctinputoctets+acctoutputoctets) div 1048576 FROM radacct WHERE username='%{User-Name}' AND date_format(acctstarttime, '%Y-%m-%d') >= date_format(now(),'%Y-%m-01') AND date_format(acctstoptime, '%Y-%m-%d') <= last_day(now());}" >= "%{sql: SELECT value FROM radgroupreply WHERE groupname='%{Group-Name}' AND attribute='Max-Monthly-Traffic';}") sql_xlat expand: %{Stripped-User-Name} -> ... expanding second conditional expand: %{User-Name} -> ptest1 expand: %{%{User-Name}:-DEFAULT} -> ptest1 expand: %{%{Stripped-User-Name}:-%{%{User-Name}:-DEFAULT}} -> ptest1 sql_set_user escaped user --> 'ptest1' expand: SELECT SUM(acctinputoctets+acctoutputoctets) div 1048576 FROM radacct WHERE username='%{User-Name}' AND date_format(acctstarttime, '%Y-%m-%d') >= date_format(now(),'%Y-%m-01') AND date_format(acctstoptime, '%Y-%m-%d') <= last_day(now()); -> SELECT SUM(acctinputoctets+acctoutputoctets) div 1048576 FROM radacct WHERE username='ptest1' AND date_format(acctstarttime, '2016-06-30') >= date_format(now(),'2016-06-01') AND date_format(acctstoptime, '2016-06-30') <= last_day(now()); rlm_sql (sql): Reserving sql socket id: 29 sql_xlat finished rlm_sql (sql): Released sql socket id: 29 expand: %{sql: SELECT SUM(acctinputoctets+acctoutputoctets) div 1048576 FROM radacct WHERE username='%{User-Name}' AND date_format(acctstarttime, '%Y-%m-%d') >= date_format(now(),'%Y-%m-01') AND date_format(acctstoptime, '%Y-%m-%d') <= last_day(now());} -> 2 sql_xlat expand: %{Stripped-User-Name} -> ... expanding second conditional expand: %{User-Name} -> ptest1 expand: %{%{User-Name}:-DEFAULT} -> ptest1 expand: %{%{Stripped-User-Name}:-%{%{User-Name}:-DEFAULT}} -> ptest1 sql_set_user escaped user --> 'ptest1' expand: SELECT value FROM radgroupreply WHERE groupname='%{Group-Name}' AND attribute='Max-Monthly-Traffic'; -> SELECT value FROM radgroupreply WHERE groupname='user' AND attribute='Max-Monthly-Traffic'; rlm_sql (sql): Reserving sql socket id: 28 sql_xlat finished rlm_sql (sql): Released sql socket id: 28 expand: %{sql: SELECT value FROM radgroupreply WHERE groupname='%{Group-Name}' AND attribute='Max-Monthly-Traffic';} -> 20480 ? Evaluating ("%{sql: SELECT SUM(acctinputoctets+acctoutputoctets) div 1048576 FROM radacct WHERE username='%{User-Name}' AND date_format(acctstarttime, '%Y-%m-%d') >= date_format(now(),'%Y-%m-01') AND date_format(acctstoptime, '%Y-%m-%d') <= last_day(now());}" >= "%{sql: SELECT value FROM radgroupreply WHERE groupname='%{Group-Name}' AND attribute='Max-Monthly-Traffic';}") -> FALSE ++? if ("%{sql: SELECT SUM(acctinputoctets+acctoutputoctets) div 1048576 FROM radacct WHERE username='%{User-Name}' AND date_format(acctstarttime, '%Y-%m-%d') >= date_format(now(),'%Y-%m-01') AND date_format(acctstoptime, '%Y-%m-%d') <= last_day(now());}" >= "%{sql: SELECT value FROM radgroupreply WHERE groupname='%{Group-Name}' AND attribute='Max-Monthly-Traffic';}") -> FALSE ++[preprocess] = ok ++[chap] = noop [mschap] Found MS-CHAP attributes. Setting 'Auth-Type = mschap' ++[mschap] = ok ++[digest] = noop [suffix] No '@' in User-Name = "ptest1", looking up realm NULL [suffix] No such realm "NULL" ++[suffix] = noop [eap] No EAP-Message, not doing EAP ++[eap] = noop [sql] expand: %{Stripped-User-Name} -> [sql] ... expanding second conditional [sql] expand: %{User-Name} -> ptest1 [sql] expand: %{%{User-Name}:-DEFAULT} -> ptest1 [sql] expand: %{%{Stripped-User-Name}:-%{%{User-Name}:-DEFAULT}} -> ptest1 [sql] sql_set_user escaped user --> 'ptest1' rlm_sql (sql): Reserving sql socket id: 27 [sql] expand: SELECT id, username, attribute, value, op FROM radcheck WHERE username = '%{SQL-User-Name}' ORDER BY id -> SELECT id, username, attribute, value, op FROM radcheck WHERE username = 'ptest1' ORDER BY id WARNING: Found User-Password == "...". WARNING: Are you sure you don't mean Cleartext-Password? WARNING: See "man rlm_pap" for more information. [sql] User found in radcheck table [sql] expand: SELECT id, username, attribute, value, op FROM radreply WHERE username = '%{SQL-User-Name}' ORDER BY id -> SELECT id, username, attribute, value, op FROM radreply WHERE username = 'ptest1' ORDER BY id [sql] expand: SELECT groupname FROM radusergroup WHERE username = '%{SQL-User-Name}' ORDER BY priority -> SELECT groupname FROM radusergroup WHERE username = 'ptest1' ORDER BY priority [sql] expand: SELECT id, groupname, attribute, Value, op FROM radgroupcheck WHERE groupname = '%{Sql-Group}' ORDER BY id -> SELECT id, groupname, attribute, Value, op FROM radgroupcheck WHERE groupname = 'user' ORDER BY id [sql] User found in group user [sql] expand: SELECT id, groupname, attribute, value, op FROM radgroupreply WHERE groupname = '%{Sql-Group}' ORDER BY id -> SELECT id, groupname, attribute, value, op FROM radgroupreply WHERE groupname = 'user' ORDER BY id rlm_sql (sql): Released sql socket id: 27 ++[sql] = ok ++[expiration] = noop ++[logintime] = noop [pap] WARNING: Auth-Type already set. Not setting to PAP ++[pap] = noop +} # group authorize = ok Found Auth-Type = MSCHAP !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!! Replacing User-Password in config items with Cleartext-Password. !!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!! Please update your configuration so that the "known good" !!! !!! clear text password is in Cleartext-Password, and not in User-Password. !!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # Executing group from file /etc/raddb/sites-enabled/default +group MS-CHAP { [mschap] Creating challenge hash with username: ptest1 [mschap] Client is using MS-CHAPv2 for ptest1, we need NT-Password [mschap] adding MS-CHAPv2 MPPE keys ++[mschap] = ok +} # group MS-CHAP = ok # Executing section session from file /etc/raddb/sites-enabled/default +group session { [radutmp] expand: /var/log/radius/radutmp -> /var/log/radius/radutmp ++[radutmp] = ok +} # group session = ok # Executing section post-auth from file /etc/raddb/sites-enabled/default +group post-auth { [sql] expand: %{Stripped-User-Name} -> [sql] ... expanding second conditional [sql] expand: %{User-Name} -> ptest1 [sql] expand: %{%{User-Name}:-DEFAULT} -> ptest1 [sql] expand: %{%{Stripped-User-Name}:-%{%{User-Name}:-DEFAULT}} -> ptest1 [sql] sql_set_user escaped user --> 'ptest1' [sql] expand: %{User-Password} -> [sql] ... expanding second conditional [sql] expand: %{Chap-Password} -> [sql] expand: INSERT INTO radpostauth (username, pass, reply, authdate) VALUES ( '%{User-Name}', '%{%{User-Password}:-%{Chap-Password}}', '%{reply:Packet-Type}', '%S') -> INSERT INTO radpostauth (username, pass, reply, authdate) VALUES ( 'ptest1', '', 'Access-Accept', '2016-06-30 13:05:14') rlm_sql (sql) in sql_postauth: query is INSERT INTO radpostauth (username, pass, reply, authdate) VALUES ( 'ptest1', '', 'Access-Accept', '2016-06-30 13:05:14') rlm_sql (sql): Reserving sql socket id: 26 rlm_sql (sql): Released sql socket id: 26 ++[sql] = ok ++[exec] = noop +} # group post-auth = ok Sending Access-Accept of id 94 to 127.0.0.1 port 49226 Service-Type := Framed-User Framed-IP-Address := 255.255.255.255 Framed-IP-Netmask := 255.255.255.0 Acct-Interim-Interval := 600 MS-CHAP2-Success = 0x24533d46303044303641413737333432343231363234364143413245333041373133433531344439353037 MS-MPPE-Recv-Key = 0x3373da01475488084e5f82abae7cbda8 MS-MPPE-Send-Key = 0xdb408d5d7f18d9fd38e6c1888b8c0b13 MS-MPPE-Encryption-Policy = 0x00000001 MS-MPPE-Encryption-Types = 0x00000006 Finished request 0. Going to the next request Waking up in 4.9 seconds. Cleaning up request 0 ID 94 with timestamp +88 Ready to process requests. rad_recv: Accounting-Request packet from host 127.0.0.1 port 58801, id=95, length=114 Acct-Session-Id = "5774A890092400" User-Name = "ptest1" Acct-Status-Type = Start Service-Type = Framed-User Framed-Protocol = PPP Calling-Station-Id = "27.151.123.121" Acct-Authentic = RADIUS NAS-Port-Type = Async Framed-IP-Address = 192.168.222.10 NAS-IP-Address = 127.0.0.1 NAS-Port = 0 Acct-Delay-Time = 0 # Executing section preacct from file /etc/raddb/sites-enabled/default +group preacct { ++[preprocess] = ok [acct_unique] WARNING: Attribute NAS-Identifier was not found in request, unique ID MAY be inconsistent [acct_unique] Hashing 'NAS-Port = 0,,NAS-IP-Address = 127.0.0.1,Acct-Session-Id = "5774A890092400",User-Name = "ptest1"' [acct_unique] Acct-Unique-Session-ID = "413ac0cc5b5f4759". ++[acct_unique] = ok [suffix] No '@' in User-Name = "ptest1", looking up realm NULL [suffix] No such realm "NULL" ++[suffix] = noop +} # group preacct = ok # Executing section accounting from file /etc/raddb/sites-enabled/default +group accounting { [detail] expand: %{Packet-Src-IP-Address} -> 127.0.0.1 [detail] expand: /var/log/radius/radacct/%{%{Packet-Src-IP-Address}:-%{Packet-Src-IPv6-Address}}/detail-%Y%m%d -> /var/log/radius/radacct/127.0.0.1/detail-20160630 [detail] /var/log/radius/radacct/%{%{Packet-Src-IP-Address}:-%{Packet-Src-IPv6-Address}}/detail-%Y%m%d expands to /var/log/radius/radacct/127.0.0.1/detail-20160630 [detail] expand: %t -> Thu Jun 30 13:05:20 2016 ++[detail] = ok [sql] expand: %{Stripped-User-Name} -> [sql] ... expanding second conditional [sql] expand: %{User-Name} -> ptest1 [sql] expand: %{%{User-Name}:-DEFAULT} -> ptest1 [sql] expand: %{%{Stripped-User-Name}:-%{%{User-Name}:-DEFAULT}} -> ptest1 [sql] sql_set_user escaped user --> 'ptest1' [sql] expand: %{Acct-Delay-Time} -> 0 [sql] expand: INSERT INTO radacct (acctsessionid, acctuniqueid, username, realm, nasipaddress, nasportid, nasporttype, acctstarttime, acctstoptime, acctsessiontime, acctauthentic, connectinfo_start, connectinfo_stop, acctinputoctets, acctoutputoctets, calledstationid, callingstationid, acctterminatecause, servicetype, framedprotocol, framedipaddress, acctstartdelay, acctstopdelay, xascendsessionsvrkey) VALUES ('%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', '%{SQL-User-Name}', '%{Realm}', '%{NAS-IP-Address}', '%{NAS-Port}', '%{NAS-Port-Type}', '%S', NULL, '0', '%{Acct-Authentic}', '%{Connect-Info}', '', '0', '0', '%{Called-Station-Id}', '%{Calling-Station-Id}', '', '%{Service-Type}', '%{Framed-Protocol}', '%{Framed-IP-Address}', rlm_sql (sql): Reserving sql socket id: 25 rlm_sql (sql): Released sql socket id: 25 ++[sql] = ok ++[exec] = noop [attr_filter.accounting_response] expand: %{User-Name} -> ptest1 attr_filter: Matched entry DEFAULT at line 12 ++[attr_filter.accounting_response] = updated +} # group accounting = updated Sending Accounting-Response of id 95 to 127.0.0.1 port 58801 Finished request 1. Cleaning up request 1 ID 95 with timestamp +94 Going to the next request Ready to process requests.
二、測試同一個×××帳號,多終端登陸
經過以下sql語句能夠看到當前用戶的撥號鏈接狀況,很明顯經過前面的配置,並無起到限制的效果。
mysql> SELECT radacctid, acctsessionid, username,nasipaddress, nasportid, framedipaddress, callingstationid, framedprotocol FROM radacct WHERE username ='yang' AND acctstoptime IS NULL; mysql> SELECT COUNT(*) from radacct WHERE username ='yang' AND acctstoptime IS NULL;
經過修改/etc/raddb/sites-enabled/default文件,註釋掉session節的radutmp配置,重啓radiusd服務後測試,發現效果符合預期
# vi /etc/raddb/sites-enabled/default
同一個帳號的第二個撥號鏈接就會直接提示驗證失敗!