Provide the new sequence number in responses. New message Local Discovery to be sent instead of Announcement via IPv4 Broadcast and IPv6 Multicast.

Detecting IPv6 link-local addresses as local ones. Fixes.
This commit is contained in:
Kleissner
2021-04-18 21:50:30 +02:00
parent 703e40c947
commit 00db57aed8
7 changed files with 50 additions and 15 deletions

View File

@@ -8,7 +8,9 @@ package core
import (
"bytes"
"encoding/hex"
"fmt"
"log"
"time"
"github.com/PeernetOfficial/core/dht"
@@ -102,7 +104,7 @@ func (peer *PeerInfo) cmdAnouncement(msg *MessageAnnouncement) {
peer.announcementStore(msg.InfoStoreFiles)
}
peer.sendResponse(added, hash2Peers, filesEmbed, hashesNotFound)
peer.sendResponse(msg.Sequence, added, hash2Peers, filesEmbed, hashesNotFound)
}
func (peer *PeerInfo) peer2Record(allowLocal, allowIPv4, allowIPv6 bool) (result *PeerRecord) {
@@ -140,7 +142,7 @@ func (peer *PeerInfo) cmdResponse(msg *MessageResponse) {
info := nodesDHT.IRLookup(peer.NodeID, hash2Peer.ID.Hash)
if info == nil {
// Response to FIND_SELF?
if bytes.Equal(info.Key, nodeID) && len(hash2Peer.Closest) > 0 {
if bytes.Equal(hash2Peer.ID.Hash, nodeID) && len(hash2Peer.Closest) > 0 {
peer.cmdResponseFindSelf(msg, hash2Peer.Closest)
}
continue
@@ -196,6 +198,30 @@ func (peer *PeerInfo) cmdChat(msg *MessageRaw) {
fmt.Printf("Chat from '%s': %s\n", msg.connection.Address.String(), string(msg.PacketRaw.Payload))
}
// cmdLocalDiscovery handles an incoming announcement via local discovery
func (peer *PeerInfo) cmdLocalDiscovery(msg *MessageAnnouncement) {
// only accept local discovery message from private IPs for IPv4
// IPv6 DHCP routers typically assign public IPv6s and they can join multicast in the local network.
if msg.connection.IsIPv4() && !msg.connection.IsLocal() {
log.Printf("cmdLocalDiscovery message received from non-local IP %s peer ID %s\n", msg.connection.Address.String(), hex.EncodeToString(msg.SenderPublicKey.SerializeCompressed()))
return
}
var added bool
if peer == nil {
// The added check is required due to potential race condition; initially the client may receive multiple incoming announcement from the same peer via different connections.
if peer, added = PeerlistAdd(msg.SenderPublicKey, msg.connection); !added {
return
}
fmt.Printf("Incoming initial local discovery from %s\n", msg.connection.Address.String())
//} else {
// fmt.Printf("Incoming secondary local discovery from %s\n", msg.connection.Address.String())
}
peer.sendAnnouncement(true, true, nil, nil, nil)
}
// pingTime is the time in seconds to send out ping messages
const pingTime = 10

View File

@@ -28,13 +28,14 @@ var UserAgent = "Peernet Core/0.1"
// Commands between peers
const (
// Peer List Management
CommandAnnouncement = 0 // Announcement
CommandResponse = 1 // Response
CommandPing = 2 // Keep-alive message (no payload).
CommandPong = 3 // Response to ping (no payload).
CommandAnnouncement = 0 // Announcement
CommandResponse = 1 // Response
CommandPing = 2 // Keep-alive message (no payload).
CommandPong = 3 // Response to ping (no payload).
CommandLocalDiscovery = 4 // Local discovery
// Blockchain
CommandGet = 4 // Request blocks for specified peer.
CommandGet = 6 // Request blocks for specified peer.
// File Discovery
@@ -762,11 +763,11 @@ func (peer *PeerInfo) sendAnnouncement(sendUA, findSelf bool, findPeer []KeyHash
}
// sendResponse sends the response message
func (peer *PeerInfo) sendResponse(sendUA bool, hash2Peers []Hash2Peer, filesEmbed []EmbeddedFileData, hashesNotFound [][]byte) (err error) {
func (peer *PeerInfo) sendResponse(sequence uint32, sendUA bool, hash2Peers []Hash2Peer, filesEmbed []EmbeddedFileData, hashesNotFound [][]byte) (err error) {
packets, err := msgEncodeResponse(sendUA, hash2Peers, filesEmbed, hashesNotFound)
for _, packet := range packets {
peer.send(&PacketRaw{Command: CommandResponse, Payload: packet})
peer.send(&PacketRaw{Command: CommandResponse, Payload: packet, Sequence: sequence})
}
return err

View File

@@ -249,13 +249,16 @@ func networkChangeIPRemove(iface net.Interface, address net.Addr) {
}
}
// IsIPLocal reports whether ip is a private (local) address. [forked function]
// IsIPLocal reports whether ip is a private (local) address.
// The identification of private, or local, unicast addresses uses address type
// indentification as defined in RFC 1918 for ip4 and RFC 4193 for ip6 with the exception of ip4 directed broadcast addresses.
// indentification as defined in RFC 1918 for ip4 and RFC 4193 (fc00::/7) for ip6 with the exception of ip4 directed broadcast addresses.
// Unassigned, reserved, multicast and limited-broadcast addresses are not handled and will return false.
// IPv6 link-local addresses (fe80::/10) are included in this check.
func IsIPLocal(ip net.IP) bool {
if ip4 := ip.To4(); ip4 != nil {
return ip4[0] == 10 || (ip4[0] == 172 && ip4[1]&0xf0 == 16) || (ip4[0] == 192 && ip4[1] == 168)
}
return len(ip) == net.IPv6len && ip[0]&0xfe == 0xfc
return len(ip) == net.IPv6len &&
(ip[0]&0xfe == 0xfc || // fc00::/7
(ip[0] == 0xfe && ip[1]&0xC0 == 0x80)) // fe80::/10
}

View File

@@ -95,7 +95,7 @@ func (network *Network) BroadcastIPv4Send() (err error) {
return err
}
raw, err := PacketEncrypt(peerPrivateKey, ipv4BroadcastPublicKey, &PacketRaw{Protocol: ProtocolVersion, Command: CommandAnnouncement, Payload: packets[0]})
raw, err := PacketEncrypt(peerPrivateKey, ipv4BroadcastPublicKey, &PacketRaw{Protocol: ProtocolVersion, Command: CommandLocalDiscovery, Payload: packets[0]})
if err != nil {
return err
}

View File

@@ -141,7 +141,7 @@ func (network *Network) MulticastIPv6Send() (err error) {
return err
}
raw, err := PacketEncrypt(peerPrivateKey, ipv6MulticastPublicKey, &PacketRaw{Protocol: ProtocolVersion, Command: CommandAnnouncement, Payload: packets[0]})
raw, err := PacketEncrypt(peerPrivateKey, ipv6MulticastPublicKey, &PacketRaw{Protocol: ProtocolVersion, Command: CommandLocalDiscovery, Payload: packets[0]})
if err != nil {
return err
}

View File

@@ -166,6 +166,11 @@ func packetWorker(packets <-chan networkWire) {
peer.cmdResponse(response)
}
case CommandLocalDiscovery: // Local discovery, sent via IPv4 broadcast and IPv6 multicast
if announce, _ := msgDecodeAnnouncement(raw); announce != nil {
peer.cmdLocalDiscovery(announce)
}
case CommandPing: // Ping
peer.cmdPing(raw)

View File

@@ -49,7 +49,7 @@ func initPeerID() {
nodeID = publicKey2NodeID(peerPublicKey)
// save the newly generated private key into the config
config.PrivateKey = hex.EncodeToString(peerPublicKey.SerializeCompressed())
config.PrivateKey = hex.EncodeToString(peerPrivateKey.Serialize())
saveConfig()
}