mietzen / porkbun-ddns

porkbun-ddns is an unoffical DDNS-Client for Porkbun Domains.
MIT License
130 stars 10 forks source link

porkbun_ddns.porkbun_ddns.PorkbunDDNS_Error: Failed to obtain IP Addresses! #51

Closed FuadAbdullah closed 5 months ago

FuadAbdullah commented 5 months ago

Hi there! I received this error just now while my router restarted and my ISP assigned me a new public IP address.

2024-04-21T17:18:41.489161082Z porkbun_ddns.porkbun_ddns.PorkbunDDNS_Error: Failed to obtain IP Addresses!
2024-04-21T17:19:43.563438284Z Traceback (most recent call last):
2024-04-21T17:19:43.563495743Z   File "/entrypoint.py", line 65, in <module>
2024-04-21T17:19:43.563439298Z 2024-04-21 17:19:43,563 WARNING  Can't reach IPv4 Address! Check IPv4 connectivity!
2024-04-21T17:19:43.563700288Z     porkbun_ddns.update_records()
2024-04-21T17:19:43.563728612Z   File "/usr/local/lib/python3.12/site-packages/porkbun_ddns-0.6.2-py3.12.egg/porkbun_ddns/porkbun_ddns.py", line 158, in update_records
2024-04-21T17:19:43.563887953Z   File "/usr/local/lib/python3.12/site-packages/porkbun_ddns-0.6.2-py3.12.egg/porkbun_ddns/porkbun_ddns.py", line 118, in get_public_ips

After digging through the Python script and checking the referenced lines per the logs, I stumbled across the URLs used to retrieve the latest public IPs:

urls = ['https://v4.ident.me',
'https://api.ipify.org',
'https://ipv4.icanhazip.com']

I copied and went to all three sites to see if any of them went down. Sure enough, the first URL pointing to v4.ident.me was down for some reason. I went to isitdownrightnow just to be sure if it was only me. Then, I copied that part of the script to test myself as to why the script failed, although there were two functioning sites (I tested the other two, and they worked) that could serve as backups to the first. Below is the script I used to test, essentially a direct copy from the source code with a little tweak to the error handling part. I am still learning Python, so I apologize if I did it wrongly:

import urllib.request

public_ips= []

urls = ['https://v4.ident.me',
'https://api.ipify.org',
'https://ipv4.icanhazip.com']
try:
    for url in urls:
        with urllib.request.urlopen(url) as response:
            if response.getcode() == 200:
                public_ips.append(response.read().decode('utf-8'))
                break
            print("Failed to retrieve IPv4 Address from %s! HTTP status code: %s", url, str(response.code()))
except Exception as e:
    print('Failed to retrieve IPv4 Address from %s! Error: %s' % (url, str(e)))

print(public_ips)

The output of the script was:

Failed to retrieve IPv4 Address from https://v4.ident.me! Error: <urlopen error [Errno 111] Connection refused>
[]

As you could see, the array was empty. This brought me to believe that the try-except block was misplaced and should've been within the for loop instead, like so:

for url in urls:
    try:
        with urllib.request.urlopen(url) as response:
            if response.getcode() == 200:
                public_ips.append(response.read().decode('utf-8'))
                break
            print("Failed to retrieve IPv4 Address from %s! HTTP status code: %s", url, str(response.code()))
    except Exception as e:
        print('Failed to retrieve IPv4 Address from %s! Error: %s' % (url, str(e)))

The refactored code above yielded the following output:

Failed to retrieve IPv4 Address from https://v4.ident.me! Error: <urlopen error [Errno 111] Connection refused>
['XXX.XXX.XXX'] <-- from the break statement once the URL response returns a 200 status

However, I wonder if I was looking at the right part of the code or if the experiment I conducted was even right. Do you have any insights into the issue I am facing? Any help is appreciated!

mietzen commented 5 months ago

Yes you're right, the try block must be inside the loop. Thank you for your contribution!

mietzen commented 5 months ago

Fixed in v0.6.3