3

I have a test C# console app that uses FtpWebRequest to transfer a file to a public FTP server.

The app works from my Dev PC with UsePassive set to False. However, when I copy the app to an Azure VM it raises the following exception:

The remote server returned an error: (500) Syntax error, command unrecognized.

So in summary, these are the results when running the app locally and on Azure:

UsePassive  Local PC   Azure VM
----------  --------   --------
True        ok         ok
False       ok         ERROR!

Enabling tracing for System.Net shows the following (extract):

System.Net Information: 0 : [5716] FtpControlStream#60068066 - Created connection from 10.0.0.4:49706 to 90.130.70.73:21.
System.Net Information: 0 : [5716] Associating FtpWebRequest#45004109 with FtpControlStream#60068066
System.Net Information: 0 : [5716] FtpControlStream#60068066 - Received response [220 (vsFTPd 2.3.5)]
System.Net Information: 0 : [5716] FtpControlStream#60068066 - Sending command [USER anonymous]
System.Net Information: 0 : [5716] FtpControlStream#60068066 - Received response [331 Please specify the password.]
System.Net Information: 0 : [5716] FtpControlStream#60068066 - Sending command [PASS ********]
System.Net Information: 0 : [5716] FtpControlStream#60068066 - Received response [230 Login successful.]
System.Net Information: 0 : [5716] FtpControlStream#60068066 - Sending command [OPTS utf8 on]
System.Net Information: 0 : [5716] FtpControlStream#60068066 - Received response [200 Always in UTF8 mode.]
System.Net Information: 0 : [5716] FtpControlStream#60068066 - Sending command [PWD]
System.Net Information: 0 : [5716] FtpControlStream#60068066 - Received response [257 "/"]
System.Net Information: 0 : [5716] FtpControlStream#60068066 - Sending command [TYPE I]
System.Net Information: 0 : [5716] FtpControlStream#60068066 - Received response [200 Switching to Binary mode.]
System.Net Information: 0 : [5716] FtpControlStream#60068066 - Sending command [PORT 10,0,0,4,194,43]
System.Net Information: 0 : [5716] FtpControlStream#60068066 - Received response [500 Illegal PORT command.]
System.Net Information: 0 : [5716] FtpWebRequest#45004109::(Releasing FTP connection#60068066.)
System.Net Error: 0 : [5716] Exception in FtpWebRequest#45004109::GetRequestStream - The remote server returned an error: (500) Syntax error, command unrecognized..
   at System.Net.FtpWebRequest.SyncRequestCallback(Object obj)

Here is the source code to my app:

var fileContents = Encoding.UTF8.GetBytes("this is a test");

Console.Write("UsePassive? (y/n)");
var passive = Console.ReadKey();

var usePassive = passive.Key == ConsoleKey.Y;

var request = (FtpWebRequest)WebRequest.Create("ftp://speedtest.tele2.net/upload/mytest.txt");
request.Credentials = new NetworkCredential("anonymous", "anonymous");
request.Method = WebRequestMethods.Ftp.UploadFile;
request.UsePassive = usePassive;
request.ContentLength = fileContents.Length;

using (var requestStream = request.GetRequestStream())
{
    requestStream.WriteAsync(fileContents, 0, fileContents.Length);
}
using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
{
    Console.WriteLine($"Upload File Complete, status {response.StatusDescription}");
}

The Azure VM is not part of a network security group. I've tried disabling the firewall on the VM but the app still raises the exception.

How can I resolve this? It's a requirement that my app has UsePassive set to False.

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
user1651370
  • 863
  • 1
  • 8
  • 15
  • Why do you use `UsePassive=False`? - Actually this most likely [the same problem you have with `ftp.exe`](https://stackoverflow.com/q/51770347/850848). It's just that the `FtpWebRequest` has a bad habit of "translating" FTP error code to its own (quite often misleading) interpretation. In this case, it translated 500 to *"Syntax error, command unrecognized."*, hiding away original FTP server error message that was probably *"Illegal PORT command."*. – Martin Prikryl Aug 09 '18 at 15:18
  • But while `ftp.exe` supports active mode only, so you have no other option. With `FtpWebRequest` you can (and should) use the passive mode, solving the problem. – Martin Prikryl Aug 09 '18 at 15:19
  • The 3rd party FTP server that I'm trying to connect to does not support Passive. I get the following error: The remote server returned an error: 227 Entering Passive Mode. (The 3rd party FTP server is not the one shown in example code) – user1651370 Aug 09 '18 at 15:38
  • If the server did not support passive mode, it would never respond *"227 Entering Passive Mode"* - Looks like you have [XY problem](https://en.wikipedia.org/wiki/XY_problem) - Instead of solving the issue with passive mode (which you should use), you ask a question about active mode (which you should not use). – Martin Prikryl Aug 09 '18 at 15:43
  • I just set UsePassive = True & that's the error that is logged. – user1651370 Aug 09 '18 at 15:47
  • Sure, that what you already wrote in your previous comment. But it does not invalidate my response. – Martin Prikryl Aug 09 '18 at 15:49
  • So the problem is with the server? – user1651370 Aug 09 '18 at 15:55
  • Unlikely, as you can connect from other machine. - I'm just saying that you should ask a question about the problem with the passive mode, rather than about the problem with the active mode. Unless you have a very good reason to use the active mode (what you do not seem to have). – Martin Prikryl Aug 09 '18 at 16:05
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/177789/discussion-between-user1651370-and-martin-prikryl). – user1651370 Aug 10 '18 at 08:20

1 Answers1

1
PORT 10,0,0,4,194,43
500 Illegal PORT command.

10.0.0.4 is a private IP address. You cannot send a private IP address to FTP server, as it cannot connect back to it (hence 500 error). You have to use your public IP address. I do not know how to override a local IP address for FtpWebRequest. Checking .NET source code, it actually seems to me, that it's not even possible.

As I have already wrote you: Do not even try to use the active mode. It is complicated to setup from a network perspective. See my article on Network configuration for FTP active and passive modes.

So again, use passive mode. I'm aware that you also have problems with the passive mode. But they are more likely solvable than the problems with the active mode.


If you insist on the active mode, use FTP client library that supports specifying a local IP address.

For example with WinSCP .NET assembly:

// Set up session options
SessionOptions sessionOptions = new SessionOptions
{
    Protocol = Protocol.Ftp,
    HostName = "10.0.0.4",
    FtpMode = FtpMode.Active,
};

using (Session session = new Session())
{
    session.AddRawConfiguration(@"Interface\ExternalIpAddress", "your public IP address");

    // Connect
    session.Open(sessionOptions);

    // Upload
    session.PutFiles(@"C:\local\path\file.txt", "/upload/mytest.txt").Check();
}

(I'm the author of WinSCP)

You still have to open the VM firewall for all data connection ports.


While I didn't test it, it looks like that if local machine (VM) has only IPv6 IP address, FtpWebRequest would use EPRT command without an IP address, instead of PORT command with IP address. What would also solve your problem. You still have to open the VM firewall for all data connection ports.

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992