Fail chalenge when change port: 80 to 8044, 443 to 8443

My domain is: vietnamthink.today

I ran this command: $ sudo certbot certonly --manual --manual-auth-hook /etc/letsencrypt/acme-dns-auth.py --preferred-challenges
dns --debug-challenges -d *.vietnamthink.today -d vietnamthink.today -v

It produced this output:

Requesting a certificate for *.vietnamthink.today and vietnamthink.today
Performing the following challenges:
dns-01 challenge for vietnamthink.today
Running manual-auth-hook command: /etc/letsencrypt/acme-dns-auth.py


Challenges loaded. Press continue to submit to CA. Pass "-v" for more info about
challenges.


Press Enter to Continue
Waiting for verification...
Challenge failed for domain vietnamthink.today
dns-01 challenge for vietnamthink.today
Certbot failed to authenticate some domains (authenticator: manual). The Certificate Authority reported these problems:
Domain: vietnamthink.today
Type: unauthorized
Detail: Incorrect TXT record "zX2iuDDspbr-gRwMJs6mI52OpTPGKfYERloxEyd62rs" found at _acme-challenge.vietnamthink.today
Hint: The Certificate Authority failed to verify the DNS TXT records created by the --manual-auth-hook. Ensure that this hook
is functioning correctly and that it waits a sufficient duration of time for DNS propagation. Refer to "certbot --help manual" and the Certbot User Guide.
Cleaning up challenges
Some challenges have failed.
Ask for help or search for solutions at https://community.letsencrypt.org. See the logfile /var/log/letsencrypt/letsencrypt.log or re-run Certbot with -v for more details.
My web server is (include version): Nginx 1.18.0 (ubuntu 22.04)

The operating system my web server runs on is (include version):

My hosting provider, if applicable, is: my server at home with NAT

