はじめに (対象読者・この記事でわかること)

この記事は、PHPの基本的な知識をお持ちの方、Webアプリケーション開発に興味がある方、または社内ツールなどで手軽なネットワーク疎通確認ツールを導入したい方を対象としています。

この記事を読むことで、PHPを使ってWebブラウザからIPアドレスやホスト名を入力し、Pingコマンドによる疎通確認が行えるシンプルなWebフォームを実装できるようになります。また、外部コマンドを実行する際のセキュリティ上の重要な注意点(コマンドインジェクション対策)についても理解を深めることができます。CUI操作に不慣れな方でも直感的に使えるツールを作成し、日々の業務効率化に役立てましょう。

前提知識

この記事を読み進める上で、以下の知識があるとスムーズです。 - HTML/CSSの基本的な知識 - PHPの基本的な構文(変数、条件分岐、関数など) - Webサーバー(Apache, Nginxなど)とPHPの実行環境 - コマンドライン操作の基本的な知識(特にpingコマンドの概念)

なぜPHPでWebベースのPing疎通確認フォームが必要なのか?

ネットワークの疎通確認は、システムの障害診断やネットワーク設定の確認において非常に基本的ながら重要な作業です。通常、この作業はコマンドプロンプトやターミナルからpingコマンドを実行して行います。しかし、次のようなシチュエーションでは、Webブラウザから手軽に疎通確認できるフォームがあると非常に便利です。

  1. CUI操作に不慣れなユーザーのため: サーバー管理経験が少ないメンバーや、Webブラウザベースのインターフェースに慣れているユーザーでも、簡単に疎通確認を行いたい場合。
  2. 特定の環境に限定してアクセスさせたい場合: SSHなどの接続権限がないが、特定のネットワーク機器やサーバーへの疎通確認だけを許可したいケース。
  3. 簡易的な監視ツールとして: 定期的に手動で複数のサーバーの疎通を確認する際に、Webインターフェースからまとめて行えるようにしたい場合。
  4. 記録・ログの自動化: Webフォームからの実行結果をデータベースに保存したり、ログファイルとして出力したりすることで、後の分析や監査に役立てたい場合。

PHPはWeb開発に特化した言語であり、サーバーサイドで外部コマンドを実行する機能も備えているため、このようなツールの作成に非常に適しています。Webブラウザという共通のインターフェースを通じて、場所を選ばずに疎通確認ができるようになることで、業務効率化やトラブルシューティングの迅速化に貢献できます。

PHPでPing疎通確認フォームを実装する

ここから、実際にPing疎通確認フォームを作成する具体的な手順を解説していきます。index.phpというファイル一つで完結するシンプルな構成を目指します。

ステップ1:HTMLフォームの作成

まず、IPアドレスやホスト名を入力するためのHTMLフォームを作成します。このフォームは、ユーザーがデータを入力し、PHPスクリプトに送信する役割を担います。

