0 votes
by (180 points)

We are using a FTPS server from www.adrive.com. Rebex can connect to it most of the time but every now and then it fails. I used FileZilla to connect to the same server and it logged this (I have added some XXX parts to hide some details).

Status: Resolving address of ftp.xxx.co
Status: Connecting to 65.49.XX.56:21...
Status: Connection attempt failed with "ECONNREFUSED - Connection refused by server", trying next address.
Status: Connecting to 65.49.XX.57:21...
Status: Connection established, waiting for welcome message...
Response:   220 ADrive.com - Username is your email address used for web interface. FTP is for Signature and Premium accounts only.

It looks like it got the IP address from the DNS (65.49.XX.56) but it failed to connect to this server, so it moved on to the next.

When using Rebex, it tries to connect to 65.49.XX.56 and fails, but doesn't move on to the next address. If I hard code the 65.49.XX.57 address then it connects okay.

I'm not sure what www.adrive.com are doing or if Rebex should be able to cope.

Any ideas?
Thanks.

Applies to: Rebex FTP/SSL

1 Answer

0 votes
by (148k points)

FTP server at ftp.adrive.com resolves into multiple addresses:

c:\>nslookup ftp.adrive.com
Server:  triton.hq.rebex.cz
Address:  192.168.2.3

Non-authoritative answer:
Name:    ftp.adrive.com
Addresses:  65.49.56.55
          65.49.56.53
          65.49.56.57
          65.49.56.56
          65.49.56.54
          65.49.56.52
          65.49.56.58

Rebex FTP/SSL uses the first address in the list. The order of resolved addresses is different each time, but the result is cached, which means Rebex FTP/SSL actually uses the same address each time until the cached DNS record expires.

We will consider changing this behavior (which means Rebex FTP/SSL would behave like FileZilla). In the meantime, use the following Resolve method as a workaround. Simply call serverName = Resolve(serverName) before calling Ftp.Connect method:

public static string Resolve(string serverName)
{
    // resolve server name
    IPHostEntry entry = Dns.GetHostEntry(serverName);

    // get all IPv4 addresses
    var addresses = new List<string>();
    foreach (IPAddress address in entry.AddressList)
    {
        if (address.AddressFamily == AddressFamily.InterNetwork)
            addresses.Add(address.ToString());
    }

    // if none found, get IPv6 addresses instead
    if (addresses.Count == 0)
    {
        foreach (IPAddress address in entry.AddressList)
        {
            if (address.AddressFamily == AddressFamily.InterNetworkV6)
                addresses.Add(address.ToString());
        }
    }

    // pick one of the addresses randomly
    if (addresses.Count > 0)
    {
        serverName = addresses[new Random().Next(0, addresses.Count - 1)];
    }

    return serverName;
}
by (180 points)
This works perfectly. Many thanks for the help.
...