Edited at

AWSのWindowsサーバに即席でFTPサーバを構築するやつ

大体ここのおかげ。

# インストール

Install-WindowsFeature -Name Web-Ftp-Server -IncludeAllSubFeature -IncludeManagementTools

# FTP サイトの名前
$ftpsite = "hogehoge"

# EC2インスタンスのパブリックIP
$publicip = "10.0.0.1"

# FTP サイトの作成
# https://codeday.me/jp/qa/20190412/611354.html
New-WebFtpSite -Name $ftpsite -Port 21 -Force
cmd /c \Windows\System32\inetsrv\appcmd set SITE $ftpsite "-virtualDirectoryDefaults.physicalPath:C:\inetpub\ftproot"

# 非SSL接続の許可
Set-ItemProperty "IIS:\Sites\$ftpsite" -Name ftpServer.security.ssl.controlChannelPolicy -Value 0
Set-ItemProperty "IIS:\Sites\$ftpsite" -Name ftpServer.security.ssl.dataChannelPolicy -Value 0

# BASIC 認証を有効化
Set-ItemProperty "IIS:\Sites\$ftpsite" -Name ftpServer.security.authentication.basicAuthentication.enabled -Value $true

# ユーザの分離を有効化
# https://docs.microsoft.com/en-us/iis/configuration/system.applicationhost/sites/site/ftpserver/userisolation/
Set-ItemProperty "IIS:\Sites\$ftpsite" -Name ftpserver.userisolation.mode -Value 3

# FTPユーザの権限を付与
Add-WebConfiguration "/system.ftpServer/security/authorization" -value @{accessType="Allow";roles="";permissions="Read,Write";users="*"} -PSPath IIS:\ -location $ftpsite

# AWSでパッシブモードにすると外部から接続できないので、外部向けのIPアドレスを設定する
# https://docs.microsoft.com/en-us/iis/configuration/system.applicationhost/sites/site/ftpserver/firewallsupport
cmd /c \Windows\System32\inetsrv\appcmd.exe set config -section:system.applicationHost/sites /siteDefaults.ftpServer.firewallSupport.externalIp4Address:$publicip /commit:apphost

# パッシブポートのレンジを制限
# https://docs.microsoft.com/en-us/iis/configuration/system.ftpserver/firewallsupport
cmd /c \Windows\System32\inetsrv\appcmd.exe set config -section:system.ftpServer/firewallSupport /lowDataChannelPort:"60000" /commit:apphost
cmd /c \Windows\System32\inetsrv\appcmd.exe set config -section:system.ftpServer/firewallSupport /highDataChannelPort:"65535" /commit:apphost

# サイトを再起動
# Restart-WebItem "IIS:\Sites\$ftpsite"

# サービスの再起動
Restart-Service ftpsvc

続いてFTP接続に使用するユーザを作成し、ホームディレクトリを用意する。

ついでにアクセス権を制限する。

# ユーザ名

$username = "FTPUSER"

# ランダムパスワードの生成
$number = 48..57
$upper = 65..90
$lower = 97..122
$password = (1..10 | foreach { $number + $upper + $lower | get-random } | foreach { [char]$_ }) -join ''

# パスワードの暗号化
$secure = $password | ConvertTo-SecureString -AsPlainText -Force

# ローカルユーザの追加
$user = New-LocalUser -PasswordNeverExpires -Name $username -Password $secure -Description "FTP User"

# パスワードの表示
Write-Host -ForegroundColor red $password

# グループの追加
Add-LocalGroupMember -Group "Users" -Member $user

# FTPUSERのホームディレクトリ
$dir = mkdir C:\inetpub\ftproot\LocalUser\$username

# ディレクトリのアクセスルールをすべて削除
icacls $dir /reset /q # 個別設定を破棄
icacls $dir /inheritance:r /q # 上位フォルダからの継承を破棄

# アクセス権を追加
icacls $dir /grant "administrators:(OI)(CI)F" /q
icacls $dir /grant "${username}:(OI)(CI)F" /q

# アクセス権を確認
icacls $dir

Set-Acl は割とどうしようもなく使えない子なのですが、icacls の構文すぐ忘れてしまうので ACL が一番思い出すのが大変です。