Html
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>PHP Ping疎通確認フォーム</title> <style> body { font-family: sans-serif; margin: 20px; background-color: #f4f4f4; color: #333; } .container { max-width: 800px; margin: auto; background-color: #fff; padding: 30px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); } h1 { color: #0056b3; text-align: center; margin-bottom: 30px; } form { display: flex; flex-direction: column; gap: 15px; } label { font-weight: bold; } input[type="text"] { padding: 10px; border: 1px solid #ccc; border-radius: 4px; font-size: 16px; } input[type="submit"] { padding: 12px 20px; background-color: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 16px; transition: background-color 0.3s ease; } input[type="submit"]:hover { background-color: #0056b3; } pre { background-color: #eee; padding: 15px; border-radius: 4px; overflow-x: auto; white-space: pre-wrap; word-break: break-all; margin-top: 20px; } .error { color: red; font-weight: bold; } </style> </head> <body> <div class="container"> <h1>Ping疎通確認</h1> <form method="POST" action=""> <label for="host">IPアドレスまたはホスト名:</label> <input type="text" id="host" name="host" placeholder="例: 8.8.8.8 または google.com" required> <input type="submit" value="Ping実行"> </form> <?php // ここにPHPスクリプトを記述します ?> </div> </body> </html>

このHTMLコードは、IPアドレスまたはホスト名を入力するためのテキストボックスと、Ping実行ボタンで構成されています。method="POST"を指定することで、フォームデータがHTTPリクエストのボディに含まれて送信され、URLに表示されないようにします。action=""とすることで、同じファイル(index.php)にデータが送信されるように設定しています。

ステップ2:PHPスクリプトでPingコマンドを実行

次に、フォームから送信されたデータを受け取り、PHPのshell_exec()関数を使ってpingコマンドを実行するPHPスクリプトを記述します。shell_exec()は、外部コマンドを実行し、その標準出力を文字列として取得する関数です。

index.phpのPHP部分(<?php ... ?>の中身)

Php
<?php // Ping結果を格納する変数 $ping_output = ""; // エラーメッセージを格納する変数 $error_message = ""; // フォームが送信されたかどうかをチェック if ($_SERVER["REQUEST_METHOD"] == "POST") { // ホスト名の入力を取得 $host = $_POST["host"] ?? ''; // 入力値のバリデーション if (empty($host)) { $error_message = "IPアドレスまたはホスト名を入力してください。"; } else { // --- ★重要★ コマンドインジェクション対策 --- // escapeshellarg() を使用して引数をエスケープする // これにより、ユーザー入力に危険な文字が含まれていても、 // それらがコマンドの一部として解釈されるのを防ぎます。 $safe_host = escapeshellarg($host); // OSによるpingコマンドのオプションの違いを吸収 // Windowsの場合は -n (送信回数) // Linux/macOSの場合は -c (送信回数) if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { // Windowsの場合: ping -n 4 <ホスト名> $command = "ping -n 4 " . $safe_host; } else { // Linux/macOSの場合: ping -c 4 <ホスト名> $command = "ping -c 4 " . $safe_host; } // shell_exec() でコマンドを実行し、結果を取得 // エラー発生時はnullを返す可能性があるので、文字列として扱う $output = shell_exec($command); if ($output === null) { $error_message = "Pingコマンドの実行に失敗しました。コマンドが見つからないか、パーミッションの問題かもしれません。"; } else { $ping_output = $output; } } } // エラーメッセージがあれば表示 if (!empty($error_message)) { echo '<p class="error">' . htmlspecialchars($error_message) . '</p>'; } // Pingの結果があれば表示 if (!empty($ping_output)) { echo '<h2>Ping結果:</h2>'; echo '<pre>' . htmlspecialchars($ping_output) . '</pre>'; } ?>

ハマった点やエラー解決:コマンドインジェクションの危険性

PHPで外部コマンドを実行する際に最も注意すべき点が「コマンドインジェクション」です。もしユーザー入力を直接pingコマンドに渡してしまうと、悪意のあるユーザーがコマンドを追加して実行できてしまう可能性があります。

例えば、ユーザーが入力フィールドにgoogle.com; rm -rf /と入力した場合、shell_exec("ping google.com; rm -rf /")というコマンドが実行されてしまい、rm -rf /というシステム破壊コマンドが実行される危険性があります。これは非常に危険な脆弱性です。

解決策

この問題を解決するためには、ユーザー入力を外部コマンドの引数として安全に渡す必要があります。PHPにはそのための便利な関数が用意されています。

  • escapeshellarg(string $arg): シェルコマンドの引数として使用するために文字列をエスケープします。単一引用符で囲み、内部の単一引用符をエスケープします。
  • escapeshellcmd(string $command): シェルコマンド全体をエスケープします。コマンド名と引数を含む文字列全体を保護する場合に使用しますが、escapeshellarg()と組み合わせて使う方が安全性が高いです。

今回のケースでは、ユーザー入力はpingコマンドの引数として使われるため、escapeshellarg()を使うのが適切です。

上記のPHPスクリプトでは、以下の行でこの対策を施しています。

Php
$safe_host = escapeshellarg($host); // ... $command = "ping -c 4 " . $safe_host; // または "ping -n 4 " . $safe_host;

escapeshellarg()を通すことで、google.com; rm -rf /のような入力は、'google.com; rm -rf /'のように単一引用符で囲まれ、pingコマンドの単なる文字列引数として扱われるため、後続のrm -rf /が別のコマンドとして実行されることを防ぎます。

また、Pingの実行結果はそのまま表示するとHTMLとして解釈される可能性があるため、htmlspecialchars()を使ってエスケープしています。これにより、スクリプトインジェクション(XSS)などのリスクも低減できます。

このセキュリティ対策を怠ると、深刻なシステム被害につながる可能性があるため、外部コマンドを実行する際には常に意識するようにしましょう。

まとめ

本記事では、PHPでWebブラウザから手軽に利用できるPing疎通確認フォームを実装する方法を解説しました。

  • HTMLフォームを使ってユーザーからのIPアドレス/ホスト名入力を受け取ります。
  • PHPのshell_exec()関数を利用して、サーバー上でpingコマンドを実行します。
  • 最も重要な点として、ユーザー入力を外部コマンドの引数に渡す際にはescapeshellarg()関数を必ず使用し、コマンドインジェクション対策を施しました。

この記事を通して、PHPで外部コマンドを実行する際の基本的なパターンと、それに伴うセキュリティ上の重要な注意点を理解し、安全かつ実用的なWebツールを作成できるようになりました。

今後は、Ping結果のデータベースへの保存、複数のホストを一括で確認する機能、JavaScriptを使った非同期通信によるよりスムーズなUIの実現、Ping以外のネットワーク診断ツール(tracerouteなど)との連携といった発展的な内容にも挑戦してみてください。

参考資料