接上篇 N2N API的一些折腾,于是就动手自己做了一个基于Python的N2N API Web Server
如果你只是为了在自建服务器上跑这个API Server,直接跳到使用步骤即可
代码
注:本示例使用BaseHTTPServer库搭建HTTP服务,非常简易,仅提供一个思路
Python2
http://file.bugxia.com/n2n/n2n-api-python2.py
# -*- coding: utf-8 -*-
import json
import sys
import urlparse
import socket
import string
import random
from BaseHTTPServer import BaseHTTPRequestHandler,HTTPServer
reload(sys)
sys.setdefaultencoding('utf-8')
SUPERNODE_HOST = "127.0.0.1"
SUPERNODE_MGT_PORT = 5645
HTTP_PORT = 58888
METHODS = ['supernodes','edges','communities','reload_communities','timestamps','packetstats','verbose']
def randomStr(digits=4):
ran_str = ''.join(random.sample(string.ascii_letters + string.digits, digits))
return ran_str
def sendData(data,tag):
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
response = client.sendto((data).encode(),(SUPERNODE_HOST.encode(),SUPERNODE_MGT_PORT))
result = list()
while True:
data = client.recvfrom(2048)
try:
data = data[0].decode('gbk')
except:
data = data[0]
data = json.loads(data)
if data['_tag'] != tag:
break
if data['_type'] == 'end':
break
if data['_type'] == 'begin':
continue
result.append(data)
return result
class N2N_API_Server(BaseHTTPRequestHandler):
def log_message(self, format, *args):
return
def do_GET(self):
method = "edges"
if "From=EasyN2N" not in self.headers['Cookie']:
return
try:
if urlparse.urlsplit(self.path).path == "/edges":
query = urlparse.urlsplit(self.path).query
if query == "":
return
if "&" in query:
community = query.split("&")[0]
tag = query.split("&")[1]
data="r "+tag+":0:bugxia "+method
else:
community = query
tag = randomStr()
data="r "+tag+":0:bugxia "+method
result = sendData(data,tag)
data_ = list()
for i in range(len(result)):
if result[i]["community"] == community:
data_.append(result[i])
else:
method = urlparse.urlsplit(self.path).path.strip("/")
if method not in METHODS:
return
tag = randomStr()
data="r "+randomStr()+":0:bugxia "+method
result = sendData(data,tag)
data_ = result
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps(data_).encode('utf8'))
return
except:
return
try:
server = HTTPServer(('', HTTP_PORT), N2N_API_Server)
print ('Started N2N API HTTP server on port ' , HTTP_PORT)
server.serve_forever()
except KeyboardInterrupt:
print ('shutting down the N2N API HTTP server')
server.socket.close()
Python3
http://file.bugxia.com/n2n/n2n-api-python3.py
# -*- coding: utf-8 -*-
import json
import socket
import string
import random
from urllib import parse
from http.server import BaseHTTPRequestHandler,HTTPServer
SUPERNODE_HOST = "127.0.0.1"
SUPERNODE_MGT_PORT = 5645
HTTP_PORT = 58888
METHODS = ['supernodes','edges','communities','reload_communities','timestamps','packetstats','verbose']
def randomStr(digits=4):
ran_str = ''.join(random.sample(string.ascii_letters + string.digits, digits))
return ran_str
def sendData(data,tag):
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
response = client.sendto((data).encode(),(SUPERNODE_HOST.encode(),SUPERNODE_MGT_PORT))
result = list()
while True:
data = client.recvfrom(2048)
try:
data = data[0].decode('gbk')
except:
data = data[0]
data = json.loads(data)
if data['_tag'] != tag:
break
if data['_type'] == 'end':
break
if data['_type'] == 'begin':
continue
result.append(data)
return result
class N2N_API_Server(BaseHTTPRequestHandler):
def log_message(self, format, *args):
return
def do_GET(self):
method = "edges"
#if "N2N" not in self.headers['Cookie']:
#return
try:
if parse.urlparse(self.path).path == "/edges":
query = parse.urlparse(self.path).query
if query == "":
return
if "&" in query:
community = query.split("&")[0]
tag = query.split("&")[1]
data="r "+tag+":0:bugxia "+method
else:
community = query
tag = randomStr()
data="r "+tag+":0:bugxia "+method
result = sendData(data,tag)
data_ = list()
for i in range(len(result)):
if result[i]["community"] == community:
data_.append(result[i])
else:
method = parse.urlparse(self.path).path.strip("/")
if method not in METHODS:
return
tag = randomStr()
data="r "+randomStr()+":0:bugxia "+method
result = sendData(data,tag)
data_ = result
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps(data_).encode('utf8'))
return
except:
return
try:
server = HTTPServer(('', HTTP_PORT), N2N_API_Server)
print ('Started N2N API HTTP server on port ' , HTTP_PORT)
server.serve_forever()
except KeyboardInterrupt:
print ('shutting down the N2N API HTTP server')
server.socket.close()
使用
pyhton2
wget -O n2n-api.py http://file.bugxia.com/n2n/n2n-api-python2.py
pyhton3
wget -O n2n-api.py http://file.bugxia.com/n2n/n2n-api-python3.py
运行
#前台运行
python n2n-api.py
#或后台运行
nohup python n2n-api.py &
一些参数可在源代码里直接修改
supernode默认管理端口为 5645
WEB API监听端口为 58888
(如果使用 EasyN2N ,请勿改变此端口,否则在软件内无法使用)
WEB API
http://IP:58888/接口
接口
supernodes
暂时没用,原话是“Reserved for edge”,占位用的
edges?community名称
列出当前community下连接的全部edge(客户端、边缘节点)
communities
列出当前supernode下连接的全部community(虚拟小组)
reload_communities
重新加载通过 -c 参数提供的community.list和用户公钥
timestamps
列出一些supernode相关的时间戳(包含start_time\last_fwd\last_reg_super)
packetstats
列出supernode的流量统计数据(包含forward\broadcast\reg_super\errors)
verbose
日志等级,默认为3
当接口为 edges 时,需带上 community名称(小组名称) 作为参数
如:http://IP:58888/edges?bugxia_5555
示例里48、49行注释掉了Cookie相关的代码,实际使用时可根据情况加入Cookie进行简单验证
22 条评论
请问一下大佬,这个python API可以输出类似netcat的可读性表格吗,我最近想搞一下但感觉又无从下手,这个baseHTTPserver能实现吗?
如果可以的话请告诉我需要去哪里学习相关知识
@Pride
python可以用prettytable模块来将数据转化为表格
baseHTTPserver只是一个基本的HTTP服务器模块
这两者没关系
@Bug侠
好的,我去试一下
为什么我用了python3的api,访问地址不论是哪个参数都是空的(访问时已经开了一个连接来测试)
@SDDD
同问
n2n api是要在已经有n2n的服务器上部署的吗
@Tata
是我白痴了 弄好了已经
我又来了 最近在尝试edge端的api的时候发现edge双方在没有建立通信的情况下无法在netcat中显示 要ping一下对方ip才有效果 但不显示就没有ip,没有ip就ping不了,ping不了就不显示 如果要知道这个community里面有多少edge,估计还是得通过supernode端来实现,edge端似乎只能用来“纠错”。
还有个问题,tap-windows9.26我虽然完成了编译和devcon封装,打包出了一个windows系统下的驱动安装包,但是没有签名就不让安装,如果安装的话就必须关secure boot和开testmode,这肯定不利于小白的使用,不知道作者您有没有解决这个签名问题的好方法
@GH
1.调用edge API我也做出来了,然后确实发现有部分edge信息缺失(我也没试过ping他),可能是n2n的bug吧
2.tap 9.26驱动我是直接用的官方的包,虽然没有整合成包,但是里面有tapinstall.exe,我还是通过命令行安装的。至于你说的给exe签名的问题,我也没辙,但是之前写了一篇利用证书配合tapinstall.exe命令行安装的方法,可以绕过安装时的安全提示
作者你好,很高兴看到您更新了2.3版本的N2N启动器,我在使用过程中遇到一些问题与你分享,官方的API其实有服务端和客户端两种。其中服务端获取的list有大概一分钟左右的延迟,即edge下线仍然会有一定时间“残留”在服务端,这导致你重启edge导致内网ip变化时,服务端不能及时更新你的ip(似乎认的是网卡),从而在列表中一直显示更换前的虚拟ip。如果通过客户端的API(netcat 127.0.0.1 5644),就可以及时更新ip,还可以看到你与别的edge的连接情况(比如中转或者P2P),而且这个实现起来似乎比服务端方便一点,也可以直接做进启动器里,以上
@GH
补充一下 客户端API是netcat -u 127.0.0.1 5644 走的是UDP端口
@GH
感谢反馈!其实这个我之前也有注意到,通过API接口和netcat输出内容延迟的问题。两者比较如你所言,netcat会更详细和及时,但是……API输出的是JSON格式,直接解析就可以用,我做这个Python API前其实也有想过输入netcat的内容,但是无奈我的水平有限……
@GH
然后做完这个PythonAPI,我突然发现我做的supernode的API,居然完全没有去做edge的,所以今天都在折腾edge的API,过两天完善以后就发出来
@Bug侠
在supernode的netcat输出内容与API接口是一致的 都会有延迟,都不会在重启edge时给你更新ip(实际上ip是更新了,但在nc输出界面仍然是之前的ip);在edge端使用nc就不会出现这种情况
@GH
牛逼牛逼,下个版本安排!
supernode默认管理端口在源代码里SUPERNODE_MGT_PORT = 35645 ,教程里少个3
另外顺便问问有没有python3版本的n2n-api.py
@鱼仙Fishroud
感谢反馈,已更正!
python3版的稍后附上
@Bug侠
感谢大佬
@鱼仙Fishroud
python3版已更新
@Bug侠
感谢,已经成功部署了
这个接口在EasyN2N上如何使用 好像没有MiniN2N那样的查看小组选项
@GH
下个EasyN2N版本提供这个功能