Solved

VB.NET 2005 FTP Program - TCPIP and Sockets using wrong ports and not working through Windows Firewall

Posted on 2008-06-16
17
1,619 Views
Last Modified: 2011-10-03
See the attached code (670 lines)

This class enables FTP ing via visual basic. I got it free on the internet !!  Only problem is, it doesn't work when the target server is running windows firewall.

I caught it in the debugger and the problem is in Private Function CreateDataSocket, on the line "s.Connect(ep)"

The variable "port" in the program is programmatically generated and is a different number each time. Windows firewall is also rejecting other ports as in the below pfirewall.log:

#Version: 1.5
#Software: Microsoft Windows Firewall
#Time Format: Local
#Fields: date time action protocol src-ip dst-ip src-port dst-port size tcpflags tcpsyn tcpack tcpwin icmptype icmpcode info path

2008-06-16 16:48:23 DROP TCP 99.99.108.178 99.99.163.114 3104 1196 48 S 507753288 0 65535 - - - RECEIVE
2008-06-16 16:48:32 DROP TCP 99.99.108.178 99.99.163.114 3104 1196 48 S 507753288 0 65535 - - - RECEIVE
2008-06-16 16:48:26 DROP TCP 99.99.108.178 99.99.163.114 3104 1196 48 S 507753288 0 65535 - - - RECEIVE
2008-06-16 17:59:07 DROP TCP 99.99.108.178 99.99.163.114 3126 1048 48 S 2942101445 0 65535 - - - RECEIVE
2008-06-16 17:59:04 DROP TCP 99.99.108.178 99.99.163.114 3126 1048 48 S 2942101445 0 65535 - - - RECEIVE
2008-06-16 17:59:13 DROP TCP 99.99.108.178 99.99.163.114 3126 1048 48 S 2942101445 0 65535 - - - RECEIVE

So ports 1196 and 1048 were attempted on different calls.

Any ideas how to fix this program so it can work just through port 21 ?

thanks

