《分享》MAC to IP與Real Switch兩個問題的後續處理 | |
MAC to IP與Real Switch兩個問題的後續處理
在Radius Proxy架構中的出現的MAC to IP解析與真正的Switch IP這兩個問題總算有解了!
在MAC解析IP部分,順子的做法是把中繼的FreeRadius當做ARP Proxy,
把所有前端的MAC to IP對應全寫在FreeRadius上,
當NAC透過SNMP協定向受控的FreeRadius取得RFC1213-MIB::atPhysAddress內容時,
就能順利解析出MAC對應的IP了。
但這個想法在實作時遇到了兩個問題,
第一,Radius認證完成前,前端Switch還無法產生MAC to IP對應表;
第二,透過FreeRadius呼叫外部程式來寫入FreeRadius本機的ARP表格時,權限不足。
而這兩個問題的對應解法自然是“延時”與“賦予執行時期root的權限”。
在真正的Switch IP顯示上,其實問題不大,
麻煩的是如何在NAC的畫面中統一呈現,而不是讓使用者再透過另一個工具(log)去查詢。
NetSight的資料庫是MySQL,NAC顯示的資料全寫在其中的netsight資料庫。
那可不可以在FreeRadius上安裝MySQL Client套件,
在驗證的過程中直接修改NAC的DB內容,完美的透過NAC畫面統一呈現?
是可以的!
但好不容易開通NetSight讓FreeRadius連結MySQL的權限,
卻因為NAC的MAC to IP延時解析,又把資源還原了...
怎麼辦?
自然是比MAC to IP的延時解析再慢一步來調整囉∼
以下為這兩個問題的Step by Step完整解法
- 開放FreeRadius連結NetSight MySQL DB的權限
於NetSight上安裝MySQL Client套件
apt-get update
apt-get install mysql-client
修改NetSight的MySQL設定檔my.cnf,將socket改為/tmp/netsight_mysql.sock,讓新裝的MySQL Client能夠運作。
vim /etc/mysql/my.cnf
[client]
port = 3306
#socket = /var/run/mysqld/mysqld.sock
socket = /tmp/netsight_mysql.sock
透過MySQL Client連結到MySQL資料庫
mysql -u netsight --port=4589 -p
(NetSight MySQL的帳號為netsight,預設密碼enterasys)
賦予FreeRadius的IP能連線到NetSight的MySQL
use mysql;
insert into user
SELECT '<FreeRadius的IP>', User, Password, Select_priv ,Insert_priv ,Update_priv ,Delete_priv ,Create_priv ,Drop_priv ,Reload_priv ,Shutdown_priv ,Process_priv ,File_priv ,Grant_priv ,References_priv ,Index_priv ,Alter_priv ,Show_db_priv ,Super_priv ,Create_tmp_table_priv ,Lock_tables_priv ,Execute_priv ,Repl_slave_priv ,Repl_client_priv ,Create_view_priv ,Show_view_priv ,Create_routine_priv ,Alter_routine_priv ,Create_user_priv ,Event_priv ,Trigger_priv ,Create_tablespace_priv ,ssl_type ,ssl_cipher ,x509_issuer ,x509_subject ,max_questions ,max_updates ,max_connections ,max_user_connections ,plugin, authentication_string ,password_expired FROM user WHERE host='localhost';
FLUSH PRIVILEGES;
- FreeRadius主機安裝MySQL Client套件
apt-get update
apt-get install mysql-client
安裝完測試能否連到NetSight主機的MySQL
mysql -h <NetSight主機IP> -u netsight --port=4589 -p
順便於FreeRadius主機安裝snmp-mibs-downloader套件,
讓snmpwalk能以較易辨識的MIBs來查詢。
apt-get install snmp-mibs-downloader
- 於FreeRadius主機上建立兩支Perl Script來解決上述兩個問題
這兩支Script順子把它建在/etc/freeradius/中。
第一支Script - ErayExec.pl,是讓Radius在驗證過程中,被呼叫執行。
#!/usr/bin/perl -w
use strict;
my $NAS_IP = $ARGV[0];
my $MAC = $ARGV[1];
exec("sudo /etc/freeradius/EraySync.pl $NAS_IP $MAC");
第二支Script - EraySync.pl,是實際用來解決兩個問題的script。
#!/usr/bin/perl -w
use DBI;
use DBD::mysql;
use strict;
use warnings;
my $NAS_IP = $ARGV[0];
my $MAC = $ARGV[1];
daemonize();
sleep(5);
#==更新ARP============================================
$MAC = uc($MAC);
$MAC =~ s/-/ /g;
print "$MAC\n";
#snmp v1
#my $SNMP = `snmpwalk -v 1 -c public $NAS_IP RFC1213-MIB::atPhysAddress | grep "$MAC"`;
#snmp v2C
#my $SNMP = `snmpwalk -v 2c -c public $NAS_IP RFC1213-MIB::atPhysAddress | grep "$MAC"`;
#snmp v3
my $SNMP = `snmpwalk -v 3 -u snmpuser -l authPriv -a MD5 -A snmpauthcred -x DES -X snmpprivcred $NAS_IP RFC1213-MIB::atPhysAddress | grep -i "$MAC"`;
if ($SNMP) {
print "Get MAC-IP information in RFC1213-MIB::atPhysAddress\n";
} else {
print "Cannot get MAC-IP information in RFC1213-MIB::atPhysAddress\n";
$SNMP = `snmpwalk -v 3 -u snmpuser -l authPriv -a MD5 -A snmpauthcred -x DES -X snmpprivcred $NAS_IP RFC1213-MIB::ipNetToMediaPhysAddress | grep -i "$MAC"`;
if ($SNMP) {
print "Get MAC-IP information in RFC1213-MIB::ipNetToMediaPhysAddress\n";
} else {
print "Cannot get MAC-IP information in RFC1213-MIB::ipNetToMediaPhysAddress\n";
}
}
#my $SNMP = `snmpwalk -v 3 -u snmpuser -l authPriv -a MD5 -A snmpauthcred -x DES -X snmpprivcred $NAS_IP 1.3.6.1.2.1.3.1.1.2 | grep -i "$MAC"`;
#格式化網卡為Linux ARP格式
$MAC =~ s/\s/:/g;
print "$MAC\n";
my $Device_IP;
if ($SNMP) {
#at.atTable.atEntry.atPhysAddress.3.1.192.168.0.1 = Hex: 7C 05 07 73 50 63
#RFC1213-MIB::atPhysAddress.1.1.192.168.10.208 = Hex-STRING: 9C EB E8 01 EC 5B
#my ($ip, $junkorether, $ether)= /(\d+\.\d+\.\d+\.\d+)\s+=\s+(Hex)?\s*([0-9a-fA-F]+[: ][0-9a-fA-F]+[: ][0-9a-fA-F]+[: ][0-9a-fA-F]+[: ][0-9a-fA-F]+[: ][0-9a-fA-F]+)/;
$SNMP =~ /(\d+\.\d+\.\d+\.\d+)\s+=\s+(Hex)/;
$Device_IP = $1;
print "$Device_IP\n";
#清除舊ARP
my @ARP = `arp -n | grep -i "$MAC"`;
for(my $i = $#ARP; $i >= 0; $i--) {
#192.168.0.1 ether 7C:05:07:73:50:63 C eth0
my ($ARP_IP) = split(/\s/,$ARP[$i]);
print "$ARP_IP\n";
`arp -d $ARP_IP -i eth0`;
}
#寫入ARP Table
`arp -s $Device_IP $MAC -i eth0`;
}
#==更新MySQL==========================================
# assign the values in the accessDB file to the variables
if ($SNMP) {
sleep(15);
} else {
sleep(50);
}
my $database = 'netsight';
my $host = '192.168.10.11';
my $userid = 'netsight';
my $passwd = 'enterasys';
# invoke the ConnectToMySQL sub-routine to make the database connection
#$connection = ConnectToMySql($database);
my $connection = DBI->connect("dbi:mysql:$database;$host;port=4589",$userid,$passwd);
print $connection;
# set the value of your SQL query
#my $query = "select version()";
my $query;
if ($SNMP) {
$query = "update tam_endsystem set ZONE='$NAS_IP' where macAddress='$MAC'";
} else {
$query = "update tam_endsystem set Zone='$NAS_IP', ipAddress='$NAS_IP', STATEDESCR='Cannot get IP from Switch $NAS_IP' where macAddress='$MAC'";
}
print $query;
my $statement = $connection->prepare($query);
$statement->execute();
$statement->finish();
$connection->disconnect();
#==建立服務============================================
sub daemonize {
use POSIX;
POSIX::setsid or die "setsid: $!";
my $pid = fork ();
if ($pid < 0) {
die "fork: $!";
} elsif ($pid) {
exit 0;
}
chdir "/";
umask 0;
foreach (0 .. (POSIX::sysconf (&POSIX::_SC_OPEN_MAX) || 1024))
{ POSIX::close $_ }
open (STDIN, "</dev/null");
open (STDOUT, ">/dev/null");
open (STDERR, ">&STDOUT");
}
為什麼要分為兩支程式?
主要是因為寫入ARP table需要root權限,
而順子不知道在FreeRadius呼叫外部程式時,如何下指令才能提升至root權限?
所以只好硬拆成兩支script,第一支用來被FreeRadius呼叫;
而第二支則是讓第一支呼叫時,能以sudo的方式提升至root權限,如此而已。
假設您知道如何讓FreeRadius在呼叫外部程式時,能以root權限來執行的話,
其實單單第二支script就足夠了。
因為第二支程式需要以sudo的方式來提升至root權限,所以我們修改了 /etc/sudoers 這個檔案,
把FreeRadius的執行帳號freerad加入檔案之中,讓freerad能以不輸入密碼的方式,透過sudo提升到root的執行權限。
freerad ALL=(ALL:ALL) NOPASSWD: /etc/freeradius/EraySync.pl
最後再變更這兩支Script的執行權限。
chmod 755 /etc/freeradius/Eray*.pl
- 設定FreeRadius,讓Post-Auth階段能去呼叫上述兩支外部程式
修改/etc/freeradius/modules/exec檔案,加人自定義程式內容。
...
exec {
wait = no
input_pairs = request
shell_escape = yes
output = none
}
exec EraySync {
wait = yes
input_pairs = request
program = "/etc/freeradius/ErayExec.pl %{NAS-IP-Address} %{Calling-Station-Id}"
shell_escape = yes
ouput = none
}
修改/etc/freeradius/sites-enabled/default檔案,在post-auth區段加入EraySync呼叫第一支程式。
post-auth {
exec
Post-Auth-Type REJECT {
attr_filter.access_reject
EraySync
}
EraySync
}
然後重啟FreeRadius服務。
- FreeRadius做為ARP Proxy,加大ARP快取
在順子的設計中,FreeRadius同時也做為ARP Proxy,收集了其下所有Switch的使用者MAC與IP對應。
若這使用者數目驚人!那就要加大這ARP快取,以免出現 No Buffer Space avaiable 的問題。
ARP快取預設值是1024,若要調大成四倍,可以下指令
sysctl -w net.ipv4.neigh.default.gc_thresh1=512
sysctl -w net.ipv4.neigh.default.gc_thresh2=2048
sysctl -w net.ipv4.neigh.default.gc_thresh3=4096
加到 /etc/sysctl.conf 可以使下次開機生效
echo "net.ipv4.neigh.default.gc_thresh1=512
net.ipv4.neigh.default.gc_thresh2=2048
net.ipv4.neigh.default.gc_thresh3=4096" >> /etc/sysctl.conf
- 修改NAC IP Resolution設定
IP Address Resolution timeout改為20秒;
Allow Retries On Failure改為2次,Delay 10秒。
- 將安裝於NetSight的MySQL Client套件移除
apt-get remove --auto-remove mysql-client
- 運作原理
當FreeRadius下的Switch送來使用者的Radius驗證訊息時,不做特別處理。
直到驗證的最後一關 Post-Auth 將證驗資訊回送Switch時,呼叫外部程式來進行兩個問題的處理。
但因為寫入ARP需要root權限,
所以藉由修改/etc/sudoers表格,將FreeRadius的執行帳號-freerad賦予執行第二支程式的root權限。
不過因為NAC的MAC to IP解析階段會覆寫資料庫,
因此將真正Switch IP寫入table 'tam_endsystem' 欄位 'zone' 的時間要延後,這樣資料才不會又被覆寫。
在第二支程式寫入MySQL前,等個10秒就是這個原因。
只是FreeRadius呼叫外部程式時,等個十幾秒鐘的話,會造成驗證失敗!
所以必需把第二支程式做成服務於背景執行,讓FreeRadius呼叫它時不必等待,才能順利完成Post-Auth階段。
這就是為什麼有 daemonize 這個副程式的原因,它讓程式本身在背景中執行,而不耽擱主程式的運行。
另外在透過snmpwalk取得Switch中的MAC與IP表格時,為什麼也要等5秒鐘?
這是因為驗證過程中,Switch還未開通該驗證port的權限,
所以使用者MAC與IP的對應資料,在這階段還無法寫入Switch。
等個幾秒鐘,讓Radius驗證程式執行完成,
Switch產生了對應的MAC與IP的資料後,
再用snmpwalk方能順利取得Switch中的MAC與IP對應關係,
並寫入FreeRadius本機的靜態ARP記錄供NAC查詢。
這樣NAC在解析MAC to IP資訊時,就可以查出之前無法解析的使用者IP資訊了。
在透過snmpwalk取得MAC與IP對應表時,由於Switch廠牌不同,對應表的位置也不一樣,
順子分別透過 atPhysAddress 與 ipNetToMediaPhysAddress 嘗試去取得MAC與IP的對應。
若還是無法取得對應表,就要去查、去試這對應Switch存放表格的地方。
最後要注意的是,第二支Script中透過snmpwalk取得Switch資訊的設定是固定的,
因此所有受控端switch的SNMP版本及相關資訊都要設定相同。
例如都使用SNMP v3版本,且密碼及加解密方式都要一致才行。
參考資料
FreeRADIUS帳號驗證機制整合 (MySQL)
FreeRadius Debugging Mode除錯, 自訂PHP 抓參數值
rlm_perl module not executing authenticate
Linux snmpwalk 簡易使用方式
Free RFC1213-MIB MIB Download - Search, ...and Upload MIBs
NAC Deployment Guide
♥順子老婆的網拍,請多關照∼
If you don't like something, change it.
If you can't change it, change your attitude.
Don't complain!
|