こんにちはGT!
木に考えを広めることなく、仕事に取り掛かろう。 高速で無検閲のインターネットを提供するために、私は長い間標準スキームを使用してきました。OpenVPNと海外で最もシンプルなVPSです。 使用されるトランスポートプロトコルはUDPです。
問題ある「良い」瞬間に、VPNが落ちて、もはや上昇していないことを発見しました。 この問題についての長い研究については説明しません。結果をすぐに言います。ポート番号の変更が役立ちました。 長い間役に立たなかった。数日後、トンネルは再び壊れ、港を変更することで再び復旧した。
仮説プロバイダーのファイアウォールでは、トラフィックの統計は次のようになります。100%以下は、単一のUDPプロトコル、単一のポート、単一のIPを通過します。 したがって、これをグラフの形で想像すると、平均的なユーザーの場合とは大きく異なります。平均的なユーザーでは、さまざまなプロトコル、ポート(TCP 80、443、993 ...)およびIPアドレスに対してグラフの「ピーク」が多くなります。
ファイアウォールのヒューリスティックはこれに正確に応答し、トラフィックの一部が特定のしきい値を通過する接続をブロックしているようです。 同時に、統計は大きな数字を好む科学であるため、そのようなフィルターは、定義上、ある程度の遅延でトリガーされます。
挑戦するファイアウォールから統計を再計算する間隔よりも明らかに短い間隔で、VPNポート番号を変更するソリューションを開発する必要があります。 フィルターが曲線より先に実行されるのを防ぐために、ポートを予測できない方法で変更する必要があります。 また、さまざまな不可抗力の場合に手動でポート変更を開始できる必要があります。 サーバー管理が完全に失われた場合でも、タイムシフトは機能するはずです。
アルゴリズム一般に、生成式は次のようになります。
port = hash(shared_secret + round(time) + ondemand_key) % (port_max - port_min + 1) + port_min
- hash()-ハッシュ関数
- shared_secret-次の結果を知らずに予測不能にするキー。 システムの唯一の秘密の部分。
- ラウンド(時間)-UTCの現在の時間からの粗面化関数。 粗さの程度によって、ポートを変更する間隔が決まります。たとえば、秒と分を落とす-1時間の間隔、さらに時間を落としてAM / PMマークを維持する-12時間などです。
- ondemand_key-信頼できるサードパーティのサーバーからロードされたキーで、このキーを変更することでポートを手動で変更できます。
- port_minおよびport_max-使用されるポートの範囲、それぞれ最小および最大。
システムがオンデマンドキーの変更に迅速に対応するために、スケジューラで数分間隔でスクリプトを実行します。 この場合、パラメーターが実際に変更されているかどうかを確認する必要があります。これにより、結果が否定的な場合、スクリプトはすぐに終了します。
検証時に既に計算されている上記の式を見てみましょう。 ハッシュ()値も範囲境界も変更されていない場合、変更はありません。 これを行うには、もう一度ハッシュを取得します。
cache = hash(hash(...) + port_min + port_max)
その後、特別なファイルから古いキャッシュ値を読み取り、比較し、それらが異なる場合はファイルを更新してスクリプトを続行します。 同じ場合-終了します。
さらに、技術的な問題:ルールテンプレートのポート値をiptablesに置き換え(スクリプトのクライアントロールとサーバーロールにこれらのテンプレートが2つあります)、テーブルにルールを追加し、別のファイルから前のルールを読み取り、存在する場合はiptablesから削除し、ファイルを更新します現在のルール。
理論的には、この時点で、接続はすでに新しいポートで動作するはずですが、実際には、何らかの理由で、デーモンが再起動するまで古いポートを使用し続けます。 誰かがこのバグフィチの理由を説明してくれたらありがたいと思いますが、今のところはスクリプトから再起動コマンドを与えるだけです。 同時に通信が中断されるのは数秒であり、不便はありません。
オンデマンド再起動システムオンデマンドキーのストレージとしてパブリックVCS(私はgithubを持っています)を使用すると非常に便利です。 原則として、無料のホスティングで対応できますが、VCSには編集の履歴を保持するという重要な利点があります。 このような状況は、トンネルの端の1つがキーを更新し、何らかの理由で2つ目がリポジトリに到達できず、キャッシュ内の古いキーで動作する場合に発生する可能性があります。 この場合、コミットのロールバックを試みることができます:管理者がオンデマンドをプルする原因となった接続のドロップがポートのブロックではなく、たとえば一時的なアップリンク障害によって引き起こされた場合、キーを返すとすぐにトンネルが上がります。 実際には、このような状況は数回発生しています。
キーをプルするスクリプトは特別なものではありません-通常のwget、戻りコードをチェックし、ファイルにキャッシュする-したがって、それを記述するのは意味がありません、コードはそれをすべて言います。
オンデマンドキーを管理するためのスクリプトは、より大規模なものですが、本質的にはシンプルでもあります。これは、キーリポジトリでの操作を簡素化するためのバインディングです。 単一のコマンドでキーを作成、削除、変更する操作を実行できます。
おわりにタスクを解決するためのツールは成功し、1年以上にわたって成功していると思います。 さらに、結果のユーティリティは、このタイプのフィルタリングに対する普遍的な武器と考えることができます。
- OpenVPNスクリプトに加えて、あらゆるネットワークサービスに使用できます。
- 任意のハッシュ関数を暗号化装置として使用できます。これにより、今日のアルゴリズムの将来的な妥協の可能性に対するデポジットが提供されます。
- 1つのサーバーで一意のキーを使用して多数のクライアントにサービスを提供できます。portgenインスタンスを個々のフォルダーに分散するだけです
参照資料github.com/Raegdan/portgen-portgenプログラム自体
github.com/Raegdan/portgen-ondemand-オンデマンドキーと私のキーを同時に管理するためのプログラム。 これは便宜のためだけに行われました。 オンデマンドキーは分類されないため、何らかの理由で誰かが突然私の/ dev / urandomの一部を必要とする場合-私は気にしません;)
ご注意コードはHabr用です! 宇宙飛行士、ドローン、ガジェットのレビューがあります!原則として、私はこの議論に反対することはできず、プログラムコードは実際にはHabrプロファイルに近いものです。 ただし、最初に、このプロジェクトはインターネットの検閲との戦いに直接関連しています。このトピックはここで明示的に再設定されました。 第二に、これまでの私の唯一の記事は分割前に書かれており、Habréに残っているため、GTアカウントに特定の制限が生じます。 理解して扱ってください。