Public Class Ftp

 

    Private m_sRemoteHost, m_sRemotePath, m_sRemoteUser As String

    Private m_sRemotePassword, m_sMess As String

    Private m_iRemotePort, m_iBytes As Int32

    Private m_objClientSocket As System.Net.Sockets.Socket

 

    Private m_iRetValue As Int32

    Private m_bLoggedIn As Boolean

    Private m_sMes, m_sReply As String

 

    'Set the size of the packet that is used to read and to write data to the FTP server

    'to the following specified size.

    Public Const BLOCK_SIZE As Integer = 512

    Private m_aBuffer(BLOCK_SIZE) As Byte

    Private ASCII As System.Text.Encoding = System.Text.Encoding.ASCII

    Public flag_bool As Boolean

    'General variable declaration

    Private m_sMessageString As String

 

    ' Parameterized constructor

    Public Sub New(ByVal sRemoteHost As String, _

                   ByVal sRemoteUser As String, _

                   ByVal sRemotePassword As String, _

                   ByVal iRemotePort As Int32, _

                   ByVal sRemotePath As String)

        m_sRemoteHost = sRemoteHost

        m_sRemotePath = sRemotePath

        m_sRemoteUser = sRemoteUser

        m_sRemotePassword = sRemotePassword

        m_sMessageString = ""

        m_iRemotePort = iRemotePort

        m_bLoggedIn = False

    End Sub

 

 

    'Set or Get the name of the FTP server that you want to connect.

    Public Property RemoteHostFTPServer() As String

        'Get the name of the FTP server.

        Get

            Return m_sRemoteHost

        End Get

        'Set the name of the FTP server.

        Set(ByVal Value As String)

            m_sRemoteHost = Value

        End Set

    End Property

 

    'Set or Get the FTP Port Number of the FTP server that you want to connect.

    Public Property RemotePort() As Int32

        'Get the FTP Port Number.

        Get

            Return m_iRemotePort

        End Get

        'Set the FTP Port Number.

        Set(ByVal Value As Int32)

            m_iRemotePort = Value

 

        End Set

    End Property

 

    'Set or Get the remote path of the FTP server that you want to connect.

    Public Property RemotePath() As String

        'Get the remote path.

        Get

            Return m_sRemotePath

        End Get

        'Set the remote path.

        Set(ByVal Value As String)

            m_sRemotePath = Value

        End Set

    End Property

 

    'Set or Get the remote password of the FTP server that you want to connect.

    Public Property RemotePassword() As String

        Get

            Return m_sRemotePassword

        End Get

        Set(ByVal Value As String)

            m_sRemotePassword = Value

        End Set

    End Property

 

    'Set or Get the remote user of the FTP server that you want to connect.

    Public Property RemoteUser() As String

        Get

            Return m_sRemoteUser

        End Get

        Set(ByVal Value As String)

            m_sRemoteUser = Value

        End Set

    End Property

 

    'Set the class MessageString.

    Public Property MessageString() As String

        Get

            Return m_sMessageString

        End Get

        Set(ByVal Value As String)

            m_sMessageString = Value

        End Set

    End Property

 

    'Return a list of files in a string() array from the file system.

    Public Function GetFileList(ByVal sMask As String) As String()

        Dim cSocket As System.Net.Sockets.Socket

        Dim bytes As Int32

        Dim seperator As Char = ControlChars.Lf

        Dim mess() As String

 

        m_sMes = ""

        'Check if you are logged on to the FTP server.

        If (Not (m_bLoggedIn)) Then

            Login()

        End If

 

        cSocket = CreateDataSocket()

        'Send an FTP command,

        SendCommand("NLST " & sMask)

 

        If (Not (m_iRetValue = 150 Or m_iRetValue = 125)) Then

            MessageString = m_sReply

            Throw New System.IO.IOException(m_sReply.Substring(4))

        End If

 

        m_sMes = ""

        Do While (True)

            Array.Clear(m_aBuffer, 0, m_aBuffer.Length)

            bytes = cSocket.Receive(m_aBuffer, m_aBuffer.Length, 0)

            m_sMes += ASCII.GetString(m_aBuffer, 0, bytes)

 

            If (bytes < m_aBuffer.Length) Then

                Exit Do

            End If

        Loop

 

        mess = m_sMes.Split(seperator)

        cSocket.Close()

        ReadReply()

 

        If (m_iRetValue <> 226) Then

            MessageString = m_sReply

            Throw New System.IO.IOException(m_sReply.Substring(4))

        End If

 

        Return mess

    End Function

 

    ' Get the size of the file on the FTP server.

    Public Function GetFileSize(ByVal sFileName As String) As Long

        Dim size As Long

 

        If (Not (m_bLoggedIn)) Then

            Login()

        End If

        'Send an FTP command.

        SendCommand("SIZE " & sFileName)

        size = 0

 

        If (m_iRetValue = 213) Then

            size = Int64.Parse(m_sReply.Substring(4))

        Else

            MessageString = m_sReply

            Throw New System.IO.IOException(m_sReply.Substring(4))

        End If

 

        Return size

    End Function

 

    'Log on to the FTP server.

    Public Function Login() As Boolean

 

        m_objClientSocket = New System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp)

 

        Dim ep As New System.Net.IPEndPoint(Net.IPAddress.Parse(m_sRemoteHost), m_iRemotePort)

 

        Try

            m_objClientSocket.Connect(ep)

        Catch ex As Exception

            MessageString = m_sReply

            Throw New System.IO.IOException("Cannot connect to remote server")

 

        End Try

 

        ReadReply()

        If (m_iRetValue <> 220) Then

            CloseConnection()

            MessageString = m_sReply

            Throw New System.IO.IOException(m_sReply.Substring(4))

        End If

        'Send an FTP command to send a user logon ID to the server.

        SendCommand("USER " & m_sRemoteUser)

        If (Not (m_iRetValue = 331 Or m_iRetValue = 230)) Then

            Cleanup()

            MessageString = m_sReply

            Throw New System.IO.IOException(m_sReply.Substring(4))

        End If

 

        If (m_iRetValue <> 230) Then

            'Send an FTP command to send a user logon password to the server.

            SendCommand("PASS " & m_sRemotePassword)

            If (Not (m_iRetValue = 230 Or m_iRetValue = 202)) Then

                Cleanup()

                MessageString = m_sReply

                Throw New System.IO.IOException(m_sReply.Substring(4))

            End If

        End If

 

        m_bLoggedIn = True

        'Call the ChangeDirectory user-defined function to change the folder to the

        'remote FTP folder that is mapped.

        ChangeDirectory(m_sRemotePath)

 

        'Return the final result.

        Return m_bLoggedIn

    End Function

 

    'If the value of mode is true, set the binary mode for downloads. Otherwise, set ASCII mode.

    Public Sub SetBinaryMode(ByVal bMode As Boolean)

 

        If (bMode) Then

            'Send the FTP command to set the binary mode.

            '(TYPE is an FTP command that is used to specify representation type.)

            SendCommand("TYPE I")

        Else

            'Send the FTP command to set ASCII mode.

            '(TYPE is a FTP command that is used to specify representation type.)

            SendCommand("TYPE A")

        End If

 

        If (m_iRetValue <> 200) Then

            MessageString = m_sReply

            Throw New System.IO.IOException(m_sReply.Substring(4))

        End If

    End Sub

 

    Public Sub SetSiteFileType(ByVal FileType As String)

        Dim cmdString As New System.Text.StringBuilder

        cmdString.Append("site filetype=").Append(FileType)

 

        SendCommand(cmdString.ToString)

 

        If (m_iRetValue <> 200) Then

            MessageString = m_sReply

            Throw New System.IO.IOException(m_sReply.Substring(4))

        End If

    End Sub

 

    ' Download a file to the local folder of the assembly, and keep the same file name.

    Public Sub DownloadFile(ByVal sFileName As String)

        DownloadFile(sFileName, "", False)

    End Sub

    ' Download a remote file to the local folder of the assembly, and keep the same file name.

    Public Sub DownloadFile(ByVal sFileName As String, _

                            ByVal bResume As Boolean)

        DownloadFile(sFileName, "", bResume)

    End Sub

    'Download a remote file to a local file name. You must include a path.

    'The local file name will be created or will be overwritten, but the path must exist.

    Public Sub DownloadFile(ByVal sFileName As String, _

                            ByVal sLocalFileName As String)

        DownloadFile(sFileName, sLocalFileName, False)

    End Sub

    ' Download a remote file to a local file name and include a path. Then, set the

    ' resume flag. The local file name will be created or will be overwritten, but the path must exist.

    Public Sub DownloadFile(ByVal sFileName As String, _

                            ByVal sLocalFileName As String, _

                            ByVal bResume As Boolean)

        Dim st As System.IO.Stream

        Dim output As System.IO.FileStream

        Dim cSocket As System.Net.Sockets.Socket

        Dim offset, npos As Long

 

        If (Not (m_bLoggedIn)) Then

            Login()

        End If

 

        'SetBinaryMode(True)

 

        If (sLocalFileName.Equals("")) Then

            sLocalFileName = sFileName

        End If

 

        If (Not (System.IO.File.Exists(sLocalFileName))) Then

            st = System.IO.File.Create(sLocalFileName)

            st.Close()

        End If

 

        output = New System.IO.FileStream(sLocalFileName, System.IO.FileMode.Open)

        cSocket = CreateDataSocket()

        offset = 0

 

        If (bResume) Then

            offset = output.Length

 

            If (offset > 0) Then

                'Send an FTP command to restart.

                SendCommand("REST " & offset)

                If (m_iRetValue <> 350) Then

                    offset = 0

                End If

            End If

 

            If (offset > 0) Then

                npos = output.Seek(offset, System.IO.SeekOrigin.Begin)

            End If

        End If

        'Send an FTP command to retrieve a file.

        SendCommand("RETR " & sFileName)

 

        If (Not (m_iRetValue = 150 Or m_iRetValue = 125)) Then

            output.Close()

            MessageString = m_sReply

            Throw New System.IO.IOException(m_sReply.Substring(4))

        End If

 

        Do While (True)

            Array.Clear(m_aBuffer, 0, m_aBuffer.Length)

            m_iBytes = cSocket.Receive(m_aBuffer, m_aBuffer.Length, 0)

            output.Write(m_aBuffer, 0, m_iBytes)

 

            If (m_iBytes <= 0) Then

                Exit Do

            End If

        Loop

 

        output.Close()

        If (cSocket.Connected) Then

            cSocket.Close()

        End If

 

        ReadReply()

        If (Not (m_iRetValue = 226 Or m_iRetValue = 250)) Then

            MessageString = m_sReply

            Throw New System.IO.IOException(m_sReply.Substring(4))

        End If

 

    End Sub

 

    ' Delete a file from the remote FTP server.

    Public Function DeleteFile(ByVal sFileName As String) As Boolean

        Dim bResult As Boolean

 

        bResult = True

        If (Not (m_bLoggedIn)) Then

            Login()

        End If

        'Send an FTP command to delete a file.

        SendCommand("DELE " & sFileName)

        If (m_iRetValue <> 250) Then

            bResult = False

            MessageString = m_sReply

        End If

 

        ' Return the final result.

        Return bResult

    End Function

    ' Rename a file on the remote FTP server.

    Public Function RenameFile(ByVal sOldFileName As String, _

                               ByVal sNewFileName As String) As Boolean

        Dim bResult As Boolean

 

        bResult = True

        If (Not (m_bLoggedIn)) Then

            Login()

        End If

        'Send an FTP command to rename a file.

        SendCommand("RNFR " & sOldFileName)

        If (m_iRetValue <> 350) Then

            MessageString = m_sReply

            Throw New System.IO.IOException(m_sReply.Substring(4))

        End If

 

        'Send an FTP command to rename a file to a file name.

        'It will overwrite if newFileName exists.

        SendCommand("RNTO " & sNewFileName)

        If (m_iRetValue <> 250) Then

            MessageString = m_sReply

            Throw New System.IO.IOException(m_sReply.Substring(4))

        End If

        ' Return the final result.

        Return bResult

    End Function

 

    'This is a function that is used to create a folder on the remote FTP server.

    Public Function CreateDirectory(ByVal sDirName As String) As Boolean

        Dim bResult As Boolean

 

        bResult = True

        If (Not (m_bLoggedIn)) Then

            Login()

        End If

        'Send an FTP command to make a folder on the FTP server.

        SendCommand("MKD " & sDirName)

        If (m_iRetValue <> 257) Then

            bResult = False

            MessageString = m_sReply

        End If

 

        ' Return the final result.

        Return bResult

    End Function

    ' This is a function that is used to delete a folder on the remote FTP server.

    Public Function RemoveDirectory(ByVal sDirName As String) As Boolean

        Dim bResult As Boolean

 

        bResult = True

        'Check if you are logged on to the FTP server.

        If (Not (m_bLoggedIn)) Then

            Login()

        End If

        'Send an FTP command to remove a folder on the FTP server.

        SendCommand("RMD " & sDirName)

        If (m_iRetValue <> 250) Then

            bResult = False

            MessageString = m_sReply

        End If

 

        ' Return the final result.

        Return bResult

    End Function

    'This is a function that is used to change the current working folder on the remote FTP server.

    Public Function ChangeDirectory(ByVal sDirName As String) As Boolean

        Dim bResult As Boolean

 

        bResult = True

        'Check if you are in the root directory.

        If (sDirName.Equals(".")) Then

            Exit Function

        End If

        'Check if you are logged on to the FTP server.

        If (Not (m_bLoggedIn)) Then

            Login()

        End If

        'Send an FTP command to change the folder on the FTP server.

        SendCommand("CWD " & sDirName)

        If (m_iRetValue <> 250) Then

            bResult = False

            MessageString = m_sReply

        End If

 

        Me.m_sRemotePath = sDirName

 

        ' Return the final result.

        Return bResult

    End Function

    ' Close the FTP connection of the remote server.

    Public Sub CloseConnection()

        If (Not (m_objClientSocket Is Nothing)) Then

            'Send an FTP command to end an FTP server system.

            SendCommand("QUIT")

        End If

 

        Cleanup()

    End Sub

 

    ' Read the reply from the FTP server.

    Private Sub ReadReply()

        m_sMes = ""

        m_sReply = ReadLine()

        m_iRetValue = Int32.Parse(m_sReply.Substring(0, 3))

    End Sub

 

    ' Clean up some variables.

    Private Sub Cleanup()

        If Not (m_objClientSocket Is Nothing) Then

            m_objClientSocket.Close()

            m_objClientSocket = Nothing

        End If

 

        m_bLoggedIn = False

    End Sub

    ' Read a line from the FTP server.

    Private Function ReadLine(Optional ByVal bClearMes As Boolean = False) As String

        Dim seperator As Char = ControlChars.Lf

        Dim mess() As String

 

        If (bClearMes) Then

            m_sMes = ""

        End If

        Do While (True)

            Array.Clear(m_aBuffer, 0, BLOCK_SIZE)

            m_iBytes = m_objClientSocket.Receive(m_aBuffer, m_aBuffer.Length, 0)

            m_sMes += ASCII.GetString(m_aBuffer, 0, m_iBytes)

            If (m_iBytes < m_aBuffer.Length) Then

                Exit Do

            End If

        Loop

 

        mess = m_sMes.Split(seperator)

        If (m_sMes.Length > 2) Then

            m_sMes = mess(mess.Length - 2)

        Else

            m_sMes = mess(0)

        End If

        'TODO fix problem reading zero length field

        If (Not (m_sMes.Substring(3, 1).Equals(" "))) Then

            Return ReadLine(True)

        End If

 

        Return m_sMes

    End Function

    ' This is a function that is used to send a command to the FTP server that you are connected to.

    Private Sub SendCommand(ByVal sCommand As String)

        sCommand = sCommand & ControlChars.CrLf

        Dim cmdbytes As Byte() = ASCII.GetBytes(sCommand)

        m_objClientSocket.Send(cmdbytes, cmdbytes.Length, 0)

        ReadReply()

    End Sub

    ' Create a data socket.

    Private Function CreateDataSocket() As System.Net.Sockets.Socket

        Dim index1, index2, len As Int32

        Dim partCount, i, port As Int32

        Dim ipData, buf, ipAddress As String

        Dim parts(6) As Int32

        Dim ch As Char

        Dim s As System.Net.Sockets.Socket

        Dim ep As System.Net.IPEndPoint

        'Send an FTP command to use a passive data connection.

        SendCommand("PASV")

        If (m_iRetValue <> 227) Then

            MessageString = m_sReply

            Throw New System.IO.IOException(m_sReply.Substring(4))

        End If

 

        index1 = m_sReply.IndexOf("(")

        index2 = m_sReply.IndexOf(")")

        ipData = m_sReply.Substring(index1 + 1, index2 - index1 - 1)

 

        len = ipData.Length

        partCount = 0

        buf = ""

 

        For i = 0 To len - 1

            If partCount > 6 Then

                Exit For

            End If

            ch = Char.Parse(ipData.Substring(i, 1))

            If (Char.IsDigit(ch)) Then

                buf += ch

            ElseIf (ch <> ",") Then

                MessageString = m_sReply

                Throw New System.IO.IOException("Malformed PASV reply: " & m_sReply)

            End If

 

            If ((ch = ",") Or (i + 1 = len)) Then

                Try

                    parts(partCount) = Int32.Parse(buf)

                    partCount += 1

                    buf = ""

                Catch ex As Exception

                    MessageString = m_sReply

                    Throw New System.IO.IOException("Malformed PASV reply: " & m_sReply)

                End Try

            End If

        Next

 

        ipAddress = parts(0) & "." & parts(1) & "." & parts(2) & "." & parts(3)

 

        ' Make this call in Visual Basic .NET 2002.  You want to

        ' bitshift the number by 8 bits. Therefore, in Visual Basic .NET 2002, you must

        ' multiply the number by 2 to the power of 8.

        'port = parts(4) * (2 ^ 8)

 

        ' Make this call and then comment out the previous line for Visual Basic .NET 2003.

        port = parts(4) << 8

 

        ' Determine the data port number.

        port = port + parts(5)

 

        s = New System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp)

        'ep = New System.Net.IPEndPoint(Dns.Resolve(ipAddress).AddressList(0), port)

        ep = New System.Net.IPEndPoint(Net.IPAddress.Parse(ipAddress), port)

 

        Try

            s.Connect(ep)                     /// ********* THIS IS THE PROBLEM LINE - EP.port is not 21 - so this hits windows firewall and times out ********** ////////

        Catch ex As Exception

            MessageString = m_sReply

            Throw New System.IO.IOException("Cannot connect to remote server")

            'If you cannot connect to the FTP

            'server that is specified, make the boolean variable false.

            flag_bool = False

        End Try

        'If you can connect to the FTP server that is specified, make the boolean variable true.

        flag_bool = True

        Return s

    End Function

 

 

    Public Sub UploadFile(ByVal sFileName As String, ByVal sUploadName As String, _

                              ByVal bResume As Boolean)

        Dim cSocket As System.Net.Sockets.Socket

        Dim offset As Long

        Dim input As System.IO.FileStream

        Dim bFileNotFound As Boolean

 

        If (Not (m_bLoggedIn)) Then

            Login()

        End If

 

        cSocket = CreateDataSocket()

        offset = 0

 

        If (bResume) Then

            Try

                'SetBinaryMode(True)

                offset = GetFileSize(sFileName)

            Catch ex As Exception

                offset = 0

            End Try

        End If

 

        If (offset > 0) Then

            SendCommand("REST " & offset)

            If (m_iRetValue <> 350) Then

 

                'The remote server may not support resuming.

                offset = 0

            End If

        End If

        'Send an FTP command to store a file.

        SendCommand("STOR " & sUploadName)

        If (Not (m_iRetValue = 125 Or m_iRetValue = 150)) Then

            MessageString = m_sReply

            Throw New System.IO.IOException(m_sReply.Substring(4))

        End If

 

        'Check to see if the file exists before the upload.

        bFileNotFound = False

        If (System.IO.File.Exists(sFileName)) Then

            ' Open the input stream to read the source file.

            input = New System.IO.FileStream(sFileName, System.IO.FileMode.Open)

            If (offset <> 0) Then

                input.Seek(offset, System.IO.SeekOrigin.Begin)

            End If

 

            'Upload the file.

            m_iBytes = input.Read(m_aBuffer, 0, m_aBuffer.Length)

            Do While (m_iBytes > 0)

                cSocket.Send(m_aBuffer, m_iBytes, 0)

                m_iBytes = input.Read(m_aBuffer, 0, m_aBuffer.Length)

            Loop

            input.Close()

        Else

            bFileNotFound = True

        End If

 

        If (cSocket.Connected) Then

            cSocket.Close()

        End If

 

        'Check the return value if the file was not found.

        If (bFileNotFound) Then

            MessageString = m_sReply

            Throw New System.IO.IOException("The file: " & sFileName & " was not found." & _

            " Cannot upload the file to the FTP site.")

 

        End If

 

        ReadReply()

        If (Not (m_iRetValue = 226 Or m_iRetValue = 250)) Then

            MessageString = m_sReply

            Throw New System.IO.IOException(m_sReply.Substring(4))

        End If

    End Sub

 

 

