显示标签为“网络”的博文。显示所有博文
显示标签为“网络”的博文。显示所有博文

2012年2月19日星期日

使用AutoIT编写的常熟理工学院-锐捷VPN登录器

首先要使用IE正常登录一次VPN,目的是安装SSL VPN的浏览器插件,因为这个登录器的目的是隐藏IE窗口进行登录,这样不要一直保持一个打开的浏览器窗口。

代码如下:

#include <ie.au3>
#include <array.au3>
#include <date.au3>
#include <ButtonConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <GuiEdit.au3>
#include <GuiListBox.au3>
#include <base64.au3>
#include <winapi.au3>

Global $oIE,$oFlag
$oFlag=False

Opt("TrayMenuMode", 1)
;Opt("TrayOnEventMode", 1) ;响应托盘事件
Opt("WinTitleMatchMode", 2) ;匹配任意位置字符串

#Region ### START Koda GUI section ### Form=D:\Tools\KodaFormDesigner\Forms\RgVPN.kxf
$Form1 = GUICreate("RGVPN-锐捷VPN登录器", 323, 109, 192, 124)
$Label1 = GUICtrlCreateLabel("用户名", 16, 12, 40, 17)
$txtUsername = GUICtrlCreateInput("", 72, 10, 129, 21)
$Label2 = GUICtrlCreateLabel("密码", 16, 40, 28, 17)
$txtPassword = GUICtrlCreateInput("", 72, 38, 129, 21, BitOR($GUI_SS_DEFAULT_INPUT,$ES_PASSWORD))
$btnLogin = GUICtrlCreateButton("登录", 224, 8, 73, 25)
$BtnLogout = GUICtrlCreateButton("注销", 224, 36, 73, 25)
$Label3 = GUICtrlCreateLabel("验证码", 16, 72, 40, 17)
$txtVCode = GUICtrlCreateInput("", 72, 70, 57, 21)
$Pic1 = GUICtrlCreatePic("", 136, 72, 60, 20)
$btnRefresh = GUICtrlCreateButton("看不清?", 208, 72, 89, 25)

TraySetIcon("", -1)
TraySetClick(64)
$MenuItem1 = TrayCreateItem("恢复窗口")
$MenuItem2 = TrayCreateItem("退出")
$MenuItem3 = TrayCreateItem("关于")
;TraySetOnEvent($MenuItem1,restore)
;TraySetOnEvent($MenuItem2,quit)
;TraySetOnEvent($MenuItem3,about)
TraySetState()
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###

GUICtrlSetState($BtnLogout,$GUI_DISABLE)
GUICtrlSetState($BtnLogin,$GUI_ENABLE)
GUICtrlSetState($BtnRefresh,$GUI_ENABLE)

