FTP Error 500 Illegal Port Command – PORT command sending different IP than source of request

ftpnicwindows-server-2008-r2wireshark

The problem I'm experiencing is that I'm getting a "500 Illegal PORT command" Response from an FTP server when attempting to upload a file programmatically.

This program is a small c# application that connects to an FTP site and copies files to the default directory. This program has been in production for several years and I am confident the code itself works just fine. I've also tested the application by connecting to my own FTP site using the same application and it works. Passive mode does not seem to be an option.

When attempting to connect to our partner's FTP site, the program runs as expected until the FTP put command is executed. I have noticed when running Wireshark that the source IP of my Request is different from the IP address the PORT command is sending. I have uploaded an image of a capture here (all sensitive information has been removed using my amazing photoshop skills):

Wireshark Screenshot of program's FTP transmission.

I have contacted the owner of the FTP site where we are attempting to transfer the files and they have opened their firewall for our new Static IP address. I can connect to their site using FTP clients from machines on both of the LAN IP's, but those PORT commands are always sent using the same LAN IP as the source of the request. I have also tried using ftp.exe from the server where the program resides, and it is successful (but the PORT command uses the same IP as the source).

So I guess the big question is how can I control what IP address the PORT command uses? Or, if I can't control it, how is the IP address and PORT determined by the ftp program?

Best Answer

It turns out the answer really has to do with the FTP library I was using. I thought for sure this wasn't a coding issue, but after I sniffed around how the library is creating the request, I think I have found the answer.

Here is the relevant section using ILSpy (I put space around the most important line):

private Socket CreateDataSocketActive()
{
    Socket socket = new Socket(2, 1, 6);
    IPHostEntry iPHostEntry = Dns.Resolve(Dns.GetHostName());

    IPEndPoint iPEndPoint = new IPEndPoint(iPHostEntry.get_AddressList()[0], 0);

    socket.Bind(iPEndPoint);
    socket.Listen(5);
    int port = ((IPEndPoint)socket.get_LocalEndPoint()).get_Port();
    IPAddress address = ((IPEndPoint)socket.get_LocalEndPoint()).get_Address();
    this.SetDataPort((IPEndPoint)socket.get_LocalEndPoint());
    return socket;
}

It looks like the library is creating the IP endpoint by simply grabbing the first address in the list of available IP addresses. For most solutions, that is probably acceptable, but because I have multiple NICs on my server, it doesn't work for me.

I know by using FTP.exe that the server will accept connections from both of my LAN IP subnets so long as the PORT command issued is issued using the same LAN IP address as the source of the request.

I'm guessing there's some kind of validation done by the FTP server that compares the two addresses to verify they're the same. Otherwise, I could theoretically transfer a file to some other device on a completely different network once I logged into the FTP site.

Now I've just got to figure out a workaround, but that should just be a matter of finding a new library or rolling my own. If it helps anyone else who might have had the same issue, the library I was using was com.enterprisedt.net.ftp.