private IP range checks
When advertising nodes and when establishing connections, private IP range checks were not done. This could cause private IPs to be advertised across the network. Also, some of the checks weren't IPv6-aware. Fixes Bitmessage#768
This commit is contained in:
parent
47f1c0c267
commit
4f26bf1059
|
@ -490,9 +490,19 @@ class receiveDataThread(threading.Thread):
|
||||||
logger.debug('sending an object.')
|
logger.debug('sending an object.')
|
||||||
self.sendDataThreadQueue.put((0, 'sendRawData', shared.CreatePacket('object',payload)))
|
self.sendDataThreadQueue.put((0, 'sendRawData', shared.CreatePacket('object',payload)))
|
||||||
|
|
||||||
|
def _checkIPAddress(self, host):
|
||||||
|
if host[0:12] == '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF':
|
||||||
|
hostStandardFormat = socket.inet_ntop(socket.AF_INET, host[12:])
|
||||||
|
return self._checkIPv4Address(host[12:], hostStandardFormat)
|
||||||
|
else:
|
||||||
|
hostStandardFormat = socket.inet_ntop(socket.AF_INET6, host)
|
||||||
|
if hostStandardFormat == "":
|
||||||
|
# This can happen on Windows systems which are not 64-bit compatible
|
||||||
|
# so let us drop the IPv6 address.
|
||||||
|
return False
|
||||||
|
return self._checkIPv6Address(host, hostStandardFormat)
|
||||||
|
|
||||||
def _checkIPv4Address(self, host, hostStandardFormat):
|
def _checkIPv4Address(self, host, hostStandardFormat):
|
||||||
# print 'hostStandardFormat', hostStandardFormat
|
|
||||||
if host[0] == '\x7F': # 127/8
|
if host[0] == '\x7F': # 127/8
|
||||||
logger.debug('Ignoring IP address in loopback range: ' + hostStandardFormat)
|
logger.debug('Ignoring IP address in loopback range: ' + hostStandardFormat)
|
||||||
return False
|
return False
|
||||||
|
@ -505,7 +515,7 @@ class receiveDataThread(threading.Thread):
|
||||||
if host[0:2] >= '\xAC\x10' and host[0:2] < '\xAC\x20': # 172.16/12
|
if host[0:2] >= '\xAC\x10' and host[0:2] < '\xAC\x20': # 172.16/12
|
||||||
logger.debug('Ignoring IP address in private range:' + hostStandardFormat)
|
logger.debug('Ignoring IP address in private range:' + hostStandardFormat)
|
||||||
return False
|
return False
|
||||||
return True
|
return hostStandardFormat
|
||||||
|
|
||||||
def _checkIPv6Address(self, host, hostStandardFormat):
|
def _checkIPv6Address(self, host, hostStandardFormat):
|
||||||
if host == ('\x00' * 15) + '\x01':
|
if host == ('\x00' * 15) + '\x01':
|
||||||
|
@ -517,7 +527,7 @@ class receiveDataThread(threading.Thread):
|
||||||
if (ord(host[0]) & 0xfe) == 0xfc:
|
if (ord(host[0]) & 0xfe) == 0xfc:
|
||||||
logger.debug ('Ignoring unique local address: ' + hostStandardFormat)
|
logger.debug ('Ignoring unique local address: ' + hostStandardFormat)
|
||||||
return False
|
return False
|
||||||
return True
|
return hostStandardFormat
|
||||||
|
|
||||||
# We have received an addr message.
|
# We have received an addr message.
|
||||||
def recaddr(self, data):
|
def recaddr(self, data):
|
||||||
|
@ -545,19 +555,9 @@ class receiveDataThread(threading.Thread):
|
||||||
38 * i):20 + lengthOfNumberOfAddresses + (38 * i)])
|
38 * i):20 + lengthOfNumberOfAddresses + (38 * i)])
|
||||||
recaddrPort, = unpack('>H', data[36 + lengthOfNumberOfAddresses + (
|
recaddrPort, = unpack('>H', data[36 + lengthOfNumberOfAddresses + (
|
||||||
38 * i):38 + lengthOfNumberOfAddresses + (38 * i)])
|
38 * i):38 + lengthOfNumberOfAddresses + (38 * i)])
|
||||||
if fullHost[0:12] == '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF':
|
hostStandardFormat = self._checkIPAddress(fullHost)
|
||||||
ipv4Host = fullHost[12:]
|
if hostStandardFormat is False:
|
||||||
hostStandardFormat = socket.inet_ntop(socket.AF_INET, ipv4Host)
|
continue
|
||||||
if not self._checkIPv4Address(ipv4Host, hostStandardFormat):
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
hostStandardFormat = socket.inet_ntop(socket.AF_INET6, fullHost)
|
|
||||||
if hostStandardFormat == "":
|
|
||||||
# This can happen on Windows systems which are not 64-bit compatible
|
|
||||||
# so let us drop the IPv6 address.
|
|
||||||
continue
|
|
||||||
if not self._checkIPv6Address(fullHost, hostStandardFormat):
|
|
||||||
continue
|
|
||||||
timeSomeoneElseReceivedMessageFromThisNode, = unpack('>Q', data[lengthOfNumberOfAddresses + (
|
timeSomeoneElseReceivedMessageFromThisNode, = unpack('>Q', data[lengthOfNumberOfAddresses + (
|
||||||
38 * i):8 + lengthOfNumberOfAddresses + (38 * i)]) # This is the 'time' value in the received addr message. 64-bit.
|
38 * i):8 + lengthOfNumberOfAddresses + (38 * i)]) # This is the 'time' value in the received addr message. 64-bit.
|
||||||
if recaddrStream not in shared.knownNodes: # knownNodes is a dictionary of dictionaries with one outer dictionary for each stream. If the outer stream dictionary doesn't exist yet then we must make it.
|
if recaddrStream not in shared.knownNodes: # knownNodes is a dictionary of dictionaries with one outer dictionary for each stream. If the outer stream dictionary doesn't exist yet then we must make it.
|
||||||
|
@ -744,9 +744,10 @@ class receiveDataThread(threading.Thread):
|
||||||
# in this version message. Let us inform the sendDataThread.
|
# in this version message. Let us inform the sendDataThread.
|
||||||
self.sendDataThreadQueue.put((0, 'setRemoteProtocolVersion', self.remoteProtocolVersion))
|
self.sendDataThreadQueue.put((0, 'setRemoteProtocolVersion', self.remoteProtocolVersion))
|
||||||
|
|
||||||
with shared.knownNodesLock:
|
if not isHostInPrivateIPRange(self.peer.host):
|
||||||
shared.knownNodes[self.streamNumber][shared.Peer(self.peer.host, self.remoteNodeIncomingPort)] = int(time.time())
|
with shared.knownNodesLock:
|
||||||
shared.needToWriteKnownNodesToDisk = True
|
shared.knownNodes[self.streamNumber][shared.Peer(self.peer.host, self.remoteNodeIncomingPort)] = int(time.time())
|
||||||
|
shared.needToWriteKnownNodesToDisk = True
|
||||||
|
|
||||||
self.sendverack()
|
self.sendverack()
|
||||||
if self.initiatedConnection == False:
|
if self.initiatedConnection == False:
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import shared
|
import socket
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
import shared
|
||||||
|
|
||||||
def convertIntToString(n):
|
def convertIntToString(n):
|
||||||
a = __builtins__.hex(n)
|
a = __builtins__.hex(n)
|
||||||
if a[-1:] == 'L':
|
if a[-1:] == 'L':
|
||||||
|
@ -23,14 +25,24 @@ def signal_handler(signal, frame):
|
||||||
print 'Unfortunately you cannot use Ctrl+C when running the UI because the UI captures the signal.'
|
print 'Unfortunately you cannot use Ctrl+C when running the UI because the UI captures the signal.'
|
||||||
|
|
||||||
def isHostInPrivateIPRange(host):
|
def isHostInPrivateIPRange(host):
|
||||||
if host[:3] == '10.':
|
if ":" in host: #IPv6
|
||||||
return True
|
hostAddr = socket.inet_pton(socket.AF_INET6, host)
|
||||||
if host[:4] == '172.':
|
if hostAddr == ('\x00' * 15) + '\x01':
|
||||||
if host[6] == '.':
|
return False
|
||||||
if int(host[4:6]) >= 16 and int(host[4:6]) <= 31:
|
if hostAddr[0] == '\xFE' and (ord(hostAddr[1]) & 0xc0) == 0x80:
|
||||||
return True
|
return False
|
||||||
if host[:8] == '192.168.':
|
if (ord(hostAddr[0]) & 0xfe) == 0xfc:
|
||||||
return True
|
return False
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
if host[:3] == '10.':
|
||||||
|
return True
|
||||||
|
if host[:4] == '172.':
|
||||||
|
if host[6] == '.':
|
||||||
|
if int(host[4:6]) >= 16 and int(host[4:6]) <= 31:
|
||||||
|
return True
|
||||||
|
if host[:8] == '192.168.':
|
||||||
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def addDataPadding(data, desiredMsgLength = 12, paddingChar = '\x00'):
|
def addDataPadding(data, desiredMsgLength = 12, paddingChar = '\x00'):
|
||||||
|
|
Reference in New Issue
Block a user