LoadHomePage()

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            if $oFlag=True Then
                Run("cmd /c start close.exe")
                Sleep(1000)
                _IELinkClickByText($oIE,"注    销")
            EndIf
            _IEErrorHandlerDeRegister()
            _IEQuit($oIE)
            Exit

        Case $GUI_EVENT_MINIMIZE
            GUISetState(@SW_HIDE)

        Case $btnRefresh
            _IENavigate($oIE,"
https://61.155.18.8/",1)
            _IELoadWait($oIE)
            Sleep(300)
            $oIE.document.getElementById("overridelink").Click
            _IELoadWait($oIE)
            Sleep(300)
            $oImg = _IEImgGetCollection ($oIE, 8)
            $oPic = $oIE.Document.body.createControlRange()
            $oPic.Add($oImg)
            $oPic.execCommand("Copy")
            $bmp = ClipGet()
            GUICtrlSetImage($pic1,$bmp)

        Case $btnLogin
            GUICtrlSetState($BtnLogout,$GUI_DISABLE)
            GUICtrlSetState($BtnLogin,$GUI_DISABLE)
            GUICtrlSetState($BtnRefresh,$GUI_DISABLE)
            $formUsername=$oIE.document.getElementById("username")
            $formPasswd=$oIE.document.getElementById("passwd")
            $chkCode=$oIE.document.getElementById("chkCode")
            $username=_GUICtrlEdit_GetText($txtUsername)
            $password=_GUICtrlEdit_GetText($txtPassword)
            $vcode=_GUICtrlEdit_GetText($txtVCode)
            if $username<>"" AND $password<>"" AND $vcode<>"" Then
                _IEFormElementSetValue($formUsername,$username)
                _IEFormElementSetValue($formPasswd,$password)
                _IEFormElementSetValue($chkCode,$vcode)
                $oForm=_IEFormGetObjByName($oIE,"Login")
                $oSubmit=_IEFormElementGetObjByName($oForm,"submit")
                _IEAction($oSubmit,"click")
                _IELoadWait($oIE)
                Sleep(300)
                Local $str=$oIE.Document.body.innerHtml
                Local $b=StringRegExp($str,"重新登录",1)
                if @error=0 Then
                    GUICtrlSetState($BtnLogout,$GUI_ENABLE)
                    GUICtrlSetState($BtnRefresh,$GUI_DISABLE)
                    GUICtrlSetState($BtnLogin,$GUI_DISABLE)
                    Sleep(20000)
                    MsgBox(0,"VPN","登录成功")
                    $oFlag=True
                Else
                    MsgBox(0,"VPN","登录失败")
                    GUICtrlSetState($BtnLogout,$GUI_DISABLE)
                    GUICtrlSetState($BtnLogin,$GUI_ENABLE)
                    GUICtrlSetState($BtnRefresh,$GUI_ENABLE)
                EndIf
            Else
                GUICtrlSetState($BtnLogout,$GUI_DISABLE)
                GUICtrlSetState($BtnLogin,$GUI_ENABLE)
                GUICtrlSetState($BtnRefresh,$GUI_ENABLE)
            EndIf

        Case $BtnLogout
            Run("cmd /c start close.exe")
            Sleep(2000)
            _IELinkClickByText($oIE,"注    销")
            _IEErrorHandlerDeRegister()
            ;_IEQuit($oIE)
            Exit

    EndSwitch
    $msg = TrayGetMsg()
    Select
        Case $msg = $MenuItem1
            GUISetState(@SW_SHOWNORMAL)

        Case $msg = $MenuItem2
            quit()

        Case $msg = $MenuItem3
            aboutme()
    EndSelect
WEnd

Func restore()
    GUISetState(@SW_RESTORE)
EndFunc

Func quit()
    if $oFlag=True Then
        Run("cmd /c start close.exe")
        Sleep(2000)
        _IELinkClickByText($oIE,"注    销")
    EndIf
    _IEErrorHandlerDeRegister()
    ;_IEQuit($oIE)
    Exit
EndFunc

Func aboutme()
    MsgBox(0,"锐捷VPN拨号器","常熟理工学院计算机学院 沈健(jimshen@gmail.com,QQ:3262743)版权所有")
EndFunc


Func LoadHomePage()
    _IEErrorHandlerRegister("MyErrFunc")
    $oIE=_IECreate("
https://61.155.18.8/",0,0,1,0)
    _IELoadWait($oIE)
    Sleep(300)
    $oIE.document.getElementById("overridelink").Click
    _IELoadWait($oIE)
    Sleep(300)
    $oImg = _IEImgGetCollection ($oIE, 8)
    $oPic = $oIE.Document.body.createControlRange()
    $oPic.Add($oImg)
    $oPic.execCommand("Copy",False)
    $bmp = ClipGet()
    GUICtrlSetImage($pic1,$bmp)
EndFunc

Func MyErrFunc()
    ; Important: the error object variable MUST be named $oIEErrorHandler
    Local $ErrorScriptline = $oIEErrorHandler.scriptline
    Local $ErrorNumber = $oIEErrorHandler.number
    Local $ErrorNumberHex = Hex($oIEErrorHandler.number, 8)
    Local $ErrorDescription = StringStripWS($oIEErrorHandler.description, 2)
    Local $ErrorWinDescription = StringStripWS($oIEErrorHandler.WinDescription, 2)
    Local $ErrorSource = $oIEErrorHandler.Source
    Local $ErrorHelpFile = $oIEErrorHandler.HelpFile
    Local $ErrorHelpContext = $oIEErrorHandler.HelpContext
    Local $ErrorLastDllError = $oIEErrorHandler.LastDllError
    Local $ErrorOutput = ""
    $ErrorOutput &= "--> COM Error Encountered in " & @ScriptName & @CR
    $ErrorOutput &= "----> $ErrorScriptline = " & $ErrorScriptline & @CR
    $ErrorOutput &= "----> $ErrorNumberHex = " & $ErrorNumberHex & @CR
    $ErrorOutput &= "----> $ErrorNumber = " & $ErrorNumber & @CR
    $ErrorOutput &= "----> $ErrorWinDescription = " & $ErrorWinDescription & @CR
    $ErrorOutput &= "----> $ErrorDescription = " & $ErrorDescription & @CR
    $ErrorOutput &= "----> $ErrorSource = " & $ErrorSource & @CR
    $ErrorOutput &= "----> $ErrorHelpFile = " & $ErrorHelpFile & @CR
    $ErrorOutput &= "----> $ErrorHelpContext = " & $ErrorHelpContext & @CR
    $ErrorOutput &= "----> $ErrorLastDllError = " & $ErrorLastDllError
    ;MsgBox(0, "COM Error", $ErrorOutput)
    SetError(1)
    Return
EndFunc

在运行的过程中IE窗口弹出的消息框,通过另一个进程来自动关闭

#include <IE.au3>

while true
    WinWaitActive("来自网页的消息","")
    If WinActive("来自网页的消息","") Then
        Send("{ENTER}")
        ExitLoop
    endif
wend

while true
    WinWaitActive("Windows Internet Explorer","")
    If WinActive("Windows Internet Explorer","") Then
        Send("{ENTER}")
        ExitLoop
    endif
wend

Exit

2011年2月1日星期二

另一个实现的很好的IP Helper代码包

 

http://www.csharpfr.com//code.aspx?ID=50722

法国网站

一个IPHelper API的实现

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Management;
using System.Runtime.InteropServices;

namespace VPNClient
{
    class iphlpapi
    {
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
        public struct IP_ADDRESS_STRING
        {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
            public string Address;
        }

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
        public struct IP_ADDR_STRING
        {
            public IntPtr Next;
            public IP_ADDRESS_STRING IpAddress;
            public IP_ADDRESS_STRING IpMask;
            public Int32 Context;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct MIB_IPFORWARDROW
        {
            public UInt32 dwForwardDest;        //destination IP address.
            public UInt32 dwForwardMask;        //Subnet mask
            public UInt32 dwForwardPolicy;      //conditions for multi-path route. Unused, specify 0.
            public UInt32 dwForwardNextHop;     //IP address of the next hop. Own address?
            public UInt32 dwForwardIfIndex;     //index of interface
            public UInt32 dwForwardType;        //route type
            public UInt32 dwForwardProto;       //routing protocol.
            public UInt32 dwForwardAge;         //age of route.
            public UInt32 dwForwardNextHopAS;   //autonomous system number. 0 if not relevant
            public int dwForwardMetric1;     //-1 if not used (goes for all metrics)
            public int dwForwardMetric2;
            public int dwForwardMetric3;
            public int dwForwardMetric4;
            public int dwForwardMetric5;
        }

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
        public struct IP_ADAPTER_INFO
        {
            public IntPtr Next;
            public Int32 ComboIndex;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256 + 4)]
            public string AdapterName;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128 + 4)]
            public string AdapterDescription;
            public UInt32 AddressLength;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
            public byte[] Address;
            public Int32 Index;
            public UInt32 Type;
            public UInt32 DhcpEnabled;
            public IntPtr CurrentIpAddress;
            public IP_ADDR_STRING IpAddressList;
            public IP_ADDR_STRING GatewayList;
            public IP_ADDR_STRING DhcpServer;
            public bool HaveWins;
            public IP_ADDR_STRING PrimaryWinsServer;
            public IP_ADDR_STRING SecondaryWinsServer;
            public Int32 LeaseObtained;
            public Int32 LeaseExpires;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct MIB_IPFORWARDTABLE
        {
            public int dwNumEntries;            //number of route entries in the table.
            public MIB_IPFORWARDROW[] table;
        }

        [DllImport("iphlpapi.dll", CharSet = CharSet.Ansi)]
        public static extern int GetAdaptersInfo(IntPtr pAdapterInfo, ref Int64 pBufOutLen);

        [DllImport("Iphlpapi.dll")]
        [return: MarshalAs(UnmanagedType.U4)]
        public static extern int CreateIpForwardEntry(ref MIB_IPFORWARDROW pRoute);

        [DllImport("Iphlpapi.dll")]
        [return: MarshalAs(UnmanagedType.U4)]
        public static extern int DeleteIpForwardEntry(ref MIB_IPFORWARDROW pRoute);

        [DllImport("Iphlpapi.dll")]
        [return: MarshalAs(UnmanagedType.U4)]
        public static extern int SetIpForwardEntry(ref MIB_IPFORWARDROW pRoute);

        [DllImport("Iphlpapi.dll")]
        [return: MarshalAs(UnmanagedType.U4)]
        public static extern int GetIpForwardTable(byte[] pIpForwardTable, out int pdwSize, bool bOrder);


        public static int createIpForwardEntry(UInt32 destIPAddress, UInt32 destMask, UInt32 nextHopIPAddress, UInt32 ifIndex,int metric)
        {
            MIB_IPFORWARDROW mifr = new MIB_IPFORWARDROW();
            mifr.dwForwardDest = destIPAddress;
            mifr.dwForwardMask = destMask;
            mifr.dwForwardNextHop = nextHopIPAddress;
            mifr.dwForwardIfIndex = ifIndex;
            mifr.dwForwardPolicy = Convert.ToUInt32(0);
            mifr.dwForwardType = Convert.ToUInt32(3);
            mifr.dwForwardProto = Convert.ToUInt32(3);
            mifr.dwForwardAge = Convert.ToUInt32(0);
            mifr.dwForwardNextHopAS = Convert.ToUInt32(0);
            mifr.dwForwardMetric1 = metric;
            mifr.dwForwardMetric2 = -1;
            mifr.dwForwardMetric3 = -1;
            mifr.dwForwardMetric4 = -1;
            mifr.dwForwardMetric5 = -1;
            return CreateIpForwardEntry(ref mifr);
        }

        public static int deleteIpForwardEntry(UInt32 destIPAddress, UInt32 destMask, UInt32 nextHopIPAddress, UInt32 ifIndex)
        {
            MIB_IPFORWARDROW mifr = new MIB_IPFORWARDROW();
            mifr.dwForwardDest = destIPAddress;
            mifr.dwForwardMask = destMask;
            mifr.dwForwardNextHop = nextHopIPAddress;
            mifr.dwForwardIfIndex = ifIndex;
            mifr.dwForwardPolicy = Convert.ToUInt32(0);
            mifr.dwForwardType = Convert.ToUInt32(3);
            mifr.dwForwardProto = Convert.ToUInt32(3);
            mifr.dwForwardAge = Convert.ToUInt32(0);
            mifr.dwForwardNextHopAS = Convert.ToUInt32(0);
            mifr.dwForwardMetric1 = -1;
            mifr.dwForwardMetric2 = -1;
            mifr.dwForwardMetric3 = -1;
            mifr.dwForwardMetric4 = -1;
            mifr.dwForwardMetric5 = -1;
            return DeleteIpForwardEntry(ref mifr);
        }

        const int MAX_ADAPTER_DESCRIPTION_LENGTH = 128;
        const int ERROR_BUFFER_OVERFLOW = 111;
        const int MAX_ADAPTER_NAME_LENGTH = 256;
        const int MAX_ADAPTER_ADDRESS_LENGTH = 8;
        const int MIB_IF_TYPE_OTHER = 1;
        const int MIB_IF_TYPE_ETHERNET = 6;
        const int MIB_IF_TYPE_TOKENRING = 9;
        const int MIB_IF_TYPE_FDDI = 15;
        const int MIB_IF_TYPE_PPP = 23;
        const int MIB_IF_TYPE_LOOPBACK = 24;
        const int MIB_IF_TYPE_SLIP = 28;

        /// <summary>
        /// IPAddressToNumber
        /// </summary>
        /// <param name="IPaddress"></param>
        /// <returns></returns>
        public static double IPAddressToNumber(string IPaddress)
        {
            int i;
            string[] arrDec;
            double num = 0;
            if (IPaddress == "")
            {
                return 0;
            }
            else
            {
                arrDec = IPaddress.Split('.');
                for (i = arrDec.Length - 1; i >= 0; i = i - 1)
                {
                    num += ((int.Parse(arrDec[i]) % 256) * Math.Pow(256, (3 - i)));
                }
                return num;
            }
        }

        /// <summary>
        /// GetAdaptersIndex
        /// </summary>
        /// <returns></returns>
        public static string GetAdaptersIndex()
        {
            string result = string.Empty;
            long structSize = Marshal.SizeOf(typeof(IP_ADAPTER_INFO));
            IntPtr pArray = Marshal.AllocHGlobal(new IntPtr(structSize));
            int ret = GetAdaptersInfo(pArray, ref structSize);

            if (ret == ERROR_BUFFER_OVERFLOW) // ERROR_BUFFER_OVERFLOW == 111
            {
                pArray = Marshal.ReAllocHGlobal(pArray, new IntPtr(structSize));
                ret = GetAdaptersInfo(pArray, ref structSize);
            }

            if (ret == 0)
            {
                IntPtr pEntry = pArray;
                do
                {
                    IP_ADAPTER_INFO entry = (IP_ADAPTER_INFO)Marshal.PtrToStructure(pEntry, typeof(IP_ADAPTER_INFO));
                    if (entry.AdapterDescription.IndexOf("PPP") >= 0 || entry.AdapterDescription.IndexOf("SLIP") >= 0 || entry.AdapterDescription.IndexOf("PPTP") >= 0 || entry.AdapterDescription.IndexOf("VPN") >= 0)
                    {
                        result += (result == string.Empty ? string.Empty : "|") + entry.Index.ToString();
                    }
                    pEntry = entry.Next;
                }
                while (pEntry != IntPtr.Zero);
                Marshal.FreeHGlobal(pArray);
                return result;
            }
            else
            {
                Marshal.FreeHGlobal(pArray);
                throw new InvalidOperationException("GetAdaptersInfo failed: " + ret);
            }

        }

        /// <summary>
        /// GetAdapters
        /// </summary>
        public static void GetAdapters()
        {
            long structSize = Marshal.SizeOf(typeof(IP_ADAPTER_INFO));
            IntPtr pArray = Marshal.AllocHGlobal(new IntPtr(structSize));

            int ret = GetAdaptersInfo(pArray, ref structSize);

            if (ret == ERROR_BUFFER_OVERFLOW) // ERROR_BUFFER_OVERFLOW == 111
            {
                // Buffer was too small, reallocate the correct size for the buffer.
                pArray = Marshal.ReAllocHGlobal(pArray, new IntPtr(structSize));

                ret = GetAdaptersInfo(pArray, ref structSize);
            } // if

            if (ret == 0)
            {
                // Call Succeeded
                IntPtr pEntry = pArray;

                do
                {
                    // Retrieve the adapter info from the memory address
                    IP_ADAPTER_INFO entry = (IP_ADAPTER_INFO)Marshal.PtrToStructure(pEntry, typeof(IP_ADAPTER_INFO));

                    // ***Do something with the data HERE!***
                    Console.WriteLine("\n");
                    Console.WriteLine("Index: {0}", entry.Index.ToString());

                    // Adapter Type
                    string tmpString = string.Empty;
                    switch (entry.Type)
                    {
                        case MIB_IF_TYPE_ETHERNET: tmpString = "Ethernet"; break;
                        case MIB_IF_TYPE_TOKENRING: tmpString = "Token Ring"; break;
                        case MIB_IF_TYPE_FDDI: tmpString = "FDDI"; break;
                        case MIB_IF_TYPE_PPP: tmpString = "PPP"; break;
                        case MIB_IF_TYPE_LOOPBACK: tmpString = "Loopback"; break;
                        case MIB_IF_TYPE_SLIP: tmpString = "Slip"; break;
                        default: tmpString = "Other/Unknown"; break;
                    }

                    Console.WriteLine("Adapter Type: {0}", tmpString);
                    Console.WriteLine("Name: {0}", entry.AdapterName);
                    Console.WriteLine("Desc: {0}\n", entry.AdapterDescription);
                    Console.WriteLine("DHCP Enabled: {0}", (entry.DhcpEnabled == 1) ? "Yes" : "No");

                    if (entry.DhcpEnabled == 1)
                    {
                        Console.WriteLine("DHCP Server : {0}", entry.DhcpServer.IpAddress.Address);

                        // Lease Obtained (convert from "time_t" to C# DateTime)
                        DateTime pdatDate = new DateTime(1970, 1, 1).AddSeconds(entry.LeaseObtained).ToLocalTime();
                        Console.WriteLine("Lease Obtained: {0}", pdatDate.ToString());

                        // Lease Expires (convert from "time_t" to C# DateTime)
                        pdatDate = new DateTime(1970, 1, 1).AddSeconds(entry.LeaseExpires).ToLocalTime();
                        Console.WriteLine("Lease Expires : {0}\n", pdatDate.ToString());
                    } // if DhcpEnabled

                    Console.WriteLine("IP Address     : {0}", entry.IpAddressList.IpAddress.Address);
                    Console.WriteLine("Subnet Mask    : {0}", entry.IpAddressList.IpMask.Address);
                    Console.WriteLine("Default Gateway: {0}", entry.GatewayList.IpAddress.Address);

                    // MAC Address (data is in a byte[])
                    tmpString = string.Empty;
                    for (int i = 0; i < entry.AddressLength - 1; i++)
                    {
                        tmpString += string.Format("{0:X2}-", entry.Address[i]);
                    }

                    Console.WriteLine("MAC Address    : {0}{1:X2}\n", tmpString, entry.Address[entry.AddressLength - 1]);
                    Console.WriteLine("Has WINS: {0}", entry.HaveWins ? "Yes" : "No");

                    if (entry.HaveWins)
                    {
                        Console.WriteLine("Primary WINS Server  : {0}", entry.PrimaryWinsServer.IpAddress.Address);
                        Console.WriteLine("Secondary WINS Server: {0}", entry.SecondaryWinsServer.IpAddress.Address);
                    }

                    // Get next adapter (if any)
                    pEntry = entry.Next;

                }
                while (pEntry != IntPtr.Zero);
                Marshal.FreeHGlobal(pArray);
            }
            else
            {
                Marshal.FreeHGlobal(pArray);
                throw new InvalidOperationException("GetAdaptersInfo failed: " + ret);
            }

        }
    }
}

