以神卓互联为例,内网穿透是一种将局域网里的利用端口公布到公网拜访的一种技术,这里的局域网是指 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++
如图所示:
到此运行环境装置实现
接下来间接装置就能够了