Windows Serverで「SFTP/TFTPが動いているか(有効か)」を確実に確認するには、Server Managerで“役割や機能が入っているか”を見るだけでは足りないことが多いです。PowerShellで実装の種類→サービス→待受ポート→ファイアウォール→ログ→実通信の順に確認すると、環境差に振り回されずに判定できます。
SFTP/TFTPの稼働確認で迷う理由(結論:何の実装を入れているか次第)
SFTPとTFTPは、どちらも「プロトコル名」ですが、Windows Server上で“標準でこのサービスが必ずある”というタイプではありません。とくにSFTPはIISのFTP(Web-Ftp-Server)とは別物で、TFTPは製品(実装)依存になりがちです。したがってPowerShellでは、1つのコマンドで万能に判定するよりも、複数の観点を組み合わせて確認するのが現実的です。
| 項目 | SFTP | TFTP |
|---|---|---|
| 何の上で動くか | SSH(Secure Shell)上のファイル転送 | UDPで動く軽量な転送(機能は最小限) |
| 代表ポート | TCP 22(変更されることもある) | UDP 69(変更されることもある) |
| Windows Serverでよくある実装 | OpenSSH Server(sshd)など | サードパーティ製TFTPサーバー/機器付属TFTPなど |
| 「役割/機能」で判定できるか | OpenSSHはCapability(Windowsの追加機能)で確認できる場合あり | Windowsにあるのは主にTFTPクライアント(サーバーは別) |
| PowerShellでの現実的な確認軸 | サービス(sshd)/待受(22/TCP)/ログ/実接続 | サービス・プロセス名/待受(69/UDP)/実転送(tftp) |
「有効/稼働」の判定基準を揃える(ここが曖昧だと結論がブレる)
“SFTP/TFTPが有効”と言っても、現場では次の状態が混在します。どれをゴールにするかを先に揃えると、確認手順がズレません。
| 判定したい状態 | 見るべきポイント | PowerShellでの代表アプローチ |
|---|---|---|
| 機能(実装)が入っている | Capability/Windows機能/インストール済みプログラム | Get-WindowsCapability / Get-WindowsFeature / サービス探索 |
| サービスが起動している | サービスの状態(Running) | Get-Service / Get-CimInstance Win32_Service |
| ポートが待受している | LISTEN(TCP)/バインド(UDP) | Get-NetTCPConnection / Get-NetUDPEndpoint |
| 疎通できる | ネットワーク経路・FW・ACL | Test-NetConnection(SFTP向き) |
| 実際に転送できる | 認証・権限・パス・サブシステム | sftp / tftp を使った実転送(最終確認) |
| 監査・証跡が取れる | イベントログ・アプリログ | Get-WinEvent |
最優先:まずはサービス/プロセスで「それっぽい実装」を特定する
「そのサーバーに何が入っているか分からない」状態では、機能名を当てに行くより、サービス名・表示名・プロセス名を広く探索するほうが早いです。ここで“候補”を掴むと、その後の確認が一気に楽になります。
サービス名・表示名で探索(ssh / sftp / tftp)
# サービス名・表示名に ssh / sftp / tftp を含むものを広く探索
Get-Service |
Where-Object { $_.Name -match 'ssh|sftp|tftp' -or $_.DisplayName -match 'ssh|sftp|tftp' } |
Sort-Object Name |
Format-Table Status, Name, DisplayName -AutoSize
# サービス詳細(実行ファイルパスや起動アカウントまで見る)
Get-CimInstance Win32_Service |
Where-Object { $*.Name -match 'ssh|sftp|tftp' -or $*.DisplayName -match 'ssh|sftp|tftp' } |
Select-Object State, Name, DisplayName, StartMode, StartName, PathName |
Sort-Object Name |
Format-Table -AutoSize
プロセス名で探索(稼働実態の把握)
# プロセス名に ssh / sftp / tftp を含むものを探索
Get-Process |
Where-Object { $_.Name -match 'ssh|sftp|tftp' } |
Sort-Object Name |
Format-Table Name, Id, CPU, StartTime -AutoSize
ポイント:SFTPの本命がOpenSSH Serverなら、サービス名はsshdであることが多いです。逆に、IISのFTP(Web-Ftp-Server)が見つかっても、それはFTP/FTPSであってSFTPではありません。
SFTPの稼働確認(OpenSSH Server / sshd を前提に“同等以上”で確認)
SFTPはSSH上で動くため、PowerShellではsshdサービスと22/TCPの待受を中心に確認するとブレません。加えて、SFTPサブシステム(sftp-server)が有効か、ログが出ているかまで見れば「動いている」の確度が上がります。
sshdサービスの状態を確認(最短で結論に近い)
# sshd の状態(存在しない場合は未導入 or 別実装の可能性)
Get-Service sshd -ErrorAction SilentlyContinue
# 起動状態を明確に表示
$svc = Get-Service sshd -ErrorAction SilentlyContinue
if ($null -eq $svc) {
'sshd サービスが見つかりません(OpenSSH Server未導入、または別実装の可能性)'
} else {
$svc | Format-List Name, DisplayName, Status, StartType
}
OpenSSH Serverが「Windowsの追加機能」として入っているか確認
Windows Serverのバージョンによっては、OpenSSH ServerがCapabilityとして管理されています。名前の末尾(バージョン文字列)は環境で揺れるため、ワイルドカードで確認するのが安全です。
# OpenSSH Server のインストール状態(Capability)
Get-WindowsCapability -Online |
Where-Object { $_.Name -like 'OpenSSH.Server*' } |
Select-Object Name, State
もし「入っているのにsshdがない」場合は、インストールはされていてもサービスが無効化されていたり、何らかの理由で構成が壊れている可能性があります。まずはサービス探索(前述)とイベントログで状況を切り分けます。
待受ポート(22/TCP)を確認(“稼働実態”に近い)
サービスがRunningでも、設定や権限、衝突などで待受できていないことがあります。待受確認は「動いているか」の精度を上げます。
# 22/TCPがLISTENしているか(ローカルサーバー上で確認)
Get-NetTCPConnection -State Listen -LocalPort 22 -ErrorAction SilentlyContinue
# sshd のプロセスIDに紐づく待受だけを確認(ポート変更にも強い)
$sshd = Get-Process sshd -ErrorAction SilentlyContinue
if ($sshd) {
Get-NetTCPConnection -State Listen -OwningProcess $sshd.Id |
Select-Object LocalAddress, LocalPort, OwningProcess, State |
Format-Table -AutoSize
} else {
'sshd プロセスが見つかりません(サービス停止中、または別実装の可能性)'
}
ファイアウォール(受信規則)の確認(“起動しているのに繋がらない”の典型原因)
Windows Defender Firewallで受信が塞がっていると、サービスが動いていても外からは接続できません。規則名は環境で異なるため、ssh/openssh/22を手掛かりに確認します。
# SSH関連のファイアウォール規則を探索
Get-NetFirewallRule |
Where-Object { $_.DisplayName -match 'SSH|OpenSSH' -or $_.Group -match 'OpenSSH|SSH' } |
Select-Object DisplayName, Enabled, Direction, Action, Profile |
Format-Table -AutoSize
# 22/TCP を対象にしている受信規則(ポートフィルタ)を確認
Get-NetFirewallRule -Direction Inbound -Enabled True |
Get-NetFirewallPortFilter |
Where-Object { $_.Protocol -eq 'TCP' -and $_.LocalPort -eq '22' } |
Select-Object LocalPort, Protocol, @{n='RuleName';e={$_.InstanceID}} |
Format-Table -AutoSize
運用上は「ドメインプロファイルだけ許可」「特定サブネットだけ許可」など、スコープで絞るのが定石です。接続試験前に、意図したプロファイル(Domain/Private/Public)で許可されているかも確認しておくと、手戻りが減ります。
SFTPサブシステムが有効か(sshd_configの確認)
SFTPはSSHの上で動きますが、sshd側でSFTPサブシステムが無効化されていると、SSHは通るのにSFTPだけ失敗するケースが起きます。WindowsのOpenSSHでは、設定ファイルが次のパスにあることが多いです。
- C:\ProgramData\ssh\sshd_config
- 実体のSFTPサーバー:C:\Windows\System32\OpenSSH\sftp-server.exe(環境により異なる場合あり)
# sshd_config の存在確認
Test-Path 'C:\ProgramData\ssh\sshd_config'
# Subsystem 設定(SFTP)を抽出
Select-String -Path 'C:\ProgramData\ssh\sshd_config' -Pattern '^\s*Subsystem\s+sftp' -ErrorAction SilentlyContinue
# sftp-server.exe の存在確認(OpenSSHの配置が一般的な場所の場合)
Test-Path 'C:\Windows\System32\OpenSSH\sftp-server.exe'
実務の落とし穴:「SSHでログインはできるのにSFTPだけできない」場合、Subsystem設定や、SFTP用の許可(ユーザーのローカル権限・NTFS権限・Chroot相当の制約など)が原因になりやすいです。まずはログを見て、認証失敗なのか、サブシステム起動失敗なのかを切り分けます。
イベントログで接続試行の痕跡を見る(監査・切り分けに強い)
GUIでイベントビューアを見る代わりに、PowerShellで直近ログを引けるようにしておくと、遠隔作業や棚卸しで強力です。ログ名は環境で差がありますが、OpenSSHの運用ログが用意されている場合はそこから辿れます。
# OpenSSH運用ログ(存在する場合)を直近から取得
Get-WinEvent -LogName 'OpenSSH/Operational' -MaxEvents 50 -ErrorAction SilentlyContinue |
Select-Object TimeCreated, Id, LevelDisplayName, Message |
Format-Table -AutoSize
もしログが見つからない/出ない場合でも、サービスの状態・待受ポート・ファイアウォール・設定ファイルの整合性を見れば、十分に切り分け可能です。
疎通確認(クライアント側から“TCP 22が開いているか”)
SFTPの入口はSSHなので、まずは22/TCPに到達できるかを確認します。これは、Server Managerでは見えない「ネットワーク越しの現実」を掴むのに有効です。
# クライアント側(別端末)から:TCP 22 が通るか
Test-NetConnection -ComputerName <サーバー名またはIP> -Port 22
さらに踏み込むなら、実際にSFTPで接続・転送して「SFTPとして動いている」を確定させます(鍵やアカウントが必要)。WindowsにOpenSSHクライアントがある環境なら、次のように確認できます。
# 例:SFTPクライアントで接続(対話)
sftp user@<サーバー名またはIP>
# OpenSSHクライアントが入っているか(任意)
Get-WindowsCapability -Online |
Where-Object { $_.Name -like 'OpenSSH.Client*' } |
Select-Object Name, State
TFTPの稼働確認(“Windows標準サーバー”と決めつけないのがコツ)
TFTPは「PXE起動」「機器設定のバックアップ」などで今も使われますが、Windows Server上では標準でTFTPサーバーが常に提供されるわけではありません。まずはTFTPクライアントとTFTPサーバーを分けて考えると、確認が一気に整理できます。
| 混同しやすいポイント | 実態 | 確認の方向性 |
|---|---|---|
| TFTPが「Windowsの機能」にある | 多くの場合それはTFTPクライアント(送受信ツール) | Get-WindowsFeature / Get-WindowsCapability で「クライアント有無」を確認 |
| TFTPが動いているか | TFTPサーバー実装が必要(製品依存) | サービス/プロセス/UDP待受(69)/実転送で確認 |
| UDP 69が空いていればOK | TFTPは転送時に動的ポートへ移る実装も多い | 実転送(GET/PUT)で最終確認し、FW要件も確認 |
サーバー側:UDP 69 の待受を確認(存在すれば強い手掛かり)
# UDP 69 で待受しているエンドポイントを確認
$udp69 = Get-NetUDPEndpoint -LocalPort 69 -ErrorAction SilentlyContinue
$udp69
# OwningProcess からプロセス名を引く(実装特定に役立つ)
if ($udp69) {
$udp69 |
Select-Object LocalAddress, LocalPort, OwningProcess,
@{n='ProcessName';e={(Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue).Name}} |
Format-Table -AutoSize
} else {
'UDP 69 の待受が見つかりません(別ポート運用、未起動、未導入の可能性)'
}
ここで何も出ない場合でも、TFTPが別ポートで動いている設計や、サービスが停止中の可能性があります。次はサービス/プロセス探索で当たりを付けます。
サービス/プロセス探索(TFTPは実装ごとに名前が違う)
# サービス名・表示名に tftp を含むものを探索
Get-Service |
Where-Object { $_.Name -match 'tftp' -or $_.DisplayName -match 'tftp' } |
Format-Table Status, Name, DisplayName -AutoSize
# サービスの実体(PathName)まで見る
Get-CimInstance Win32_Service |
Where-Object { $*.Name -match 'tftp' -or $*.DisplayName -match 'tftp' } |
Select-Object State, Name, DisplayName, StartMode, PathName |
Format-Table -AutoSize
# プロセス名に tftp を含むものを探索
Get-Process |
Where-Object { $_.Name -match 'tftp' } |
Format-Table Name, Id, CPU, StartTime -AutoSize
サードパーティ製の場合、表示名にTFTPが入らないこともあります。その場合は「UDP 69 のOwningProcess」や、インストール済みアプリ一覧、サービス一覧の“パス(PathName)”から推測するほうが確実です。
Windows機能として確認できるのは主に「TFTPクライアント」
Server Managerで見える「TFTP Client」は、基本的にクライアント機能です。棚卸しでは「TFTPで検証できる端末か」を判断する材料になります。
# Windows Server の機能(Feature)としての TFTP クライアント(環境により名称が異なる場合あり)
Get-WindowsFeature -Name TFTP-Client -ErrorAction SilentlyContinue |
Select-Object Name, DisplayName, Installed
もし上記が取れない環境では、Capabilityとして提供されているケースもあるため、次のように広く検索します。
# Capability 側にあるケースに備え、tftp を含むCapabilityを広く探索
Get-WindowsCapability -Online |
Where-Object { $_.Name -match 'tftp' } |
Select-Object Name, State
実通信で確認する(TFTPは“実転送”が最終的に一番確実)
TFTPはUDPで、単純なポート疎通だけでは判定しにくいです。可能なら、実際にGET/PUTをして成功するかで確認します。TFTPクライアントが利用できる場合は、次のように検証できます(TFTPサーバー側の許可・対象ファイル・ルートディレクトリ設定が必要です)。
# 例:tftp.exe を使って GET(外部コマンド。環境によりオプションは差が出ます)
# -i はバイナリ転送指定として使われることが多い例です
tftp -i <TFTPサーバー> GET <取得したいファイル名>
# PowerShell内で実行して結果を把握したい場合の例(出力が簡素なため、成功/失敗は終了コードやファイル有無で判定)
$server = '<TFTPサーバー>'
$file = 'test.txt'
$tgt = Join-Path $PWD $file
# 事前に同名ファイルがあると判定が紛れるので削除
Remove-Item $tgt -ErrorAction SilentlyContinue
# 実行
& tftp -i $server GET $file
# 成否判定(簡易)
if (Test-Path $tgt) {
"GET成功($tgt を取得)"
} else {
"GET失敗(ファイルが作成されない。FW/許可/パス/ルート設定などを確認)"
}
TFTPの現場あるある:UDP 69 を開けても、転送フェーズで動的ポートを使う実装だと途中で止まります。疎通確認は「UDP 69待受」+「実転送」でセットにしておくと、原因切り分けが速くなります。
TFTPを運用するなら押さえたいセキュリティ注意点
- TFTPは認証や暗号化が基本的にありません。置くネットワーク(隔離・ACL・IP制限)を前提にします。
- ファイアウォールは「全開放」ではなく、送受信元の範囲を絞ります(機器の管理セグメントだけ等)。
- 監査が必要な環境では、TFTPの利用ログが取れる実装か、代替(SFTP/HTTPS等)へ寄せることも検討します。
Server Manager相当以上:チェック結果を“表”で出して棚卸しする(複数台にも対応)
Server Managerで1台ずつ画面確認する代わりに、PowerShellで「機能」「サービス」「待受」「FW」をまとめて収集すると、棚卸しや監査が一気に楽になります。ここでは、SFTP(sshd)とTFTP(UDP 69)の“現実的な判定材料”を一括で取る例を紹介します。
| 収集項目 | 目的 | 主なコマンド |
|---|---|---|
| OpenSSH Serverの導入状態 | 実装が入っているか | Get-WindowsCapability |
| sshdサービス状態 | SFTPの土台が起動しているか | Get-Service sshd |
| sshdの待受ポート | 実際に受け付けているか | Get-NetTCPConnection |
| TCP 22の受信FW | 外から繋がる設計か | Get-NetFirewallRule / Get-NetFirewallPortFilter |
| UDP 69待受 | TFTPサーバー候補の有無 | Get-NetUDPEndpoint |
| TFTP関連サービス探索 | 製品依存の実装特定 | Get-CimInstance Win32_Service |
単体サーバー用:ローカルで結果をまとめて出す例
# SFTP/TFTP 棚卸し(ローカル実行想定)
$report = [pscustomobject]@{
ComputerName = $env:COMPUTERNAME
OpenSSH_Server_Capability = (Get-WindowsCapability -Online -ErrorAction SilentlyContinue |
Where-Object { $_.Name -like 'OpenSSH.Server*' } |
Select-Object -First 1 -ExpandProperty State)
sshd_ServiceStatus = (Get-Service sshd -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Status)
sshd_ListenPorts = (
$p = Get-Process sshd -ErrorAction SilentlyContinue
if ($p) {
(Get-NetTCPConnection -State Listen -OwningProcess $p.Id -ErrorAction SilentlyContinue |
Sort-Object LocalPort |
Select-Object -ExpandProperty LocalPort) -join ','
} else {
$null
}
)
TCP22_Listen = [bool](Get-NetTCPConnection -State Listen -LocalPort 22 -ErrorAction SilentlyContinue)
UDP69_EndpointCount = (
(Get-NetUDPEndpoint -LocalPort 69 -ErrorAction SilentlyContinue | Measure-Object).Count
)
}
$report | Format-List
複数台向け:Invoke-Commandで一括収集する例(WinRMが有効な前提)
サーバー一覧(例:servers.txt)を用意して、リモートで同じ収集を走らせます。結果はCSVに落とせるため、監査・台帳にも転用しやすくなります。
# servers.txt にサーバー名を1行1台で記載しておく想定
$servers = Get-Content .\servers.txt
$script = {
$openSshState = (Get-WindowsCapability -Online -ErrorAction SilentlyContinue |
Where-Object { $_.Name -like 'OpenSSH.Server*' } |
Select-Object -First 1 -ExpandProperty State)
$sshdSvc = Get-Service sshd -ErrorAction SilentlyContinue
$sshdProc = Get-Process sshd -ErrorAction SilentlyContinue
$sshdPorts = $null
if ($sshdProc) {
$sshdPorts = (Get-NetTCPConnection -State Listen -OwningProcess $sshdProc.Id -ErrorAction SilentlyContinue |
Sort-Object LocalPort |
Select-Object -ExpandProperty LocalPort) -join ','
}
$tcp22Listen = [bool](Get-NetTCPConnection -State Listen -LocalPort 22 -ErrorAction SilentlyContinue)
$udp69 = Get-NetUDPEndpoint -LocalPort 69 -ErrorAction SilentlyContinue
$udp69Count = ($udp69 | Measure-Object).Count
$udp69ProcNames = $null
if ($udp69) {
$udp69ProcNames = ($udp69 |
Select-Object -ExpandProperty OwningProcess -Unique |
ForEach-Object { (Get-Process -Id $_ -ErrorAction SilentlyContinue).Name } |
Where-Object { $_ } |
Sort-Object -Unique) -join ','
}
[pscustomobject]@{
ComputerName = $env:COMPUTERNAME
OpenSSH_Server_Capability = $openSshState
sshd_ServiceStatus = $sshdSvc.Status
sshd_ListenPorts = $sshdPorts
TCP22_Listen = $tcp22Listen
UDP69_EndpointCount = $udp69Count
UDP69_OwningProcessNames = $udp69ProcNames
}
}
$result = Invoke-Command -ComputerName $servers -ScriptBlock $script -ErrorAction Continue
# 画面確認
$result | Sort-Object ComputerName | Format-Table -AutoSize
# 台帳化(例)
$result | Export-Csv .\sftp_tftp_inventory.csv -NoTypeInformation -Encoding UTF8
この形にしておくと、「sshdはRunningだがTCP22がListenしていない」「UDP69が1件だけ出ていてプロセス名が特定できた」など、GUIより早く原因に近づけます。
よくある判定ミスと、最短での切り分け
「IISのFTPを入れたからSFTPも動くはず」
誤りです。IISのWeb-Ftp-ServerはFTP/FTPSであり、SFTPではありません。SFTPを確認したいなら、sshd(OpenSSH Server)の状態と待受を見ます。
「サービスは起動しているのに繋がらない」
- サーバー側:Get-NetTCPConnection -LocalPort 22で待受があるか
- サーバー側:受信FW(22/TCP)が許可されているか
- クライアント側:Test-NetConnection -Port 22で到達できるか
この3点を揃えると、ネットワーク要因なのか、サービス要因なのかを短時間で切り分けできます。
「TFTPはUDP69が開いているのに転送できない」
- サーバー側:UDP 69の待受(Get-NetUDPEndpoint)
- 実装の仕様:転送時に動的ポートを使うか(FW要件が変わる)
- サーバー設定:ルートディレクトリ/GET許可/PUT許可/読み書き権限
TFTPは「ポートが開いている=転送できる」とは限りません。実運用で必要なら、必ず実転送で最終確認しておくのが安全です。
まとめ:PowerShellなら「実装依存」を吸収して、確実に“動いている”を判定できる
- SFTPはSSH実装(例:OpenSSH Server/sshd)が前提。確認はsshdサービス+待受(22/TCP)+FW+ログ+実接続が王道。
- TFTPはWindows標準の“サーバー機能”としては限定的で、実装依存になりやすい。確認はサービス/プロセス探索+UDP待受(69)+実転送が確実。
- 棚卸しや監査は、Invoke-Commandで一括収集→表やCSV化すると、Server Managerより速く再現性も高い。

コメント