修改windows系统路由表

/// <summary>
        /// 添加靜態路由
        /// </summary>
        /// <returns></returns>
        private int AddIpRouteEntries(){
            HttpClient wc = new HttpClient();
            int res=AddIpRouteEntriesFromFile("http://61.155.18.16:81/cernet.txt");
             if(res!=0){
                 MessageBox.Show("不能下载路由列表,即将把常熟理工学院内部地址添加到系统路由表并通过VPN访问,其他地址继续通过原网络访问!");
                 return res;
             }
             res = AddIpRouteEntriesFromFile("http://61.155.18.16:81/userdefine.txt");
             if (res != 0)
             {
                 MessageBox.Show("不能下载路由列表,即将把常熟理工学院内部地址添加到系统路由表并通过VPN访问,其他地址继续通过原网络访问!");
                 return res;
             }
            res=AddIpRouteEntry("10.0.0.0","255.0.0.0");
            return res;
        }

        private int AddIpRouteEntriesFromFile(string url){
            int res = 0;
            HttpClient wc = new HttpClient();
            try
            {
                byte[] str = wc.DownloadData(url);
                String restext = Encoding.Default.GetString(str);
                String[] ads = restext.Split(new char[] { '\n' });
                for (int i = 0; i < ads.Length; i++)
                {
                    string ent = ads[i].Trim();
                    if (ent.Length != 0)
                    {
                        string[] xx = ent.Split(new char[] { ',' });
                        res = AddIpRouteEntry(xx[0], xx[1]);
                        if (res != 0)
                            return res;
                    }

                }
            }
            catch (Exception exp)
            {
                return 1976;
            }
            return res;
        }

        /// <summary>
        /// 添加靜態路由
        /// </summary>
        /// <param name="network"></param>
        /// <param name="netmask"></param>
        /// <returns></returns>
        private int AddIpRouteEntry(string network,string netmask){
            UInt32 dest = BitConverter.ToUInt32(IPAddress.Parse(network).GetAddressBytes(), 0);
            UInt32 mask = BitConverter.ToUInt32(IPAddress.Parse(netmask).GetAddressBytes(), 0);
            UInt32 nextHop = BitConverter.ToUInt32(IPAddress.Parse(this.ClientIp).GetAddressBytes(), 0);
            return iphlpapi.createIpForwardEntry(dest, mask, nextHop, Convert.ToUInt32(this.interfaceIndex), metric);
        }

        /// <summary>
        /// 獲取系統路由表中目標地址為0.0.0.0的路由項的metric
        /// </summary>
        private void GetMetric(){
            IEnumerable<RouteEntry> ienum=iphlp.GetRoutesTable();
            IEnumerator<RouteEntry> enums=ienum.GetEnumerator();
            enums.MoveNext();
            while(enums.Current!=null){
                RouteEntry ent = enums.Current;
                if (ent.Destination.Equals(IPAddress.Parse("0.0.0.0")))
                {
                    metric=ent.Metric1;
                    return;
                }
                enums.MoveNext();
            }
        }

