pirate/mesh-networking
GitHub: pirate/mesh-networking
一个Python网络拓扑模拟库,用于在单机或多机上创建和测试灵活的mesh网络结构。
Stars: 359 | Forks: 61
# Mesh Networking [](https://pypi.python.org/pypi/mesh-netwrking/) [](https://pypi.python.org/pypi/mesh-networking/) [](https://twitter.com/thesquashSH)
**⚠️ 注意:** 本项目已不再积极维护。如果我重拾此项目,有很多地方我会在第二次开发时做得更好。
目前,我建议仅将其用于小型的玩具项目和测试,切勿用于生产环境,也不要作为你发布给其他人的软件包的依赖项。
```
apt install libdnet python-dumbnet # or `brew install --with-python libdnet`
pip install mesh-networking
```
这是一个帮助你创建和测试模拟网络拓扑的库。它提供了一些简单的构建块,如“Nodes”(节点)、“Links”(链路)和“Filters”(过滤器),帮助你在单台计算机上构建模拟网络,或在任意数量的机器上构建真实网络。
它既适用于本地机器上的 mesh 网络模拟,也适用于现实生活中跨网络的程序连接。在最近的一个项目中,我们将其用作一个[讲故事](https://github.com/cowpig/blockchain)区块链项目的节点发现和通信层。
它与 `scapy` 配合使用非常好,可用于构建和测试网络协议或网络应用程序。Scapy 有助于构建高层网络协议,但它不提供模拟不同底层网络布局的工具。* 这正是 mesh-networking 的用武之地,你可以创建带有接口的虚拟机,编写脚本来发送和接收,并在节点连接时动态改变网络的形状。
该库提供了一些简单的原语来表示网络栈的不同部分。每一层都实现为一个线程,带有一个 `in` 和 `out` 队列,以及一些决定流量如何向前传输的纯函数。
`Node`(计算机)是一种网络连接设备,可以运行 `Programs`(程序)并通过 `Filters`(类似 iptables)和 `Links`(类似网络接口)接收流量。
使用这些简单的构建块,你可以在单台机器上模拟大型网络拓扑,或者连接多台机器,并使用真实的连接通道(如 ethernet、wifi 甚至 IRC)链接它们。
理论上你可以在生产环境中使用它在某些物理链路之上构建虚拟网络,但它是用 python 编写的,所以我不建议将其用于任何对性能要求苛刻的场景。
一个示例用例是构建一个小型聊天网络,你希望节点在 LAN 上自动发现彼此,并能够在聊天室中进行聊天。
```
from mesh.node import Node
from mesh.link import UDPLink
from mesh.programs import Printer
lan = UDPLink('en0', 8080) # traffic will be sent using UDP-broadcast packets to all machines on your LAN
node1 = Node([lan], 'bob', Program=Printer) # programs are just threads with a send() and recv() method
node2 = Node([lan], 'alice', Program=Printer)
(lan.start(), node1.start(), node2.start())
node1.send('hi alice!')
# node2 获取 > 'hi alice!'
# node2 上的 Printer 线程调用了其 recv() 方法并传入 "hi alice!"
# 后续步骤:尝试添加 IRCLink 以允许它们在 LAN 外部通信!
```
## 快速入门指南
**建立一个能在 LAN 上自动发现所有节点的秘密聊天室:**
```
# 安装 package 并 clone repo,然后在不同的终端窗口或不同的计算机上运行其中的多个
# 它们将 autodiscover 任何 peers 并允许您通过 LAN 进行聊天!
python3 examples/lan_chat.py
```
**模拟一个包含 6 个节点的小型网络拓扑:**
```
python3 examples/small_network.py
```
**模拟一个节点间连接随机化的大型网络:**
```
python3 examples/large_network.py
```
要了解 API 和功能,你可以阅读源码并运行一些更复杂的示例。请注意,所有示例都需要 python3 才能运行,尽管该库本身兼容 python2。
```
# 运行上述示例并从源代码安装 package:
git clone https://github.com/pirate/mesh-networking
cd mesh-networking
python3 setup.py install
```

## 功能
该项目允许你在 Python 中构建节点网络,并通过各种物理层在它们之间发送流量。
- 通过创建 `nodes` 并将它们连接起来,模拟大型网络拓扑
- 使用 `links` 连接节点,可以是虚拟的(仅连接计算机上的节点)、UDP(连接 LAN 内的所有节点)或 IRC(通过互联网连接)
- 对进出节点的流量应用数据包 `filters`(类似 iptables,但也支持有状态过滤器!)
- 在节点上运行任意 `programs`,例如回显程序、数据包交换机,甚至是 Web 服务器
- 使用 d3.js 图形 UI `visualize`(可视化)网络并创建/链接节点(WIP)
对于每个 `高亮` 的词,你可以在相应的文件中查找其代码,例如 `filters.py`。
## 目标
**问:** 为什么这个库叫 `mesh-networking` 而不是 `py-networking` 或类似的名字?
**答:** 本项目的最初目标是建立一个测试框架,以便开发一种安全、去中心化且快速的通用 mesh-network 路由系统。
后来我决定将这个库作为一个通用的网络工具发布,并在另一个项目中继续研究 mesh 路由相关的内容。
## Mesh 路由开发进展
有几个组件是从 OSI 网络模型复制而来的,但使用方式与现在不同(IPV6, ARP)。其他部分则必须完全重写(routing, DNS)。
第一步是创建网络中节点的抽象表示,以便我们测试协议,你会 在 `node.py` 中找到它,以及一个可以在 `multinode.py` 中生成多个节点的控制器。你可以使用真实或虚拟的网络接口将节点彼此链接。
第二步是为 MESHP 达成通用协议,并开始设计多台计算机之间的路由算法。有了通用的规范,我们就不会局限于使用 Python。我们可以用 go 或 C 编写客户端,以测试 namecoin 区块链系统和 meshp+mesharp 路由系统的不同细微之处。
目前,我们使用 UDP 广播数据包来模拟两个节点之间的原始 Ethernet BROADCAST 式连接。到达时会剥离 UDP 报头和以太网帧。将来,我想为 [snabbswitch](https://github.com/SnabbCo/snabbswitch) 编写一个包装器,允许我们直接操作网络接口。
### 注意事项:
* TUN/TAP tun0 beef:0/10
* create new loopback interfase lo2 IPV6 only, address beef::0
* SOCKS5 > over tun0
* meshpd attached to tun0, when user wants to send a packet to a mesh node, he sends it to the mesh IPV6 addr on tun0, and meshpd will pick it up, read the header, and route it accordingly over real en0, bt0, vlan0, etc.
* local->tun0:localhost packets to lo2:beef::0 so you can ping yourself
* local->tun0:broadcast packets go out to all mesh nodes in the same zone, and back to lo2
* local->tun0:multicast: packets to individual hosts are routed based on zone mesh routes
* tun0:broadcast->local: packets go to lo2:beef::0 (which userland programs can bind to, like httpd, ftp, etc.)
* tun0:multicast->local: packets go to lo2:beef::0
* tun0:localhost->local: packets go to lo2:beef::0
源地址和目的地址信息存储在 MESHP 报头中,每当它们到达 tun0 时,会被 meshpd 读取。
## 目标(Zooko 三角):
1. 去中心化(无 CA,无 SPOF DNS 服务器)
2. 人类可读(提供能安全解析为我们的 IPV6 mesh eeee:::::::01 地址格式的 DNS)
3. 安全(数据包仅发往其预期目的地)
## 全新技术:
* MESHP(取代 IP 层,扩展了自定义定制的 IPv6 实现)
* MESHDNS(namecoin 风格)
* MESHARP(需要重大更改,以防止新节点加入时 DDoS 整个 mesh 网络)
* MESHTRACEROUTE(显示到达主机所经过的 mesh 跳数的更多细节)
## 待重新实现的技术:
* IPv6(我们将使用遵循 IPv6 格式 eeee:::::::01 的自定义寻址方案)
* IP tables 和路由(通过创建遵循我们自己规则而不是内核规则的虚拟网络接口)
* ARP
* DNS(namecoin 风格 + 公钥,允许将私钥认证和 SSL 证书整合进 dns)
## 我们不会重新实现的技术:
我们可以使用现有的互联网框架中的组件越多,保持真正的互联网和我们的 mesh 网络兼容就越容易:
* Ethernet
* TCP
* UDP
* ICMP
## 使用 MESHP 的典型 HTTP 数据包结构:
我们的 mesh 协议介入并取代了 IP 层,保持其他层不变。为了让它工作,唯一需要的其他操作是访问内核的路由表,允许我们将流量路由到正确的方向。
+ Ethernet frame (normal ethernet with MAC addressing)
+ MESHP Header (instead of IP header)
+ TCP Header (normal TCP)
+ HTTP Header (normal HTTP)
+ Data
## 目前遇到的问题:
Mac OS X 不允许你轻易从网络接口读取原始帧。
在 linux 上,你可以打开一个 raw_socket 并随心所欲地读取:
```
rawSocket = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(0x0003))
data = rawSocket.readto(1024)
```
在 Mac(或任何基于 FreeBSD 的系统)上,这不起作用,因为 AF_PACKET 套接字不可用。
可以使用 pcap 或 BPF/tcpdump 之类的东西来嗅探经过的数据包,但我认为不可能拦截它们(如果我在这一点上错了请纠正我)。
我们被迫通过 python 的 sockets 指定一个端口来绑定,但我们可以使用 `SO_REUSEPORT` 在多个进程之间共享一个端口,这非常酷。这允许两个客户端都接收到发送到该端口的数据包。setblocking(0) 是为了方便(只是要注意,你必须做一些错误处理来检查 socket 是否准备好读或写)。
```
s = socket(AF_INET, SOCK_DGRAM)
s.setsockopt(SOL_SOCKET, SO_REUSEPORT, 1)
s.setblocking(0)
s.bind(('',3003))
ready_to_read, ready_to_write, going_to_error_out = select.select([s], [s], [s], 1) # needed for nonblocking sockets
if s in ready_to_read:
data = s.recvfrom(1024)
```
迄今为止,我在 libdnet(而不是 scapy 或 pypcap)上取得了最大的成功。dnet 代表“dumb networking”,这正是它的含义。这是一个非常简单的 API,用于访问 raw sockets 和网络接口。`dnet.iface('en1').send('HI')` 会将字面上的 "HI" 写入网络接口(没有以太网帧,没有 IP 报头,没有 TCP 报头,只有 'hi')。实际上,你可以利用这一点对个人甚至整个本地网络发起 DDoS 攻击。只需在 `while True:` 循环中运行它。无意义的格式错误数据包流导致 hackerschool 的 wifi 连接在几秒钟内陷入停滞。这种攻击方式的完整代码可以在 `bring_it_down.py` 中找到。
我最近发现的另一个问题是,大多数高端路由器会将 UDP 广播传输限制在其最低可能的传输速率,以防止流量淹没 LAN。这是为了鼓励开发人员使用正确的 multicast,以便数据包只能被定向到感兴趣的接收方,而不是将每个数据包发送给每个 LAN 接收方。有关广播 UDP 传输速率限制的更多信息,请参阅此 [Network Engineering Stack Exchange question] question](http://networkengineering.stackexchange.com/questions/1782/why-does-my-udp-broadcast-wireless-communication-is-capped-at-1mbs/)。
## 酷炫之事:
正如我上面提到的,你可以允许多个进程连接到同一个端口上的同一个 socket,并且它们都会收到发送到该 socket 的每个数据包的副本。这是一个简单的 socket 选项,但其意义重大。现在我们可以让多个客户端监听同一个端口,这意味着对客户端来说这不再是一个端口,它只是一个广播接口。每个客户端都会收到每个数据包。每个客户端处理每个数据包,并过滤掉它不关心的所有内容。
```
datagram_socket = socket(AF_INET, SOCK_DGRAM)
datagram_socket.setsockopt(SOL_SOCKET, SO_REUSEPORT, 1)
```
另一件很酷的事情是,你可以在 python 中创建一个行为像真实接口一样的虚拟虚拟网络接口。下面的设置允许我们向任何接口写入和接收广播 UDP 数据包。为了模拟我们的 mesh 网络协议(位于 IP 层,比 UDP 低一级),我们打算简单地截断我们接收的每个数据包的 IP 和 UDP 报头。由于 UDP 允许我们进行广播网络传输,我们可以通过假装没有从系统通过 IP 和 UDP 获得任何路由帮助,来模拟与另一台计算机处于同一硬件链路上的以太网层级。然后我们可以附加自己的路由协议,鉴于没有更好的名字,我称之为 "MESHP"。MESHP 扩展了 IPv6 并允许 mesh 风格的 adhoc 数据包路由,但这留待以后再说。下面是创建硬接口和虚拟接口的代码。
```
class HardLink:
name = "en"
readface = None
writeface = None
def __init__(self, iface="en1"):
self.name = iface
self.writeface = socket(AF_INET, SOCK_DGRAM)
self.writeface.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
self.writeface.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
self.writeface.setblocking(0)
self.readface = socket(AF_INET, SOCK_DGRAM)
self.readface.setsockopt(SOL_SOCKET, SO_REUSEPORT, 1)
self.readface.setblocking(0)
self.readface.bind(('',3003))
def send(self, indata):
_1, ready_to_write, _2 = select.select([], [self.writeface], [], 1) # needed for nonblocking sockets
if ready_to_write:
self.writeface.sendto(indata, ('255.255.255.255', 3003))
else:
print("NETWORK ERROR: WRITE FAILED") # this should never happen unless the interface goes down or you run out of memory to buffer packets
def recv(self):
ready_to_read, _1, _2 = select.select([self.readface], [], [], 1) # needed for nonblocking sockets
if ready_to_read:
return self.readface.recvfrom(1024)
else:
return ""
class VirtualLink:
name = "vlan"
data = []
def __init__(self, iface="vlan0"):
self.name = iface
def send(self, indata):
self.data.append(indata)
def recv(self):
if self.data:
return self.data.pop()
```
由于这两种 Link 类型具有相同的访问器方法,我们可以将节点连接到真实接口或虚拟接口,并观察它们的行为。同时连接到真实链路和虚拟链路的节点可以在两者之间传递数据包,充当所有其他节点的网桥。
```
red, green, blue, purple = HardLink("en1"), VirtualLink(), VirtualLink(), VirtualLink()
nodes = [Node([red, green, blue]),
Node([red, green]),
Node([green, blue]),
Node([purple]),
Node([green, purple],
Node([purple, red]))
]
for node in nodes:
node.start()
nodes[0].send("HELLO")
```
每个节点接受它所连接的链路列表。一条链路上的所有节点就像一个广播以太网。你可以将其想象为一堆使用红色、绿色、蓝色和紫色以太网线相互连接的服务器。除了红色链路实际上是真实链路,允许你通过 wifi、蓝牙或任何其他硬件接口测试你的节点。绿色、蓝色和紫色允许你在本地计算机上模拟网络分支以测试拓扑。这很酷的部分在于,它允许你使用几台通过以太网线或 wifi 连接的笔记本电脑来模拟一个复杂的 350 节点网络。要查看 Node 类的代码,请查看 `node.py`。
## 链接
#### 相关项目
类似的 Python 网络构建块 / 玩具 / 模拟库:
- [`Mininet`](https://github.com/mininet/mininet) — 具有用于模拟的 Python API 的完整网络仿真(主机、交换机、链路)
- [`FNSS`](https://fnss.github.io/) — Fast Network Simulation Setup — 拓扑即代码(topology-as-code),带有 ns-2, ns-3, Mininet 等适配器
- [`pypacker`](https://github.com/mike01/pypacker) — 最快/最简单的 Python 数据包操作库(精简的 scapy 替代品)
- [`py2p`](https://pypi.org/project/py2p/) — 具有简单 `MeshSocket` API 的点对点 mesh 网络
- [`AnyMesh`](https://github.com/AnyMesh/anyMesh-Python) — 基于 Twisted 构建的去中心化自动发现/自动连接 mesh API
- [`mrpc-python`](https://github.com/alex-sherman/mrpc-python) — 用于 mesh 拓扑的轻量级 RPC 框架,面向 IoT
- [`Meshtastic`](https://github.com/meshtastic/python) — 用于 Meshtastic LoRa mesh 设备的 API
#### 更多链接
* http://dpk.io/blockchain
* http://www.aaronsw.com/weblog/squarezooko
* http://www.aaronsw.com/weblog/uncensor
* https://squaretriangle.jottit.com/faq
* http://libdnet.sourceforge.net/pydoc/public/frames.html
* https://github.com/SnabbCo/snabbswitch
* https://github.com/ewust
* https://en.wikipedia.org/wiki/IEEE_802.1aq (Shortest-Path-Bridging)
* https://developer.apple.com/reference/multipeerconnectivity (Apple's mesh framework)
* http://www.secdev.org/projects/scapy/
* http://battlemesh.org/ (Mesh Networking Battle conf)
* https://www.zerotier.com/ ("Mesh" vlan that can scale up to millions of nodes using social routing)
* http://redecentralize.org/interviews/2013/07/30/02-adam-zerotierone.html (quick explanation of zerotier)
标签:DNS解析, Google搜索, IP 地址批量处理, P2P, Scapy, SOC Prime, 内核驱动, 分布式系统, 区块链, 响应大小分析, 密码管理, 对等网络, 开发工具, 开源项目, 模拟测试, 流量捕获, 网状网络, 网络仿真, 网络协议, 网络堆栈, 网络拓扑, 网络编程, 网络过滤器, 自定义脚本, 节点发现, 逆向工具, 链路模拟, 防御绕过