以太坊是如何防止日蚀攻击的

 什么是日蚀攻击

首先简单介绍一下日蚀攻击

以太坊的节点发现机制基于Kademlia,但其目的却不同,Kademlia旨在成为在分布式对等网络中     存储   和查找内容的手段,而以太坊仅用于发现新的节点。由于以太坊的节点是由其公钥表示的,并且不受IP限制,因此在一个机器上可以同时存在很多节点。攻击者在很少的服务器上制作出很多的节点,并积极的     pi   ng受害者的服务器。通过Kademlia协议,攻击者的节点信息将存储并填充在受害者节点列表中。下一步就是让受害者重启机器,手段包括断电、ddos攻击等等。重启后,攻击者再不停的ping被害者的节点以建立tcp连接,一旦被害者所有的tcp连接都是攻击者     制造   的,那么就达到了把被害者与正常的网络隔离的目的,当然最大的目的应该还是为了双花。

 以太坊是如何防止日蚀攻击的_设计制作_模拟技术

网上有很多关于日蚀攻击的详细介绍,在这里不做赘述。

在刚才提到的论文中,提到了以太坊的geth1.8.0解决了日蚀攻击,于是作者拿1.8.0和1.7.3做对比,理清了以太坊解决这个问题的做法。

直接看代码。

以太坊启动时加载p2p网络的流程如下,

cmd/geth/m     ai   n.go init方法-》 geth -》 startNode() -》 u     ti   ls.StartNode() -》 stack.Start() -》 running.Start()

这个running.Start()调用的即是p2p/server.go中的Start()方法,看看这个方法做了什么:

// Start starts running the server.

// Serve     rs       can   not be re-used af     te   r 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 connec  TI on has passed the encryp  TI on handshake so

// the remote iden  TI ty is known (but hasn‘t been ver     if   ied 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.encHandshakeChecks(peers, inboundCount, c):

case 《-srv.quit:

break running

}

case c := 《-srv.addpeer:

// At this point the connec  TI on is past the protocol handshake.

// Its capabilities are known and the remote identity is verified.

err := srv.protoHandshakeChecks(peers, inboundCount, c)

if err == nil {

// The handshakes are done and it passed all checks.

p := newPeer(c, srv.Protocols)

// If message events are enab     led   , pass the pee     rF   eed

// 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() {

inboundCount++

}

}

。..

case pd := 《-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() {

inboundCount--

}

}

}

。..

}

注意加粗的代码,有一个针对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 !c.is(trustedConn) && c.is(inboundConn) && inboundCount 》= srv.maxInboundConns():

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个
来源: 区块链兄弟

53
140
0
67

相关资讯

  1. 1、《兵界之王》魔族紫将鬼手超燃属性资料曝光721
  2. 2、郎骑竹马弄青梅《芈月传之传奇佳人》手游剧情赏析1126
  3. 3、X三国新版本历史更新公告(持续更新ing)251
  4. 4、《侠客风云传》双十一活动结束侠客OL预约火热进行中215
  5. 5、女主播的游戏上线仅一周注册过十万压抑的男性疯了2173
  6. 6、水火相容《龙门镖局》恭叔与青橙镖师决712
  7. 7、《怪兽大作战》超土豪玩家见面会iPhone7任性送4659
  8. 8、《召唤师》巨人兄弟的相爱相杀一个人一座城1287
  9. 9、修仙实力派冰河游戏《古剑绝学》变强就靠TA537
  10. 10、你的爱心已发送《剑网3》收书小游戏上线869
全部评论(0)
我也有话说
0
收藏
点赞
顶部