注意:如果不获取系统路由表中目标地址为0的项的metric而直接添加路由项(metric1=-1),则CreateIpForwardEntry()函数会返回87(Invalid parameter)

获取VPN拨号后的IP地址

 

private void GetVpnClientIp(){
           GetMetric();
           foreach (RasConnection connection in RasConnection.GetActiveConnections())
           {
               if (connection.EntryName == entry.Name)
               {
                   RasIPInfo ipAddresses = (RasIPInfo)connection.GetProjectionInfo(RasProjectionType.IP);
                  
                   interfaceIndex =Convert.ToUInt32(iphlpapi.GetAdaptersIndex());
                   if (ipAddresses != null)
                   {
                       //this.ClientAddressTextBox.Text = ipAddresses.IPAddress.ToString();
                       //this.ServerAddressTextBox.Text = ipAddresses.ServerIPAddress.ToString();
                       this.Ipbar.Text = ipAddresses.IPAddress.ToString();
                       this.ClientIp = ipAddresses.IPAddress.ToString();
                       this.ServerIp = ipAddresses.ServerIPAddress.ToString();
                   }
               }
           }
       }

使用DotRas进行VPN拨号

 

/// <summary>
       /// 初始化VPN連接
       ///
       /// </summary>
       private void InitVpnEntry(){
           try
           {
               this.AllUsersPhoneBook.Open();
               entry = RasEntry.CreateVpnEntry(EntryName, "61.155.18.16", RasVpnStrategy.Default,
                   RasDevice.GetDeviceByName("(PPTP)", RasDeviceType.Vpn));
               entry.Options.RemoteDefaultGateway = bDefaultGw;
               entry.Options.NetworkLogOn = false;
               entry.Options.PreviewDomain = false;
               this.AllUsersPhoneBook.Entries.Remove(entry.Name);
               this.AllUsersPhoneBook.Entries.Add(entry);
               this.statusbar.Text = "VPN连接创建成功,程序初始化完成!";
               this.DisconnectButton.Enabled = false;
           }catch(Exception ex){
               //MessageBox.Show(ex.GetType()+":打开或创建电话簿时发生错误。请检查VPN连接是否已经存在!");
           }
       }

       /// <summary>
       /// 建立VPN連接
       /// </summary>
       /// <param name="sender"></param>
       /// <param name="e"></param>
       private void button2_Click(object sender, EventArgs e)
       {
           InitVpnEntry();
           this.Dialer.EntryName = EntryName;
           this.Dialer.PhoneBookPath = RasPhoneBook.GetPhoneBookPath(RasPhoneBookType.AllUsers);

           this.username = txtUsername.Text.Trim();
           this.password = txtPassword.Text.Trim();
           if (this.username.Length == 0 || this.password.Length == 0)
           {
               MessageBox.Show("请填写用户名和密码!");
               return;
           }

           try
           {
               this.Dialer.Credentials = new NetworkCredential(username,password);
               this.handle = this.Dialer.DialAsync();
               this.DisconnectButton.Enabled = true;
               this.BtnExit.Enabled = false;
               this.btnConnect.Enabled = false;
           }
           catch (Exception ex)
           {
               MessageBox.Show(ex.ToString());
           }
       }

/// <summary>
        /// 斷開VPN連接
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void DisconnectButton_Click(object sender, EventArgs e)
        {
            if (entry == null)
                return;
            if (this.Dialer.IsBusy)
            {
                this.Dialer.DialAsyncCancel();
            }
            else
            {
                RasConnection connection = RasConnection.GetActiveConnectionByHandle(this.handle);
                if (connection != null)
                {
                    connection.HangUp();
                }
            }
            this.BtnExit.Enabled = true;
            this.btnConnect.Enabled = true;
            this.DisconnectButton.Enabled = false;
            this.statusbar.Text = "VPN连接已断开!";
        }

