两网隔离情况下非法连接外网的检测

现在一些单位为了避免资料泄露,都实行了隔离外网的措施,但是这样的单位往往分支机构比较多,很难保证所有的下级分支机构不会自己接入光纤、开通ADSL,实际上造成了内网、外网两网隔离工作的失败。这里提出一个在两网隔离情况下非法连接外网的检测方法,这个也是一个08年工作内容之一的总结。

首先,我们需要向所有用户工作用机部署一个常态运行的软件,可以是桌面管理程序,也可以是其他均需要有的程序,我们在这个程序的基础上做一定的开发工作。

业务流程图如下:

外网检测业务流程图

首先在某个应用MIS中完成对部门、人员、IP段是否可以连通互联网的权限进行设置,有连通互联网权限的终端可以不做外网连接检测,相当于设置外网连接检测的免检名单。

根据设置的连接外网检测权限和系统设置的本地Web应用URL前缀、外连检测URL、外联检测程序尝试使用路由检测、IE历史记录检测、maxthon历史记录检测、Firefox历史记录检测、代理上网检测、其他常用网络软件检测等手段检测桌面终端和外网连通情况。这种方式避免传统靠检测附加硬件设备(判断是否存在Modem等)判定的方式的局限性,更为通用和有效。

路由检测法:尝试路由到指定IP,并获取返回的路由结果。判定给定网关前缀是否在路由链中,如果在则说明通过路由检测,否则说明存在连接外网行为。

IE历史记录检测:通过编程实现获取IE的浏览页面历史记录,并剔除URL前缀符合管理员设置的本地web应用URL(自动剔除file://开头的本地文件URL),形成桌面终端用户访问网页历史记录,判定用户是否访问外网。

Firefox历史记录检测:探测firefox路径,通过编程实现获取Firefox的浏览页面历史记录,并剔除URL前缀符合管理员设置的本地web应用URL(自动剔除file://开头的本地文件URL),形成桌面终端用户访问网页历史记录,判定用户是否访问外网。Firefox 的url历史记录,可参考firefox源代码或者处理local data 目录下\Mozilla\Firefox\Profiles**.default\Cache下的文件。另外,在firefox下访问about:cache可以看到url访问历史记录。

直连及代理上网检测:在系统设定的外连检测url中挑选3~5条作为检测项。直接使用socket连接这些检测项的URL,如果能够正常返回数据,在检测返回的数据中是否包含检测项中指定的检测字符串,如果包含则说明该桌面终端连接到外网,如果连接URL是socket出现错误,则判定不能连接外网。读取注册表(HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\)中的ProxyEnable项,如果值为0或读取失败,则判定不能连接外网,如果值为非0值,读取ProxyServer的值,依次使用该值提供的代理设置,尝试使用代理连接这些检测项的URL,如果能够正常返回数据,在检测返回的数据中是否包含检测项中指定的检测字符串,如果包含则说明该桌面终端连接到外网,如果连接URL是socket出现错误,则判定不能连接外网。

其他常用网络软件检测:根据系统设定的外连检测程序,在系统的进程列表中检测是否存在管理员指定的进程,如果存在则判定连接外网。

其中每个检测所需要的参数均需要通过管理控制台来设置,在检测到有外网连接的时候,可以通过网管工具或者其他手段自动断开内网或者告警。

获取IE访问历史记录参考代码如下:

//Powered by fOx,转载请保留作者信息 : Email Destiny-fOx@hotmail.com
void GetUrlHistoryMethod2()
{
HANDLE hFind = NULL;
DWORD dwSize = NULL;
hFind = ::FindFirstUrlCacheEntryA(“visited:”,NULL,&dwSize);
HANDLE hHeap = ::HeapCreate(NULL,0x100,0x10000000);
LPINTERNET_CACHE_ENTRY_INFOA pInfo = (LPINTERNET_CACHE_ENTRY_INFOA)::HeapAlloc(hHeap,LPTR,dwSize);
hFind = ::FindFirstUrlCacheEntryA(“visited:”,pInfo,&dwSize);
if(hFind)
{
int n = 0;
while(pInfo != NULL)
{
/
typedef struct _INTERNET_CACHE_ENTRY_INFOA {
DWORD dwStructSize; // version of cache system.0
LPSTR lpszSourceUrlName; // embedded pointer to the URL name string.4
LPSTR lpszLocalFileName; // embedded pointer to the local file name.8
DWORD CacheEntryType; // cache type bit mask.C
DWORD dwUseCount; // current users count of the cache entry.10
DWORD dwHitRate; // num of times the cache entry was retrieved.
DWORD dwSizeLow; // low DWORD of the file size.
DWORD dwSizeHigh; // high DWORD of the file size.
FILETIME LastModifiedTime; // last modified time of the file in GMT format.
FILETIME ExpireTime; // expire time of the file in GMT format
FILETIME LastAccessTime; // last accessed time in GMT format
FILETIME LastSyncTime; // last time the URL was synchronized
// with the source
LPSTR lpHeaderInfo; // embedded pointer to the header info.
DWORD dwHeaderInfoSize; // size of the above header.
LPSTR lpszFileExtension; // File extension used to retrive the urldata as a file.
union { // Exemption delta from last access time.
DWORD dwReserved;
DWORD dwExemptDelta;
}; // Exemption delta from last access
} INTERNET_CACHE_ENTRY_INFOA, LPINTERNET_CACHE_ENTRY_INFOA;
/
LPBYTE p = (LPBYTE)(pInfo->lpHeaderInfo);
p += (PWORD)p;
if(p != NULL)
if(p[2] != 0x10)
p = NULL;
else
{
if(p[3] == 0x1F)
p += 4;
else
p = NULL;
}
printf(“[%d] SourceUrlName : %s ,LocalFileName : %s Title : %S \r\n”
,n,pInfo->lpszSourceUrlName,pInfo->lpszLocalFileName,p);
n++;
pInfo = NULL;
dwSize = 1000;
pInfo = (LPINTERNET_CACHE_ENTRY_INFOA)::HeapAlloc(hHeap,LPTR,dwSize);

         <span class="kwrd">if</span>(pInfo == NULL)
         {
              DWORD dwError = ::GetLastError();
              printf(<span class="str">"HeapAlloc Error : %d\r\n"</span>,dwError);
         }
         BOOL bSus = ::FindNextUrlCacheEntryA(hFind,pInfo,&amp;dwSize);
         <span class="kwrd">if</span>(bSus == FALSE)
         {
              pInfo = NULL;
              DWORD dwError = ::GetLastError();
              printf(<span class="str">"Error : %d\r\n"</span>,dwError);
         }
    }
    ::FindCloseUrlCache(hFind);
    ::HeapDestroy(hHeap);
}

}