TCPパケットを用いて通信経路を可視化するネットワーク診断コマンド
- tcptraceroute -
tcptracerouteは、TCPパケットを使用して宛先までの通信経路を調査するコマンドです。通常のtracerouteでは確認できない経路でも、実際のサービスが使用するTCPポートを指定することで確認できる可能性があります。
本記事では、tcptracerouteとは何かという基礎知識から、tracerouteとの違い、インストール手順、コマンドの使い方、主要オプションの解説までを一気通貫で解説します。
さらに、VirtualBoxで構築したデモ環境において、tcptracerouteとtcpdumpを使った実践検証を行います。通常のtracerouteとのパケットレベルの違いや、宛先ポートがopen・closedの場合の挙動、中継ルーターがICMPパケットを破棄した場合の結果も確認します。
tcptracerouteの概要
tcptracerouteとは
tcptracerouteは、TCPのSYNパケットを利用して通信経路を可視化するコマンドラインツールです。具体的にはTCP SYNフラグを付与したパケットを送信し、経路上のルーターから返されるICMP Time Exceeded、および宛先からのTCP応答(SYN/ACKまたはRST/ACK)を解析することで経路を特定します。
公式GitHub:https://github.com/mct/tcptraceroute
オープンソースで開発されており、主要なLinuxディストリビューションの公式リポジトリからインストール可能です。
「traceroute」と「tcptraceroute」の違い
tracerouteとtcptracerouteの最大の違いは、経路探索に使用するプロトコルとポート番号です。
| 使用するプロトコル | 宛先ポート | |
|---|---|---|
| traceroute | UDP(一部環境ではICMP) | 33434番からプローブごとに1ずつ増加 |
| tcptraceroute | TCP SYNパケット | 指定したTCPポートに固定(デフォルト:80) |
一般的なLinux環境では、tracerouteはデフォルトでUDPを使用し、33434番ポートを起点としてプローブごとに1つずつ加算しながらパケット送信します。一方、tcptracerouteはTCPを使用し、指定された宛先ポート番号を固定してパケットを送信します。
tcptracerouteを使うメリット
Linux標準のtracerouteはUDPを使用しますが、業務システムで実際に使われるプロトコルの大半はTCPです。例えば、TCP/443(Webサーバー)やTCP/22(SSHサーバー)への通信経路が確保されていても、経路上のファイアウォールでUDPが遮断されている場合、tracerouteではそれ以降の経路情報を取得できません。
- TCP/443:許可
- TCP/22:許可
- UDP:破棄
しかし、tracerouteの結果から「通信不可」と判断される場合でも、実際には対象のTCPサービスまで正常に到達できているケースも少なくありません。(例.tracerouteは応答しないが、HTTPS通信は正常に行える など)
tcptracerouteは、実際に業務で使用されるTCPポートを指定してSYNパケットを送信するため、UDPが制限されている環境でも通信経路を確認することができます。
tcptracerouteの実装には2系統ある
tcptracerouteという名称のコマンドには、提供元が異なる2つの実装が存在します。どちらも「TCPパケットを使って通信経路を可視化する」という目的は共通していますが、開発元や提供パッケージなどが異なります。
| TCPトレース専用コマンド | traceroute(*)のオプション機能 | |
|---|---|---|
| 開発者 | Michael C. Toren氏 | Dmitry Butskoy氏 |
| 提供パッケージ | tcptraceroute | traceroute |
| 実行コマンド | tcptraceroute(シンボリックリンク) | tcptraceroute(シンボリックリンク) traceroute -T |
| 実体となるファイル | /usr/bin/tcptraceroute.mt | /usr/sbin/tcptraceroute.db |
| 送信パケット | TCP(SYNフラグ) | TCP(SYNフラグ) |
(*)Linux環境で広く採用されている「traceroute」(Modern traceroute for Linux)
1つはMichael C. Toren氏が開発した専用コマンド(tcptracerouteパッケージ)、もう1つはtracerouteパッケージに同梱されているtcptracerouteラッパー(実体はtraceroute -T -O infoを呼んでいるだけのシェルスクリプト)です。
Michael C. Toren氏開発の専用コマンド
1つ目は、TCPパケットを利用して宛先までの通信経路を調査する専用コマンドで、2001年にMichael C. Toren氏によって公開されました。GPLv2に基づいて提供されており、パケット処理にはlibpcapとlibnetの2つのライブラリを利用します。
主要なLinuxディストリビューションでは、tcptracerouteという名前のパッケージで提供されています。tcptracerouteパッケージをインストールすると、/usr/bin/tcptraceroute.mtという実体ファイルが/usr/bin/tcptracerouteというコマンドとして登録されます。
Linux標準tracerouteのオプション機能
もう1つの実装は、Dmitry Butskoy氏が開発したtracerouteパッケージに組み込まれているTCPトレース機能です。このパッケージには単一のtracerouteコマンドだけでなく、/usr/bin/lft.db、/usr/bin/traceproto.db、/usr/bin/traceroute-nanog、/usr/bin/traceroute.db、そして/usr/sbin/tcptraceroute.dbといった複数の実行ファイルが含まれます。
tracerouteのTCPトレース機能は-Tオプションで実行できるほか、/usr/sbin/tcptraceroute.dbというコマンドからも呼び出せます。tcptraceroute.dbは独立した専用実装ではなく、tracerouteコマンドをTCPモードで動作させるためのコマンドです。つまり、同じtcptracerouteというコマンド名を実行しても、その実体はtraceroute -Tを呼び出すラッパーです。
本記事で使用するデモ環境のシステム構成
送信元マシンと宛先ホストの間に2台のルーターを配置した仮想ネットワークを構築し、tcptracerouteがどのように動作するかを検証します。
仮想化ソフトウェアは「VirtualBox」を使用する
仮想化ソフトウェアには、Oracleが無償で提供する仮想化ソフトウェア「VirtualBox」を使用します。VirtualBoxを利用することで、物理的なルーターや複数台のコンピューターを準備しなくても、1台のホストマシン上に複数の仮想マシンと仮想ネットワークを構築できます。
ネットワークモードは「ホストオンリーネットワーク」を使用する
VirtualBoxのネットワークモードには、「NAT」「ブリッジ」「内部ネットワーク」「ホストオンリーネットワーク」など複数の選択肢がありますが、本記事ではホストオンリーネットワークを採用します。
ホストオンリーネットワークを使用すれば、検証対象をVirtualBox上の仮想マシンに限定しやすく、外部ネットワークへ意図しないパケットを送信するリスクを低減できます。
パッケージのインストールには、インターネット接続が必要です。
ホストオンリーネットワークでは、仮想マシンからインターネットへ接続できません。そのため、以下のいずれかの方法で対応します。
- パッケージのインストール時のみ、一時的にNATアダプターを追加する
- あらかじめ必要なパッケージを取得しておく
- 常時、NATアダプターを有効にする
常時、NATアダプターを有効にする場合、tcptracerouteコマンド実行時に-iオプションにてホストオンリーネットワーク側のネットワークインターフェースを指定します。これにより、意図しないネットワークインターフェースからパケットが送信されることを防ぎます。
仮想ネットワーク一覧
本記事で使用する仮想ネットワークは、以下のとおりです。
| セグメント | ネットワークアドレス | 用途 |
|---|---|---|
| セグメント10 | 192.168.10.0/24 | 送信元ネットワーク |
| セグメント20 | 192.168.20.0/24 | |
| セグメント30 | 192.168.30.0/24 | 宛先ネットワーク |
tcptracerouteの動作を正しく理解するには、複数セグメントをまたぐ通信経路を用意し、実際の挙動を目視で確認することが近道です。
仮想マシン一覧
本記事で使用する仮想マシンは、以下のとおりです。
| 仮想マシン | 用途 | IPアドレス | 所属セグメント | 備考 |
|---|---|---|---|---|
| Kali Linux | 送信元マシン | 192.168.10.11/24 | セグメント10 | |
| Ubuntu Desktop | 〃 | 192.168.10.12/24 | セグメント10 | |
| VyOS | 1台目の仮想ルーター | 192.168.10.254/24 192.168.20.254/24 | セグメント10 セグメント20 | |
| Ubuntu Server | 2台目の仮想ルーター | 192.168.20.253/24 192.168.30.253/24 | セグメント20 セグメント30 | Linuxルーターとして動作 |
| Debian | 宛先ホスト | 192.168.30.107/24 | セグメント30 | 開放ポート:TCP/22 |
- Kali LinuxとUbuntu Desktopは、
tcptracerouteを実行する送信元マシンとして使用します。 - VyOSとUbuntu Serverは、送信元と宛先の間にある仮想ルーターとして動作します。それぞれ2枚の仮想ネットワークアダプターを割り当て、ネットワーク間のパケット転送を担当します。
- Debianは、
tcptracerouteの宛先として使用します。
送信元マシンからDebianへ送信されたパケットは、次の順序で転送されます。
- 送信元マシンからVyOSへ送信される
- VyOSからUbuntu Serverへ転送される
- Ubuntu ServerからDebianへ転送される
返信パケットは、逆の経路を通ります。経路を正しく成立させるには、各仮想マシンに適切なスタティックルートまたはデフォルトゲートウェイが設定されている必要があります。
本記事では、仮想マシンや仮想ネットワークは構築済みであることを前提とします。そのため、本記事ではVirtualBoxや各OSのインストール手順、ルーターの構築手順については扱いません。
tcptracerouteのインストール
このセクションでは、送信元マシンとして使用するKali LinuxとUbuntu Desktopにtcptracerouteをインストールします。
Kali LinuxおよびUbuntu Desktopは、ともにDebian系のLinuxディストリビューションで、いずれもパッケージ管理にはaptを採用しています。基本的なインストール方法は共通しているため、各ディストリビューションで手順が異なる箇所のみ個別に補足します。
既にインストール済みか確認する
パッケージのインストール状況を確認
$ apt list --installed | grep tcptraceroute- 未インストールの場合、何も出力されません。
- インストール済みの場合、
tcptraceroute/kali-rolling ... [installed]のような結果が出力されます。
本記事のデモ環境の場合、Kali Linux、Ubuntu Desktopいずれもインストールされていません。
実行ファイルのパスを確認
$ command -v tcptraceroute
/usr/sbin/tcptraceroute- 実行可能ファイルが見つからない場合は、何も出力されません。
- 実行可能ファイルが見つかった場合、該当ファイルのパスが表示されます。
本記事のデモ環境の場合、Kali Linuxで実行可能ファイルが検出されました。以下の手順で、どの実装が呼び出されているかを確認します。
対象ファイルの種類を確認
$ file "$(command -v tcptraceroute)"
/usr/sbin/tcptraceroute: symbolic link to /etc/alternatives/tcptraceroute対象ファイルの実体を確認
対象ファイルはシンボリックリンクのため、リンク先の実体ファイルを確認します。
$ realpath "$(command -v tcptraceroute)"
/usr/sbin/tcptraceroute.dbどのパッケージからインストールされたかを確認
$ dpkg -S "$(realpath "$(command -v tcptraceroute)")"
traceroute: /usr/sbin/tcptraceroute.dbKali Linuxの初期状態では、tcptracerouteコマンドを実行すると、tracerouteパッケージに含まれる/usr/sbin/tcptraceroute.dbが呼び出されます。
tcptracerouteのインストール
Kali LinuxおよびUbuntu DesktopのNATアダプターを無効にしている場合は、インストール前に有効化してください。
パッケージ情報の最新化
$ sudo apt updateパッケージ情報の確認
$ apt show tcptraceroute
Package: tcptraceroute
Version: 1.5beta7+debian-4.2+b1
Priority: optional
Section: net
Source: tcptraceroute (1.5beta7+debian-4.2)
Maintainer: Martin Zobel-Helas <zobel@debian.org>
Installed-Size: 75.8 kB
Depends: libc6 (>= 2.38), libnet9 (>= 1.1.2.1), libpcap0.8t64 (>= 0.9.8)
Homepage: https://github.com/mct/tcptraceroute
Tag: implemented-in::c, interface::commandline, protocol::ip, protocol::tcp,
role::program, scope::utility, use::checking,
works-with::network-traffic
Download-Size: 29.2 kB
APT-Sources: http://http.kali.org/kali kali-rolling/main amd64 Packages
Description: traceroute implementation using TCP packets
The more traditional traceroute(8) sends out either UDP or ICMP ECHO packets
with a TTL of one, and increments the TTL until the destination has been
reached. By printing the gateways that generate ICMP time exceeded messages
along the way, it is able to determine the path packets are taking to reach the
destination.
.
The problem is that with the widespread use of firewalls on the modern
Internet, many of the packets that traceroute(8) sends out end up being
filtered, making it impossible to completely trace the path to the destination.
However, in many cases, these firewalls will permit inbound TCP packets to
specific ports that hosts sitting behind the firewall are listening for
connections on. By sending out TCP SYN packets instead of UDP or ICMP ECHO
packets, tcptraceroute is able to bypass the most common firewall filters.Kali Linux、Ubuntu Desktopいずれも最新バージョン(1.5beta7)がインストールされます。
- Kali Linux:1.5beta7+debian-4.2+b1
- Ubuntu Desktop:1.5beta7+debian-4.2build1
tcptracerouteのインストール
$ sudo apt install tcptraceroute
Installing:
tcptraceroute
Summary:
Upgrading: 0, Installing: 1, Removing: 0, Not Upgrading: 502
Download size: 29.2 kB
Space needed: 75.8 kB / 62.9 GB available
Get:1 http://http.kali.org/kali kali-rolling/main amd64 tcptraceroute amd64 1.5beta7+debian-4.2+b1 [29.2 kB]
Fetched 29.2 kB in 3s (9,698 B/s)
Selecting previously unselected package tcptraceroute.
(Reading database… 425756 files and directories currently installed.)
Preparing to unpack …/tcptraceroute_1.5beta7+debian-4.2+b1_amd64.deb…
Unpacking tcptraceroute (1.5beta7+debian-4.2+b1)…
Setting up tcptraceroute (1.5beta7+debian-4.2+b1)…
update-alternatives: renaming tcptraceroute link from /usr/sbin/tcptraceroute to /usr/bin/tcptraceroute
update-alternatives: using /usr/bin/tcptraceroute.mt to provide /usr/bin/tcptraceroute (tcptraceroute) in auto mode
Processing triggers for man-db (2.13.1-1)…
Processing triggers for kali-menu (2026.2.6)…インストール後の確認
# 実行ファイルのパス
$ command -v tcptraceroute
/usr/bin/tcptraceroute
# バージョン確認
$ tcptraceroute
tcptraceroute 1.5beta7
Copyright (c) 2001-2006 Michael C. Toren <mct@toren.net>
Updates are available from http://michael.toren.net/code/tcptraceroute/
Usage: tcptraceroute [-nNFSAE] [-i <interface>] [-f <first ttl>]
[-l <packet length>] [-q <number of queries>] [-t <tos>]
[-m <max ttl>] [-pP] <source port>] [-s <source address>]
[-w <wait time>] <host> [destination port] [packet length]Kali Linux、Ubuntu Desktopともに最新の1.5beta7がインストールされました。
tcptracerouteコマンドの基本的な使い方
$ tcptraceroute [オプション] 宛先ホスト [宛先ポート] [パケット長]tcptracerouteコマンドの最もシンプルな実行方法は、宛先ホストだけを指定します。(宛先ポートを省略した場合は、TCPポート80が使用されます。)
$ tcptraceroute 192.0.2.1このコマンドを実行すると、宛先ホストのTCPポート80に向けて、TTL(Time To Live)を1から順に増やしながらTCP SYNパケットを送出し、各ホップ(経由するルーター)からのICMP Time Exceededメッセージを収集することで、経路上の各ノードを可視化します。
- 送信元マシンは
TTL=1のパケットから送り始め、以降TTL=2, 3, 4 ...と1つずつ増やしていく。 - 各ルーターはパケットを転送する際にTTLを1減らす。
- TTL切れ(
TTL=0)になった時点で、そのルーターはパケットを破棄し、送信元にICMP Time Exceededメッセージを返す。 - これにより、送信元は「何ホップ目にどのルーターがいるか」を把握できる。
tcptracerouteは、TTLを1、2、3と段階的に増やしながら、意図的に小さい値からパケットを送信します。TTLが0となったルーターが返すICMP Time ExceededメッセージからIPアドレスを取得し、経路上のルーターを1台ずつ特定していきます。
宛先ポートを指定する場合は、宛先ホストの後ろにポート番号を記述します。
$ tcptraceroute 192.0.2.1 22 # TCP/22(SSH)の場合
$ tcptraceroute 192.0.2.1 443 # TCP/443(HTTPS)の場合主要オプションのコマンド例
tcptracerouteは、実行時に指定するオプションによって、送信するTCPパケットの種類や送信元情報、プローブ回数などを細かく制御できます。ここでは、ネットワーク調査で活用される代表的な5つのオプションについて、コマンド例とともに解説します。
-S:TCP SYNパケットを送信
-Sは、送信するTCPパケットにSYNフラグを明示的に設定するオプションです。
$ tcptraceroute -S 192.0.2.1オプションを指定しない場合でもデフォルトでSYNパケットを送信する仕様になっているため、-Sを付けても付けなくても、パケットの内容は同じです。
それでも-Sを明示する意味があります。後述する-A(ACKフラグでのプローブ)と結果を比較する際、どちらのモードで実行したコマンドなのかを明確にできるためです。
-A:TCP ACKパケットを送信
-Aは、送信するTCPパケットにACKフラグを設定するオプションです。
$ tcptraceroute -A 192.0.2.1-i:ネットワークインタフェースの指定
複数のNICを搭載したマシンでは、ルーティングテーブルの設定状況によって、意図しないインターフェースからパケットが送信される場合があります。
$ tcptraceroute -i enp0s8 192.0.2.1-iオプションを使用することで、プローブパケットを送信するネットワークインターフェースを明示的に指定できます。
ネットワークインターフェース名が分からない場合は、以下のコマンドで確認します。
$ ip -br addrその他の確認方法については、『ネットワークインターフェース(NIC)確認コマンド』をご覧ください。
-p:送信に使用するTCPポート
-pオプションは、プローブパケットの送信元ポート番号を明示的に指定するオプションです。オプションを指定しない場合、OSが空きポートを自動的に割り当てます。
$ sudo tcptraceroute -p 50000 192.0.2.1このコマンド例の場合、送信元ポートを50000番に固定してプローブパケットを送信します。
-pを指定すると権限不足のエラーが発生するため、sudoを付けて実行します。
$ tcptraceroute -p 50000 192.0.2.1
Sorry, must be root to use -p-q:プローブパケットの送信回数
-qオプションは、送信するプローブパケットの回数を指定するオプションです。デフォルトでは1ホップあたり3回送信されますが、-q 5を指定すると1ホップあたり5回送信します。
$ tcptraceroute -q 5 192.0.2.1プローブ数を増やすことで、一時的なパケットロスや応答遅延の影響を平準化し、応答時間(RTT)のばらつきを高い精度で確認できます。特に、無線区間や輻輳が生じやすい経路では、複数回の測定結果を用いることで、通信品質の変動を定量的に評価できます。
【実践検証】デモ環境でtcptracerouteを実行する
ここからは、実際にデモ環境を使ってtcptracerouteコマンドを実行し、結果がどのように表示されるかを確認していきます。
- 検証1:「traceroute」と「tcptraceroute」の違いをパケットレベルで比較する
- 検証2:宛先ポートの状態の違いを比較する
- 検証3:中継ルーターでICMPパケットを破棄した場合の挙動を確認する
送信元マシンから宛先ホスト(Debian)まで到達するには、VyOSとLinuxルーターの2台のルーターを経由します。そのため、tcptracerouteの実行結果では、以下のようなホップが確認できる想定です。
| ホップ数 | 想定される機器 | IPアドレス |
|---|---|---|
| 1 | VyOS | 192.168.10.254 |
| 2 | Linuxルーター | 192.168.20.253 |
| 3 | Debian(宛先ホスト) | 192.168.30.107 |
なお、本セクションのデモでは、Linuxで広く利用されているパケットキャプチャツール『tcpdump』を使用し、tcptracerouteが実際に送受信するパケットの内容を確認します。Kali Linux、Ubuntu Desktopにはtcpdumpがプリインストールされているため、別途インストールは不要です。tcpdumpの使い方については、「tcpdumpの使い方とオプションを徹底解説」をご覧ください。
検証1:「traceroute」と「tcptraceroute」の違いをパケットレベルで比較する
検証1では、パケットキャプチャの結果をもとに、tracerouteとtcptracerouteの違いを確認します。具体的には、Kali Linuxの1つ目のターミナルでtcpdumpを起動してパケットを監視し、2つ目のターミナルでtraceroute / tcptracerouteを実行します。Kali LinuxからDebianへ送出されたプローブパケットをtcpdumpでキャプチャし、両コマンドの挙動の違いをパケットレベルで比較・検証します。
- 1つ目のターミナル:tcpdumpを起動して、ネットワークインタフェースを通過するパケットを監視
- 2つ目のターミナル:traceroute / tcptracerouteを実行して、プローブパケットを送出
tcpdumpを起動する
まず、1つ目のターミナルでtcpdumpを起動して、192.168.10.0/24に接続しているインターフェースを通過するパケットを監視します。
$ sudo tcpdump -i eth0 -ntcpdumpを起動すると待ち受け状態になります。パケットがネットワークインターフェースを通過すると、その内容がこのターミナルにリアルタイム表示されます。
tracerouteを実行する
2つ目のターミナルでtracerouteコマンドを実行します。
$ traceroute -q 1 -N 1 192.168.30.107通常、traceroute系コマンドではホップごとに複数回のプローブパケットを送信します。今回の検証ではパケットの違いを確認しやすくするため、送信回数を1回にします。
-q 1:1ホップあたりプローブパケット数(デフォルト:3)-N 1:同時に送信するプローブパケット数(デフォルト:16)
tracerouteの実行結果は、以下のとおりです。
traceroute to 192.168.30.107 (192.168.30.107), 30 hops max, 60 byte packets
1 192.168.10.254 (192.168.10.254) 0.400 ms
2 192.168.20.253 (192.168.20.253) 0.838 ms
3 192.168.30.107 (192.168.30.107) 0.976 msこの時、1つ目のターミナルには、ネットワークインターフェースを通過したパケットがリアルタイムで表示されます。
tcpdumpのキャプチャ結果
06:35:45.664625 IP 192.168.10.11.53180 > 192.168.30.107.33434: UDP, length 32
06:35:45.665014 IP 192.168.10.254 > 192.168.10.11: ICMP time exceeded in-transit, length 68
06:35:45.665404 IP 192.168.10.11.57346 > 192.168.30.107.33435: UDP, length 32
06:35:45.666239 IP 192.168.20.253 > 192.168.10.11: ICMP time exceeded in-transit, length 68
06:35:45.666389 IP 192.168.10.11.37358 > 192.168.30.107.33436: UDP, length 32
06:35:45.667362 IP 192.168.30.107 > 192.168.10.11: ICMP 192.168.30.107 udp port 33436 unreachable, length 68このキャプチャ結果から、宛先ポート番号33434を開始値として、送信のたびにポート番号を1ずつ増加させながらUDPパケットを送信していることが分かります。さらに、経路上の2台のルーターからICMP Time Exceededが返され、最終ホップであるDebianからICMP Port Unreachableが返されていることを確認できます。
tcptracerouteを実行する
続けて、同じ2つ目のターミナルでtcptracerouteコマンドを実行します。
$ tcptraceroute -q 1 192.168.30.107-q 1を指定し、1ホップあたりプローブパケットを1回送信します。(tcptracerouteではTTLごとにプローブパケットを送信し、その結果を処理してから次のTTLへ進む実装のため、同時送信数の指定はありません。)
tcptracerouteの実行結果は、以下のとおりです。
Selected device eth0, address 192.168.10.11, port 43239 for outgoing packets
Tracing the path to 192.168.30.107 on TCP port 80 (http), 30 hops max
1 192.168.10.254 0.451 ms
2 192.168.20.253 0.934 ms
3 192.168.30.107 [closed] 1.398 msこの時、1つ目のターミナルには、ネットワークインターフェースを通過したパケットがリアルタイムで表示されます。
tcpdumpのキャプチャ結果
06:35:51.527547 IP 192.168.10.11.43239 > 192.168.30.107.80: Flags [S], seq 1781905623, win 0, length 0
06:35:51.527972 IP 192.168.10.254 > 192.168.10.11: ICMP time exceeded in-transit, length 48
06:35:51.529651 IP 192.168.10.11.43239 > 192.168.30.107.80: Flags [S], seq 1781905623, win 0, length 0
06:35:51.530566 IP 192.168.20.253 > 192.168.10.11: ICMP time exceeded in-transit, length 48
06:35:51.539477 IP 192.168.10.11.43239 > 192.168.30.107.80: Flags [S], seq 1781905623, win 0, length 0
06:35:51.540857 IP 192.168.30.107.80 > 192.168.10.11.43239: Flags [R.], seq 0, ack 1781905624, win 0, length 0- 通常のtracerouteではUDPパケットが送信されていましたが、tcptracerouteではTCP SYNパケット(
Flags [S])が送信されていることがわかります。 - 経路上のルーターの挙動は、通常のtracerouteと同じです。(
ICMP Time Exceededを返す) - 最終ホップのDebianでは80番ポートが閉じているため、TCPの仕様どおりRST/ACKパケット(
Flags [R.])が返送されます。
パケットキャプチャの結果を比較する
パケットキャプチャの結果を整理すると、tracerouteとtcptracerouteの違いは次のとおりです。
| traceroute | tcptraceroute | |
|---|---|---|
| 送信パケット | UDP | TCP(SYNフラグ) |
| デフォルトの宛先ポート | 33434番から1ずつ増加 | TCP 80番 |
| 経路上のルーターからの応答 | ICMP Time Exceeded | ICMP Time Exceeded |
| 宛先ホストからの応答 | ICMP Port Unreachable | Flags [S.]:SYN/ACK ※開放ポートの場合 Flags [R.]:RST/ACK ※閉塞ポートの場合 |
tcpdumpのキャプチャ内容を比較した結果、まず共通点として、経路上のルーターの応答はUDPプローブでもTCPプローブでも同じ(ICMP Time Exceeded)です。
一方で、決定的に異なるのは、両コマンドが送出するパケットのプロトコルとポート番号です。tracerouteは宛先ポート番号をインクリメントさせながらUDPパケットを送出するのに対し、tcptracerouteは指定した単一の宛先ポートに対してTCP SYNパケットを送出し続けます。
また、宛先ホストの応答内容にも差異があります。tcpdumpではICMP Port Unreachableが、tcptracerouteではSYN/ACKまたはRST/ACKが返されます。
検証2:宛先ポートの状態の違いを比較する
tcptracerouteは、宛先ポートを指定して経路を確認できる点が特徴です。ここでは、Debian側のTCPポート22が開いている場合と、TCPポート80が閉じている場合を比較します。
宛先ポートが「open」の場合
まず、Ubuntu Desktopで以下のコマンドを実行します。
$ tcptraceroute -q 1 192.168.30.107 22
Selected device enp0s8, address 192.168.10.12, port 38483 for outgoing packets
Tracing the path to 192.168.30.107 on TCP port 22 (ssh), 30 hops max
1 192.168.10.254 0.537 ms
2 192.168.20.253 0.880 ms
3 192.168.30.107 [open] 1.308 msこの結果から、Ubuntu DesktopからDebianまでの通信が、想定どおり2台のルーターを経由して到達していることがわかります。特に注目すべき点は、最終行に表示されている[open]です。[open]は、指定したTCPポート22に対して、Debianが応答したことを示します。
tcpdumpのキャプチャ結果からも、Debian(192.168.30.107)からSYN/ACK(Flags [S.])が返ってきていることが確認できます。
$ sudo tcpdump -i enp0s8 -n
17:40:46.270000 IP 192.168.10.12.38483 > 192.168.30.107.22: Flags [S], seq 1193168123, win 0, length 0
17:40:46.270522 IP 192.168.10.254 > 192.168.10.12: ICMP time exceeded in-transit, length 48
17:40:46.276942 IP 192.168.10.12.38483 > 192.168.30.107.22: Flags [S], seq 1193168123, win 0, length 0
17:40:46.277807 IP 192.168.20.253 > 192.168.10.12: ICMP time exceeded in-transit, length 48
17:40:46.287034 IP 192.168.10.12.38483 > 192.168.30.107.22: Flags [S], seq 1193168123, win 0, length 0
17:40:46.288302 IP 192.168.30.107.22 > 192.168.10.12.38483: Flags [S.], seq 2481842459, ack 1193168124, win 64240, options [mss 1460], length 0
17:40:46.288327 IP 192.168.10.12.38483 > 192.168.30.107.22: Flags [R], seq 1193168124, win 0, length 0宛先ポートが「closed」の場合
次に、同じDebianに対して、TCPポート80を指定してtcptracerouteを実行します。
$ tcptraceroute -q 1 192.168.30.107 80
Selected device enp0s8, address 192.168.10.12, port 34885 for outgoing packets
Tracing the path to 192.168.30.107 on TCP port 80 (http), 30 hops max
1 192.168.10.254 0.475 ms
2 192.168.20.253 0.913 ms
3 192.168.30.107 [closed] 6.605 ms最終行を見ると、TCPポート22を指定した場合とは異なり、[closed]と表示されています。[closed]は、宛先ホストには到達できたものの、指定したTCPポート80が開いていないことを示します。
tcpdumpのキャプチャ結果からも、DebianからRST/ACK(Flags [R.])が返ってきていることが確認できます。
$ sudo tcpdump -i enp0s8 -n
17:40:53.334545 IP 192.168.10.12.34885 > 192.168.30.107.80: Flags [S], seq 80212669, win 0, length 0
17:40:53.335003 IP 192.168.10.254 > 192.168.10.12: ICMP time exceeded in-transit, length 48
17:40:53.341147 IP 192.168.10.12.34885 > 192.168.30.107.80: Flags [S], seq 80212669, win 0, length 0
17:40:53.342043 IP 192.168.20.253 > 192.168.10.12: ICMP time exceeded in-transit, length 48
17:40:53.351126 IP 192.168.10.12.34885 > 192.168.30.107.80: Flags [S], seq 80212669, win 0, length 0
17:40:53.357711 IP 192.168.30.107.80 > 192.168.10.12.34885: Flags [R.], seq 0, ack 80212670, win 0, length 0[closed]は、「通信経路に問題がある」という意味ではありません。むしろ、宛先ホストからポートが閉じていることを示す応答が返ってきているため、Ubuntu DesktopからDebianまでの経路は成立していると判断できます。
検証3:中継ルーターでICMPパケットを破棄した場合の挙動を確認する
検証3では、経路の途中に位置するLinuxルーターにおいて、ICMPプロトコルを意図的に遮断した場合、traceroute、およびtcptracerouteの実行結果がどのように変化するかを検証します。
- VyOS(192.168.10.254)
- Linuxルーター(192.168.20.253) ← ここでICMPパケットを遮断
- Debian(192.168.30.107)
Linuxルーターで以下のコマンドを実行し、ICMPパケットを遮断します。
# 通過するICMPを遮断
$ sudo iptables -A FORWARD -p icmp -j DROP
# 自身が出力するICMPを遮断
$ sudo iptables -A OUTPUT -p icmp -j DROPこのルールは一時的な設定であるため、OSを再起動すると削除されます。
Linuxルーターの準備が整ったら、Kali Linuxでtraceroute / tcptracerouteマンドを実行します。
tracerouteの実行結果
$ traceroute 192.168.30.107
traceroute to 192.168.30.107 (192.168.30.107), 30 hops max, 60 byte packets
1 192.168.10.254 (192.168.10.254) 0.325 ms 0.286 ms 0.270 ms
2 * * *
3 * * *
4 * * *
5 * * *
6 * * *
7 * * *
8 * * *
9 * * *
10 * * *2ホップ目以降がこれまでとは異なり、* * *と表示されます。これは、3回のプローブがいずれも既定のタイムアウト時間以内に応答を受信できなかったことを意味します。
tracerouteでは、経路上のルーターおよび宛先ホストからICMPメッセージが返されます。
- 各ルーターからの応答:ICMP Time Exceeded
- 宛先ホストからの応答:ICMP Port Unreachable
今回、2ホップ目のLinuxルーター以降の応答が確認できないことから、前述のiptablesルールによってICMP応答が遮断されていると判断できます。
tcptracerouteの実行結果
$ tcptraceroute 192.168.30.107 22
Selected device eth0, address 192.168.10.11, port 49643 for outgoing packets
Tracing the path to 192.168.30.107 on TCP port 22 (ssh), 30 hops max
1 192.168.10.254 0.485 ms 0.479 ms 0.425 ms
2 * * *
3 192.168.30.107 [open] 1.441 ms 1.229 ms 1.394 mstcptracerouteにおいても、中継ルーターからの応答にはICMP Time Exceededが使用されるため、2ホップ目の応答がタイムアウトしています。(tracerouteの結果と同じ)
ここで注目すべきは、2ホップ目の応答が欠落しているにもかかわらず、3ホップ目の最終到達点の判定結果には一切影響が出ていない点です。3ホップ目には引き続き、宛先IPアドレスとポート状態、およびRTTが表示されており、TCPポート22がopen状態であることを確認できます。
これは、3ホップ目のTCP SYNパケットがLinuxルーターを通過してDebianまで到達し、Debianから返されるSYN/ACKがICMPフィルタの影響を受けることなくUbuntu Desktopまで届いているためです。
まとめ
通常の疎通確認では、「ping」や「traceroute」を使う場面が多いです。しかし、実際の業務環境では、「ICMPは応答しないが、WebサービスやSSHは接続可能」といった構成も珍しくありません。このような環境では、ICMPやUDPを用いた確認結果だけでは、実際の通信経路を正確に把握できない場合があります。
本記事では、tcptracerouteの基本概念からtracerouteとの違い、インストール手順、主要オプションの使い方、そしてデモ環境での検証までを解説しました。
デモ環境での検証では、次の点を実際のパケットキャプチャを通じて確認しました。
- tracerouteとtcptracerouteでは、送信するプロトコル(UDP・TCP)が異なるため、tcpdumpで取得したパケットキャプチャの内容にも明確な差異が現れる。
- 宛先ポートが開放(open)している場合、TCP SYN/ACKパケットが返送され、経路特定に加えてポートの状態判別が可能。
- 宛先ポートが閉塞(closed)している場合は、TCP RST/ACKパケットが返送される。(openの場合と応答パケットが異なる)
- 中継ルーターがICMPパケットを破棄している場合、該当ホップから応答を得られないため、経路情報に欠落が生じる。ただし、TCPパケットの転送が行われていれば、宛先ホストへの到達は確認できる。
このようにtcpdumpを併用すると、コマンドの表示結果だけでは見えにくい通信の実態を確認できます。
