Take the 2-minute tour ×
Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

I am having Powershell FTP script problems. I have pulled my hair out over this one.

I recently setup an "automated build server" for my software projects. All software projects get built and bundled into a zip file. In theory, this zip file will be downloaded via FTP to several different servers. I am trying to build a powershell script that will download my package and unzip it into the desired directories.

The part I am having problem with is downloading the file via FTP. I am able to access the source file by manually logging into FTP via DOS command window. I can download the file just fine, so I know this is not a firewall issue. Atleast I dont think it is.

Whenever powershell starts to download the source .zip file, it hangs. I can see the file appear on the harddrive, but then disappears when the script fails. It never gets any bytes from the FTP server. I then receive this error:

Powershell FTP Script Error: The remote server returned an error: 227 Entering Passive Mode (10,255,130,77,231,5) Blockquote

Here is my script:

#create destination directory (this is where the build files will be dropped)
[IO.Directory]::CreateDirectory("C:\tempftp")

"Creating staging folder..."
#create staging folder for deployment package bundle unzip
[IO.Directory]::CreateDirectory("C:\FINALDEPLOYMENTFOLDER")

#create destination and source paths for FTP copy command
$File = "C:\tempftp\MyPackageT.zip"
$ftp = "ftp://AdminiUser:adm1n1pwd@255.255.255.255/MyPackage.zip"

"ftp url: $ftp"

$webclient = New-Object System.Net.WebClient
$uri = New-Object System.Uri($ftp)

"Downloading $File..."

#perform the actual data transfer via FTP
$webclient.DownloadFile($ftp, $File)

"Unzip build package..."
#unzip the file that was transferred via FTP
$shell_app=new-object -com shell.application 
$zip_file = $shell_app.namespace("C:\tempftp\MyPackage.zip")         #source
$destination = $shell_app.namespace("C:\FINALDEPLOYMENTFOLDER")       #final destination

#unzip to destination folder
foreach ($item in $zip_file.Items())
{
$destination.CopyHere($item, 16)
}

I am able to run this script, locally, on my build server and it runs fine. I know this script works. My trouble is, why does this script barf on my non-build servers? Why is Passive Mode such a problem for this scenario and how do I fix it? Ive tried FTP IPv4 Address rules, FTP Firewall support changes, etc. But no success.

Noteworthy, I do see a warning message on my FTP Firewall Support section of IIS7. It states:

To accept passive connections when you are using FTP over SSL (FTPS) or when your firewall does not filter packets, configure the external IPv4 address of your firewall.

^ I am unsure what that really means, but I will give it a shot. Any ideas why Passive Mode is such a pain in my neck? Should I not be using WebClient? I really want to avoid having to download another program/patch to make this work. Id rather this work in native Powershell...so no, I cant use FTP Client libraries!!

EDIT: I was able to fix this issue by opening "All Ports" on my firewall, but that seems a bit scary. Any suggestions on tracking down what ports are needed so that this Passive Mode error disappears? I already had a rule allowing a few specific ports I thought the FTP was using....but how can I see which ports I need to enable?

share|improve this question
    
"Any suggestions on tracking down what ports are needed so that this Passive Mode error disappears?" <--- Go to FTP Firewall Support in IIS. There you will find the Data Channel port range setting. Use that for your firewall rule. My issue was that the range was 20,000 ports, which is nearly impossible to individually list in the Firewall Rule list. I narrowed down to 20 ports in my range, and used those in my Firewall Rule, and it works fine. –  D3vtr0n Apr 19 '11 at 17:46

1 Answer 1

up vote 1 down vote accepted

When you connect to the FTP site from a command prompt, you're using active FTP (only one available) which is far more predictable on the part of the firewall. When you connect using the System.Net.WebClient, you are connecting using PASV which takes a random port from a predefined available range. These requests are getting stopped at your firewall. You could also try opening up the range of ports on the firewall if you have to stick with PASV. Otherwise, you need to figure out how to specify to use an active FTP connection. This cannot be done using System.Net.WebClient.

Take a look at System.Net.FtpWebRequest, it may do what you want. I see there is a UsePassive property.

share|improve this answer
    
Cheers! Do you know how I can figure out which ports need "unblocking"? I have a firewall rule that allows specific ports (20,21,2020,25,21234) to be open. But apparently my script doesnt use those ports. How can I figure out which ports need to be opened? –  D3vtr0n Mar 29 '11 at 16:41
1  
    
The problem ended up being my Data Channel Port Range. It was configured to use 20,000 different ports. I instead narrowed it down to 20 ports, and specified those ports in a Firewall Rule. This worked like a charm. –  D3vtr0n Apr 19 '11 at 15:24

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.