以神卓互联为例,内网穿透是一种将局域网里的利用端口公布到公网拜访的一种技术,这里的局域网是指NAT之后的网络。比方家里有一台笔记本,连贯路由器的WIFI,笔记本上有一个Tomcat或者web利用,端口是8080,这个时候只能够通过家庭的局域网关上拜访,同学在家里就不能拜访你的笔记本上的web利用,而在笔记本上装置一个神卓互联的内网穿透客户端,增加一个须要映射的端口就能够实现同学在里面拜访你的笔记本上的web利用,是不是很神奇。
利用场景
提供内网穿透服务
连贯内网服务器,在外网演示内网web站点
无需服务器部署,疾速调试本地程序,微信公众号开发利器
反对http、https协定站点,省去证书中间件简单配置,http协定站点间接降级为https站点
反对TCP,UDP协定端口转发。反对数据库、SSH、远程桌面、网络摄像头等等凋谢到外网 包含但不限于以上场景。
内网穿透协定
规范的内网穿透协定是WanGooeTunnel通信协议
实现的性能
让外网申请通过各种简单的路由和防火墙拜访到内网的设施
成熟的内网穿透产品
目前国内正规的内网穿透产品是神卓互联和花生壳,商业化和成熟度都比拟高客户群体有比拟大。
实现内网穿透的办法
内网穿透基本上是以C语言实现,因为对性能的要求比拟高
如何实现数据包的转发,因为内网穿透反对的协定比拟多,这里就写一个简略的数据转发的代码,具体要实现成熟的性能还有很长的路要走
tcp_server* tcp_server::server_ptr = NULL;tcp_server::tcp_server(){} tcp_server::tcp_server(const tcp_server&){} bool tcp_server::server_listen(){ listen_fd = socket(AF_INET, SOCK_STREAM, 0); if (listen_fd < 0) { perror("socket"); return false; } addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; addr.sin_port = htons(8851); int ret = bind(listen_fd,(struct sockaddr*)&addr,sizeof(addr)); if (ret < 0) { perror("bind"); return false; } ret = listen(listen_fd,128); if (ret < 0) { perror("listen"); return false; } //创立epoll树 epoll_tree = epoll_create(1); //上epoll树 struct epoll_event evt; evt.data.fd = listen_fd; evt.events = EPOLLIN; ret = epoll_ctl(epoll_tree, EPOLL_CTL_ADD, listen_fd, &evt); if (ret == -1) { perror("epoll_ctl"); std::cout << "listen fd:" << listen_fd << std::endl; std::cout << "epoll_tree fd:" << epoll_tree << std::endl; return false; } std::cout << "established listen and create epoll tree" << std::endl; return true;} void tcp_server::server_run(){ if (!server_listen()) { std::cout << "server listen error" << std::endl; server_close(); return; } int size = sizeof(epr) / sizeof(epoll_event); //将所有被动连贯的socket都记录并监听 std::cout << "main server loop start" << std::endl; while(1) { epoll_count = epoll_wait(epoll_tree, epr, size, -1); for (int i = 0; i < epoll_count; i++) { if (epr[i].data.fd == listen_fd) { //判断是不是监听文件,如果监听文件有变动则将对应的通信文件增加到epoll树和vector int cfd = accept(listen_fd, NULL, NULL); if (cfd < 0){ perror("accept"); continue; } epoll_event evt; evt.data.fd = cfd; evt.events = EPOLLIN; int ret = epoll_ctl(epoll_tree, EPOLL_CTL_ADD, cfd, &evt); if (ret == -1) { perror("epoll_ctl"); return ; } accept_list.push_back(cfd); std::cout << "Add a link file" << std::endl; } else{ //获取音讯并退出音讯队列或转发 char buf[100] = { 0 }; int count = recv(epr[i].data.fd, buf, sizeof(buf), 0); if (count <= 0 ){ perror("recv"); continue; } for (auto it : accept_list){ //转发数据 if (it != epr[i].data.fd){ send(it, buf, count, 0); std::cout << "send data: " << buf << " file describes: " << it << std::endl; } } } } }} void tcp_server::server_close(){ for (auto it : accept_list){ close(it); } close(listen_fd); close(epoll_tree);} tcp_server* tcp_server::getinstance(){ if (server_ptr != nullptr){ return server_ptr; } server_ptr = new tcp_server; return server_ptr;}
以上是通过epoll来实现高性能的端口数据转发,只反对linux零碎,不反对windows,因为windows里没有epoll。
以下是神卓互联内网穿透windows版客户端绑定通道后的截图:
Linux版以ubuntu为例,装置之前须要先装置C++环境,
apt-get install g++
如图所示:
到此运行环境装置实现
接下来间接装置就能够了