/// <summary>
       /// 異步VPN連接過程回調函數
       /// </summary>
       /// <param name="sender"></param>
       /// <param name="e"></param>
       private void Dialer_StateChanged(object sender, StateChangedEventArgs e)
       {
           this.statusbar.Text = e.State.ToString();
       }

       /// <summary>
       /// 異步VPN連接過程回調函數
       /// </summary>
       /// <param name="sender"></param>
       /// <param name="e"></param>
       private void Dialer_DialCompleted(object sender, DialCompletedEventArgs e)
       {
           if (e.Cancelled)
           {
               this.DisconnectButton.Enabled = false;
               this.BtnExit.Enabled = true;
               this.btnConnect.Enabled = true;
               this.statusbar.Text = "拨号已被取消!";
           }
           else if (e.TimedOut)
           {
               this.DisconnectButton.Enabled = false;
               this.BtnExit.Enabled = true;
               this.btnConnect.Enabled = true;
               this.statusbar.Text = "连接超时!";
           }
           else if (e.Error != null)
           {
               this.DisconnectButton.Enabled = false;
               this.BtnExit.Enabled = true;
               this.btnConnect.Enabled = true;
               this.statusbar.Text = e.Error.ToString();
           }
           else if (e.Connected)
           {
               this.DisconnectButton.Enabled = true;
               this.BtnExit.Enabled = false;
               this.btnConnect.Enabled = false;
               this.statusbar.Text = "VPN拨号成功!";
               WriteSettings();
               GetVpnClientIp();
           }

           if (!e.Connected)
           {
               this.DisconnectButton.Enabled = false;
               this.BtnExit.Enabled = true;
               this.btnConnect.Enabled = true;
               this.statusbar.Text = "未能成功连接VPN服务器!";
               MessageBox.Show("VPN拨号失败!请检查服务器是否正常,用户名和密码是否正确。");
           }
       }

2011年1月3日星期一

锐捷交换机关闭流控

锐捷S2026在出厂时默认打开了流控,sh run看不到这个配置

在机房机器网络同传时速度只有20多MB每分钟,一个机房要安装24小时。下面的命令用来关闭流控功能

int ran fa0/1-24
no sto uni
no sto mul
no sto bro
flo off

交换机配置的备份与恢复

 

copy flash:config.text xmodem:

copy xmodem: flash:config.txt

2010年4月15日星期四

2009年4月17日星期五

使用VB.NET编写了一个定时登录Dr.COM Hotspot上网验证系统的Windows服务

使用Visual Studio 2005编写,项目类型是Windows服务。
从组件菜单中选择Timer组件,注意默认的Timer组件是System.Windows.Forms.Timer,并不能在服务中使用,要使用System.Timer.Timer组件,可以在工具箱的组件面板上点击右键,出现下面的菜单,选择红色框子圈出的项,从对话框中将需要的组件添加到面板


将正确的Timer组件拖到类的设计面板,设置合适的interval,并将Timer设置为Enable。双击Timer组件,添加代码如下(加粗部分)
Imports System.Text
Imports System.Net
Imports System.Timers
Public Class AutoLogonService
    Protected Overrides Sub OnStart(ByVal args() As String)
        ' 请在此处添加代码以启动您的服务。此方法应完成设置工作,
        ' 以使您的服务开始工作。
    End Sub
    Protected Overrides Sub OnStop()
        ' 在此处添加代码以执行任何必要的拆解操作,从而停止您的服务。
    End Sub
    Private Sub Timer1_Elapsed(ByVal sender As System.Object, ByVal e As System.Timers.ElapsedEventArgs) Handles Timer1.Elapsed
        Dim MyClient As New WebClient
        Dim MyURL As String
        Dim data As String
        Dim postData As Byte()

        MyURL = "http://10.29.0.250/F.htm"
        data = "DDDDD=你的用户名&upass=你的密码&0MKKey=登录 Login"
        postData = Encoding.ASCII.GetBytes(data)
        MyClient.UploadData(MyURL, "POST", postData)
    End Sub
End Class
右击设计视图选择“添加安装程序”,为该服务添加安装程序,并设置项目、安装程序的名称和相关属性。最后生成Service。
Service的安装
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\InstallUtil c:\Dr.COM.LogonService.exe
Service的卸载
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\InstallUtil c:\Dr.COM.LogonService.exe /u
将服务安装后,可以在管理工具|服务中去启动他,这样,即使机器重启或者长时间没数据流量,也能保证不断网,使得某些需要定时联网的程序正常工作
参考资料
  1. http://support.microsoft.com/kb/842793/zh-cn
  2. http://support.microsoft.com/kb/820639/zh-cn
  3. http://lonely7345.javaeye.com/blog/249015

VB.NET实现Dr.COM自动登录

Imports System.Text
Imports System.Net

Module Module1

    Sub Main()
        Dim MyClient As New WebClient
        Dim MyURL, srcString As String
        Dim data As String
        Dim postData As Byte()
        Dim responseData As Byte()

        MyURL = "http://10.29.0.250/F.htm"
        data = "DDDDD=你的用户名&upass=你的密码&0MKKey=登录 Login"

        postData = Encoding.ASCII.GetBytes(data)
        responseData = MyClient.UploadData(MyURL, "POST", postData)
        srcString = Encoding.UTF8.GetString(responseData)

        'Console.WriteLine(srcString)
        'Console.ReadKey()

    End Sub

End Module

2009年4月13日星期一

使用curl实现Dr.COM Hotspot上网验证系统的登录

方便在Linux环境下使用,呵呵

curl -d "DDDDD=你的账号&upass=你的密码&0MKKey=%u767B%u5F55%20Login"  http://10.29.0.250/F.htm

[原创]通过Java程序实现Dr.COM Hotspot的上网验证

package drcom;

import java.io.IOException;
import java.io.InputStream;

import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;

public class Login {

    String userAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; InfoPath.1; .NET CLR 2.0.50727; MAXTHON 2.0)";
    HttpClient client = new HttpClient();
    static final String TARGET_SITE = "10.29.0.250";
    static final int TARGET_PORT = 80;
    public static void main(String[] args) throws HttpException, IOException {
        Login l=new Login();
        PostMethod method=new PostMethod("http://10.29.0.250/F.htm");
        l.initMethod(method);
        l.fillLogonData(method);
        method.setRequestHeader("Referer","http://10.29.0.250/");
        l.client.executeMethod(method);
        String s=l.getResponse(method);
        System.out.println(s);
    }
    public Login() {
        client.getHostConfiguration().setHost(TARGET_SITE, TARGET_PORT);
    }

    public void initMethod(HttpMethod method) {
        method.setRequestHeader("User-Agent", userAgent);
        method.setRequestHeader("Accept-Encoding", "gzip, deflate");
        method.setRequestHeader("Accept-Language", "zh-cn");
        method.setRequestHeader("Accept", "*/*");
        method.setRequestHeader("Connection", "Keep-Alive");
        method.getParams().setCookiePolicy(CookiePolicy.RFC_2109);
        method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
                new DefaultHttpMethodRetryHandler());
    }
    public String getResponse(HttpMethod method) throws IOException {
        InputStream is = method.getResponseBodyAsStream();
        StringBuffer buf = new StringBuffer();
        byte b[] = new byte[16384];
        int len = 0;
        while ((len = is.read(b)) > 0) {
            buf.append(new String(b, 0, len, "gb2312"));
        }
        String response = buf.toString();
        return response;
    }
    public void fillLogonData(PostMethod method) {
        NameValuePair[] data = new NameValuePair[3];
        data[0] = new NameValuePair("DDDDD", "username");
        data[1] = new NameValuePair("upass", "password");
        data[2]=new NameValuePair("0MKKey","登录 Login");
        method.addParameters(data);
    }

}

2009年3月27日星期五

Linux下安装iscsi-initiator

转自 http://clusters.blog.51cto.com/632801/123773

1.1 连接ISCSI

操作系统:redhat linux AS 5(默认安装)

Iscsi包:  iscsi-initiator-utils-6.2.0.742-0.5.el5.i386.rpm

1.1.1 安装rpm包
[root@linux ~]# rpm –ivh iscsi-initiator-utils-6.2.0.742-0.5.el5.i386.rpm

运行此命令后,会生成一个目录/etc/iscsi,该目录下有两个文件:

