下面是我用於執行此操作的功能(來回移動Qualys的使用和格式之間通過IPADDR提供的對象的實例:
def is_valid_ip_address(address, version=None):
""" Check validity of address
Return True if 'address' is a valid ipv4 or ipv6 address.
"""
# Validate version:
if version:
if not isinstance(version, int):
raise TypeError, 'Version is not of type "int"'
return False
if not (version == 4 or version == 6):
raise ValueError, 'IP version is set to an invalid number: %s' % version
return False
try:
ipaddr.IPAddress(address.strip(),version)
except ValueError:
return False
return True
def is_valid_ipv4_address(address):
""" Check validity of address
Return True if 'address' is a valid ipv4 address.
"""
return is_valid_ip_address(address,4)
def is_valid_ipv6_address(address):
""" Check validity of address
Return True if 'address' is a valid ipv6 address.
"""
return is_valid_ip_address(address,6)
def is_valid_ip_range(iprange, version=None):
""" Check validity of iprange
Return True if 'iprange' is a range of ip addresses in a format that Qulys's API will accept (i.e. "startip-endip" where startip < endip).
"""
# Validate version:
if version:
if not isinstance(version, int):
raise TypeError, 'Version is not of type "int"'
return False
if not (version == 4 or version == 6):
raise ValueError, 'IP version is set to an invalid number: %s' % version
return False
try:
(start_ip,end_ip) = iprange.split('-')
start_ip = start_ip.strip()
end_ip = end_ip.strip()
if ipaddr.IPAddress(start_ip) == ipaddr.IPAddress(end_ip):
logging.debug('%s/%s-%s, Error: %s' % (package,module,version,'Start and End IP Address in an IP Range can not be the same IP Address.'))
return False
# A valid range requires:
# 1) The start_ip must be a valid ip address.
# 2) The end_ip must be a valid ip address.
# 3) The start_ip must be less than the end_ip.
# Although socket operations (as are used in qualysconnect.util) are nice, it's not feasible to determine that the start_ip is less than the
# end_ip without considerable effort. We'll use the ipaddr.summarize_address_range function to test all three at one time.
ipaddr.summarize_address_range(ipaddr.IPAddress(start_ip,version),ipaddr.IPAddress(end_ip,version))
except ipaddr.AddressValueError, e:
logging.debug('%s/%s-%s, Error: %s' % (package,module,version,e))
return False
except ValueError, e:
logging.debug('%s/%s-%s, Error: %s' % (package,module,version,e))
return False
return True
def is_valid_ipv4_range(iprange):
""" Check validity of iprange
Return True if 'iprange' is a range of ipv4 addresses in a format that Qulys's API will accept (i.e. "startip-endip" where startip < endip).
"""
return is_valid_ip_range(iprange,4)
def is_valid_ipv6_range(iprange):
""" Check validity of iprange
Return True if 'iprange' is a range of ipv4 addresses in a format that Qulys's API will accept (i.e. "startip-endip" where startip < endip).
"""
return is_valid_ip_range(iprange,6)
def cidr_to_ip(cidr,version=None):
""" Convert an ip address or ip range provided in cidr notation (either bitmask or netmask notation) to the ip address or ip range format that is
accepted by Qualys's API. (e.g. cidr_to_ip('10.0.0.0/24') returns the string '10.0.0.0-10.0.0.255'.
Returns a String containing an ip address or ip range that can be provided to the Qualys API.
"""
# Validate version:
if version:
if not isinstance(version, int):
raise TypeError, 'Version is not of type "int"'
return False
if not (version == 4 or version == 6):
raise ValueError, 'IP version is set to an invalid number: %s' % version
return False
try:
cidr_net = ipaddr.IPNetwork(cidr,version)
except ValueError, e:
logging.debug('%s/%s-%s, Error: %s' % (package,module,version,e))
raise ValueError, e
if cidr_net[0] == cidr_net[-1]:
return str(cidr_net[0])
iprange = '%s-%s' % (cidr_net[0],cidr_net[-1])
return iprange
def cidr_to_ipv4(cidr):
""" Convert an ipv4 address or ipv4 range provided in cidr notation (either bitmask or netmask notation) to the ip address or ip range format that is
accepted by Qualys's API. (e.g. cidr_to_ip('192.0.2.0/24') returns the string '192.0.2.0-192.0.2.255'.
Returns a String containing an ip address or ip range that can be provided to the Qualys API.
"""
return cidr_to_ip(cidr,4)
def cidr_to_ipv6(cidr):
""" Convert an ipv6 address or ipv6 range provided in cidr notation (either bitmask or netmask notation) to the ip address or ip range format that is
accepted by Qualys's API. (e.g. cidr_to_ip('2001:db8::fff/120') returns the string '2001:db8::f00-2001:db8::fff'.
Returns a String containing an ipv6 address or ipv6 range that can be provided to the Qualys API.
"""
return cidr_to_ip(cidr,4)
def decode_ip_string(ipstring):
""" Validates ipstring is in a format that can be provided to the Qualys API, if it is not in a format that can be accepted by the Qualys API, it attempts
to put it in a format that is acceptable (e.g. converting cidr notation to the ip range notation that Qualys expects)
Returns a string that is valid to hand to the 'ips' key in the Qualys API.
"""
cml=[]
ip_list = ipstring.split(',')
# Should probably check for any repeated or overlapping IP addresses here, but skipping for now.
for i in ip_list:
# This is a kludge, but I couldn't come up with a good way to make the error report the string that generated the error, rather than the
# potentially modified version of the string that caused the error.
new_i=i
if '/' in i:
new_i = cidr_to_ip(i)
if (is_valid_ip_address(new_i) or is_valid_ip_range(new_i)):
cml.append(new_i)
else:
raise ValueError, "IP argument cannot be parsed, \'%s\' is not a valid IP Range or IP Address" % i
return ",".join(cml)
def ip_string_to_cidr(ipstring):
""" Accepts ipstring - a string list of IPs in the format the Qualys expects or has provided (via API calls) and returns a list of ipaddr.IPNetwork objects."""
ret_list = []
ip_list = ipstring.split(',')
for i in ip_list:
if is_valid_ip_address(i):
ret_list.append(ipaddr.IPNetwork(i.strip()))
elif is_valid_ip_range(i.strip()):
(start_ip,end_ip) = i.split('-')
range_list = ipaddr.summarize_address_range(ipaddr.IPAddress(start_ip.strip()), ipaddr.IPAddress(end_ip.strip()))
for j in range_list:
ret_list.append(j)
return ipaddr.collapse_address_list(ret_list)
def ip_list_to_ip_string(iplist):
return decode_ip_string(",".join([decode_ip_string(str(i)) for i in iplist]))
對於你將使用上面的函數和ipaddr.IPNetwork對象實例中的'exclude_address'方法來編寫一個新函數,該函數接受original_range和subtract_range輸入,返回ipaddr對象列表(或Qualys預期格式的ip_string)使用上面的ip_list_to_ip_string函數)。唯一棘手的部分將運行'ip_string_to_cidr(exclude_list)'時,您將收到需要從'original_range'中減去的IPNetwork對象列表。
如果您需要更多幫助,我可能會將某種exclude_ips函數放在一起,因爲在某個時候我需要它,請讓我知道。
Google有一個名爲ipaddr-py(http://code.google.com/p/ipaddr-py/)的python庫。這可以用來解決問題嗎? – paragbaxi