End Class

Open in new window

0
Comment
Question by:plq
  • 8
  • 4
  • 3
17 Comments
 
LVL 45

Expert Comment

by:sunnycoder
Comment Utility
       Try
            s.Connect(ep)                     /// ********* THIS IS THE PROBLEM LINE - EP.port is not 21 - so this hits windows firewall and times out ********** ////////

I am not very familiar with VB but shouldn't this work

        Try
            ep.port = 21
            s.Connect(ep)                     /// ********* THIS IS THE PROBLEM LINE - EP.port is not 21 - so this hits windows firewall and times out ********** ////////
0
 
LVL 8

Author Comment

by:plq
Comment Utility
Thanks Sunny - I appreciate you coming across to vb to help..

Yes I tried that yesterday. It does get further.. The line that actually uploads the ftp file fails with error 425..

        'Send an FTP command to store a file.
        SendCommand("STOR " & sUploadName)
        If (Not (m_iRetValue = 125 Or m_iRetValue = 150)) Then
            MessageString = m_sReply
            Throw New System.IO.IOException(m_sReply.Substring(4))
        End If

in function "UploadFile" then throws an exception because m_iRetVal returned 425 - cant open connection

0
 
LVL 8

Author Comment

by:plq
Comment Utility
The problem seems to be that the programmer decided to use a "passive data connection", where the server decides the port for you randomly..
So now I am reseaching what an alternative might be ...

