FtpWebRequest sends an invalid PORT command

  • Thread starter Thread starter Tsahi Asher
  • Start date Start date
T

Tsahi Asher

hi,
I have a windows service which connects to various FTP servers, and
sends them files, using the FtpWebRequest class. It works most of the
time, because almost all of them use passive mode.

One server, however, uses active (or Port) mode.

A short explanation about passive vs. active mode: FTP uses two
channels, one for control and one for data. the control channel
usually uses port 21 on the server. the data channel will use some
random port negotiated between the two sides. in passive mode, the
client will send the server the PASV command, and the the server will
reply with the IP and port the client should connect to send or
receive the data. in active mode, the client will send the PORT
command, with the IP and port the server should connect to in order to
send or receive the data.

my problem is, that when UsePassive is false, the FtpWebRequest sends
the PORT command with the IP 127.0.0.1, instead of the external IP, so
the server replies with "Invalid PORT Command" and the connection
closes. I found this by adding trace listeners in the app.config.

the service runs on the SYSTEM account. i tried running it on the
NetworkService account, but that didn't change anything. the same
code, running from a web site (under the ASPNET account i assume)
sends the external IP with the PORT command (or at least used to until
recently. this appear to revert to 127.0.0.1 too somehow in recent
days.)

any idea on what's causing this, or how to force FtpWebRequest to use
the external IP?

note that i have no control over that server, so i can't change it to
passive. it probably has some firewall problem, because when i try to
connect in passive mode, it replies to the STOR command (which starts
the file upload) with "Can't open data connection". the server appears
to be the one microsoft provides with IIS. it replies with "Microsoft
FTP Service" to the initial connection.

the code is quite trivial, and looks like this:

ftpRequest =
(FtpWebRequest)FtpWebRequest.Create(ReceiveDetails + "/" + fileName);
ftpRequest.UsePassive = usePassive;
ftpRequest.KeepAlive = false;
ftpRequest.UseBinary = true;
ftpRequest.Credentials = new
NetworkCredential(UserName, Password);
ftpRequest.Method = WebRequestMethods.Ftp.UploadFile;

FileInfo ff = new FileInfo(exportFileName);
byte[] fileContents = new byte[ff.Length];

using (FileStream fr = ff.OpenRead())
{
fr.Read(fileContents, 0,
Convert.ToInt32(ff.Length));
}
using (Stream writer = ftpRequest.GetRequestStream())
{
writer.Write(fileContents, 0,
fileContents.Length);
}
ftpRequest.GetResponse();
 
I have a windows service which connects to various FTP servers, and
sends them files, using the FtpWebRequest class. It works most of the
time, because almost all of them use passive mode.
One server, however, uses active (or Port) mode.
A short explanation about passive vs. active mode: FTP uses two
channels, one for control and one for data. the control channel
usually uses port 21 on the server. the data channel will use some
random port negotiated between the two sides. in passive mode, the
client will send the server the PASV command, and the the server will
reply with the IP and port the client should connect to send or
receive the data. in active mode, the client will send the PORT
command, with the IP and port the server should connect to in order to
send or receive the data.
my problem is, that when UsePassive is false, the FtpWebRequest sends
the PORT command with the IP 127.0.0.1, instead of the external IP, so
the server replies with "Invalid PORT Command" and the connection
closes. I found this by adding trace listeners in the app.config.
the service runs on the SYSTEM account. i tried running it on the
NetworkService account, but that didn't change anything. the same
code, running from a web site (under the ASPNET account i assume)
sends the external IP with the PORT command (or at least used to until
recently. this appear to revert to 127.0.0.1 too somehow in recent
days.)
any idea on what's causing this, or how to force FtpWebRequest to use
the external IP?
note that i have no control over that server, so i can't change it to
passive. it probably has some firewall problem, because when i try to
connect in passive mode, it replies to the STOR command (which starts
the file upload) with "Can't open data connection". the server appears
to be the one microsoft provides with IIS. it replies with "Microsoft
FTP Service" to the initial connection.
the code is quite trivial, and looks like this:
           ftpRequest =
(FtpWebRequest)FtpWebRequest.Create(ReceiveDetails + "/" + fileName);
                 ftpRequest.UsePassive = usePassive;
                 ftpRequest.KeepAlive = false;
                 ftpRequest.UseBinary = true;
                 ftpRequest.Credentials = new
NetworkCredential(UserName, Password);
                 ftpRequest.Method = WebRequestMethods.Ftp.UploadFile;
                 FileInfo ff = new FileInfo(exportFileName);
                 byte[] fileContents = new byte[ff.Length];
                 using (FileStream fr = ff.OpenRead())
                 {
                     fr.Read(fileContents, 0,
Convert.ToInt32(ff.Length));
                 }
                 using (Stream writer = ftpRequest.GetRequestStream())
                 {
                     writer.Write(fileContents, 0,
fileContents.Length);
                 }
                 ftpRequest.GetResponse();

My guess would be that there is a problem with the TCP/IP config
on the client system causing it to use 127.0.0.1.

Best approach may be to find that problem and fix it.

As a last chance alternative I have a source code FTP implementation,
where you can hack the code to do what you want.

Arne

now here's the fun part: i created a test service that just retrieves
the list of files from the FTP server (NLST command), and it sends the
correct IP in the PORT command, running on the SYSTEM account.

Thanks for the help, Arne, but i would rather not maintain more code
than i need to. where should i look for the TCP/IP config?


Tsahi
 
now here's the fun part: i created a test service that just retrieves
the list of files from the FTP server (NLST command), and it sends the
correct IP in the PORT command, running on the SYSTEM account.

This somehow indicates it is related to access to something.
where should i look for the TCP/IP config?

My Windows expertise is not big enough to help with this.
Thanks for the help, Arne, but i would rather not maintain more code
than i need to.

Understandable.

Arne
 
Back
Top