以太坊是如何解决日蚀攻击(eclipse attack)的?
发布日期:2019-09-07 10:39:48
浏览:次
什么是日蚀攻击
首先简单介绍一下日蚀攻击
以太坊的节点发现机制基于Kademlia,但其目的却不同,Kademlia旨在成为在分布式对等网络中存储和查找内容的手段,而以太坊仅用于发现新的节点。由于以太坊的节点是由其公钥表示的,并且不受IP限制,因此在一个机器上可以同时存在很多节点。攻击者在很少的服务器上制作出很多的节点,并积极的ping受害者的服务器。通过Kademlia协议,攻击者的节点信息将存储并填充在受害者节点列表中。下一步就是让受害者重启机器,手段包括断电、ddos攻击等等。重启后,攻击者再不停的ping被害者的节点以建立tcp连接,一旦被害者所有的tcp连接都是攻击者制造的,那么就达到了把被害者与正常的网络隔离的目的,当然最大的目的应该还是为了双花。有一篇论文是专门介绍日蚀攻击的,大家可以找来看看。
网上有很多关于日蚀攻击的详细介绍,在这里不做赘述。
以太坊是如何防止日蚀攻击的
在刚才提到的论文中,提到了以太坊的geth1.8.0解决了日蚀攻击,于是作者拿1.8.0和1.7.3做对比,理清了以太坊解决这个问题的做法。
直接看代码。
以太坊启动时加载p2p网络的流程如下,
cmd/geth/main.go init方法-> geth -> startNode() -> utils.StartNode() -> stack.Start() -> running.Start()
这个running.Start()调用的即是p2p/server.go中的Start()方法,看看这个方法做了什么:
// Start starts running the server.// Servers can not be re-used after stopping.func (srv *Server) Start() (err error) { ...... srv.loopWG.Add(1) go srv.run(dialer) srv.running = true return nil}
这篇文章主要关注解决日蚀攻击相关代码,其他的不做介绍。
上面的go srv.run(dialer)连接池管理协程,负责维护TCP连接的列表,监听各种信号,处理peer的增删改
func (srv *Server) run(dialstate dialer) { ...running: for { scheduleTasks() select { ... case c := <-srv.posthandshake: a="" connection="" has="" passed="" the="" encryption="" handshake="" so="" the="" remote="" identity="" is="" known="" (but="" hasn't="" been="" verified="" yet).="" if="" trusted[c.id]="" {="" ensure="" that="" the="" trusted="" flag="" is="" set="" before="" checking="" against="" maxpeers.="" c.flags="" |="trustedConn" }="" todo:="" track="" in-progress="" inbound="" node="" ids="" (pre-peer)="" to="" avoid="" dialing="" them.="" select="" {="" case="" c.cont="">-srv.posthandshake:><- case="">-><-srv.quit: break="" running="" }="" case="" c="" :="">-srv.quit:><-srv.addpeer: at="" this="" point="" the="" connection="" is="" past="" the="" protocol="" handshake.="" its="" capabilities="" are="" known="" and="" the="" remote="" identity="" is="" verified.="" if="" err="=" nil="" {="" the="" handshakes="" are="" done="" and="" it="" passed="" all="" checks.="" p="" :="newPeer(c," srv.protocols)="" if="" message="" events="" are="" enabled,="" pass="" the="" peerfeed="" to="" the="" peer="" if="" srv.enablemsgevents="" {="" p.events="&srv.peerFeed" }="" name="" :="truncateName(c.name)" srv.log.debug("adding="" p2p="" peer",="" "name",="" name,="" "addr",="" c.fd.remoteaddr(),="" "peers",="" len(peers)="" 1)="" go="" srv.runpeer(p)="" peers[c.id]="p" if="" p.inbound()="" {="" }="" }="" ...="" case="" pd="" :="">-srv.addpeer:><-srv.delpeer: a="" peer="" disconnected.="" d="" :="common.PrettyDuration(mclock.Now()" -="" pd.created)="" pd.log.debug("removing="" p2p="" peer",="" "duration",="" d,="" "peers",="" len(peers)-1,="" "req",="" pd.requested,="" "err",="" pd.err)="" delete(peers,="" pd.id())="" if="" pd.inbound()="" {="" }="" }="" }="">-srv.delpeer:>
注意加粗的代码,有一个针对inboundCount的操作,当有posthandshake、addpeer消息的时候,会先去check,如果add或del了一个peer,则有对应的inboundCount 或者inboundCount--。看看到底check了什么:
protoHandshakeChecks最终也是调用encHandshakeChecks:
func (srv *Server) encHandshakeChecks(peers map[discover.NodeID]*Peer, inboundCount int, c *conn) error { switch { case !c.is(trustedConn|staticDialedConn) && len(peers) >= srv.MaxPeers: return DiscTooManyPeers case peers[c.id] != nil: return DiscAlreadyConnected case c.id == srv.Self().ID: return DiscSelf default: return nil }}
inboundConn表示连接类型为主动连接过来。
看加粗的这段逻辑:如果该连接是信任的,且是主动连接过来的,且主动连接过来的节点数量大于srv.maxInboundConns()时,则拒绝此连接。
可以看出来,以太坊是通过限制主动连接过来的数量来阻止日蚀攻击的。我们顺便看下这个数量是多少:
func (srv *Server) maxInboundConns() int { return srv.MaxPeers - srv.maxDialedConns()}func (srv *Server) maxDialedConns() int { if srv.NoDiscovery || srv.NoDial { return 0 } r := srv.DialRatio if r == 0 { r = defaultDialRatio } return srv.MaxPeers / r}
MaxPeers默认是25,defaultDialRatio表示能够接受主动连接的比例,默认是3,所以最多允许传入的tcp连接数量就是25/3 = 8个
- 193811AAX 价格竞猜活动 (8
- 189122万字回顾NFT市场发展
- 175233全览60个永续合约协议
- 162264Gate.io 双周报2021年
- 145955Gate.io 双周报2021年
- 113496Oleksandr Usyk 限量
- 110017星球日报 | BALD近乎
- 105598ETH周报 | 以太坊创世
- 97849法币出售流程(APP版
- 941810一周融资速递 | 15家
- 932211一文梳理模块化Layer2
- 872312Gate.io 联合 APENFT
- 829413AOFEX第22期新项目上
- 791014Gate.io 联合 APENFT
- 762615闪电网络被骂“难用”
- 732916币赢研究院——Liquid
- 720417Gate.io 今日智能量化
- 716218Gate.io OpenPunks 全
- 706619Gate.io 今日智能量化
- 706620Gate.io 今日智能量化
- 706421Gate.io 今日智能量化
- 706422Gate.io 今日智能量化
- 705623Gate.io 今日智能量化
- 703724Gate.io 今日智能量化
- 692625ATA、MASK上线DeFi矿
- 669126Gate.io 今日智能量化
- 648527Gate.io 创世OpenPunk
- 648228Gate.io 今日智能量化
- 639229ETH 限时折扣第二期,
- 637930Gate.io 今日智能量化