0
 
LVL 45

Expert Comment

by:sunnycoder
Comment Utility
That means you have a control connection in place but cant open a data connection

http://support.microsoft.com/kb/129395

If an FTP error 425 occurs, this indicates that the server was unable to open the connection back to the client. The most likely cause for this is an FTP client application that is attempting to re-use a socket that is still in the TCP TIME-WAIT state due to an earlier connection that hasn't been timed out yet.

Issue appears to be something else
0
 
LVL 8

Author Comment

by:plq
Comment Utility
I think the problem is that the data connection is opened on a port which is blocked by windows firewall

This thread below seems helpful in understanding why FTP needs 2 ports to work. But then I'm left wondering why FTP.EXE works fine through windows firewall port 21 but my program doesn't

http://www.tcpipguide.com/free/t_FTPDataConnectionManagementNormalActiveandPassiveD-3.htm

The thread states that port 21 is used as the control connection but having a data connection on the same port is "a bad idea" !!

I think creating a "NORMAL" data connection instead of a PASV connection passive connection sound like it might work ?? Or perhaps I should go back to BAT files !

0
 
LVL 45

Expert Comment

by:sunnycoder
Comment Utility
Is there a firewall on your client machine that is causing issues? Windows FTP.exe might be on white list of this firewall.
The firewall to the remote server should not block outgoing connections.

