開発環境でHTTPリバースプロキシが大好きになり、DNSベースの仮想ホストリバースプロキシが非常に便利であることがわかりました。ファイアウォールで1つのポート(および標準ポート)のみを開くと、管理がはるかに簡単になります。
SSH接続に似たものを見つけたいのですが、あまり運がありません。標準以外のポート範囲を開く必要があるため、単純にSSHトンネリングを使用するのは好ましくありません。これを行うことができるものはありますか?
HAProxyはこれを実行できますか?
開発環境でHTTPリバースプロキシが大好きになり、DNSベースの仮想ホストリバースプロキシが非常に便利であることがわかりました。ファイアウォールで1つのポート(および標準ポート)のみを開くと、管理がはるかに簡単になります。
SSH接続に似たものを見つけたいのですが、あまり運がありません。標準以外のポート範囲を開く必要があるため、単純にSSHトンネリングを使用するのは好ましくありません。これを行うことができるものはありますか?
HAProxyはこれを実行できますか?
回答:
プロトコルがどのように機能するかを考えると、名前ベースのSSHが可能になるとは思わない。
いくつかの選択肢があります。
できることは、ポート22がゲートウェイとして機能するように応答するホストをセットアップすることです。次に、キーに基づいてリクエストを内部に転送するようにsshサーバーを構成できます。キーを使用したSSH ゲートウェイの例
そのホストをプロキシとして使用するようにクライアントを調整できます。つまり、ゲートウェイホストにsshし、そのホストを使用して内部ホストに接続します。クライアント構成を使用した SSHプロキシ。
エッジで簡単なhttpプロキシをセットアップすることもできます。次に、それを使用して着信接続を許可します。HTTPプロキシ経由のSSH 。
明らかに、上記のすべてで、ゲートウェイを適切に構成してロックダウンすることを確認することは非常に重要です。
過去16か月間、この問題の解決策をオンとオフで探していました。しかし、私が見るたびに、関連するRFCで指定され、主要な実装で実装されているSSHプロトコルでこれを行うことは不可能のようです。
ただし、わずかに変更されたSSHクライアントを使用する意思があり、設計時にプロトコルが正確に意図されていなかった方法でプロトコルを利用する場合は、達成することができます。詳細については、以下をご覧ください。
不可能な理由
クライアントは、SSHプロトコルの一部としてホスト名を送信しません。
DNSルックアップの一部としてホスト名を送信する場合がありますが、キャッシュされる可能性があり、リゾルバを介して信頼できるサーバーへのクライアントからのパスがプロキシを通過しない場合があります。特定のDNSルックアップを特定のSSHクライアント。
SSHプロトコル自体でできることは何もありません。クライアントからSSHバージョンバナーを見なくてもサーバーを選択する必要があります。プロキシに何かを送信する前に、クライアントにバナーを送信する必要があります。サーバーからのバナーは異なる可能性があり、推測する可能性はありません。どちらを使用するのが正しいかを推測してください。
このバナーは暗号化されずに送信されますが、変更することはできません。そのバナーのすべてのビットが接続のセットアップ中に検証されるため、少し下の接続障害が発生することになります。
私への結論はかなり明確です。この接続を機能させるためには、クライアント側で何かを変更する必要があります。
回避策のほとんどは、SSHトラフィックを別のプロトコル内にカプセル化しています。SSHプロトコル自体に追加することも考えられます。このプロトコルでは、クライアントが送信するバージョンバナーにホスト名が含まれます。これは既存のサーバーとの互換性を保つことができます。これは、バナーの一部が現在、自由形式識別フィールドとして指定されているためです。最初。sshクライアントの最近のバージョン(Ubuntu 14.04など)では、サーバーバナーを待たずにバナーを送信します。
このバナーにサーバーのホスト名を含めるための措置を講じたクライアントは知りません。このような機能を追加するために、OpenSSHメーリングリストにパッチを送信しました。しかし、SSHトラフィックを覗き見する人にホスト名を明かさないという願望に基づいて拒否されました。秘密のホスト名は基本的に名前ベースのプロキシの動作と互換性がないため、SSHプロトコルの公式のSNI拡張機能がすぐに表示されることを期待しないでください。
実際のソリューション
私にとって最適なソリューションは、実際にはIPv6を使用することでした。
IPv6では、各サーバーに個別のIPアドレスを割り当てることができるため、ゲートウェイは宛先IPアドレスを使用して、パケットを送信するサーバーを見つけることができます。SSHクライアントは、IPv6アドレスを取得する唯一の方法がTeredoを使用するネットワーク上で実行されている場合があります。Teredoは信頼できないことが知られていますが、接続のネイティブIPv6エンドがパブリックTeredoリレーを使用している場合のみです。プロキシを実行するゲートウェイにTeredoリレーを配置するだけです。Miredoは、5分未満でリレーとしてインストールおよび構成できます。
回避策
ジャンプホスト/要塞ホストを使用できます。このアプローチは、個々のサーバーのSSHポートを公開インターネットに直接公開したくない場合を対象としています。SSHに必要な外部に面したIPアドレスの数を減らすという利点があります。このため、このシナリオで使用できます。セキュリティ上の理由から別の保護層を追加することを目的としたソリューションであるという事実は、追加のセキュリティが必要ない場合に使用を妨げるものではありません。
ssh -o ProxyCommand='ssh -W %h:%p user1@bastion' user2@target
実際のソリューション(IPv6)が手の届かないところにある場合に機能させるためにハッキングするのは汚い
これから説明するハックは、最後の手段としてのみ使用してください。このハックの使用について考える前に、SSHを介して外部からアクセスできるようにする各サーバーのIPv6アドレスを取得することを強くお勧めします。SSHサーバーにアクセスする主な方法としてIPv6を使用し、IPv6の展開に影響しないIPv4専用ネットワークからSSHクライアントを実行する必要がある場合にのみ、このハックを使用します。
これは、クライアントとサーバー間のトラフィックが完全に有効なSSHトラフィックである必要があるという考え方です。ただし、プロキシはホスト名を識別するためにパケットのストリームについて十分に理解する必要があります。SSHはホスト名を送信する方法を定義していないため、そのような可能性を提供する他のプロトコルを検討することができます。
HTTPとHTTPSはどちらも、サーバーがデータを送信する前にクライアントがホスト名を送信できるようにします。ここでの問題は、SSHトラフィックとHTTPおよびHTTPSの両方として同時に有効なバイトストリームを構築できるかどうかです。HTTPでは、ほとんどスターターではありませんが、HTTPは可能です(HTTPの十分に自由な定義のため)。
SSH-2.0-OpenSSH_6.6.1 / HTTP/1.1
$:
Host: example.com
これはSSHまたはHTTPのように見えますか?SSHであり、RFCに完全に準拠しています(一部のバイナリ文字はSFレンダリングによって少し変更されています)。
SSHバージョン文字列にはコメントフィールドが含まれており、上記の値はです/ HTTP/1.1
。改行後、SSHにはバイナリパケットデータが含まれます。最初のパケットはMSG_SSH_IGNORE
、クライアントによって送信され、サーバーによって無視されるメッセージです。無視されるペイロードは次のとおりです。
:
Host: example.com
HTTPプロキシが受け入れる内容が十分に自由な場合、同じバイトシーケンスが呼び出されるHTTPメソッドとして解釈されSSH-2.0-OpenSSH_6.6.1
、無視メッセージの先頭のバイナリデータはHTTPヘッダー名として解釈されます。
プロキシは、HTTPメソッドも最初のヘッダーも理解しません。しかしHost
、バックエンドを見つけるために必要なのはヘッダーだけです。
これが機能するためには、プロキシはバックエンドを見つけるのに十分なHTTPを理解するだけでよいという原則に基づいて設計する必要があり、バックエンドが見つかるとプロキシは単純に生のバイトストリームを渡し、実際の終了を終了しますバックエンドによって行われるHTTP接続の。
HTTPプロキシについて非常に多くの仮定を行うことは、少しストレッチのように聞こえるかもしれません。ただし、SSHをサポートするために開発された新しいソフトウェアをインストールする場合は、HTTPプロキシの要件はそれほど悪くないようです。
私自身の場合、このメソッドは、コード、構成などを変更せずに、既にインストールされているプロキシで動作することがわかりました。そして、これはHTTPのみでSSHを考慮しないで書かれたプロキシ用でした。
概念実証のクライアントとプロキシ。(プロキシは私が運営するサービスであるという免責事項。他のプロキシがこの使用をサポートしていることが確認されたら、リンクを交換してください。)
このハックの注意事項
the gateway can use the destination IP address to find out which server to send the packet to
IPv6ソリューションで、あなたが意味することを詳しく説明できますか?
-J
、次を使用できます。ssh -J user1 @ front user2 @ target
少なくともあなたが説明したように、これが可能になるとは思わないが、間違っていると証明されるのが大好きだ。クライアントが接続したいホスト名を送信するようには見えません(少なくとも平文では)。SSH接続の最初のステップは、暗号化をセットアップすることです。
また、ホストキーの検証にも問題があります。SSHクライアントは、IPアドレスとホスト名に基づいてキーを検証します。異なるキーを持つ複数のホスト名がありますが、接続しているIPは同じです。
可能な解決策は、クライアントがそのマシンにsshし、通常の(または必要に応じて制限された)シェルを取得し、そこから内部ホストにsshできる「要塞」ホストを持つことです。
ブロックに新しい子供がいます。SSHパイパーは、事前定義されたユーザー名に基づいて接続をルーティングします。これは、内部ホストにマップされる必要があります。これは、リバースプロキシのコンテキストでの最適なソリューションです。
私の最初のテストでは、SSHとSFTPの両方が機能することが確認されました。
debug1: Sending subsystem: sftp
。シャツフロントはサブシステムをサポートしていないことがわかります。SShパイパーで裾をサポートしていますか?
プロキシモードを備えたHoneytrap(低相互作用ハニーポット)は、それを達成するために変更できないのではないかと思っています。
このハニーポットは、任意のプロトコルを別のコンピューターに転送できます。名前ベースのvhostシステム(Apacheで実装されている)を追加すると、あらゆるプロトコルの完全なリバースプロキシになる可能性がありますか?
私にはそれを達成するスキルはありませんが、素晴らしいプロジェクトかもしれません。