Initiatorname.iscsi和iscsid.conf

1.1.2 启动ISCSI服务

安装完iscsi服务默认是关闭的,需要手工启动

[root@linux ~]# cd /etc/init.d

[root@linux ~]# ./iscsi start

1.1.3 搜寻盘阵
运行以下命令搜寻target,即目标端:存储设备

[root@linux ~]#iscsiadm --mode discovery --type sendtargets --portal 192.168.1.221

以上IP即是存储设备IP

1.1.4 显示盘阵
显示存储端target name

[root@linux ~]# iscsiadm --mode node

显示结果与在7612i串口 iscsi management→iscsi node名字相同

1.1.5 登陆盘阵
target登陆
[root@linux ~]#iscsiadm --mode node --targetname targetname --portal 192.168.1.221:3260 --login

经过以上几步,fdisk–l就可以看到所挂接分区了!!!

(为确保重启后也能看到,再修改一下/etc/iscsi/iscsid.conf
[root@linux ~]# vi /etc/iscsi/iscsid.conf
iscsiadm --mode node --targetname targetname --portal 192.168.1.221:3260 –login
添加到该文件中的开始部分
设置服务启动chkconfig --level 35 iscsid .)

其实这个文件大多数内容处于被注释状态,该命令添加位置应该影响不大.然后重启电脑后直接fdisk –l 依然可以看到所挂接的分区。至此iscsi所有操作完成,但挂载的分区不是linux所识别,必须使用FDISK进行磁盘分区。
1.2 设置分区
1.2.1 使用fdisk命令进行磁盘分区

fdisk是各种Linux发行版本中最常用的分区工具,是被定义为Expert级别的分区工具。我们可以通过fdisk来分区使用iscsi设备。它还包括一个二级选单,首先输入命令,然后出现问答式界面,用户通过在这个界面中输入命令参数来操作fdisk。

# fdisk /dev/hdb

运行后出现fdiak的命令提示符:

Command (m for help):

使用n命令创建一个分区,会出现选择主分区(p primary partition)还是扩展分区(llogical)的提示,通常选用主分区。然后按照提示输入分区号(Partion number(1-4):)、新分区起始的磁盘块数(FirstCylinder)和分区的大小,可以是以MB为单位的数字(Last cylindet or +siza or +sizeM or+sizeK:)。例如:

[root@linux ~]#fdisk /dev/sdb

查看分区,如果是第一次操作时,显示为无。

Command (m for help):p

Disk /dev/sdb:255 heads, 63 sectors, 4427 cylinders

Units = cylinders of 16065 * 512 bytes

Device Boot    Start       End    Blocks   Id  System

建立分区

Command (m for help):n

Command action

e   extended

p   primary partition (1-4)

p

Partition number (1-4): 1

First cylinder (1-4427, default 1):

Using default value 1

Last cylinder or +size or +sizeM or +sizeK (1-4427, default 4427):

Using default value 4427

保存分区信息

Command (m for help):w

The partition table has been altered!

Calling ioctl() to re-read partition table.

WARNING:If you have created or modified any DOS 6.x

partitions, please see the fdisk manual page for additional

information.

Syncing disks.
1.2.2 现在验证新分区:

[root@linux ~]# fdisk /dev/sdb

The number of cylinders for this disk is set to 4427.

There is nothing wrong with that, but this is larger than 1024,

and could in certain setups cause problems with:

1) software that runs at boot time (e.g., old versions of LILO)

2) booting and partitioning software from other OSs

(e.g., DOS FDISK, OS/2 FDISK)

Command (m for help):p

Disk /dev/sdb:255 heads, 63 sectors, 4427 cylinders

Units = cylinders of 16065 * 512 bytes

Device Boot    Start       End    Blocks   Id  System

/dev/sdb1             1      4427  35559846   83  Linux

Command (m for help):q
1.2.3 格式化分区

[root@localhost ~]# mkfs -t ext3 /dev/sdb1

mke2fs 1.39 (29-May-2006)

Filesystem label=OS type: Linux

Block size=4096 (log=2)

Fragment size=4096 (log=2)

214761472 inodes, 429495759 blocks

21474787 blocks (5.00%) reserved for the super user

First data block=0

Maximum filesystem blocks=0

13108 block groups

32768 blocks per group, 32768 fragments per group

16384 inodes per group

Superblock backups stored . blocks:

            32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,

            4096000, 7962624, 11239424, 20480000, 23887872, 71663616, 78675968,

            102400000, 214990848

Writing inode tables: done                          

Creating journal (32768 blocks): done

Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 31 mounts or

180 days, whichever comes first.  Use tune2fs -c or -i to override.

1.2.4 设定加载点:

文件系统必须有一个挂载点,它只是一个空的目录,新文件系统在这里与系统目录树“相连”。经过以上的操作,我的 Linux服务器已经连接到 iSCSI 储存设备, 并且如同Linux 本机上面的一个 SCSI 硬盘一样。 使用的方式几乎一模一样。

假设iSCSI 主机挂载到 /cluster/raid 目录下:

[root@linux ~]# mkdir /cluster/raid

[root@linux ~]# mount  /dev/sda1 /cluster/raid

[root@linux ~]# df

Filesystem       1K-blocks          Used    Available  Use%  Mounted .

/dev/hda1         10080488       2950408     6618012   31%   /

tmpfs              5036316         81172     4699312   0%    /dev/shm

/dev/sda1       1914788196      27040372  1790482212   2%    /cluster/raid
1.2.5 设定自动挂载:

在机器重新启动后自动加载分区,你必须在/etc/fstab中加入相应分区,但分区类型必须市"_netdev".例如加载的分区sdb1:

[root@linux ~]# vi /etc/fstab

/dev/sdb1   /cluster/raid   ext3    ­_netdev     0   0

/dev/sdc1   /data/sdc1      ext3    _netdev     0   0

/dev/sdd1   /data/sdd1      ext3    _netdev     0   0
1.2.6 查看挂载分区:

[root@localhost ~]# df -h

文件系统              容量    已用     可用     已用%      挂载点

/dev/sda1              64G    5.6G      55G     10%         /

tmpfs                 1.7G       0     1.7G      0%         /dev/shm

/dev/sdb1             1.6T    197M     1.5T      1%         /data/sdb1

/dev/sdc1             1.6T    197M     1.5T      1%         /data/sdc1

[转载] openfiler的权限控制

openfiler的共享使用初看起来比较简单,但实际上具体的搭配相当灵活,有时候让人觉得有些混乱,无所适从。

根据我的理解,他的共享权限在3个地方进行限制:

第一,general里面的local network部分的ip设置,这个ip实际上是针对所有访问openfiler的用户的,不单单是对共享的限制,就是说,在这里你添加了ip,其他的pc才能根openfiler进行通信。

第二,就是在make share里面的host access configuation部分,针对某个客户端的具体访问进行设置,按协议来分,cifs/smb、nfs、http和ftp,并且可以设置3中访问级别,none、ro和rw。需要注意的是,每次更改后,最好点上restart services再确定修改,否则的话可能会出现修改无效。

第三,就是group access configuation配置了,这部分最让人糊涂,因为他有个pg项,就是primary group,很长一段时间里,都没搞清楚这个是什么意思,到底有什么用,至少对我是这样。就字面来说,因为openfiler的user是可以加入多个组的,因此必须有个pg属性,但是具体的使用权限体现在那里呢?

在 openfiler中,group access的级别是高于host access的,对于ftp协议,host access的作用仅限于控制用户是否能访问openfiler,如果是none,就不能访问,如果是ro或者rw,就可以访问,因此,使用ftp时, ro和rw是相同的(对于host access中的这是来说),然后具体的是读还是读写有group access里面的设置决定。