If that does not work, to be sure that this is not a case of stale connections, can you reboot once and try.
0
 
LVL 8

Author Comment

by:plq
Comment Utility
No, I'm in a network of about 20 pcs in the uk, and the ftp server is a webserver on ThePlanet...

My network is firewalled with a cisco firewall. I don't think its stale connections as they're not showing up in the server iis and ftp.exe works every time.

The windows firewall log is showing these "ephemeral ports" as rejected, so thats obviously stopping it working.

This thread gives a better clue... but no code showing what SENDCOMMAND commands are needed to use the ftp standard method instead of passive method
0
What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

 
LVL 8

Author Comment

by:plq
Comment Utility
0
 
LVL 17

Expert Comment

by:rstaveley
Comment Utility
If you are expecting to do active FTP, you'll need your client to accept a connection from the server.  Generally that's harder to set up in your firewall than passive FTP, which simply requires that your client needs to be able to connect to an unprivileged port > 1023 on the server as well as the privileged command port 21.

Here's a nice explanation: http://slacksite.com/other/ftp.html
0
 
LVL 17

Expert Comment

by:rstaveley
Comment Utility
Can't you get your firewall set up to allow connections to > 1023 on the FTP servers? Allowing active FTP connections back to your 20 client PCs will be tricky if you are going through NAT.
0
 