I can login to a root shell on my machine (yes or no, or I don't know): yes

I'm using a control panel to manage my site (no, or provide the name and version of the control panel): no

The version of my client is (e.g. output of certbot --version or certbot-auto --version if you're using Certbot): 1.21.0
Thank you
I follow this tuto: How To Acquire a Let's Encrypt Certificate Using DNS Validation with acme-dns-certbot on Ubuntu 18.04 | DigitalOcean

A DNS-01 challenge request for two "names" will require two TXT record entries.
Using --manual will force certbot to prompt you for each action and guide you every step of the way.

Since you are having trouble, and will likely be testing things for a bit until you get it right, you should do your testing against the staging system [use: --staging].
Once all tests are passed, then you can switch to production [removing --staging from the working test].

I'd start by removing the existing TXT record.
Then slowly follow the prompts and verify all steps while using the staging environment until you are confident your testing is complete.

Thank for your support, but with --manual and --staging, it still not show TXT token

How are you adding the TXT records?
And into which DNS system are you adding them?

I deleted TXT in FreeDNS.afraid.org DNS system. But it not show step by step for TXT token

How is /etc/letsencrypt/acme-dns-auth.py configured? It suggests that you're using acme-dns, but the fact you can actually delete a TXT record at Afraid is kinda weird if you'd use acme-dns.. Contradictory..

This is my acme-dns-auth.py

!/usr/bin/env python3
import json
import os
import requests
import sys
### EDIT THESE: Configuration values ###
# URL to acme-dns instance
ACMEDNS_URL = "https://auth.acme-dns.io"
# Path for acme-dns credential storage
STORAGE_PATH = "/etc/letsencrypt/acmedns.json"
# Whitelist for address ranges to allow the updates from
# Example: ALLOW_FROM = ["192.168.10.0/24", "::1/128"]
ALLOW_FROM = []
# Force re-registration. Overwrites the already existing acme-dns accounts.
FORCE_REGISTER = False
###   DO NOT EDIT BELOW THIS POINT   ###
###         HERE BE DRAGONS          ###
DOMAIN = os.environ["CERTBOT_DOMAIN"]
if DOMAIN.startswith("*."):
    DOMAIN = DOMAIN[2:]
VALIDATION_DOMAIN = "_acme-challenge."+DOMAIN
VALIDATION_TOKEN = os.environ["CERTBOT_VALIDATION"]
class AcmeDnsClient(object):
    """
    Handles the communication with ACME-DNS API
    """
    def __init__(self, acmedns_url):
        self.acmedns_url = acmedns_url
    def register_account(self, allowfrom):
        """Registers a new ACME-DNS account"""
        if allowfrom:
            # Include whitelisted networks to the registration call
            reg_data = {"allowfrom": allowfrom}
            res = requests.post(self.acmedns_url+"/register",
                                data=json.dumps(reg_data))
        else:
            res = requests.post(self.acmedns_url+"/register")
     if res.status_code == 201:
            # The request was successful
            return res.json()
        else:
            # Encountered an error
            msg = ("Encountered an error while trying to register a new acme-dns "
                   "account. HTTP status {}, Response body: {}")
            print(msg.format(res.status_code, res.text))
            sys.exit(1)
    def update_txt_record(self, account, txt):
        """Updates the TXT challenge record to ACME-DNS subdomain."""
        update = {"subdomain": account['subdomain'], "txt": txt}
        headers = {"X-Api-User": account['username'],
                   "X-Api-Key": account['password'],
                   "Content-Type": "application/json"}
        res = requests.post(self.acmedns_url+"/update",
                            headers=headers,
                            data=json.dumps(update))
        if res.status_code == 200:
            # Successful update
            return
        else:
           msg = ("Encountered an error while trying to update TXT record in "
                   "acme-dns. \n"
                   "------- Request headers:\n{}\n"
                   "------- Request body:\n{}\n"
                   "------- Response HTTP status: {}\n"
                   "------- Response body: {}")
            s_headers = json.dumps(headers, indent=2, sort_keys=True)
            s_update = json.dumps(update, indent=2, sort_keys=True)
            s_body = json.dumps(res.json(), indent=2, sort_keys=True)
            print(msg.format(s_headers, s_update, res.status_code, s_body))
            sys.exit(1)
class Storage(object):
    def __init__(self, storagepath):
        self.storagepath = storagepath
        self._data = self.load()
    def load(self):
        """Reads the storage content from the disk to a dict structure"""
        data = dict()
        filedata = ""
        try:
            with open(self.storagepath, 'r') as fh:
                filedata = fh.read()
        except IOError as e:
            if os.path.isfile(self.storagepath):
                # Only error out if file exists, but cannot be read
                print("ERROR: Storage file exists but cannot be read")
                sys.exit(1)
        try:
            data = json.loads(filedata)
        except ValueError:
            if len(filedata) > 0:
                # Storage file is corrupted
                print("ERROR: Storage JSON is corrupted")
                sys.exit(1)
        return data
    def save(self):
        """Saves the storage content to disk"""
        serialized = json.dumps(self._data)
        try:
            with os.fdopen(os.open(self.storagepath,
                                   os.O_WRONLY | os.O_CREAT, 0o600), 'w') as fh:
                fh.truncate()
                fh.write(serialized)
        except IOError as e:
            print("ERROR: Could not write storage file.")
            sys.exit(1)
    def put(self, key, value):
        """Puts the configuration value to storage and sanitize it"""
        # If wildcard domain, remove the wildcard part as this will use the
        # same validation record name as the base domain
        if key.startswith("*."):
            key = key[2:]
        self._data[key] = value
    def fetch(self, key):
        """Gets configuration value from storage"""
        try:
            return self._data[key]
        except KeyError:
           return None
if __name__ == "__main__":
    # Init
    client = AcmeDnsClient(ACMEDNS_URL)
    storage = Storage(STORAGE_PATH)
    # Check if an account already exists in storage
    account = storage.fetch(DOMAIN)
    if FORCE_REGISTER or not account:
        # Create and save the new account
        account = client.register_account(ALLOW_FROM)
        storage.put(DOMAIN, account)
        storage.save()
        # Display the notification for the user to update the main zone
        msg = "Please add the following CNAME record to your main DNS zone:\n{}"
        cname = "{} CNAME {}.".format(VALIDATION_DOMAIN, account["fulldomain"])
        print(msg.format(cname))
    # Update the TXT record in acme-dns instance
    client.update_txt_record(account, VALIDATION_TOKEN)


This is acmedns.json file

Certbot failed to authenticate some domains (authenticator: manual). The Certificate Authority reported these problems:
Domain: vietnamthink.today
Type: unauthorized
Detail: Incorrect TXT record "1906fa54-XXXX-XXXX-a5ab-3db60907c0d4.auth.acme-dns.io" found at _acme-challenge.vietnamthink.today
Domain: vietnamthink.today
Type: unauthorized
Detail: Incorrect TXT record "1906fa54-XXXX-XXXX-a5ab-3db60907c0d4.auth.acme-dns.io" found at _acme-challenge.vietnamthink.today
Hint: The Certificate Authority failed to verify the DNS TXT records created by the --manual-auth-hook. Ensure that
this hook is functioning correctly and that it waits a sufficient duration of time for DNS propagation. Refer to "certbot --help manual" and the Certbot User Guide.
Cleaning up challenges
Some challenges have failed.
Ask for help or search for solutions at https://community.letsencrypt.org. See the logfile /var/log/letsencrypt/letsencrypt.log or re-run Certbot with -v for more details.

I must agree.

I think you may have skipped a step [CNAME _acme-challenge.vietnamthink.today to 1906fa54-xxxx-xxxx-a5ab-3db60907c0d4.auth.acme-dns.io]
OR
You don't fully understand how ACME-DNS.IO is used.

BTW, My system has two server, the web hosting server 192.168.1.111 (ubuntu 22.04, Nginx, Wordpress with Letsencrypt SSL) for www.vietnamthink.today/vietnamthink.today its ok; and the mail server (192.168.1.222 with ubuntu 22.04, Nginx, iRedMail) for mail.vietnamthink.today:8044/8443. Both behind NAT by ADSL (8044/8443 to mail server 192.168.1.222 and 80/443 NAT to web server 192.168.1.111)

I tested with Mxtoolbox, it has been deployed

That is NOT a CNAME.
It's a TXT record with the contents of the CNAME entry.

Then we only need to talk about the web server.

YEEEEESSSSS, I changed to CNAME and it worked, thank you so much