主页 > 苹果商城可以直接下载imtoken吗 > 以太坊如何抵御 Eclipse 攻击
以太坊如何抵御 Eclipse 攻击
什么是日蚀攻击
一、eclipse攻击简介
以太坊的节点发现机制基于Kademlia,但目的不同。 Kademlia 旨在成为一种在分布式对等网络中存储和查找内容的方式,而以太坊仅用于发现新节点。 由于以太坊的节点由公钥表示,不受IP限制,一台机器上可以同时存在多个节点。 攻击者在少数服务器上创建多个节点并主动 ping 受害者的服务器。 通过 Kademlia 协议,攻击者的节点信息将被存储并填充到受害者节点列表中。 接下来就是让受害者重启机器,包括断电、ddos攻击等等。 重启后,攻击者不断ping受害者的节点,建立tcp连接。 一旦受害者的所有tcp连接都被攻击者建立起来,就达到了将受害者与正常网络隔离的目的。 当然,最大的目的应该还是为了双花。
网上关于eclipse攻击的详细介绍很多,这里不再赘述。
在刚才的论文中,提到了以太坊的geth1.8.0解决了eclipse攻击,所以笔者对比了1.8.0和1.7.3来阐明以太坊是如何解决这个问题的。
直接看代码。
以太坊启动时加载p2p网络的过程如下,
cmd/geth/main.go 初始化方法 -> geth -> startNode() -> uTIls.StartNode() -> stack.Start() -> running.Start()
这个running.Start()调用了p2p/server.go中的Start()方法,看看这个方法做了什么:
// Start 开始运行服务器。
// 服务器停止后不能重新使用。
func (srv *Server) Start() (err 错误) {
srv.loopWG.Add(1)
去srv.run(拨号器)
srv.running = true
返回零
}
本文主要解决eclipse攻击相关代码,其他不再介绍。
上面的go srv.run(dialer)连接池管理协程负责维护TCP连接列表,监听各种信号以太坊pow重启,处理peer的增删改查
func(srv *Server) run(dialstate dialer) {
. ..
跑步:
为了 {
调度任务()
选择 {
. ..
case c := "-srv.posthandshake:
// 一个连接已经通过了加密握手所以
// 远程身份已知(但尚未验证)。
如果可信[c.id] {
// 确保在检查 MaxPeers 之前设置可信标志。
c.flags |= trustedConn
}
// TODO:跟踪进行中的入站节点 ID(Peer-Peer)以避免拨打它们。
选择 {
case c.cont "- srv.encHandshakeChecks(peers, inboundCount, c):
案例“-srv.quit:
休息跑步
}
case c := "-srv.addpeer:
// 此时连接已通过协议握手。
// 它的能力是已知的,并且远程身份已经过验证。
错误:= srv.protoHandshakeChecks(同行,inboundCount,c)
如果错误 == 无 {
// 握手完成并通过所有检查。
p := newPeer(c, srv.协议)
// 如果启用了消息事件,则传递 peerFeed
// 对等体
如果 srv。 EnableMsgEvents {
p.events = &srv.peerFeed
}
名称:=截断名称(c.name)
srv.log.Debug("Adding p2p peer", "name", name, "addr", c.fd.RemoteAddr(), "peers", len(peers)+1)
去 srv.runPeer(p)
同行[c.id] = p
如果 p.Inbound() {
入站计数++
}
}
. ..
case pd := "-srv.delpeer:
// 对等点断开连接。
d := common.PrettyDuration(mclock.Now() - pd.created)
pd.log.Debug("移除 p2p peer", "duration", d, "peers", len(peers)-1, "req", pd.requested, "err", pd.err)
删除(同行,pd.ID())
如果PD。 入站(){
inboundCount--
}
}
}
. ..
}
注意加粗的代码,里面有一个inboundCount的操作,当有posthandshake,addpeer message的时候,会先检查,如果add或者del一个peer,会有对应的inboundCount++或者inboundCount--。 查看选中的内容:
protoHandshakeChecks 最终调用 encHandshakeChecks:
func (srv *Server) encHandshakeChecks(peers map [discover.NodeID] *Peer, inboundCount int, c *conn) error {
转变 {
案件! c.is(trustedConn|staticDialedConn) && len(peers) "= srv.MaxPeers:
返回 DiscTooManyPeers
案件! c.is(trustedConn) && c.is(inboundConn) && inboundCount 》= srv.maxInboundConns():
返回 DiscTooManyPeers
案例同行[c.id]! = 无:
返回 DiscAlreadyConnected
案例 c.id == srv.Self().ID:
返回 DiscSelf
默认:
返回零
}
}
inboundConn 指示连接类型是活动连接。
看黑体部分的逻辑:如果连接可信且主动连接,且主动连接的节点数大于srv.maxInboundConns(),则拒绝连接。
可以看出,以太坊通过限制活跃连接数来防止eclipse攻击。 我们顺便看看这个数字是多少:
func(srv *Server) maxInboundConns() int {
返回 srv.MaxPeers - srv.maxDialedConns()
}
func(srv *Server) maxDialedConns() int {
如果 srv.NoDiscovery || srv.NoDial {
返回 0
}
r := srv.DialRatio
如果 r == 0 {
r = defaultDialRatio
}
返回 srv.MaxPeers /r
}
MaxPeers默认为25,defaultDialRatio表示可以接受活跃连接的比例。 默认值为 3以太坊pow重启,因此允许的最大传入 tcp 连接数为 25/3 = 8