FTP Active Mode - Can't Get Server To Connect after PORT Command

  • Thread starter Thread starter Jim Davis
  • Start date Start date
J

Jim Davis

I am trying to implement a Active mode connection to an FTP server, but
cannot get the server to connect to the port specified by the PORT command.
Below is the code that creates an active data connection. It is based on
code found in the FtpWebRequest class referenced in the following article:
http://aspalliance.com/articleViewer.aspx?aId=253&pId=. When this code
executes, the ftp server never makes a connection to my Socket.

I have seen a couple other examples that look similar. I know Active mode
works with my test FTP server, as I can use a 3rd party product in that mode
without any problems. No doubt there is some simple aspect I am not doing
that I should be. Can someone point out what I am missing.?

Thanks,

Jim


private Socket createDataSocketActive()
{
dataSocket = new Socket( AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp );
dataSocket.Blocking = false;

IPHostEntry lhi = Dns.GetHostByName(Dns.GetHostName());

IPEndPoint epListener = new IPEndPoint(lhi.AddressList[0], 0);
dataSocket.Bind(epListener);
dataSocket.Listen(5); // Put the dataSocket * & in Listen mode

//Extract the port of the new Socket to use in the FTP PORT command
IPEndPoint localEP = (IPEndPoint) dataSocket.LocalEndPoint;
Byte[] adrBytes =localEP.Address.GetAddressBytes();

//Format PORT command arguments, Ex: 192,168,0,59,106,223
String szLocal = FormatAddress(adrBytes, localEP.Port);

this.sendCommand("PORT " + szLocal);

if ( this.resultCode != 200 ) throw new
FtpException(this.result.Substring(4));

Socket s = dataSocket.Accept();
return s;
}
 
Jim Davis said:
I am trying to implement a Active mode connection to an FTP server, but
cannot get the server to connect to the port specified by the PORT command.
Below is the code that creates an active data connection. It is based on
code found in the FtpWebRequest class referenced in the following article: ....

private Socket createDataSocketActive()
{
dataSocket = new Socket( AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp );
dataSocket.Blocking = false;

IPHostEntry lhi = Dns.GetHostByName(Dns.GetHostName());

IPEndPoint epListener = new IPEndPoint(lhi.AddressList[0], 0);

....

Please check what lhi.AddressList[0] is resolved to. You are asking for
troubles on multihomed systems, as you are only listening on first adress
resolved. Use IPAdress.Any insted ("0.0.0.0").

Regards,
Goran
 
lhi.Address[0] is resolved to my workstation. When I use IPAddress.Any, the
PORT command arguments sent are "0, 0, 0, 0, 5, 193", and I get an "Invalid
PORT command" response from the FTP server.





Goran Sliskovic said:
Jim Davis said:
I am trying to implement a Active mode connection to an FTP server, but
cannot get the server to connect to the port specified by the PORT command.
Below is the code that creates an active data connection. It is based on
code found in the FtpWebRequest class referenced in the following
article: ...

private Socket createDataSocketActive()
{
dataSocket = new Socket( AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp );
dataSocket.Blocking = false;

IPHostEntry lhi = Dns.GetHostByName(Dns.GetHostName());

IPEndPoint epListener = new IPEndPoint(lhi.AddressList[0], 0);

...

Please check what lhi.AddressList[0] is resolved to. You are asking for
troubles on multihomed systems, as you are only listening on first adress
resolved. Use IPAdress.Any insted ("0.0.0.0").

Regards,
Goran
 
Jim Davis said:
lhi.Address[0] is resolved to my workstation. When I use IPAddress.Any, the
PORT command arguments sent are "0, 0, 0, 0, 5, 193", and I get an "Invalid
PORT command" response from the FTP server.
....
You have to send IP address reachable from server in port command (that
means you can as well listen on only one address). The problem with active
transfer is:
a) It's not easy to determine reachable address from server if you are
multihomed (have multiple IP addresses bind to one interface or have
multiple interfaces)
b) it won't work accross NAT routers (unless NAT router has statefull packet
analysis and is configured to accept FTP)
c) it won't work through firewalls
d) because of security issues, this is usually disabled