在过了host access这一关后,pg属性的作用就会体现出来。举例来说,假定现在有两个共享文件夹,121和222,有两个用户,user1和user2,分别属于组aaa和bbb,也是主组。我们现在对121的make share进行设置。把pg设置在aaa上,那么aaa下的用户user1就有相应的权限,none、ro或者rw,然后对bbb设置none、ro或者 rw。此时,就设置的权限看来,user2也有对121的访问权限,none、ro或者rw之一。这时候用user2这个帐户来登录ftp,你会发现,你根本就看不到121这个文件夹……也就是说,pg属性的组才拥有文件夹的所有权限。

而在nfs协议访问,不存在ftp的这个问题,因为他不需要用户先登录,因此,设置的host access中的ro或rw就会体现出作用,也就是说,使用ftp时,ro和rw要用group access中的设置。

其实,如果更深入一点的话,这种变化你可以在文件夹的uid和gid属性中体现出来,改变不同的权限,这两个值就会相应改变,这两个属性是最可靠的,上面的分析都是根据他们而来。linux下面的权限管理,相当丰富,可以做到很具体的设置,但是也相当复杂,需要慢慢研究。

[转载] 用Openfiler打造中小企业网络存储服务器

转自 http://liuyuanljy.blog.51cto.com/607434/124593

Openfiler是一个强大的基于WEB浏览器的网络存储软件,Openfiler能够在一个单一的框架中提供对基于文件的网络附加存储和基于块的存储区域网络的支持。

Openfiler是在rPath Linux基础上开发的,它能够作为一个独立的Linux操作系统发行。企业版本有三十天的试用期,其它版本是支持开放原代码的。它支持使一台X86-64的系统变为一台支持高达64TB的企业SAN或NAS存储服务器。

Openfiler支持的绝大部分的基于文件的网络协议,它们包括Network File System(NFS)3,Server Message Block/Common Internet File System(SMB / CIFS )(服务器消息块/常见的网际网路档案系统) ,Web-based Distributed Authoring and Versioning基于Web的分布式创作和版本控制( WebDAV )的,即HTTP / 1.1 ,文件传输协议( FTP ) ,和iSCSI 。你还可以使用廉价磁盘冗余阵列0、1 、5、6和10来配置你的磁盘系统 。 openfiler ,它甚至可以结合的验证机制,如轻量级目录访问协议( LDAP ) , Active Directory及网络信息服务( NIS )和Hesiod来进行安全型存储设备存取。

像其它专业的存储服务器一样,Openfiler同样提供文件快照方式来保证数据易于恢复。无论如何,Openfiler提供与专业存储服务器一样的功能、性能及可用性,同时,使用它的花费却远远低于专业的存储服务器。

要想使用Openfiler来打造一台企业级存储服务器,那么对于所使用的硬件就有一定的要求。当然,我在这里所列出的硬件列表,只是我个人所使用的设备,对于你,可以根据自己企业的实际需求,来定制你的系统硬件。但是,硬件的选择也与所使用的存储连接方式有关。当然,硬件性能越高,性能也越好,但是,与此相同的是,其造价也相应增加。当然,对于一个中小企业来说,要打造一台存储服务器,下列的硬件是有必要的2.0GHZ的处理器,1GB以上的内存,至少5GB的剩余磁盘空间,你还需要一块RAID硬件控制卡,卡应当按磁盘连接类型来定。以及最好是1000Mbit的以太网卡。当然,即然是用来做存储服务器,那么你所需要的磁盘是必需的。为了适合做RAID,你最少需要三块独立的磁盘。我的系统使用了三块250G的SATA接口的磁盘。

当你将硬件准备好后,接下的就是得到Openfiler的安装包。它有两种类型,主要取决于你想以普通方式还是以虚拟机方式运行它。可以根据你的需要下载它的相应版本。它所支持的虚拟机包括VMWARE、XEN等。我下载了它的安装ISO,其文件大小为332MB。你可以至www. Openfiler.com去下载。

由于Openfiler是作为一个独立的基于LINUX内核的系统发布的,因此,安装它就如安装一个基本的LINUX发行版本相同,例如REDHAT发行版本。这对于一些读者来说很容易,但是,在安装过程中,还有一些必需注意的部分,就是在安装过程中,你应当指将Openfiler安装到一个指定的磁盘的分区当中。同时,你还应当说输入一些必要的住处,它会在适当的时候给你相应的提示,例如ROOT密码、时区等等。以及在安装时为Openfiler存储服务器的以太网卡指定一个固定IP地址,这样有利于你在以后使用WEB浏览器来管理它。当所有工作完成后,Openfiler安装文件将全部自动完成最后的安装。你所有做的,就是先等待它安装完成后开始着手设置它。在我的AMD3200+ 1G内存、80GSATA磁盘上安装花费差不多达一个小时。

当Openfiler安装完成后,你可以在你的局域网中的任何一台与它同一个网段的主机中,打开任何一个浏览器,在地址栏中输入:https:// Openfiler主机IP地址:446,就可以通过WEB方式对Openfiler进行配置管理。你可以放心的是,Openfiler是通过安全套接字(SSL)来与Openfiler主机的446端口通信的。连接后,将会出现一个常规的登录窗口,要你输入登录用户名和密码,如果你是初次对Openfiler进行配置,那么你可以输入它的默认用户名“openfiler”和默认密码“password”来进行首次登录。在登录后,你首先要做的,就是将这些默认的用户名和密码进行更改。登录后,你将看到一个WEBGUI接口,在此窗口中,你将会开始创建企业网络存储器的工作。

第一步,创建存储卷。单击WEB GUI窗口中的“VOLUMES TAB”标签,然后单击“BLOCK”设备,此时,你就可以选择要创建的物理磁盘。你可以选择系统上磁盘的表现方式,例如SDA、SDB或SDC等。磁盘可以是一个物理磁盘,也可以是一个磁盘阵列的成员。如果你想配置RAID,你应当选择“member of an array”项。

一旦你选择好的磁盘安装方式,在这里选择了RAID方式,那么你接下来就可以开始对所选择的磁盘选择一种RAID方式。至于你使用何种方式的RAID,得看你使用了几块磁盘,以及以后的需要等来定。例如你可以将某块磁盘只作为一各备用方式而非成员方式加入系统RAID中。

然后,你就可以在同一个标签下开始创建逻辑卷。当创建逻辑卷时,你可以为它指事实上一种文件系统,例如XFS或EXT3及ISCSI。要注意的是,当你使用ISCSI共享时,你只能为它们指定同样的文件系统。

当你创建完逻辑卷后,你就可以为它们创建SMB或WEBDAV共享。在共享选项卡中,选择你已经建立的逻辑卷,然后创建一个共享文件夹。然后,你可以指定你的共享文件夹使用SMB、NFS、WEBDAV或RSYNC来连接这些共享文件夹。同时,你至少要为存储服务器指定一个网络或某强网络主机,不然,任何网络主机也不能访问它。你可以在网络选项卡中设备存储服务器所处的网段。我指定了192。168。1。0/24来为共享文件夹的网段。以及使用控制访问当您想要使用的验证机制,如LDAP和Active Directory和你想每个用户或组访问。我选择了公众查阅。检查本地子网配置,并允许读/写( RW光碟)获得使用SMB和WebDAV

如果你要配置ISCSI卷,首先要确保ISCSI服务器已经启用。在ISCSI卷,添加一个openfiler作为一个目标。在此选项卡你可以改变一些ISCSI配置。但是,最后,你得去logical unit number (LUN)映射你所创建的卷与ISCSI绑定。

