ip.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. from re import compile
  4. from os import name as os_name, popen
  5. from socket import socket, getaddrinfo, gethostname, AF_INET, AF_INET6, SOCK_DGRAM
  6. from logging import debug, error
  7. try: # python3
  8. from urllib.request import urlopen, Request
  9. except ImportError: # python2
  10. from urllib2 import urlopen, Request # type: ignore[import-untyped] # noqa: F401
  11. # IPV4正则
  12. IPV4_REG = r"((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])"
  13. # IPV6正则
  14. # https://community.helpsystems.com/forums/intermapper/miscellaneous-topics/5acc4fcf-fa83-e511-80cf-0050568460e4
  15. IPV6_REG = r"((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))" # noqa: E501
  16. def default_v4(): # 默认连接外网的ipv4
  17. s = socket(AF_INET, SOCK_DGRAM)
  18. s.connect(("1.1.1.1", 53))
  19. ip = s.getsockname()[0]
  20. s.close()
  21. return ip
  22. def default_v6(): # 默认连接外网的ipv6
  23. s = socket(AF_INET6, SOCK_DGRAM)
  24. s.connect(("1:1:1:1:1:1:1:1", 8))
  25. ip = s.getsockname()[0]
  26. s.close()
  27. return ip
  28. def local_v6(i=0): # 本地ipv6地址
  29. info = getaddrinfo(gethostname(), 0, AF_INET6)
  30. debug(info)
  31. return info[int(i)][4][0]
  32. def local_v4(i=0): # 本地ipv4地址
  33. info = getaddrinfo(gethostname(), 0, AF_INET)
  34. debug(info)
  35. return info[int(i)][-1][0]
  36. def _open(url, reg):
  37. try:
  38. debug("open: %s", url)
  39. res = (
  40. urlopen(Request(url, headers={"User-Agent": "Mozilla/5.0 ddns"}), timeout=60)
  41. .read()
  42. .decode("utf8", "ignore")
  43. )
  44. debug("response: %s", res)
  45. return compile(reg).search(res).group()
  46. except Exception as e:
  47. error(e)
  48. def public_v4(url="https://api-ipv4.ip.sb/ip", reg=IPV4_REG): # 公网IPV4地址
  49. return _open(url, reg)
  50. def public_v6(url="https://api-ipv6.ip.sb/ip", reg=IPV6_REG): # 公网IPV6地址
  51. return _open(url, reg)
  52. def _ip_regex_match(parrent_regex, match_regex):
  53. ip_pattern = compile(parrent_regex)
  54. matcher = compile(match_regex)
  55. if os_name == "nt": # windows:
  56. cmd = "ipconfig"
  57. else:
  58. cmd = "ip address || ifconfig 2>/dev/null"
  59. for s in popen(cmd).readlines():
  60. addr = ip_pattern.search(s)
  61. if addr and matcher.match(addr.group(1)):
  62. return addr.group(1)
  63. def regex_v4(reg): # ipv4 正则提取
  64. if os_name == "nt": # Windows: IPv4 xxx: 192.168.1.2
  65. regex_str = r"IPv4 .*: ((?:\d{1,3}\.){3}\d{1,3})\W"
  66. else:
  67. regex_str = r"inet (?:addr\:)?((?:\d{1,3}\.){3}\d{1,3})[\s/]"
  68. return _ip_regex_match(regex_str, reg)
  69. def regex_v6(reg): # ipv6 正则提取
  70. if os_name == "nt": # Windows: IPv4 xxx: ::1
  71. regex_str = r"IPv6 .*: ([\:\dabcdef]*)?\W"
  72. else:
  73. regex_str = r"inet6 (?:addr\:\s*)?([\:\dabcdef]*)?[\s/%]"
  74. return _ip_regex_match(regex_str, reg)