System.Net.WebException: The server returned an address in response to the PASV command that is different than the address to which the FTP connection was made.
at System.Net.FtpWebRequest.CheckError()
at System.Net.FtpWebRequest.SyncRequestCallback(Object obj)
at System.Net.CommandStream.Abort(Exception e)
at System.Net.FtpWebRequest.FinishRequestStage(RequestStage stage)
at System.Net.FtpWebRequest.GetRequestStream()
at BackupDB.Program.FTPUploadFile(String serverPath, String serverFile, FileInfo LocalFile, NetworkCredential Cred) in D:\PROJEKTI\BackupDB\BackupDB\Program.cs:line 119
code:
FTPMakeDir(new Uri(serverPath + "/"), Cred);
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(serverPath+serverFile);
request.UsePassive = true;
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = Cred;
byte[] buffer = new byte[10240]; // Read/write 10kb
using (FileStream sourceStream = new FileStream(
LocalFile.ToString(), FileMode.Open))
{
using (Stream requestStream = request.GetRequestStream())
{
int bytesRead;
do
{
bytesRead = sourceStream.Read(buffer, 0, buffer.Length);
requestStream.Write(buffer, 0, bytesRead);
} while (bytesRead > 0);
}
response = (FtpWebResponse)request.GetResponse();
response.Close();
}
omg. What's up with all the pandering here for buying their 3rd party solutions instead of informing you to change one line of code?
Try toggling the Passive value to see which works:
request.UsePassive = false;
This may depend on the firewall between the Machines (client and server).
I've noticed if I go through our firewall, then I need it left at True, otherwise it will return the Exception:
The remote server returned an error: (500) Syntax error, command
unrecognized.
However, if I'm behind the firewall (like two machines connecting directly to each other within a data-center) then I need to set it to False, otherwise it will return the Exception:
The server returned an address in response to the PASV command that is different than the address to which the FTP connection was
made.
If this works and you want to make your solution more adaptable, you could wrap your request in a try-catch block using the default True value, and if you get the 500 error, then switch UsePassive to False and try it again.
if anyone have the same problem, this is solution for proftpd
http://www.proftpd.org/docs/howto/NAT.html
In passive mode FTP conversation goes as follows:
client: PASV
(i would like to transfer files. Tell me which port and ip address should I use)
server: 227 Entering Passive Mode (172,16,3,4,204,173)
(ok, use port 52397 on IP address 172.16.3.4.)
client: connects to this IP address/port and starts data transfer.
It looks like the FTP server with two public IP address (e.g. 1.2.3.4) returns a private IP address as a response to PASV command.
Solution
Switching to Active mode.
In active mode FTP server connects to FTP client for data transfers. It would solve this issue, but is not firewall friendly. It will not work when incoming connections are blocked (very common).
Ignoring IP address send as response to PASV command
If the public ftp server IP address is a public one, and IP address returned as a response for PASV command is from private range (such as 10., 192.168.). In such case the FTP client should use the public IP address.
This is exactly what does our Rebex FTP do in such situation. It works well (this behavior can be switched off). It can be even turned on for servers with multiple public IP addresses.
I don't know whether similar workaround is possible with FtpWebRequest.
You can download trial and check whether it solves your problem.
After a lot of digging around I found the only way to solve this problem was to change the PASV settings on the server.
Fortunately I control both the client and server machines so I was able to tell the server (FileZilla in my case) to use the public IP rather than the private IP.
Your FTP server is misconfigured.
In the passive mode the server reports an IP address and port to which the client should connect to for a data transfer. Your FTP server reports its IP address within an internal network, although it's behind a firewall/NAT. The client cannot connect to that internal address for obvious reason. You have to configure the FTP server to report its external IP address.
How that's done is server-specific and you didn't tell us, what your FTP server is.
- IIS: In IIS Manager, open FTP > FTP Firewall Support. See section Servers behind external Firewall/NAT in my guide to installing IIS server.
- FileZilla FTP server: Go to Edit > Settings > Passive mode settings > IPv4 specific > External Server IP Address for passive mode transfers. See FTP server running on Port 2000 over NAT not working on Passive Mode.
- ProFTPD: Use
MasqueradeAddress
directive.
- vsftpd:
pasv_address
directive.
Some answer here suggest using the active mode.
request.UsePassive = false;
But that can help only if there's no firewall/NAT between the client and the server, in which case you won't have the problem in the first place (unless the server is really broken and reports a completely wrong IP address, not only the internal one). Or if the firewall/NAT is configured to allow inbound connections, what is not usual.
Another approach is using a different FTP library that can workaround the problem by ignoring the incorrect IP address reported by the server and using the primary/control connection IP address. Or by using the EPSV
command instead of PASV
command that implicitly uses the primary/control connection IP address.