Bottom line is, don't do it. It will probably break in any setup other than
LAN. Use passive transfer.

Anyway, you FTP sequence is not correct:
You accept socket after PORT command, which blocks. Correct sequence for
file transimission is:
client: PORT ...
server: 200 PORT successfull
client: RETR filename
server: 150 Opening binary mode data connection ....
server: connects to socket identified by PORT command
client: accepts socket

Regards,
Goran
 
Thank you for your feed back, especially pointing out the sequence error. I
put the Socket.Accept command after sending the data request to the FTP
server and it works.

Based on all the feedback concerning the difficulty of implementing robust
FTP, I think I can now convice my boss to let a bit of money go and buy a
comercial component for FTP.




Goran Sliskovic said:
Jim Davis said:
lhi.Address[0] is resolved to my workstation. When I use IPAddress.Any, the
PORT command arguments sent are "0, 0, 0, 0, 5, 193", and I get an "Invalid
PORT command" response from the FTP server.
...
You have to send IP address reachable from server in port command (that
means you can as well listen on only one address). The problem with active
transfer is:
a) It's not easy to determine reachable address from server if you are
multihomed (have multiple IP addresses bind to one interface or have
multiple interfaces)
b) it won't work accross NAT routers (unless NAT router has statefull
packet
analysis and is configured to accept FTP)
c) it won't work through firewalls
d) because of security issues, this is usually disabled

Bottom line is, don't do it. It will probably break in any setup other
than
LAN. Use passive transfer.

Anyway, you FTP sequence is not correct:
You accept socket after PORT command, which blocks. Correct sequence for
file transimission is:
client: PORT ...
server: 200 PORT successfull
client: RETR filename
server: 150 Opening binary mode data connection ....
server: connects to socket identified by PORT command
client: accepts socket

Regards,
Goran
 
Jim Davis said:
Thank you for your feed back, especially pointing out the sequence error. I
put the Socket.Accept command after sending the data request to the FTP
server and it works.

Based on all the feedback concerning the difficulty of implementing robust
FTP, I think I can now convice my boss to let a bit of money go and buy a
comercial component for FTP.
....
Yes, I'd advise so. FYI, windows come with wininet.lib, which implements ftp
client functionality. As far as I can see, it supports both passive and
active FTP transfer. Check InternetConnect in MSDN. You may use it, but of
course, you'll have to wrap (use interop) to use it in C#.

Regards,
Goran
 
BTW, the .Net framework 2.0 has very nice FtpWebRequest and FtpWebResponse
classes, that I have used with great success.

--
HTH,

Kevin Spencer
Microsoft MVP
..Net Developer
Big things are made up of
lots of little things.

Jim Davis said:
Thank you for your feed back, especially pointing out the sequence error.
I put the Socket.Accept command after sending the data request to the FTP
server and it works.

Based on all the feedback concerning the difficulty of implementing robust
FTP, I think I can now convice my boss to let a bit of money go and buy a
comercial component for FTP.




Goran Sliskovic said:
Jim Davis said:
lhi.Address[0] is resolved to my workstation. When I use IPAddress.Any, the
PORT command arguments sent are "0, 0, 0, 0, 5, 193", and I get an "Invalid
PORT command" response from the FTP server.
...
You have to send IP address reachable from server in port command (that
means you can as well listen on only one address). The problem with
active
transfer is:
a) It's not easy to determine reachable address from server if you are
multihomed (have multiple IP addresses bind to one interface or have
multiple interfaces)
b) it won't work accross NAT routers (unless NAT router has statefull
packet
analysis and is configured to accept FTP)
c) it won't work through firewalls
d) because of security issues, this is usually disabled

Bottom line is, don't do it. It will probably break in any setup other
than
LAN. Use passive transfer.

Anyway, you FTP sequence is not correct:
You accept socket after PORT command, which blocks. Correct sequence for
file transimission is:
client: PORT ...
server: 200 PORT successfull
client: RETR filename
server: 150 Opening binary mode data connection ....
server: connects to socket identified by PORT command
client: accepts socket

Regards,
Goran
 
Back
Top