LVL 8

Author Comment

by:plq
Comment Utility
I don't think windows firewall lets you setup a port range, I'd have to create every port from 1023 to 5000 odd manually ??
0
 
LVL 8

Accepted Solution

by:
plq earned 0 total points
Comment Utility
Here's a solution

http://www.newagedigital.com/cgi-bin/newagedigital/articles/ms-firewall-ftp.html

1. Run this on the server

C:\Inetpub\AdminScripts>cscript.exe adsutil.vbs set /MSFTPSVC/PassivePortRange "33256-33257"

2. Add ports 33256 and 33257 to windows firewall

Now the program works.

Not ideal to have to open ports but thankfully those ports can be restricted to certain IPs only so not a security risk unless there are more bugs in windows firewall :)


0
 
LVL 17

Expert Comment

by:rstaveley
Comment Utility
> Not ideal to have to open ports but thankfully those ports can be restricted to certain IPs only so not a security risk unless there are more bugs in windows firewall :)

Those are outbound ports remember. I'm not up to speed with Windows firewall, but I expect that will only set up firewall holes for established connections (i.e. it will not be allow listening for new connections on that port).

Good job you don't have to mess around with the Cisco firewall for this, eh? Network administrators come from the same school of thought as traffic wardens and dictators.
0
 
LVL 17

Expert Comment

by:rstaveley
Comment Utility
[By the way, no issues here with the point allocation and flagging http:#21801614 as the correct solution in the PAQ.]
0
 
LVL 8

Author Comment

by:plq
Comment Utility
FYI no they are inbound ports because we are putting settings on the server windows firewall

    vb.net > my dev pc in my network  |  cisco firewall  |  internet   |   TP firewall   |  win firewall on server > server at TP

Windows firewall holes apply to existing connections and new connections but you can lock down to only open that port to certain ip addresses which works for me..

thanks for your help
0

Featured Post

Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Article by: jpaulino
XML Literals are a great way to handle XML files and the community doesn’t use it as much as it should.  An XML Literal is like a String (http://msdn.microsoft.com/en-us/library/system.string.aspx) Literal, only instead of starting and ending with w…
A while ago, I was working on a Windows Forms application and I needed a special label control with reflection (glass) effect to show some titles in a stylish way. I've always enjoyed working with graphics, but it's never too clever to re-invent …
In this tutorial you'll learn about bandwidth monitoring with flows and packet sniffing with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're interested in additional methods for monitoring bandwidt…
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

8 Experts available now in Live!

Get 1:1 Help Now