openwrt / packages

Community maintained packages for OpenWrt. Documentation for submitting pull requests is in CONTRIBUTING.md
GNU General Public License v2.0
4.02k stars 3.5k forks source link

ddns-scripts: incorrectly interprets response from namecheap #7195

Closed zxdavb closed 6 years ago

zxdavb commented 6 years ago

Firstly thanks for a great package!

Maintainer: @dibdot Environment: OpenWrt 18.06-SNAPSHOT, r7317-f506de2cda

Description: When chasing a bug of my own devising (the 192.168.0.100, below), I found this in the logs:

Sat Oct 13 10:11:19 2018 user.warn ddns-scripts[9587]: namecheap: Updating IP at DDNS provider failed - starting retry 96/0

Part of the issue is caused by ddns-scripts incorrectly interpreting the response from namecheap as successful, when it was not, due to an incorrect password (below is anonymised):

 101119       : Detect registered/public IP
 101119       : #> /usr/bin/host -t A -4 domain.co.uk >/var/run/ddns/namecheap.dat 2>/var/run/ddns/namecheap.err
 101119       : Registered IP '192.168.0.100' detected
 101119  WARN : Updating IP at DDNS provider failed - starting retry 96/0
 101119       : Detect local IP on 'web'
 101120       : #> /usr/bin/wget-ssl -nv -t 1 -O /var/run/ddns/namecheap.dat -o /var/run/ddns/namecheap.err -4 --no-proxy 'http://myip.dnsomatic.com/'
 101120       : Local IP '87.62.58.193' detected on web at 'http://myip.dnsomatic.com/'
 101120       : Update needed - L: '87.62.58.193' <> R: '192.168.0.100'
 101121       : #> /usr/bin/wget-ssl -nv -t 1 -O /var/run/ddns/namecheap.dat -o /var/run/ddns/namecheap.err -4 --no-proxy 'http://dynamicdns.park-your-domain.com/update?host=%40&domain=domain.co.uk&password=***PW***&ip=87.62.58.193'
 101121       : DDNS Provider answered:
<?xml version="1.0"?><interface-response><Command>SETDNSHOST</Command><Language>eng</Language><ErrCount>1</ErrCount><errors><Err1>Passwords do not match</Err1></errors><ResponseCount>1</ResponseCount><responses><response><ResponseNumber>304156</ResponseNumber><ResponseString>Validation error; invalid ; password</ResponseString></response></responses><Done>true</Done><debug><![CDATA[]]></debug></interface-response>
 101122  info : Update successful - IP '87.62.58.193' send
 101122  info : Forced update successful - IP: '87.62.58.193' send
 101122       : Waiting 600 seconds (Check Interval)

As you can see, the response includes:

<ErrCount>1</ErrCount>
<errors>
    <Err1>Passwords do not match</Err1>
</errors>

... but the logs also include:

101122  info : Update successful - IP '87.62.58.193' send
101122  info : Forced update successful - IP: '87.62.58.193' send
dibdot commented 6 years ago

@zxdavb Nice try - I'm not maintainer of this epic script eldorado. Anyway I try to keep this running, but I'm not using this package ... you have been warned! ;-))

Looking at the code I think it works as designed. In "services" file the namecheap definition looks like this:

"namecheap.com"     "http://dynamicdns.park-your-domain.com/update?host=[USERNAME]&domain=[DOMAIN]&password=[PASSWORD]&ip=[IP]"

There is no third column with a possible update answer string defined. In dynamic_dns_functions.sh whithin the send_update() function I found the following code snippet:

[...]
        write_log 7 "DDNS Provider answered:${N}$(cat $DATFILE)"

        [ -z "$UPD_ANSWER" ] && return 0    # not set then ignore
[...]

That means the ddns package will always return 0 as long as no UPD_ANSWER string has been defined. Feel free to define a valid answer string for namecheap and open a PR to this repo. Thanks!

zxdavb commented 6 years ago

Ha! I meant to write @chris5560 & got confused (adblock is my other go-to package).

Fair enough about the PR - I will add this to my list!

For my own reference, in: https://www.namecheap.com/support/api/methods/domains-dns/set-custom.aspx, we have an example response:

<?xml version="1.0" encoding="UTF-8"?>
<ApiResponse xmlns="http://api.namecheap.com/xml.response" Status="OK">
  <Errors />
  <RequestedCommand>namecheap.domains.dns.setCustom</RequestedCommand>
  <CommandResponse Type="namecheap.domains.dns.setCustom">
    <DomainDNSSetCustomResult Domain="domain.com" Updated="true" />
  </CommandResponse>
  <Server>SERVER-NAME</Server>
  <GMTTimeDifference>+5</GMTTimeDifference>
  <ExecutionTime>32.76</ExecutionTime>
</ApiResponse>

This is not in the same format as my error, above - but it's using a much different URL:

https://api.namecheap.com/xml.response?ApiUser=apiexample&ApiKey=56b4c87ef4fd49cb96d915c0db68194&UserName=apiexample&Command=namecheap.domains.dns.setCustom&ClientIp=192.168.1.109&SLD=domain&TLD=com&NameServers=dns1.name-servers.com,dns2.name-servers.com

This git appears to have better information re: responses: https://github.com/bci/Namecheap-DDNS-Update/blob/master/NamecheapDdnsUpdate.sh, they have:

<?xml version="1.0"?>
<interface-response>
  <Command>SETDNSHOST</Command>
  <Language>eng</Language>
  <IP>1.2.3.4</IP>
  <ErrCount>0</ErrCount>
  <ResponseCount>0</ResponseCount>
  <Done>true</Done>
  <debug><![CDATA[]]></debug>
</interface-response>

The above 'successful' xml appears to be very difficult to differentiate from a 'unsuccessful' response, maybe: <ErrCount>0? However, the special character may present a problem.

zxdavb commented 6 years ago

Options to try would be a) use answer = <ErrCount>0, b) use api.namecheap.com rather than dynamicdns.park-your-domain.com, - will need a provider specific update script c) re-write scripts to handle answers of failure (otherwise assume OK), as well as answers of success (otherwise assume failed)

I will try a) & b) & report back...

dibdot commented 6 years ago

@zxdavb any news on this?

zxdavb commented 6 years ago

Option a) works great, although I am using: "<ErrCount>0<\ErrCount>" in the third column.

Below is an example of failure (wrong password) - <ErrCount>1</ErrCount>:

201156       : DDNS Provider answered:
<?xml version="1.0"?><interface-response><Command>SETDNSHOST</Command><Language>eng</Language><ErrCount>1</ErrCount><errors><Err1>Passwords do not match</Err1></errors><ResponseCount>1</ResponseCount><responses><response><ResponseNumber>304156</ResponseNumber><ResponseString>Validation error; invalid ; password</ResponseString></response></responses><Done>true</Done><debug><![CDATA[]]></debug></interface-response>
201157 ERROR : IP update not accepted by DDNS Provider

Below is an example of success - <ErrCount>0</ErrCount>:

201355       : DDNS Provider answered:
<?xml version="1.0"?><interface-response><Command>SETDNSHOST</Command><Language>eng</Language><IP>99.99.99.99</IP><ErrCount>0</ErrCount><ResponseCount>0</ResponseCount><Done>true</Done><debug><![CDATA[]]></debug></interface-response>
201355  info : Update successful - IP '99.99.99.99' send
dibdot commented 6 years ago

Great, thanks for your efforts. Since this a configuration issue, I will close this issue. Feel free to open a PR with that changed config.