Skip to content

Commit 50e699b

Browse files
committed
docs: 多層防御(Defense in Depth)セキュリティ設計を文書化
- 二層のファイアウォール構成の説明 - Layer 1: さくらのクラウド パケットフィルター - Layer 2: iptables(サーバー内部) - なぜ両方が必要なのかを詳細に説明 - 時系列での保護 - 障害時の冗長性 - 管理の観点 - 攻撃シナリオへの対策 - パケットフィルター確認ツールも追加 - トラブルシューティングガイド - ベストプラクティス
1 parent 155dd98 commit 50e699b

File tree

2 files changed

+275
-0
lines changed

2 files changed

+275
-0
lines changed

docs/security-defense-in-depth.md

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
# DojoPaaS セキュリティ設計:多層防御(Defense in Depth)
2+
3+
## 概要
4+
5+
DojoPaaSでは、CoderDojoのサーバーを保護するために**多層防御(Defense in Depth)**戦略を採用しています。これは、単一の防御機構に依存せず、複数の独立したセキュリティ層を重ねることで、より強固な防御を実現する設計思想です。
6+
7+
## 二層のファイアウォール構成
8+
9+
```
10+
インターネット
11+
12+
[Layer 1: さくらのクラウド パケットフィルター]
13+
14+
サーバー
15+
16+
[Layer 2: iptables (サーバー内部)]
17+
18+
アプリケーション
19+
```
20+
21+
### Layer 1: パケットフィルター(クラウド側)
22+
23+
**設定ID**: `112900922505`
24+
**管理場所**: さくらのクラウドコントロールパネル
25+
**特徴**:
26+
- サーバーの外側でトラフィックを制御
27+
- サーバー起動前から有効
28+
- 複数サーバーで設定を共有可能
29+
30+
**開放ポート**:
31+
- 22/tcp (SSH)
32+
- 80/tcp (HTTP)
33+
- 443/tcp (HTTPS)
34+
- 1024-65535/tcp (高位ポート)
35+
- 1024-65535/udp (高位ポート)
36+
37+
### Layer 2: iptables(サーバー内部)
38+
39+
**設定ファイル**: `startup-scripts/112900928939`
40+
**管理場所**: サーバー内部(`/etc/iptables/rules.v4`
41+
**特徴**:
42+
- サーバー内部でトラフィックを制御
43+
- より細かい制御が可能(rate limiting等)
44+
- スタートアップスクリプトで自動設定
45+
46+
**セキュリティ機能**:
47+
- SSH ブルートフォース攻撃対策(hashlimit)
48+
- ICMP フラッド攻撃対策
49+
- TCP フラグ異常パケットのドロップ
50+
- IPv6 完全ブロック
51+
52+
## なぜ両方必要なのか?
53+
54+
### 1. 時系列での保護
55+
56+
```
57+
サーバー起動
58+
↓ [この間も保護が必要]
59+
スタートアップスクリプト実行(数秒〜数分)
60+
61+
iptables 有効化
62+
```
63+
64+
パケットフィルターは**サーバー起動直後から有効**なため、スタートアップスクリプトが実行されるまでの間もサーバーを保護します。
65+
66+
### 2. 障害時の冗長性
67+
68+
- パケットフィルターが無効になっても → iptablesが保護
69+
- iptables設定が失敗しても → パケットフィルターが保護
70+
- どちらか片方が機能していれば、最低限のセキュリティを維持
71+
72+
### 3. 管理の観点
73+
74+
| 項目 | パケットフィルター | iptables |
75+
|------|------------------|----------|
76+
| 設定変更 | Webコンソール/API | SSH接続が必要 |
77+
| 複数サーバー管理 | 一括設定可能 | 個別設定必要 |
78+
| 設定の複雑さ | シンプル | 複雑な制御可能 |
79+
| 適用タイミング | 即座 | 再起動/reload必要 |
80+
81+
### 4. 攻撃シナリオへの対策
82+
83+
**例:DDoS攻撃**
84+
- Layer 1(パケットフィルター): 基本的なフィルタリング
85+
- Layer 2(iptables): rate limitingで詳細な制御
86+
87+
**例:設定ミス**
88+
- 管理者がiptablesを誤って無効化 → パケットフィルターが保護継続
89+
- パケットフィルターの設定ミス → iptablesが最後の砦
90+
91+
## SSH セキュリティの追加強化
92+
93+
スタートアップスクリプトでは、ファイアウォールに加えてSSH自体のセキュリティも強化:
94+
95+
```bash
96+
# rootログインを無効化
97+
PermitRootLogin no
98+
99+
# パスワード認証を無効化(鍵認証のみ)
100+
PasswordAuthentication no
101+
```
102+
103+
## 実装コード
104+
105+
### パケットフィルターの適用(Ruby)
106+
107+
```ruby
108+
# scripts/sakura_server_user_agent.rb
109+
def apply_packet_filter(params = nil)
110+
@interface_id ||= params[:interface_id]
111+
@packet_filter_id ||= params[:packet_filter_id]
112+
113+
# パケットフィルターIDが指定されていない場合はスキップ
114+
if @packet_filter_id.nil?
115+
puts "パケットフィルターは適用されません(packet_filter_id is nil)"
116+
return
117+
end
118+
119+
response = send_request('put',
120+
"interface/#{@interface_id}/to/packetfilter/#{@packet_filter_id}", nil)
121+
end
122+
```
123+
124+
### デフォルト設定
125+
126+
```ruby
127+
# デフォルトで本番環境のパケットフィルターを適用
128+
def initialize(zone:"31002", packet_filter_id:'112900922505', ...)
129+
@packet_filter_id = packet_filter_id
130+
# ...
131+
end
132+
```
133+
134+
## テスト環境での無効化
135+
136+
開発・テスト環境では、必要に応じてパケットフィルターを無効化可能:
137+
138+
```ruby
139+
# テスト用スクリプト
140+
ssua = SakuraServerUserAgent.new(packet_filter_id: nil)
141+
```
142+
143+
⚠️ **警告**: 本番環境では絶対にパケットフィルターを無効化しないでください。
144+
145+
## トラブルシューティング
146+
147+
### SSH接続できない場合
148+
149+
1. **パケットフィルター確認**
150+
```bash
151+
ruby scripts/utils/check_packet_filter.rb
152+
```
153+
154+
2. **サーバーステータス確認**
155+
```bash
156+
ruby scripts/utils/check_server_status.rb <サーバー名>
157+
```
158+
159+
3. **ポート疎通確認**
160+
```bash
161+
curl -v telnet://<IPアドレス>:22 --max-time 3
162+
```
163+
164+
### セキュリティ設定の確認
165+
166+
パケットフィルターの現在の設定を確認:
167+
```bash
168+
ruby scripts/utils/check_packet_filter.rb
169+
```
170+
171+
期待される出力:
172+
- ポート22, 80, 443が開放されている
173+
- その他のポートは基本的にdeny
174+
175+
## ベストプラクティス
176+
177+
1. **両方の層を常に有効に保つ**
178+
- パケットフィルターとiptablesの両方を有効化
179+
- 片方だけに依存しない
180+
181+
2. **定期的な設定確認**
182+
- パケットフィルターIDが有効か確認
183+
- スタートアップスクリプトが最新か確認
184+
185+
3. **テスト環境での検証**
186+
- 本番環境に適用する前にテスト環境で検証
187+
- セキュリティ設定の変更は慎重に
188+
189+
4. **ログの監視**
190+
- 不正なアクセス試行を監視
191+
- 異常なトラフィックパターンを検知
192+
193+
## 関連ファイル
194+
195+
- `scripts/sakura_server_user_agent.rb` - パケットフィルター適用ロジック
196+
- `startup-scripts/112900928939` - iptables設定スクリプト
197+
- `scripts/utils/check_packet_filter.rb` - パケットフィルター確認ツール
198+
- `scripts/utils/check_server_status.rb` - サーバー状態確認ツール
199+
200+
## 更新履歴
201+
202+
- 2019年9月: パケットフィルター機能を導入
203+
- 2025年7月: cloud-init対応でSSH鍵設定を改善
204+
- 2025年9月: 多層防御ドキュメント作成
205+
206+
---
207+
208+
*このドキュメントは、DojoPaaSのセキュリティ設計思想を説明するものです。実際の運用では、さくらインターネット様のセキュリティガイドラインも併せて参照してください。*
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#!/usr/bin/env ruby
2+
3+
require 'dotenv/load'
4+
require_relative '../sakura_server_user_agent.rb'
5+
6+
# パケットフィルターAPIにアクセスするための拡張クラス
7+
class PacketFilterChecker < SakuraServerUserAgent
8+
def get_packet_filter(id)
9+
send_request('get', "packetfilter/#{id}", nil)
10+
end
11+
12+
def list_packet_filters
13+
send_request('get', 'packetfilter', nil)
14+
end
15+
end
16+
17+
puts "=== パケットフィルター情報確認 ==="
18+
puts ""
19+
20+
checker = PacketFilterChecker.new
21+
22+
# デフォルトのパケットフィルターIDを確認
23+
default_id = '112900922505'
24+
puts "📋 デフォルトパケットフィルター ID: #{default_id}"
25+
puts ""
26+
27+
begin
28+
# 特定のパケットフィルター詳細を取得
29+
puts "詳細情報を取得中..."
30+
filter_info = checker.get_packet_filter(default_id)
31+
32+
if filter_info && filter_info['PacketFilter']
33+
pf = filter_info['PacketFilter']
34+
puts "名前: #{pf['Name']}"
35+
puts "説明: #{pf['Description']}"
36+
puts ""
37+
38+
if pf['Expression'] && pf['Expression'].any?
39+
puts "📝 ルール一覧:"
40+
pf['Expression'].each_with_index do |rule, i|
41+
puts " ルール#{i+1}:"
42+
puts " - プロトコル: #{rule['Protocol']}"
43+
puts " - 送信元: #{rule['SourceNetwork'] || 'any'}"
44+
puts " - 送信元ポート: #{rule['SourcePort'] || 'any'}"
45+
puts " - 宛先ポート: #{rule['DestinationPort'] || 'any'}"
46+
puts " - アクション: #{rule['Action']}"
47+
puts " - 説明: #{rule['Description']}" if rule['Description']
48+
puts ""
49+
end
50+
end
51+
else
52+
puts "❌ パケットフィルター情報を取得できませんでした"
53+
end
54+
55+
# 利用可能なパケットフィルター一覧
56+
puts "\n=== 利用可能なパケットフィルター一覧 ==="
57+
all_filters = checker.list_packet_filters
58+
if all_filters && all_filters['PacketFilters']
59+
all_filters['PacketFilters'].each do |pf|
60+
puts "- ID: #{pf['ID']} / 名前: #{pf['Name']}"
61+
end
62+
end
63+
64+
rescue => e
65+
puts "エラー: #{e.message}"
66+
puts e.backtrace if ENV['DEBUG']
67+
end

0 commit comments

Comments
 (0)