单 位的学生成绩管理系统是ASP.NET做的,很担心非法人员修改。为了方便管理,单位的每台机子IP是固定的。由于只是允许办公计算机访问成绩修改的页 面,计算机数量并不多,所以我把所有办公计算机的IP-MAC专门做一张数据库表,且一一对应。操作之前判断来访的IP-MAC地址,且IP-MAC成对 限制。两个地址必须同时正确才可以访问,若不一致则拒绝访问,并且记录该信息,方便我们找出非法操作者。这是我们最初方案,但是程序做好以后,却发现了新 的问题。当有人要做非法操作,会出现以下情况:只修改IP、只修改MAC、同时修改IP-MAC。对于前两种情况,我们的服务器端已全可以判断、限制了。 但是对于情况三,非法操作者成对修改IP-MAC,而且该IP-MAC对是其他被授权的主机的正确IP-MAC对,在服务器端我们已经无力限制。于是便有 了方案二:做一个判断MAC地址是否被修改的Windows服务,这个服务安装在每个客户机上,如果MAC地址被修改,关闭客户端的IE,从而限制访问,
方案一
服务器端实现,实现的关键代码如下:
using System.Runtime.InteropServices ;//请注意引用动态链接库,则需要此命名空间,它提供各种各样支持 COM interop 及平台调用服务的成员。其中最重要的属性有 DllImportAttribute(可以用来定义用于访问非托管 API 的平台调用方法)
[DllImport("iphlpapi.dll", ExactSpelling=true)] //在.net中使用动态链接库
public static int SendARP( int DestIP, int SrcIP, [Out] byte[] pMacAddr, ref int PhyAddrLen );
[DllImport("Ws2_32.dll")]
private static extern Int32 inet_addr(string ip);
private void Button1_Click(object sender, System.EventArgs e)
{
string client_ip=Request.UserHostAddress ;//获得客户端IP
Label_ip.Text =client_ip;
Int32 ldest= inet_addr(client_ip);//将客户端IP转换成目的地的ip
Int32 lhost= inet_addr("192.168.1.80");//本地的ip,也可以自动生成
try
{
byte[] macinfo=new byte[6]; //做一个数组,准备存储MAC地址
int len=macinfo.Length; //得到数组长度
int ii=SendARP(ldest,lhost, macinfo,ref len);//①macinfo就是返回的MAC地址指针
Label_mac.Text ="Mac Add:"+BitConverter.ToString(macinfo,0,len);//将获得的MAC地址转换成易读 的形式
}
catch(Exception err)
{
Label_ip.Text=err.ToString ();//获取系统给出的错误信息
}
}
SendARPSendARP的函数原型如下:
DWORD SendARP(
IPAddr DestIP, // 目标IP地址
IPAddr SrcIP, // 源IP地址
PULONG pMacAddr, // 返回MAC地址指针
PULONG PhyAddrLen // 返回MAC地址长度
);
当有人进行非法操作,会出现如下情况:
1. 只修改IP
2. 只修改MAC
3. 同时修改IP和MAC
情况1,非法操作者做如下修改:选择“本地连接”的属性,进入Internet协议,修改自己IP。
情况2,非法操作者做如下修改:选择“本地连接”的属性。选择“配置”,修改网卡属性。
在 “高级”选项卡选中“Network Address”,默认“值”是“不存在”,非法操作者在“值”中随便填入一个MAC值,达到修改MAC的目的。MAC地址存储在网卡的EEPROM中并 且唯一确定,但网卡驱动在发送Ethernet报文时,并不从EEPROM中读取MAC地址,而是在内存中来建立一块缓存区,Ethernet报文从中读 取源MAC地址。而且,用户可以通过上述方式或者三方软件修改实际发送的Ethernet报文中的源MAC地址。
方案二
它作为一个服务安装在每个客户机上,把服务设置为随Windows启动而启动,禁止“暂停”和“停止”该服务。
加 入一个Timer控件(timer_watchmac),用于确定监控MAC地址值的时间间隔。注意,该控件一定是“工具箱/组件”中的Timer,C# 中有3个Timer控件, System.Timers.Timer(基于服务器的计时器);System.Windows.Forms.Timer(基于 Windows 的标准计时器,位于“工具箱”的“Windows 窗体”选项卡);;System.Threading.Timer(仅可在编程时使用的线程计时器)。它们是不一样的。
服务监控的关键代码如下:
using System.Management ;//要操作WMI需要此命名空间
public string mymac1;//记录原始MAC
public string mymac2;//服务监控当前MAC
初始化服务的时候,就读取本机MAC地址:
protected override void OnStart(string[] args)
{ // TODO: 在此处添加代码以启动服务。
timer_watchmac.Enabled =true;
ManagementClass mcMAC = new anagementClass("Win32_NetworkAdapterConfiguration");
ManagementObjectCollection mocMAC = mcMAC.GetInstances();
foreach(ManagementObject m in mocMAC)
{
if((bool)m["IPEnabled"])
{
mymac1= m["MacAddress"].ToString();
break;
}
}
}
在Timer控件的Elapsed(达到间隔时发生)事件添加如下代码:
private void timer_watchmac_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{ //WMI在c#中的使用
ManagementClass mcMAC = new anagementClass("Win32_NetworkAdapterConfiguration");
ManagementObjectCollection mocMAC = mcMAC.GetInstances();
foreach(ManagementObject m in mocMAC)//循环实例化管理对象
{
if((bool)m["IPEnabled"])
{ mymac2= m["MacAddress"].ToString();//管理对象(NIC)的当前mac地址
if (mymac2!=mymac1)//发现mac地址被修改
{ //关闭ie浏览器
Process[] myProcesses = Process.GetProcesses();
string test="";
foreach(Process myProcess in myProcesses)//枚举系统当前进程
{ test =myProcess.ProcessName ;
if (test=="IEXPLORE")//发现ie进程,还可以添加其他浏览器进程名称
{ myProcess.Kill (); //关闭ie进程 }
}
}
break;
}
}
}
WMI中Win32_NetworkAdapterConfiguration的定义:
MACAddress
Data type: string
Access type: Read-only //mac地址是只读的
Media Access Control (MAC) address of the network adapter. A MAC address is assigned by the manufacturer to uniquely identify the network adapter.
Example: "00:80:C7:8F:6C:96"
总 结一下我自己的防范方式:在服务器上和客户机上作了双重限制,更为保险的方式是找一个能够直接读取EEPROM地址的三方软件,将它读取的值作为初始值提 供给监视服务,再和当前MAC做比较。这样的话,非法操作者就只有通过修改数据包的方式来进行破坏了。当然现在流行的做法是把IP-MAC和交换机端口绑 定,只是我们公司没有用这种能绑定端口的交换机