func (nn *netNotifiee) Disconnected(n inet.Network, v inet.Conn) { // undo the setting of addresses to peer.ConnectedAddrTTL we did ids := nn.IDService() ps := ids.Host.Peerstore() addrs := ps.Addrs(v.RemotePeer()) ps.SetAddrs(v.RemotePeer(), addrs, pstore.RecentlyConnectedAddrTTL) }
func (ids *IDService) consumeObservedAddress(observed []byte, c inet.Conn) { if observed == nil { return } maddr, err := ma.NewMultiaddrBytes(observed) if err != nil { log.Debugf("error parsing received observed addr for %s: %s", c, err) return } // we should only use ObservedAddr when our connection's LocalAddr is one // of our ListenAddrs. If we Dial out using an ephemeral addr, knowing that // address's external mapping is not very useful because the port will not be // the same as the listen addr. ifaceaddrs, err := ids.Host.Network().InterfaceListenAddresses() if err != nil { log.Infof("failed to get interface listen addrs", err) return } log.Debugf("identify identifying observed multiaddr: %s %s", c.LocalMultiaddr(), ifaceaddrs) if !addrInAddrs(c.LocalMultiaddr(), ifaceaddrs) { // not in our list return } // ok! we have the observed version of one of our ListenAddresses! log.Debugf("added own observed listen addr: %s --> %s", c.LocalMultiaddr(), maddr) ids.observedAddrs.Add(maddr, c.RemoteMultiaddr()) }
func (ids *IDService) IdentifyConn(c inet.Conn) { ids.currmu.Lock() if wait, found := ids.currid[c]; found { ids.currmu.Unlock() log.Debugf("IdentifyConn called twice on: %s", c) <-wait // already identifying it. wait for it. return } ch := make(chan struct{}) ids.currid[c] = ch ids.currmu.Unlock() defer close(ch) s, err := c.NewStream() if err != nil { log.Debugf("error opening initial stream for %s: %s", ID, err) log.Event(context.TODO(), "IdentifyOpenFailed", c.RemotePeer()) c.Close() return } defer s.Close() s.SetProtocol(ID) if ids.Reporter != nil { s = mstream.WrapStream(s, ids.Reporter) } // ok give the response to our handler. if err := msmux.SelectProtoOrFail(ID, s); err != nil { log.Debugf("error writing stream header for %s", ID) log.Event(context.TODO(), "IdentifyOpenFailed", c.RemotePeer()) return } ids.ResponseHandler(s) ids.currmu.Lock() _, found := ids.currid[c] delete(ids.currid, c) ids.currmu.Unlock() if !found { log.Debugf("IdentifyConn failed to find channel (programmer error) for %s", c) return } }
func logProtocolMismatchDisconnect(c inet.Conn, protocol, agent string) { lm := make(lgbl.DeferredMap) lm["remotePeer"] = func() interface{} { return c.RemotePeer().Pretty() } lm["remoteAddr"] = func() interface{} { return c.RemoteMultiaddr().String() } lm["protocolVersion"] = protocol lm["agentVersion"] = agent log.Event(context.TODO(), "IdentifyProtocolMismatch", lm) log.Debugf("IdentifyProtocolMismatch %s %s %s (disconnected)", c.RemotePeer(), protocol, agent) }
func (ids *IDService) populateMessage(mes *pb.Identify, c inet.Conn) { // set protocols this node is currently handling protos := ids.Host.Mux().Protocols() mes.Protocols = make([]string, len(protos)) for i, p := range protos { mes.Protocols[i] = string(p) } // observed address so other side is informed of their // "public" address, at least in relation to us. mes.ObservedAddr = c.RemoteMultiaddr().Bytes() // set listen addrs, get our latest addrs from Host. laddrs := ids.Host.Addrs() mes.ListenAddrs = make([][]byte, len(laddrs)) for i, addr := range laddrs { mes.ListenAddrs[i] = addr.Bytes() } log.Debugf("%s sent listen addrs to %s: %s", c.LocalPeer(), c.RemotePeer(), laddrs) // set our public key ownKey := ids.Host.Peerstore().PubKey(ids.Host.ID()) if ownKey == nil { log.Errorf("did not have own public key in Peerstore") } else { if kb, err := ownKey.Bytes(); err != nil { log.Errorf("failed to convert key to bytes") } else { mes.PublicKey = kb } } // set protocol versions pv := LibP2PVersion av := ClientVersion mes.ProtocolVersion = &pv mes.AgentVersion = &av }
func (ids *IDService) consumeReceivedPubKey(c inet.Conn, kb []byte) { lp := c.LocalPeer() rp := c.RemotePeer() if kb == nil { log.Debugf("%s did not receive public key for remote peer: %s", lp, rp) return } newKey, err := ic.UnmarshalPublicKey(kb) if err != nil { log.Errorf("%s cannot unmarshal key from remote peer: %s", lp, rp) return } // verify key matches peer.ID np, err := peer.IDFromPublicKey(newKey) if err != nil { log.Debugf("%s cannot get peer.ID from key of remote peer: %s, %s", lp, rp, err) return } if np != rp { // if the newKey's peer.ID does not match known peer.ID... if rp == "" && np != "" { // if local peerid is empty, then use the new, sent key. err := ids.Host.Peerstore().AddPubKey(rp, newKey) if err != nil { log.Debugf("%s could not add key for %s to peerstore: %s", lp, rp, err) } } else { // we have a local peer.ID and it does not match the sent key... error. log.Errorf("%s received key for remote peer %s mismatch: %s", lp, rp, np) } return } currKey := ids.Host.Peerstore().PubKey(rp) if currKey == nil { // no key? no auth transport. set this one. err := ids.Host.Peerstore().AddPubKey(rp, newKey) if err != nil { log.Debugf("%s could not add key for %s to peerstore: %s", lp, rp, err) } return } // ok, we have a local key, we should verify they match. if currKey.Equals(newKey) { return // ok great. we're done. } // weird, got a different key... but the different key MATCHES the peer.ID. // this odd. let's log error and investigate. this should basically never happen // and it means we have something funky going on and possibly a bug. log.Errorf("%s identify got a different key for: %s", lp, rp) // okay... does ours NOT match the remote peer.ID? cp, err := peer.IDFromPublicKey(currKey) if err != nil { log.Errorf("%s cannot get peer.ID from local key of remote peer: %s, %s", lp, rp, err) return } if cp != rp { log.Errorf("%s local key for remote peer %s yields different peer.ID: %s", lp, rp, cp) return } // okay... curr key DOES NOT match new key. both match peer.ID. wat? log.Errorf("%s local key and received key for %s do not match, but match peer.ID", lp, rp) }
func (ids *IDService) consumeMessage(mes *pb.Identify, c inet.Conn) { p := c.RemotePeer() // mes.Protocols ids.Host.Peerstore().SetProtocols(p, mes.Protocols...) // mes.ObservedAddr ids.consumeObservedAddress(mes.GetObservedAddr(), c) // mes.ListenAddrs laddrs := mes.GetListenAddrs() lmaddrs := make([]ma.Multiaddr, 0, len(laddrs)) for _, addr := range laddrs { maddr, err := ma.NewMultiaddrBytes(addr) if err != nil { log.Debugf("%s failed to parse multiaddr from %s %s", ID, p, c.RemoteMultiaddr()) continue } lmaddrs = append(lmaddrs, maddr) } // if the address reported by the connection roughly matches their annoucned // listener addresses, its likely to be an external NAT address if HasConsistentTransport(c.RemoteMultiaddr(), lmaddrs) { lmaddrs = append(lmaddrs, c.RemoteMultiaddr()) } // update our peerstore with the addresses. here, we SET the addresses, clearing old ones. // We are receiving from the peer itself. this is current address ground truth. ids.Host.Peerstore().SetAddrs(p, lmaddrs, pstore.ConnectedAddrTTL) log.Debugf("%s received listen addrs for %s: %s", c.LocalPeer(), c.RemotePeer(), lmaddrs) // get protocol versions pv := mes.GetProtocolVersion() av := mes.GetAgentVersion() // version check. if we shouldn't talk, bail. // TODO: at this point, we've already exchanged information. // move this into a first handshake before the connection can open streams. if !protocolVersionsAreCompatible(pv, LibP2PVersion) { logProtocolMismatchDisconnect(c, pv, av) c.Close() return } ids.Host.Peerstore().Put(p, "ProtocolVersion", pv) ids.Host.Peerstore().Put(p, "AgentVersion", av) // get the key from the other side. we may not have it (no-auth transport) ids.consumeReceivedPubKey(c, mes.PublicKey) }