这样,所有设置工作差不多已经完成。很简单吧。

当所有设置工作完成后,你就可以连接到你的存储服务器,我使用SMB连接映射共享文件夹,必需使用下列格式:\\192.168.100.50\store1.nas.test1。

如果使用WEBDAV的话,你必需使用另一种方式。例如https://192.168.100.50/mnt/store1/nas/test1

如果要使用ISCSI,你还需要在客户端安装一个ISCSI的发起者。例如在WINDOWS下使用ISCSI连接存储服务器时,你得下载一个WINDOWS下的ISCSI初始化器装载器,然后安装,才可以使用存储服务器的IP地址来连接它,然后,在WINDOWS 的资源管理器中就会多出一个ISCSI分区,iSCSI协议可以使用SAN技术,所有操作就如同操作本地磁盘分区一样。

openfiler中的HTTP/WebDAV

WebDAV(Web-based Distributed Authoring and Versioning)是基于 HTTP 1.1 的一个通信协议。它为 HTTP 1.1 添加了一些扩展(就是在 GET、POST、HEAD 等几个 HTTP 标准方法以外添加了一些新的方法),使得应用程序可以直接将文件写到 Web Server 上,并且在写文件时候可以对文件加锁,写完后对文件解锁,还可以支持对文件所做的版本控制。这个协议的出现极大地增加了 Web 作为一种创作媒体对于我们的价值。基于 WebDAV 可以实现一个功能强大的内容管理系统或者配置管理系统。

openfiler支持HTTP/WebDAV。

Windows 2000/XP 安装后已经具备访问基于 WebDAV 协议的 Web 文件夹的功能,而且可以把 Web 文件夹映射为一个本地文件夹,支持拖放、拷贝/粘贴等等功能,使用起来非常方便。

在 Windows 2000/XP 中添加 Web 文件夹的方法是:

打开“网上邻居”

添加网上邻居,在“请键入网上邻居的位置”中输入 Web 文件夹的 URL,例如 http://nas/mnt/myvg/myvol1/sharedfolder,其中nas是openfiler服务器的IP地址或者域名,myvg是所创建的卷组,myvol1是创建的卷,sharedfolder是设置的共享文件夹。然后按照向导的提示继续做就可以了,非常的简单。
配置好了以后你就可以把这个 Web 文件夹当作本地文件夹一样使用了。

如果是使用SMB也可以访问共享文件夹,格式为 \\nas\myvg\myvol1\sharedfolder

注意,必须为openfiler设置用户和网络ACL后才能访问共享文件夹。

openfiler安装之后Rsync Server无法启动的解决方法

after running an update from a new install of Openfiler, ENABLE of RSYNC service does not work. It remains disabled after clicking ENABLE. The function worked before the update.

There's a stuck /var/lock/subsys/rsync file, remove it and the rsync should work.

2009年3月26日星期四

openfiler的internal LDAP server配置

openfiler用户帐户通过LDAP或者Windows活动目录等来配置。

这里说明一下使用内置的LDAP Server的设置。

首先,在Accounts标签页中配置LDAP

勾选LDAP和use local LDAP server,BASE DN一栏填写(假设你机器的域名是nas.yourdomain.com.cn)dc=nas,dc=domain,dc=com,dc=cn;Root Bind DN一栏填写dc=openfiler,dc=nas,dc=domain,dc=com,dc=cn;提交修改。

切换到services标签,enable ldap server。

回到Accounts标签页,即可在右侧的Administration中添加group和user。

openfiler默认在Root Bind DN一栏中的内容是openfiler,如果按照默认的提交,将会造成OpenLDAP配置文件slapd.conf错误。LDAP服务器无法启动。

openfiler的安装

想知道openfiler是什么,请Google。

之前在一台DELL PowerEdge 2950上安装了openfiler做实验,只尝试了基本的安装,没有深入研究配置。这台机器的磁盘配置是2个500G的SAS,可配置成RAID0或者RAID1。

近日,在一台新的2950上安装openfiler,想作为实际应用。用openfiler 2.3启动机器,在复制文件之前都没有问题,安装系统正确地识别出了硬盘。但是在复制文件时出错,居然是“out of disk space”。天哪,那个服务器可是6个750G的SAS硬盘。

在安装过程中发现,系统发现的虚拟驱动器不是通常我认为的1个(因为是做RAID5,我以为是把6个硬盘都弄到一个虚拟驱动器了),进入PERC 6/i的配置程序删除两个虚拟驱动器,并新建一个虚拟驱动器,将所有的磁盘加入。

开始安装系统,使用自动分区,/boot和swap使用默认大小,/在自动分区后改成4096MB足够了。(一定要改,剩下的空间不要分配,在安装完openfiler之后用于添加volume) 系统安装正常,重启后,从浏览器进入 https://IP:446,默认用户名openfiler,密码password。接下来在Volumes标签页中选择Block Devices,将剩余未分配的空间生成Physical Volume。发现无论如何,剩下的3.4TB的空间都无法分配,最多只能创建1.4TB的Volume。

在openfiler社区中找到这篇文章(https://forums.openfiler.com/viewtopic.php?id=3169):

The short of it:
MSDOS - Bootable, must be less than 2TB
GPT - Not bootable, support for > 2TB
The longer explanation and what to do about it:
What this means is that if you've got a single volume on your system that is > 2TB, or you plan to later expand your array past 2TB, then you cannot boot from it.  The solution is to open up your RAID controller BIOS and do one of the following:
1. If your controller does not have an "OS Volume" option and does not support multiple arrays across a given disk: a. boot from something else and use all your drives for data storage, or b. pick two drives and stick them in RAID 1 for your OS and then take the rest of your drives and put them in a RAID level of your choice for your data.
2. If your controller supports an "OS Volume" (I know 3Ware has this, others probably do as well): Create a single array of all your disks and then specify an "OS Volume" of 4-8GB.
3. If your controller does not support an "OS Volume" but can create multiple arrays on a set of disks: Create a small RAID 1 array of 4-8GB across ALL your disks for the OS and then use the remainder of the space in a RAID level of your choice for your data volumes.
The end result should be that you've got a small volume (probably /dev/sda) for your OS and then a large volume (probably /dev/sdb) for your data.
When installing, allow the installer to initialize the OS volume (/dev/sda) but NOT the data volume (/dev/sdb).  If you allow the initialization of the data volume then it will receive an MSDOS table and will act oddly when trying to create a > 2TB PV on it later (this can be fixed if you've already passed this point, though it will require the wipe of your data volume).

于是,再次进入PERC 6/i的配置程序重新创建虚拟驱动器,其中一个虚拟驱动器使用所有磁盘,RAID5,大小设置为6GB;另一个虚拟驱动器也使用所有磁盘,RAID5,使用所有剩余空间。重新安装系统,将系统安装在/dev/sda上。重新启动系统。

参照文章(https://forums.openfiler.com/viewtopic.php?id=3174),SSH登录到openfiler机器:

fdisk does not work with gpt partition tables (use parted) and I've got no idea why you're trying to create a file system directly on the disk (OpenFiler uses LVM).
1. Type "parted /dev/sdb" (assuming your raid volume is sdb)
2. Type "print"
3. If the output says "Disk label type: msdos" then type "mklabel gpt"
4. Type "quit"
From there you should be able to create a PV in the web interface to use the entire volume.

参照上面的4步完成GPT。

使用浏览器登录进入openfiler管理界面,这时可以在Volumes标签页中将所有的剩余空间创建为一个Physical Volume。 之后,再添加Volume Group。然后在Physical Volume中为特定的用途添加不同类型的Volume。