
自己完結型のSSHハニーポットで、攻撃者の操作を捕捉し、構造化されたセキュリティインテリジェンスに変換します。
SSHintel は、PythonとParamikoを使用して構築された軽量SSHハニーポットです。偽のLinuxシェルをシミュレートして、不正アクセスの試みを記録し、認証情報を取得し、管理された環境で攻撃者の行動を分析します。
ls、cd、pwd、cat、echo、grep、find、tree、head、tail、wc、stat、ps、df、free、env、id、whoami など)--tarpit モードSSHintel は完全なBash/Linuxシェルではありません。攻撃者のテレメトリを収集するために、一般的なコマンドの信頼できるサブセットをシミュレートします。コマンドは軽量なレジストリによってディスパッチされます。コマンドを追加するということは、小さなハンドラ関数を追加することを意味します。
pip install -r requirements.txt
注: SSHホストキーは初回実行時に自動生成されます。手動でのキー生成は不要です。
特定のポート、ユーザー名、パスワードでハニーポットを実行します:
python3 run.py serve --port 2222 --username user1 --password pass123
デフォルトのポートは
2222、ホストは0.0.0.0です。
ハニーポットは、初回実行時に static/server.key にSSHホストキーが存在しない場合、自動的に生成します。手動でのキー生成は不要です。
ターピットモードを有効にするには:
python3 run.py serve --port 2222 --username user1 --password pass123 --tarpit
SQLiteテレメトリを無効にするには(JSONLのみ):
python3 run.py serve --port 2222 --username user1 --password pass123 --no-db
SSHintel は、多数の同時接続や無期限に維持される接続によるリソース枯渇から保護します。これらはCLIで設定可能です:
例:
python3 run.py serve --port 2222 --username user1 --password pass123 \
--max-connections 25 --auth-timeout 30 --session-idle-timeout 300
開いている接続が多すぎる場合、超過した接続は即座に閉じられ、connection_rejected セキュリティイベント(reason: connection_limit 付き)がJSONLログに書き込まれます。停滞した認証は reason: auth_timeout の切断として記録され、アイドルシェルは reason: idle_timeout で終了します。
ターピットモードは攻撃者を引き付けておくために意図的に出力を遅く送信するため、ターピットバナーループは非アクティブタイムアウトの対象外ですが、ターピットセッションは接続制限にはカウントされます。
SSHintel には、SQLiteに保存されたセキュリティテレメトリを可視化するローカルWebダッシュボードが含まれています。
python3 run.py dashboard
次に、ブラウザで http://localhost:5000 を開きます。
ダッシュボードはデフォルトで
data/sshintel.dbのSQLiteデータベースから読み取ります。最初にハニーポットを起動してテレメトリがキャプチャされるようにしてから、ダッシュボードを起動してデータが蓄積されるのを確認してください。
セッションIDをクリックするか(または /session/<session_id> に移動して)、単一の攻撃を時系列で再構築するセッション調査ビューを開きます:
$ command ビュー(作業ディレクトリ付き)# ターミナル1: ハニーポットを起動
python3 run.py serve --port 2222 --username user1 --password pass123
# ターミナル2: ダッシュボードを起動
python3 run.py dashboard
# ターミナル3: 攻撃者をシミュレート
ssh user1@localhost -p 2222
# (いくつかのコマンドを実行してから終了)
次に、http://localhost:5000 を開いてキャプチャされたアクティビティを確認します。
ダッシュボードはライブテレメトリをサポートしています — 2秒ごとにハニーポットをポーリングし、自動的に更新されます。新しいセッション、コマンド、イベントはページを更新することなくリアルタイムで表示されます。ライブインジケーター(● Live)が接続ステータスを示します。
2番目のターミナルを開いて接続を試みます:
ssh user1@localhost -p 2222
認証情報が一致する場合、エミュレートされたシェルにドロップされます。
古いSSHフィンガープリントを削除するには:
notepad "%USERPROFILE%\.ssh\known_hosts"
localhostまたはハニーポットのIPを含む関連行を削除します。
creds_logger に記録されますfunnel_logger を介して記録されますlog_files/events.jsonl に書き込まれます — 各行に1つの有効なJSONオブジェクト各JSONLイベントには、UTC ISO-8601形式の timestamp、event_type、一意の session_id、および source_ip が含まれます。接続、認証の試行/結果、コマンド実行、ターピットのアクティブ化、切断はすべて構造化イベントとして記録されます。
各着信SSH接続は、独自の session_id を持つ独立したセッションとして追跡されます。セッションはソースIP、接続/切断時刻、認証結果、接続期間を記録し、その接続内で生成されたすべてのイベントは同じ session_id を保持します(そのため、認証試行、コマンド、切断を単一の接続に結び付けることができます)。セッションは接続ごとに分離されています — 同時クライアント間で状態が共有されることはありません。
各セッションはまた、独自の分離されたインメモリ偽ファイルシステムを受け取ります — シミュレートされたファイルシステムは各接続ごとに新しく作成され、接続が終了するとクリーンアップされます。ある攻撃者によって作成または変更されたファイル、ディレクトリ、作業ディレクトリは、同時に接続されている別の攻撃者には決して見えません。ファイルシステム全体はPythonメモリ内でシミュレートされ、実際のホストファイルシステムに触れることは決してありません。
現在の event_type 値: connect、auth_attempt、auth_success、auth_failure、command、disconnect、connection_rejected、tarpit。
SSHintel/
├── honeypot/ # コアハニーポットロジック
│ ├── __init__.py
│ ├── main.py # 受け入れループ + 接続制限
│ ├── handlers.py # SSHトランスポート設定 + エミュレートされたシェル
│ ├── server.py # Paramikoサーバーインターフェース(認証)
│ ├── session.py # 接続ごとのセッション追跡
│ ├── fs.py # インメモリ偽ファイルシステム(セッションごとに分離)
│ ├── shell.py # 偽シェル: コマンドレジストリ + ディスパッチャ
│ ├── limits.py # スレッドセーフな同時接続制限
│ ├── logger.py # JSONLイベントロギング + SQLiteブリッジ
│ └── telemetry_store.py # SQLiteテレメリストア + クエリレイヤー
│
├── dashboard/ # ローカルWebダッシュボード
│ ├── app.py # Flaskアプリケーション + APIルート
│ ├── templates/
│ │ ├── index.html # メインダッシュボードテンプレート
│ │ └── session.html # セッション調査テンプレート
│ └── static/
│ ├── style.css # ダッシュボードスタイル
│ ├── dashboard.js # メインダッシュボードJS(ライブ更新)
│ └── session.js # セッション調査JS
│
├── log_files/ # ランタイムログ(git-ignored)
│ ├── creds_audits.log # 認証情報の試行
│ ├── cmd_audits.log # コマンド監査トレイル
│ └── events.jsonl # 構造化されたJSONLセキュリティイベント
│
├── data/ # SQLiteデータベース(git-ignored)
│ └── sshintel.db
│
├── static/ # SSHホストキー(自動生成)
│ └── server.key
│
├── .github/workflows/ # CI設定
│ └── tests.yml
│
├── Dockerfile
├── README.md
├── requirements.txt # ランタイム依存関係(paramiko、flask)
├── requirements-dev.txt # テスト依存関係(pytest、pytest-cov)
└── run.py # CLIエントリポイント
コンテナ化された環境でハニーポットを実行したい場合は、同梱のDockerfileを使用できます。
docker build -t sshintel .
これにより、
sshintelという名前のDockerイメージが作成されます。
docker run -p 2222:2222 sshintel
これにより:
static/server.key にSSH秘密キーが自動生成されます(まだ存在しない場合)2222 でハニーポットが起動します:username: user1、password: pass1232番目のターミナルを開いてSSHで接続します:
ssh user1@localhost -p 2222
認証情報が一致する場合、シミュレートされたシェルにドロップされます。
コンテナを停止するには:
docker ps # コンテナIDを確認
docker stop <container_id>
イメージを削除するには:
docker rmi sshintel
また、
docker save -o sshintel.tar sshintelを使用してイメージをエクスポートし、後でdocker load -i sshintel.tarでロードすることもできます。
このプロジェクトは MITライセンス の下でライセンスされています。
| フラグ | デフォルト | 目的 |
|---|
--max-connections | 50 | 最大同時アクティブ接続数。超過した接続は拒否され、connection_rejected イベントとして記録されます |
--auth-timeout | 60 (秒) | SSHハンドシェイク/認証を完了するために許可される時間。停滞したクライアントは切断されます |
--session-idle-timeout | 300 (秒) | 認証済みシェルの非アクティブタイムアウト。アイドルセッションは終了しますが、アクティブに入力中の攻撃者が強制終了されることはありません |