在Azure VM上处于活动模式(UsePassive = False)时,FtpWebRequest出现“ 500语法错误,命令无法识别”

时间:2018-07-25 09:06:13

标签: c# .net azure ftp ftpwebrequest

我有一个测试C#控制台应用程序,它使用FtpWebRequest将文件传输到公共FTP服务器。

该应用程序可在我的Dev PC上运行,并且UsePassive设置为False。但是,当我将应用程序复制到Azure VM时,会引发以下异常:

  

远程服务器返回错误:(500)语法错误,命令   无法识别。

因此,总而言之,以下是在本地和Azure上运行应用程序时的结果:

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

System.Net启用跟踪将显示以下内容(摘录):

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)

这是我的应用程序的源代码:

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}");
}

Azure VM不属于网络安全组。我曾尝试在VM上禁用防火墙,但该应用仍然会引发异常。

我该如何解决?我的应用要求将UsePassive设置为False

1 个答案:

答案 0 :(得分:1)

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

10.0.0.4是专用IP地址。您无法将专用IP地址发送到FTP服务器,因为它无法重新连接到它(因此出现500错误)。您必须使用您的公共IP地址。我不知道如何为FtpWebRequest覆盖本地IP地址。在我看来,检查.NET源代码实际上是不可能的。

正如我已经写过的那样:甚至不要尝试使用活动模式。从网络角度来看,设置很复杂。请参阅我在Network configuration for FTP active and passive modes上的文章。

同样,使用被动模式。我知道您在被动模式下也遇到问题。但是它们比主动模式的问题更有可能解决。


如果您坚持使用活动模式,请使用支持指定本地IP地址的FTP客户端库。

例如使用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();
}

(我是WinSCP的作者)

您仍然必须为所有数据连接端口打开VM防火墙。


虽然我没有对其进行测试,但看起来如果本地计算机(VM)仅具有IPv6 IP地址,FtpWebRequest将使用EPRT命令地址,而不是带有IP地址的PORT命令。什么也可以解决您的问题。您仍然必须为所有数据连接端口打开VM防火墙。