Node.JS中UDP打洞穿透内网路由,架设内网服务器技术详解及源码

UDP Node.js   2018-01-03 15:21:37 发布
您的评价:
     
0.0
收藏     0收藏
文件夹
标签
(多个标签用逗号分隔)

在制作一款私有云网络存储产品时,很多客户反应,他们希望能远程访问。远程访问内网服务器成本最低的方式应该就是P2P内网穿透了,这里介绍一下实现原理。

UDP穿透原理

打洞主要采用的是udp的无面向连接的特性来实现,同过user1连接server,打通user1的对外ip和端口,然后在一段时间内server都能通过这个端口和IP实现路由穿透,向局域网内的服务器发送消息。

此时user2连接server,打通uer2对外的ip和端口,然后user1和user2通过彼此已经打通的对外ip和端口实现通讯。

这就是P2P不同网络间通信协议的基础。

为了简单起见,这只仅演示从 user1 向 server 打洞穿透的过程。需要先准备一台服务器和一台本地电脑。

UDP打洞源代码

因为UDP是既可以侦听又可以发送数据的,所以node.js的代码实现非常简单,服务器和本地用一套代码即可。命名为 onceair.udp.server.js 此文件接收命令行参数,侦听本地 8090 端口:

var os        = require('os')
var fs        = require('fs')
var net       = require('net')
var dgram     = require('dgram')
var cp        = require('child_process')
var path      = require('path')
var udp       = dgram.createSocket('udp4')

udp.on('message', function(data, ipdr) {
  console.log('message')
  console.log(data.toString())
  console.log(ipdr)
})

udp.on('error', function(err) {
  console.log('error')
  console.log(arguments)
})

udp.on('listening', function(err) {
  console.log('listening')
  console.log(arguments)
})

udp.bind(8090)
console.log('udp listening on port 8090')


var send = function(message, port, host) {
  console.log('send')
  console.log(arguments)
  udp.send(Buffer.from(message), port || 8090, host || 'anynb.com')
}

//called directly in command line
if (require.main === module) {
  var port = parseInt(process.argv[2])
  var host = process.argv[3]
  if (port) {
    send('echo', port, host)
  } else {
    send('echo')
  }
}

示例

将 udp.server 上传到服务器端,然后运行在后台运行,默认侦听 8090 端口

/root/node/bin/node onceair.udp.server.js

在客户端向服务器的 8090 发送消息,同时本地侦听 8090

$ node onceair.udp.server.js 8090 112.124.126.185

服务器端接收到响应,我们看到这里接收到的客户端公网IP是180.173.98.126,端口号是 43191,这是路由转出消息的随机端口,通过这个端口,就能连接到本地UDP侦听的8090端口,即是一个临时的session通道。

message
echo
{ address: '180.173.98.126',
  family: 'IPv4',
  port: 43191,
  size: 4 }

Ctrl + C 中上 onceair.udp.server.js 进程,然后向这个IP和穿透的端口发送数据包,记住操作时间不要太长,否则打通的 session 可能会过期。

/root/node/bin/node onceair.udp.server.js 43191 180.173.98.126

udp listening on port 8090
send
{ '0': 'echo', '1': 43191, '2': '180.173.98.126' }
listening
{}

本地接收到的消息,代表通过已经打通

message
echo
{ address: '112.124.126.185',
  family: 'IPv4',
  port: 8090,
  size: 4 }

TCP的内网穿透

实现基于TCP协议的p2p“打洞”过程中,最主要的问题不是来自于TCP协议,而是来自于来自于应用 程序的API接口。这是由于标准的伯克利(Berkeley)套接字的API是围绕着构建客户端/服务器程序 而设计的,API允许TCP流套接字通过调用connect()函数来建立向外的连接,或者通过listen()和 accept函数接受来自外部的连接,但是,API不提供类似UDP那样的,同一个端口既可以向外连接, 又能够接受来自外部的连接。而且更糟的是,TCP的套接字通常仅允许建立1对1的响应,即应用程 序在将一个套接字绑定到本地的一个端口以后,任何试图将第二个套接字绑定到该端口的操作都会 失败。

因此要实现基于TCP的内网穿透,在内网架设一台HTTP网站,要比UDP复杂得多。

 

来自:http://ourjs.com/detail/5a4c46fe3506837194998bda

 

扩展阅读

使用四种框架分别实现1百万websocket常连接的服务器
Node.js 初体验
消息服务器 Json Messaging
iwebpp.io - 利用Node.js发布Peer/P2P风格的Web Service
深入浅出Nodejs读书笔记

为您推荐

MySql双机热备解决方案
七天学会NodeJS
Snort 中文手册
Cacti监控
Nodejs学习资料

更多

UDP
Node.js
Node.js 开发
相关文档  — 更多
相关经验  — 更多
相关讨论  — 更多