
DNSサーバーを介してIPv4データをトンネリングし、ファイアウォールの制限を回避して、ペネトレーションテスト用の隠密なネットワークアクセスを提供します。
これは、DNSサーバーを介してIPv4データをトンネリングするためのソフトウェアです。インターネットアクセスがファイアウォールで制限されているがDNSクエリは許可されている、といったさまざまな状況で役立ちます。
Iodineにはconfigureスクリプトはありません。Linux向けのオプション機能が2つ(SELinuxとsystemd対応)あり、関連するヘッダファイルが/usr/include内に見つかると自動的に有効になります。(./src/osflagsのスクリプトを参照)
makeを実行して、サーバーとクライアントのバイナリをコンパイルします。make installを実行して、バイナリとmanページを宛先ディレクトリにコピーします。make testを実行して、ユニットテストをコンパイルおよび実行します。(checkライブラリが必要です)
自分の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オプションを使用してDNSリクエストをiodinedに転送させます。(この手順は、iodinedのDNS転送が完全に透過的ではないため、本番環境では推奨されないことに注意してください。例えばゾーン転送は機能しません。)あるいは、DNSサーバーからサブドメインをiodinedに転送することもできます。その場合、iodinedは別のポート(-p)で実行する必要があります。
次に、サブドメイン(例:t1.mydomain.com)をiodinedサーバーに委任します。ドメインにBINDを使用している場合は、ゾーンファイルに以下のような2行を追加します:
t1 IN NS t1ns.mydomain.com. ; note the dot!
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. ; note the dot!
次に、ネームサーバープログラムをリロードまたは再起動します。これで、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つで、1つ目はローカルの中継DNSサーバー(オプション)、2つ目は使用したドメイン(t1.mydomain.com)です。1つ目の引数を指定しない場合、システムの現在のDNS設定が参照されます。
DNSクエリが任意のコンピュータに対して許可されている場合、iodinedサーバーのアドレスを最初の引数として直接指定できます(例ではt1ns.mydomain.comまたは10.15.213.99)。その場合、任意のコンピュータのDNSポート(53 UDP)への_あらゆる_トラフィックが許可されていることもあります。iodineはこれを検出し、可能であればraw UDPトンネリングに切り替えます。どうしてもDNSトンネリングを強制したい場合は、-rオプションを使用します(自分のネットワーク内でテストする場合に特に便利です)。
クライアントのトンネルインターフェースには、サーバーに近いIP(この場合192.168.99.2や.3など)と適切なMTUが割り当てられます。サーバーと同じパスワードを、コマンドラインオプションまたはクライアント起動後に入力します。-fオプションを使用すると、iodineクライアントがフォアグラウンドで実行され続けます。
この例の状況での最終的なコマンドラインです。-rを追加すると、raw UDPトンネリングが可能な場合でもDNSトンネリングが強制されます:
./iodine -f -P secretpassword t1.mydomain.com
これで、どちらの側からでもトンネルの反対側のIPアドレスにpingを打てるはずです。この場合、iodineクライアントからはping 192.168.99.1、iodineサーバーからはping 192.168.99.2を実行します。
トンネル内のデータはIPv4のみです。
サーバーはデフォルトでIPv4とIPv6の両方で着信リクエストを待ち受けます。-4または-6オプションを使用すると、いずれか一方のプロトコルだけで待ち受けます。rawモードはログインで使用されたプロトコルと同じもので試行されます。
クライアントはIPv4またはIPv6のネームサーバーを使用してiodinedに接続できます。中継ネームサーバーは必要に応じてプロトコル間を自動的に変換します。-4または-6オプションを使用すると、クライアントのDNSクエリで特定のIPバージョンを強制できます。
サーバーがIPv6で待ち受けており到達可能な場合は、DNS設定にAAAAレコードを追加します。上記の例を拡張すると次のようになります:
t1 IN NS t1ns.mydomain.com. ; note the dot!
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
これらのすべてのケースで、応答は文字化けしたテキストのように見えるはずです。
Mac OS X 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であることに注意してください。
アップストリームデータはgzip圧縮され、Base32でエンコードされて送信されます。リレーサーバーがドメイン名で大文字小文字の混在と+をサポートしている場合は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で実行してください。
lazyモードでの応答遅延により、一部の「キャリアグレード」の商用DNSリレーが同じDNSクエリをiodinedサーバーに繰り返し再送信することがあります。DNSリレーが実際には並列サーバーのプールとして実装されている場合、重複リクエストが複数の送信元から到着することもあります。この影響はiodinedサーバーでのネットワークトラフィックにのみ現れ、クライアントの接続には影響しません。iodinedはこれらの重複に気付き、(その時が来たら)同じ応答を元のクエリと最新の重複の両方に送信します。その後、完全な応答はしばらくキャッシュされます。さらに遅れてサーバーに到着した遅延重複には、iodineクライアントが無視する応答(仮にそこに到達したとしても)が返されます。
問題が発生した場合は、tcpdumpやethereal/wiresharkなどのネットワーク監視ツールでトラフィックを調査し、中継DNSサーバーが応答をキャッシュしていないことを確認してください。キャッシュされたエラーメッセージは、サーバーより先にクライアントを起動したことを意味する可能性があります。サーバー側の-D(および-DD)オプションでも、受信および送信されたクエリを表示できます。
特定のインターフェースでポート53が、それを使用しないアプリケーションによって占有されている場合は、iodinedで-pを使用して代替ポート(例:-p 5353)を指定し、たとえばiptables(Linuxの場合)を使用してトラフィックを転送します:
iptables -t nat -A PREROUTING -i eth0 -p udp --dport 53 -j DNAT --to :5353
(Tom Schouten氏による提供)
iodinedは、60秒以上アクティブ(データ/ping)でないクライアントからのデータを拒否します。同様に、iodineは60秒間ダウンストリームデータを受信しないと終了します。長時間のネットワーク障害などが発生した場合は、iodineを再起動(再ログイン)するだけで、以前のIPアドレスを取り戻すまで、場合によっては複数回再起動してください。それが完了したら、しばらく待つだけで、障害前に中断した場所からトンネル化されたTCPトラフィックが再び流れ始めるのが確認できます。
サーバーにダウンストリームパケットキューが導入されたことにより、デフォルト構成でのメモリ使用量は数メガバイト増加しました。低メモリ環境(例:DSLルーターでの実行)で使用する場合は、常に最大1つのクライアントしか接続されないという前提であれば、user.hでUSERSを減らし、OUTPACKETQ_LENを未定義にしても悪影響はありません。小さなDNSCACHE_LENを設定することは依然として推奨されます(できれば2以上)が、さらに数キロバイトを節約するために未定義にすることもできます。
1つのiodineサーバーで複数のドメインを処理できます。同じドメインに、すべて同じホストを指す異なるNSレコードを設定し、トップドメイン引数の先頭にワイルドカードを使用します(例:*.mydomain.com)。iodineはそのパターンに一致するすべてのドメインのトンネルトラフィックを受け入れます。ワイルドカードはトップドメイン引数の先頭にあり、その後にドットが続く必要があります。
このセクションでは、いくつかのパフォーマンス測定結果を表にまとめています。正しく表示するには、Courierのような等幅フォントを使用してください。
測定はlazyモードのプロトコル00000502で行われました。アップストリームエンコーディングは常にBase128、iodine -M255、iodined -m1130です。ネットワーク環境は非常に良好というわけではありませんでした。結果はベンチマークではなく、同様の状況で期待できる実際のパフォーマンスを示す現実的な指標です。
アップストリーム/ダウンストリームのスループットは、事前に/dev/urandomから読み取った(つまり圧縮不可能な)ファイルをscpで転送し、別の非トンネル接続でls -l ; sleep 30 ; ls -lを使用してサイズを測定することで計測しました。scpのブロックサイズが16 kBと大きいため、分解能は4.3 kbit/sとなり、一部の値が完全に等しくなる理由が説明できます。pingの往復時間はping -c100で測定し、平均rttと平均偏差(平均値の周りのばらつきを示す)をミリ秒単位で示しています。
Laptop -> Wifi AP -> Home server -> DSL provider -> Datacenter iodine DNS "relay" bind9 DNS cache iodined
downstr. upstream downstr. ping-up ping-down
fragsize kbit/s kbit/s avg +/-mdev avg +/-mdev
-----------------------------------------------------------------------------
iodine -> Wifi AP :53
-Tnull (= -Oraw) 982 43.6 131.0 28.0 4.6 26.8 3.4
iodine -> Home server :53
-Tnull (= -Oraw) 1174 48.0 305.8 26.6 5.0 26.9 8.4
iodine -> DSL provider :53
-Tnull (= -Oraw) 1174 56.7 367.0 20.6 3.1 21.2 4.4
-Ttxt -Obase32 730 56.7 174.7*
-Ttxt -Obase64 874 56.7 174.7
-Ttxt -Obase128 1018 56.7 174.7
-Ttxt -Oraw 1162 56.7 358.2
-Tsrv -Obase128 910 56.7 174.7
-Tcname -Obase32 151 56.7 43.6
-Tcname -Obase128 212 56.7 52.4
iodine -> DSL provider :53
wired (no Wifi) -Tnull 1174 74.2 585.4 20.2 5.6 19.6 3.4
[174.7* : these all have 2frag/packet]
Laptop -> Wifi+vpn / wired -> Home server iodine iodined
downstr. upstream downstr. ping-up ping-down
fragsize kbit/s kbit/s avg +/-mdev avg +/-mdev
-----------------------------------------------------------------------------
wifi + openvpn -Tnull 1186 166.0 1022.3 6.3 1.3 6.6 1.6
wired -Tnull 1186 677.2 2464.1 1.3 0.2 1.3 0.1
パフォーマンスは低いping時間と強く関連しています。iodineは次のデータフラグメントに進む前に、すべてのデータフラグメントの確認を必要とするためです。TCPのように複数のフラグメントを同時進行で許可するとパフォーマンスが向上する可能性がありますが、中間のDNSサーバーに深刻な過負荷を引き起こす可能性が高いでしょう。現在のプロトコルでは、DNSサーバーが平均してクライアントあたり最大1つのDNSリクエストしか処理しないため、パフォーマンスはDNSの応答性に応じて拡張されます。
iodineは、Linux(arm、ia64、x86、AMD64、SPARC64)、FreeBSD(ia64、x86)、OpenBSD(x86)、NetBSD(x86)、MacOS X(ppcおよびx86、http://tuntaposx.sourceforge.net/を使用)、Windows(OpenVPN TAP32ドライバーを使用。win32のreadmeファイルを参照)でテストされています。TUN/TAPトンネリングサポートを備えた他のUnix系システムへの移植は容易なはずです。他のプラットフォームで動作させることができた場合はお知らせください。
iodineという名前は、IOD(IP Over DNS)で始まることと、ヨウ素(iodine)の原子番号が53であり、それが偶然にもDNSのポート番号と一致することから選ばれました。
Copyright (c) 2006-2014 Erik Ekman [email protected], 2006-2009 Bjorn Andersson [email protected]. また、Anne Bezemerによる多大な貢献があります。
上記の著作権表示およびこの許可表示がすべてのコピーに記載されていることを条件として、本ソフトウェアを目的の如何を問わず、無償または有償で使用、複製、変更、および/または配布することを許可します。
本ソフトウェアは「現状のまま」で提供され、作者は、商品性および特定目的への適合性の黙示的保証を含む、本ソフトウェアに関するすべての保証を否認します。いかなる場合も、作者は、契約行為、過失、その他の不法行為によるか否かを問わず、本ソフトウェアの使用または性能に起因または関連して生じる、特別損害、直接損害、間接損害、結果的損害、または使用、データ、利益の喪失によるいかなる損害に対しても責任を負いません。
MD5実装はL. Peter Deutschによるものです(ライセンスとソースはsrc/md5.[ch]にあります)
Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.