美文网首页
双网隔离

双网隔离

作者: 上官宏竹 | 来源:发表于2021-04-22 17:05 被阅读0次

总览

双网隔离是一种安全高效的隔离网络桌面云切换方案,TC只需搭配一个网络切换器,通过切换器便能够在物理隔离的网络之间快速切换,达到快速访问另一个网络的桌面云资源,并且物理隔离,提供了高安全性。

原理

监控系统网线拔插事件,当网线被拔插时触发切换流程。切换流程为:找到与当前WI配对的另一个WI地址,并检查到该WI地址是否连通,如果连通则加载该WI地址。

1、Windows下网线拔插监控

NotifyAddrChange // IPV4地址变化
NotifyIpInterfaceChange // IPV6地址变化
GetAdaptersAddresses  // 获取详细网卡信息

NotifyAddrChange函数主要的功能是用来通知应用程序IPv4地址的变化。注意这个函数仅仅支持IPv4地址的变化,如果需要得到IPv6地址的变化,请使用NotifyIpInterfaceChange。实战经验:通过NotifyAddrChange侦测网络变化
NotifyAddrChange只是简单的告诉我们系统的IP地址发生了变化,但是具体是怎样变化,我们无法从此函数调用中得到。这个时候,我们可以使用GetAdaptersAddresses这一函数来得到当前最新的IP地址来判断。
根据GetAdaptersAddresses接口获取一个网络的详细数据,其中可以获取到IP_ADAPTER_ADDRESSES_LH结构,当中的IF_OPER_STATUS可以知晓网卡状态,为1时表示接口已启动,为2时表示接口已关闭。

2、Linux下网线拔插监控

网络设备在系统中注册、注销和关闭、打开等事件都可以通知给相应的内核组件或用户空间应用程序,其中内核组件通过netdev_chain通知链获取消息,而用户空间应用程序则通过注册Netlink RTMGRP_LINK多播群组获取事件消息
使用netlink协议,循环从内核中读取创建网络设备的信息,判断状态,后获取网线拔插消息。
通过Netlink检测网线插拔

#include <sys/types.h>  
#include <sys/socket.h>  
#include <asm/types.h>  
#include <linux/netlink.h>  
#include <linux/rtnetlink.h>  
#include <stdlib.h>  
#include <stdio.h>  
#include <sys/ioctl.h>  
#include <linux/if.h>  
#include <string.h>  
  
#define BUFLEN 20480  
  
int main(int argc, char *argv[])  
{  
    int fd, retval;  
    char buf[BUFLEN] = {0};  
    int len = BUFLEN;  
    struct sockaddr_nl addr;  
    struct nlmsghdr *nh;  
    struct ifinfomsg *ifinfo;  
    struct rtattr *attr;  

    fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);  

    setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &len, sizeof(len));  

    memset(&addr, 0, sizeof(addr));  

    addr.nl_family = AF_NETLINK;  
    addr.nl_groups = RTNLGRP_LINK;  // 多播群组RTNLGRP_LINK
    bind(fd, (struct sockaddr*)&addr, sizeof(addr));  
    while ((retval = read(fd, buf, BUFLEN)) > 0)  
    {  
        for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, retval); nh = NLMSG_NEXT(nh, retval))  
        {  
            if (nh->nlmsg_type == NLMSG_DONE)  
                break;  
            else if (nh->nlmsg_type == NLMSG_ERROR)  
                return;  
            else if (nh->nlmsg_type != RTM_NEWLINK)  
                continue;  
            ifinfo = NLMSG_DATA(nh);  
            printf("%u: %s", ifinfo->ifi_index,  (ifinfo->ifi_flags & IFF_LOWER_UP) ? "up" : "down" );  
            attr = (struct rtattr*)(((char*)nh) + NLMSG_SPACE(sizeof(*ifinfo)));  
            len = nh->nlmsg_len - NLMSG_SPACE(sizeof(*ifinfo));  
            for (; RTA_OK(attr, len); attr = RTA_NEXT(attr, len))  
            {  
                if (attr->rta_type == IFLA_IFNAME)  
                {  
                    printf(" %s", (char*)RTA_DATA(attr));  
                    break;  
                }  
            }  
            printf("\n");  
        }  
    }  
    return 0;  
}  

3、切换流程

检测到网络状态改变后,发送信号给主消息流程,执行切换流程:找到与当前WI配对的另一个WI地址,并检查到该WI地址是否连通,如果连通则加载该WI地址。

4、检测WI地址是否连通

1、发送ICMP报文探测

ICMP:它是TCP/IP协议簇的一个子协议,用于在IP主机路由器之间传递控制消息。控制消息是指网络通不通、主机是否可达、路由是否可用等网络本身的消息。
Windows下使用IcmpCreateFile IcmpSendEcho两个接口
Linux下,从内核中循环发送和读取ICMP数据包,发送时带一个特定盐值数据,接收时验证。

    struct protoent *proto = getprotobyname("ICMP");
    sock_fd = socket(PF_INET, SOCK_RAW, proto->p_proto);
    setsockopt(sock_fd, SOL_IP, IP_TTL, &ttl_val, sizeof(ttl_val);  // 生存时间
2、利用QNetworkAccessManager实现非ping的探测

对每一个需要探测的WI地址,新建一个QNetworkAccessManager实例,并加入一些特定盐值,在QObject::connect(nam, SIGNAL(finished(QNetworkReply*)), this, SLOT(onAccessibilityFinished(QNetworkReply*)));回调中检测盐值,实现WI是否可达的探测。

相关文章

网友评论

      本文标题:双网隔离

      本文链接:https://www.haomeiwen.com/subject/bwsskltx.html