DNSサーバーを介してIPv4データをトンネリングし、ファイアウォールの制限を回避して、ペネトレーションテスト用の隠密なネットワークアクセスを提供します。
これは、DNSサーバーを介してIPv4データをトンネリングできるソフトウェアです。インターネットアクセスがファイアウォールで制限されているものの、DNSクエリは許可されているといった、さまざまな状況で利用できます。
iodineをコンパイルするにはmesonが必要です。
build ディレクトリ内でコンパイルするには、以下のコマンドを実行してください:
meson setup build
cd build
ninja
テストをビルドして実行するには check ライブラリが必要です。ビルドディレクトリ内で
ninja test を実行してテストを開始してください。
自分の LAN 内で試してみましょう!次の簡単な手順に従ってください:
./iodined -f 10.0.0.1 test.com。
すでに 10.0.0.0 ネットワークを使用している場合は、172.16.0.0 のような
別の内部ネットを使用してください。./iodine -f -r 192.168.0.1 test.com。
192.168.0.1 をサーバーの IP アドレスに置き換えてください。10.0.0.2 を、サーバーは 10.0.0.1 を持ちます。実際にリレー用ネームサーバー経由で使用するには、以下を参照してください。
注意:サーバーとクライアントはまったく同じプロトコルで通信する必要があります。ほとんどの 場合、これは同じ iodine バージョンを実行することを意味します。残念ながら、後方および前方 プロトコル互換性を実装することは通常現実的ではありません。
このトンネルを使用するには、実際のドメイン(mydomain.com など)の制御と、
iodined を実行するためのパブリック IP アドレスを持つサーバーが必要です。このサーバーで
すでに DNS プログラムが動作している場合は、その待ち受けポートを変更し、iodined の
-b オプションを使用して iodined に DNS リクエストを転送させてください。(この手順は
本番環境では推奨されません。iodined の DNS 転送は完全に透過的ではなく、たとえばゾーン
転送は機能しないためです。)
あるいは、DNS サーバーからサブドメインを iodined に転送することもできます。その場合、
iodined は別のポート(-p)で実行する必要があります。
次に、サブドメイン(たとえば t1.mydomain.com)を iodined サーバーに委任します。
ドメインに BIND を使用している場合は、次のような 2 行をゾーンファイルに追加します:
t1 IN NS t1ns.mydomain.com. ; ドットに注意!
t1ns IN A 10.15.213.99
NS 行は、t1 サブドメインへのクエリを t1ns サーバーにルーティングするために必要な
すべてです。データトラフィックにできるだけ多くのスペースを確保するため、サブドメインには
短い名前を使用します。NS 行の末尾は iodined サーバーの名前です。これはどこを指しても
よい任意の名前ですが、この場合は同じゾーンファイル内に簡単に保持できます。これは名前
(IP アドレスではない)である必要があり、その名前自体に A レコード(CNAME ではない)
が必要です。
iodined サーバーが動的 IP を持っている場合は、動的 DNS プロバイダーを使用してください。
単に NS 行をそのプロバイダーに向け、A 行を省略します:
t1 IN NS myname.mydyndnsprovider.com. ; ドットに注意!
その後、ネームサーバープログラムをリロードまたは再起動します。これで、t1.mydomain.com
で終わるドメインへの DNS クエリはすべて iodined サーバーに送信されます。
最後に、サーバー上で iodined を起動します。最初の引数はトンネル内の IP アドレスで、
まだ使用していない任意の範囲(たとえば 192.168.99.1)から指定できます。2 番目の引数は
割り当てられたドメイン(この場合は t1.mydomain.com)です。-f オプションを使用すると
iodined がフォアグラウンドで実行され続けるため、テスト時に役立ちます。iodined は仮想
インターフェース(「tun デバイス」)を開き、UDP ポート 53 で DNS クエリの待ち受けも
開始します。パスワードはコマンドライン(-P pass)で入力するか、サーバー起動後に入力
します。これでクライアントの準備がすべて整いました。
予期しない環境から iodine トンネルを使用する可能性がある場合は、-c オプションを付けて
iodined を起動してください。
この例の状況での結果のコマンドライン:
./iodined -f -c -P secretpassword 192.168.99.1 t1.mydomain.com
セットアップはすべて完了しているので、iodine を起動するだけです。引数は 1 つまたは
2 つで、最初はローカルのリレー用 DNS サーバー(オプション)、2 番目は使用したドメイン
(t1.mydomain.com)です。最初の引数を指定しない場合は、システムの現在の DNS 設定が
参照されます。
DNSクエリが任意のコンピュータに対して許可されている場合、iodinedサーバーのアドレスを最初の引数として直接指定できます(例ではt1ns.mydomain.comまたは10.15.213.99)。その場合、任意のコンピュータのDNSポート(53 UDP)への_あらゆる_トラフィックが許可されている可能性もあります。iodineはこれを検出し、可能であれば生のUDPトンネリングに切り替えます。いずれの場合でもDNSトンネリングを強制するには、-rオプションを使用します(特に自身のネットワーク内でテストする場合に便利です)。
クライアントのトンネルインターフェースには、サーバーに近いIP(この場合は192.168.99.2や.3など)と適切なMTUが割り当てられます。サーバーと同じパスワードを、コマンドラインオプションとして、またはクライアント起動後に入力してください。-fオプションを使用すると、iodineクライアントはフォアグラウンドで実行され続けます。
この例の状況での結果としてのコマンドラインです。-rを追加すると、生のUDPトンネリングが可能であってもDNSトンネリングが強制されます:
./iodine -f -P secretpassword t1.mydomain.com
どちらの側からでも、トンネルの反対側の端のIPアドレスにpingできるはずです。この場合、iodineクライアントからはping 192.168.99.1、iodineサーバーからは192.168.99.2です。
トンネル内のデータはIPv4のみです。
サーバーはデフォルトで、着信リクエストに対してIPv4とIPv6の両方で待ち受けます。片方のプロトコルのみで待ち受けるには、オプション-4または-6を使用します。生モードは、ログインに使用されたプロトコルと同じプロトコルで試行されます。
クライアントは、iodinedに接続するためにIPv4またはIPv6のネームサーバーを使用できます。リレーネームサーバーは、必要に応じてプロトコル間を自動的に変換します。クライアントにDNSクエリで特定のIPバージョンを強制的に使用させるには、オプション-4または-6を使用します。
サーバーがIPv6で待ち受けており、到達可能な場合は、DNS設定にそのAAAAレコードを追加してください。上記の例を拡張すると次のようになります:
t1 IN NS t1ns.mydomain.com. ; ドットに注意!
t1ns IN A 10.15.213.99
t1ns IN AAAA 2001:db8::1001:99
すべてのトラフィックをDNSトンネル経由でルーティングすることが可能です。これを行うには、まずiodineが使用するネームサーバーへのホストルートを、デフォルトゲートウェイをゲートウェイとして有線/無線インターフェース上に追加します。次に、デフォルトゲートウェイをDNSトンネル内のiodinedサーバーのIPアドレスに置き換え、サーバーをNATを行うように設定します。
ただし、トンネル化されたデータトラフィックはまったく暗号化されておらず、外部の第三者によって比較的容易に読み取られ、変更される可能性があることに注意してください。最大限のセキュリティを得るには、DNSトンネル経由でVPNを実行する(=二重トンネリング)か、ポートフォワーディングを伴うセキュアシェル(SSH)アクセスを使用してください。後者は、サーバー上でWebプロキシ(例えばPrivoxy)を実行している場合、Webブラウジングにも使用できます。
iodinedサーバーは、トンネルドメインのサブドメインに対して送信されたNSリクエストに応答します。iodinedのサブドメインがt1.mydomain.comの場合、foo123.t1.mydomain.comに対してNSリクエストを送信して、委任が機能するかどうかを確認してください。
digはこれに適したツールです:
% dig -t NS foo123.t1.mydomain.com
ns.io.citronna.de.
また、iodinedサーバーは、サポートされている任意のリクエストタイプに対して、'z'で始まるリクエストにも応答します。例えば:
dig -t TXT z456.t1.mydomain.com
dig -t SRV z456.t1.mydomain.com
dig -t CNAME z456.t1.mydomain.com
これらのすべての場合において、応答は文字化けしたテキストのように見えるはずです。
macOS 10.6以降では、iodineはOSに組み込まれたネイティブのutunデバイスをサポートしています - -d utunXを使用してください。
DNS応答のフラグメントサイズは、最大帯域幅を得るために通常自動プローブされます。特定の値を強制する(そして処理を高速化する)には、-mオプションを使用します。
DNSホスト名は通常、最大長である255文字まで使用されます。
一部のDNSリレーでは、フルレングスのクエリに対して信頼性の低い応答を返すものが見つかっており、断片サイズの自動プローブを繰り返し試行すると結果が大きくばらつきます(そしてほとんどが非常に悪い結果となります)。このような場合は、-M スイッチを使用してDNSホスト名の長さを例えば200文字に短縮すると、これらのDNSリレーははるかに安定します。これは、応答をクエリの完全なコピー2つで埋めてしまい、下流データ用のスペースがほとんど残らない一部の「非最適化」DNSリレー(EDNS0にも対応していない)でも有用です。-M スイッチは、上流帯域の一部を下流帯域と引き換えにすることができます。プロトコルはパケット(最大1200バイト)をわずか16個の断片にしか分割できず、断片あたり少なくとも75バイトの実データが必要となるため、-M の最小値は約100であることに注意してください。
上流データはBase32でgzipエンコードされて送信されます。リレーサーバーがドメイン名における大文字小文字の混在と + をサポートしている場合はBase64、代わりに _ がサポートされている場合はBase64u、高位バイト値の文字がサポートされている場合はBase128が使用されます。この上流エンコーディングは自動検出されます。DNSプロトコルでは1パケットにつき1つのクエリが許可され、1つのクエリは最大256文字です。各ドメイン名の部分は最大63文字です。したがって、上流のスループットを最大化するには、ドメイン名とサブドメインはできるだけ短くする必要があります。
いくつかのDNSリクエストタイプがサポートされており、NULL と PRIVATE タイプが最大の下流帯域を提供すると期待されています。PRIVATE タイプはプライベート使用範囲の値65399を使用します。その他の利用可能なタイプは TXT、SRV、MX、CNAME、A(CNAME を返す)で、帯域の降順に並んでいます。通常、「最良の」リクエストタイプが自動検出されて使用されます。しかし、DNSリレーが例えばNULLやTXTに制限を課す場合があり、その場合はSRVやMXが実際に最良の選択肢となります。これは自動検出されませんが、-T オプションを使用して強制することができます。特に自動検出されたリクエストタイプが200バイト未満の下流断片サイズを提供する場合は、さまざまな代替案を試すことをお勧めします。
SRV、MX、A(CNAME を返す)クエリは、「スマートな」キャッシングネームサーバーによる実際のIPアドレス取得のための追加ルックアップを引き起こす可能性があり、速度低下や完全な失敗につながることがあります。
非 NULL/PRIVATE クエリに対するDNS応答は、上流データと同じコーデックのセットでエンコードできます。これも通常は自動検出されますが、完全に網羅的なテストは行われないため、より高度なコーデックを選択する際に一部の問題が見逃される可能性があります。その場合、断片サイズの自動プローブで失敗や破損が発生します。特に、ホスト名(SRV、MX、CNAME、A)を返す応答を、そのホスト名が約180文字を超える場合にのみ小文字に変更するDNSリレーがいくつか見つかっています。こうした場合や類似のケースでは、-O オプションを使用して他の下流コーデックを試してください。Base32は常に動作するはずです。
現在の通常の動作では、サーバーは次のDNSリクエストが到着するまでDNSリクエストに応答しません。いわゆる「lazy」動作です。これにより、新しい下流データを送信する必要があるときに、サーバーは常にDNSリクエストを手元に持つことができます。これにより(インタラクティブな)パフォーマンスとレイテンシが大幅に改善され、デフォルトで静止時のpingリクエストを4秒間隔まで、場合によってはそれ以上に遅くすることができます。実際、現在のpingの主な目的は、前回のpingへの応答を強制し、DNSサーバーのタイムアウト(通常、RFC1035では少なくとも5〜10秒)を防ぐことです。一部のDNSサーバーはよりせっかちで、トンネルデータトラフィックがない期間にSERVFAILエラー(タイムアウト)を返します。これらの場合でもすべてのデータは通過するはずですが、iodine はエラーメッセージの数を減らすためにping間隔をとにかく1秒(-I1)に短縮します。これは、1秒以下でタイムアウトする dnsadvantage.com(ultradns)のような非常にせっかちなDNSリレーには役立たないかもしれません。それでもデータは通過するので、SERVFAIL エラーは無視してかまいません。
ローカルネットワーク上で間にDNSサーバーが存在しない環境で実行している場合は、-I 50 を試してください(iodineとiodinedは60秒間の無通信で接続を閉じます)。速度低下に気づくのは、DNS応答パケットが失われた場合だけです。その場合、iodined サーバーはデータを再送するために新しいpingを待たなければなりません。上流トラフィック(キー入力、ping)を生成することでこれを高速化できます。これが頻繁に発生する場合は、ネットワークのボトルネックを確認するか、-I1 で実行してください。
レイジーモードでの応答遅延により、一部の「キャリアグレード」商用DNSリレーが同じDNSクエリをiodinedサーバーに繰り返し再送する原因になります。DNSリレーが実際に並列サーバーのプールとして実装されている場合、重複リクエストが複数のソースから到着することさえあります。この影響は iodined サーバーのネットワークトラフィックでのみ確認でき、クライアントの接続には影響しません。iodinedはこれらの重複を検知し、(そのタイミングが来たときに)元のクエリと最新の重複の両方に同じ応答を送信します。その後、完全な応答はしばらくの間キャッシュされます。サーバーにさらに遅れて到着する遅延重複には、iodineクライアントが無視する応答が返されます(そもそもそこまで到達した場合の話ですが)。
問題が発生した場合は、tcpdumpやethereal/wiresharkなどのネットワーク監視ツールでトラフィックを検査し、リレーDNSサーバーが応答をキャッシュしていないことを確認してください。キャッシュされたエラーメッセージは、サーバーより先にクライアントを起動したことを意味する可能性があります。サーバーの -D(および -DD)オプションでも、送受信されたクエリを表示できます。