Refactored IP matching, ignore results of hostname. Added cloudflare direct IPv4 & IPv6 (#4181)

This commit is contained in:
Rob van Oostenrijk
2024-08-18 10:14:28 +02:00
committed by GitHub
parent 0dd7b28e03
commit 1490dc820f
2 changed files with 17 additions and 10 deletions
@@ -139,7 +139,9 @@
<Default>web_dyndns</Default>
<ValidationMessage>An IP service type is required.</ValidationMessage>
<OptionValues>
<web_dyndns>cloudflare</web_dyndns>
<web_cloudflare>cloudflare</web_cloudflare>
<web_cloudflare_ipv4 value="cloudflare-ipv4">cloudflare-ipv4</web_cloudflare_ipv4>
<web_cloudflare_ipv6 value="cloudflare-ipv6">cloudflare-ipv6</web_cloudflare_ipv6>
<web_dyndns>dyndns</web_dyndns>
<web_freedns>freedns</web_freedns>
<web_he>he</web_he>
@@ -26,10 +26,12 @@
import subprocess
import re
import ipaddress
from urllib.parse import urlparse
checkip_service_list = {
'cloudflare': '%s://one.one.one.one/cdn-cgi/trace',
'cloudflare-ipv4': '%s://1.1.1.1/cdn-cgi/trace',
'cloudflare-ipv6': '%s://[2606:4700:4700::1111]/cdn-cgi/trace',
'dyndns': '%s://checkip.dyndns.org/',
'freedns': '%s://freedns.afraid.org/dynamic/check.php',
'he': '%s://checkip.dns.he.net/',
@@ -48,17 +50,18 @@ checkip_service_list = {
}
def extract_address(txt):
def extract_address(host, txt):
""" Extract first IPv4 or IPv6 address from provided string
:param txt: text blob
:return: str
"""
for regexp in [r'[^a-fA-F0-9\:]', r'[^F0-9\.]']:
for line in re.sub(regexp, ' ', txt).split():
if line.count('.') == 3 or line.count(':') >= 2:
for regexp in [r'(?:\d{1,3}\.){3}\d{1,3}', r'([a-f0-9:]+:+)+[a-f0-9]+']:
matches = re.finditer(regexp, txt)
for match in matches:
if match.group() != host:
try:
ipaddress.ip_address(line)
return line
ipaddress.ip_address(match.group())
return match.group()
except ValueError:
pass
return ""
@@ -79,8 +82,10 @@ def checkip(service, proto='https', timeout='10', interface=None):
if interface is not None:
params.append("--interface")
params.append(interface)
params.append(checkip_service_list[service] % proto)
return extract_address(subprocess.run(params, capture_output=True, text=True).stdout)
url = checkip_service_list[service] % proto
params.append(url)
return extract_address(urlparse(url).hostname,
subprocess.run(params, capture_output=True, text=True).stdout)
elif service in ['if', 'if6'] and interface is not None:
# return first non private IPv[4|6] interface address
ifcfg = subprocess.run(['/sbin/ifconfig', interface], capture_output=True, text=True).stdout