๋ณด์
๋ณด์
SSH-Frontiรจre๋ ๋ณด์ ์ปดํฌ๋ํธ์ ๋๋ค. ์์ SSH ์ฐ๊ฒฐ์ด ์ํํ ์ ์๋ ์์ ์ ์ ํํ๋ ๊ฒ์ด ์กด์ฌ ์ด์ ์ ๋๋ค. ์ด ํ์ด์ง๋ ๋ณด์ ๋ชจ๋ธ, ๊ตฌํ๋ ๊ธฐ๋ฅ, ๊ทธ๋ฆฌ๊ณ ๋ณด์ฅ๋์ง ์๋ ์ฌํญ์ ๋ฌธ์ํํฉ๋๋ค.
๋ณด์ ๋ชจ๋ธ
๊ธฐ๋ณธ ์์น: deny by default
๋ช ์์ ์ผ๋ก ๊ตฌ์ฑ๋์ง ์์ผ๋ฉด ์๋ฌด๊ฒ๋ ์คํ๋์ง ์์ต๋๋ค. ๋ช ๋ น์ด TOML ํ์ดํธ๋ฆฌ์คํธ์ ์์ผ๋ฉด ๊ฑฐ๋ถ๋ฉ๋๋ค. ํ์ฉ ๋ชจ๋๋ ์๊ณ , ์ ธ๋ก์ ํด๋ฐฑ๋ ์์ต๋๋ค.
์ฌ์ธต ๋ฐฉ์ด์ ์ธ ๊ณ์ธต
| ๊ณ์ธต | ๋ฉ์ปค๋์ฆ | ๋ณดํธ |
|---|---|---|
| 1 | authorized_keys์ command= + restrict | ์ ๊ทผ ์์ค ๊ฐ์ , ํฌ์๋ฉ/PTY ์ฐจ๋จ |
| 2 | SSH-Frontiรจre (๋ก๊ทธ์ธ ์ ธ) | TOML ํ์ดํธ๋ฆฌ์คํธ์ ๋ํด ๋ช ๋ น ๊ฒ์ฆ |
| 3 | sudoers์ sudo ํ์ดํธ๋ฆฌ์คํธ | ๊ถํ์ด ํ์ํ ์์คํ ๋ช ๋ น ์ ํ |
๊ณต๊ฒฉ์๊ฐ SSH ํค๋ฅผ ํ์ทจํ๋๋ผ๋(์ 1๊ณ์ธต), TOML ํ์ดํธ๋ฆฌ์คํธ์ ํ๊ฐ๋ ๋ช ๋ น๋ง ์คํํ ์ ์์ต๋๋ค(์ 2๊ณ์ธต). ์ 2๊ณ์ธต์ ์ฐํํ๋๋ผ๋, sudoers์ ํ๊ฐ๋ ๋ช ๋ น์ ๋ํด์๋ง ๊ถํ ์์น์ด ๊ฐ๋ฅํฉ๋๋ค(์ 3๊ณ์ธต).
๋ฌธ๋ฒ ํ์, ๋ธ๋๋ฆฌ์คํธ๊ฐ ์๋
SSH-Frontiรจre๋ ์
ธ์ด ์๋๋๋ค. ๋ณด์์ ๋ฌธ์ ํํฐ๋ง(|, ;, &์ ๋ธ๋๋ฆฌ์คํธ ์์)์ด ์๋ ๋ฌธ๋ฒ ํ์์ ๊ธฐ๋ฐํฉ๋๋ค.
์์๋๋ ๋ฌธ๋ฒ์ ๋๋ฉ์ธ ์ก์
[key=value ...]์
๋๋ค. ์ด ๊ตฌ์กฐ๋ฅผ ๋ฐ๋ฅด์ง ์๋ ๋ชจ๋ ๊ฒ์ ๊ฑฐ๋ถ๋ฉ๋๋ค. ๋ฐ์ดํ ์์ ํน์ ๋ฌธ์๋ ๊ตฌ๋ฌธ์ด ์๋ ์ธ์์ ๋ด์ฉ์ด๋ฏ๋ก ์ ํจํฉ๋๋ค.
std::process::Command๋ ์ค๊ฐ ์
ธ์ ๊ฑฐ์น์ง ์๊ณ ์ง์ ์คํํฉ๋๋ค. ๋ช
๋ น ์ธ์ ์
์ ๊ตฌ์กฐ์ ์ผ๋ก ๋ถ๊ฐ๋ฅํฉ๋๋ค.
AI ์์ด์ ํธ์ ๋ํ ๊ฒฐ์ ๋ก
์ด ๋์์ ๊ฒฐ์ ๋ก ์ ์ ๋๋ค: ์ฃผ์ด์ง ๋ช ๋ น์ ์ปจํ ์คํธ์ ๊ด๊ณ์์ด ํญ์ ๋์ผํ ๊ฒ์ฆ ๊ฒฐ๊ณผ๋ฅผ ์์ฑํฉ๋๋ค. ์ด๋ ๋ณธ์ง์ ์ผ๋ก ๋น๊ฒฐ์ ์ ์ธ AI ์์ด์ ํธ์ ์์ ํ ๋ ํ์์ ์ธ ์์ฑ์ ๋๋ค โ ๋ชจ๋ธ์ด ํธํฅ๋ ์ ์๊ฑฐ๋, ์์ด์ ํธ ์์ฐ ์ฒด์ธ์ด ์์๋์ด ์ถ๊ฐ ์ ๋ณด๋ฅผ ์์งํ๊ฑฐ๋ ๋น๋ฐ์ ์ ์ถํ๊ธฐ ์ํด ์ ธ์ ๋ ธ๋ฆด ์ ์์ต๋๋ค. SSH-Frontiรจre๋ฅผ ์ฌ์ฉํ๋ฉด, ์์๋ ์์ด์ ํธ๋ ํ์ดํธ๋ฆฌ์คํธ๋ฅผ ์ฐํํ ์ ์๊ณ , ์ ธ์ ๋ช ๋ น์ ์ฃผ์ ํ ์ ์์ผ๋ฉฐ, ๊ตฌ์ฑ๋์ง ์์ ๋ฆฌ์์ค์ ์ ๊ทผํ ์ ์์ต๋๋ค. ์ด๊ฒ์ ๊ตฌ์กฐ์ ์ผ๋ก ๋ถ๊ฐ๋ฅํฉ๋๋ค.
๊ตฌํ๋ ๊ธฐ๋ฅ
Rust ์ธ์ด
SSH-Frontiรจre๋ Rust๋ก ์์ฑ๋์ด ์์คํ ํ๋ก๊ทธ๋จ์์ ๊ฐ์ฅ ํํ ์ทจ์ฝ์ ๋ถ๋ฅ๋ฅผ ์ ๊ฑฐํฉ๋๋ค:
- ๋ฒํผ ์ค๋ฒํ๋ก ์์
- Use-after-free ์์
- ๋ ํฌ์ธํฐ ์ญ์ฐธ์กฐ ์์
- ์ฝ๋์
unsafe์์ (Cargo.toml์ lint ์ค์ ์์unsafe_code = "deny"๋ก ๊ธ์ง)
399๊ฐ์ cargo ํ ์คํธ + 72๊ฐ์ E2E SSH ์๋๋ฆฌ์ค
ํ๋ก์ ํธ๋ 399๊ฐ์ cargo ํ ์คํธ์ 72๊ฐ์ ์ถ๊ฐ E2E SSH ์๋๋ฆฌ์ค๋ก ์ปค๋ฒ๋ฉ๋๋ค:
| ์ ํ | ์๋ | ์ค๋ช |
|---|---|---|
| ๋จ์ ํ ์คํธ | ~340 | ๊ฐ ๋ชจ๋์ ๋
๋ฆฝ์ ์ผ๋ก ํ
์คํธ (10๊ฐ์ *_tests.rs ํ์ผ) |
| ํตํฉ ํ ์คํธ | 50 | ์์ ํ stdio ์๋๋ฆฌ์ค (๋ฐ์ด๋๋ฆฌ ์คํ) |
| ์ ํฉ์ฑ ํ ์คํธ | 1 (6๊ฐ ์๋๋ฆฌ์ค) | JSON ์ธํฐํ์ด์ค ๊ณ์ฝ ๊ฒ์ฆ (ADR 0003) |
| proptest ํ ์คํธ | 8 | ์์ฑ ํ ์คํธ (์ ์ฝ ๊ธฐ๋ฐ ํผ์ง) |
| cargo ํฉ๊ณ | 399 | |
| E2E SSH ์๋๋ฆฌ์ค | 72 | ์ค์ SSH ์๋ฒ๊ฐ ์๋ Docker Compose ํ๊ฒฝ |
| cargo-fuzz harness | 9 | ๋น์ ์ฝ ํผ์ง (๋ฌด์์ ๋ณ์ด) |
E2E SSH ํ ์คํธ๋ ์์ ํ ํ๋กํ ์ฝ, ์ธ์ฆ, ์ธ์ , ๋ณด์, ๊ฒฌ๊ณ ์ฑ ๋ฐ ๋ก๊น ์ ์ปค๋ฒํฉ๋๋ค. ์ค์ SSH ์๋ฒ๊ฐ ์๋ Docker Compose ํ๊ฒฝ์์ ์คํ๋ฉ๋๋ค.
์์กด์ฑ ๊ฐ์ฌ
- CI์์
cargo deny์คํ: ๋ผ์ด์ ์ค ๋ฐ ์๋ ค์ง ์ทจ์ฝ์ ํ์ธ (RustSec ๋ฐ์ดํฐ๋ฒ ์ด์ค) cargo audit: ์์กด์ฑ ๋ณด์ ๊ฐ์ฌ- pedantic ๋ชจ๋์
cargo clippy: ๊ฒฝ๊ณ 0๊ฐ ํ์ฉ - ์ง์ ์์กด์ฑ 3๊ฐ๋ง:
serde,serde_json,tomlโ ๋ชจ๋ Rust ์ปค๋ฎค๋ํฐ์์ ๋๋ฆฌ ๊ฐ์ฌ๋ ํฌ๋ ์ดํธ
RBAC ์ ๊ทผ ์ ์ด
์ธ ๊ฐ์ง ๊ณ์ธต์ ์ ๋ขฐ ์์ค:
| ์์ค | ์ฉ๋ | ์์ |
|---|---|---|
read | ์กฐํ ์ ์ฉ | healthcheck, status, list |
ops | ์ผ๋ฐ ์ด์ | backup, deploy, restart |
admin | ๋ชจ๋ ์ก์ | ๊ตฌ์ฑ, ๋ฏผ๊ฐํ ๋ฐ์ดํฐ |
๊ฐ ์ก์
์๋ ํ์ํ ์์ค์ด ์์ต๋๋ค. ๊ฐ SSH ์ฐ๊ฒฐ์๋ ์ ํจ ์์ค์ด ์์ต๋๋ค(authorized_keys์ --level ๋๋ ํ ํฐ ์ธ์ฆ์ ํตํด).
๊ฐ์์ฑ ํ๊ทธ
์์ง์ RBAC์ ๋ํด, ํ๊ทธ๋ก ์ํ์ ํํฐ๋ง์ด ๊ฐ๋ฅํฉ๋๋ค: forgejo ํ๊ทธ๊ฐ ์๋ ํ ํฐ์ ops ์์ค์ด์ด๋ forgejo ํ๊ทธ๊ฐ ๋ฌ๋ฆฐ ์ก์
๋ง ๋ณผ ์ ์์ต๋๋ค.
ํ ํฐ ์ธ์ฆ
๋ ๊ฐ์ง ์ธ์ฆ ๋ชจ๋:
- ๋จ์ ๋ชจ๋ (
challenge_nonce = false): ์ฑ๋ฆฐ์ง-์๋ตSHA-256(secret)โ ํด๋ผ์ด์ธํธ๊ฐ ๋น๋ฐ์ ์๊ณ ์์์ ์ฆ๋ช - ๋
ผ์ค ๋ชจ๋ (
challenge_nonce = true): ์๋ฒ๊ฐ ๋ณด๋ธ ๋ ผ์ค๋ฅผ ์ฌ์ฉํ ์ฑ๋ฆฐ์ง-์๋ตSHA-256(XOR_encrypt(secret || nonce, secret)). ๋ ผ์ค๋ ์ธ์ฆ ์ฑ๊ณต ํ ์ฌ์์ฑ๋์ด ๊ฐ๋ก์ฑ proof์ ์ฌ์ฌ์ฉ์ ๋ฐฉ์ง
์ถ๊ฐ ๋ณดํธ
- ํ๋ก์ธ์ค ๊ทธ๋ฃน kill์ ํตํ ๋ช ๋ น๋ณ ํ์์์ (SIGTERM ํ SIGKILL)
- Nํ ์ธ์ฆ ์คํจ ํ ์ ๊ธ (๊ตฌ์ฑ ๊ฐ๋ฅ, ๊ธฐ๋ณธ๊ฐ: 3)
- ๊ตฌ์ฑ ๊ฐ๋ฅํ ์ธ๋ถ ๋ช ๋ น์ ํตํ ์ ํ์ IP ์ฐจ๋จ
- ๋ก๊ทธ์์ ๋ฏผ๊ฐํ ์ธ์์ ๋ง์คํน (SHA-256)
- ์บก์ฒ๋ ์ถ๋ ฅ์ ํฌ๊ธฐ ์ ํ (stdout, stderr)
- ํ๊ฒฝ ์ ๋ฆฌ: ์์ ํ๋ก์ธ์ค์
env_clear(),PATH์SSH_FRONTIERE_SESSION๋ง ์ฃผ์
๋ณด์ฅ๋์ง ์๋ ์ฌํญ
์๋ฒฝํ ์ํํธ์จ์ด๋ ์์ต๋๋ค. ์๋ ค์ง ๋ฌธ์ํ๋ ์ ํ ์ฌํญ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
8๋นํธ XOR ์นด์ดํฐ
์ํธํ ๊ตฌํ์ 8192๋ฐ์ดํธ๋ก ์ ํ๋ ํค์คํธ๋ฆผ์ ๊ฐ์ง XOR ์นด์ดํฐ๋ฅผ ์ฌ์ฉํฉ๋๋ค. ํ์ฌ ์ฉ๋(64์์ SHA-256 proof)์๋ ์ถฉ๋ถํ์ง๋ง, ๋์ฉ๋ ๋ฐ์ดํฐ ์ํธํ๋ฅผ ์ํด ์ค๊ณ๋ ๊ฒ์ด ์๋๋๋ค.
๋น๊ต ์ ๊ธธ์ด ์ ์ถ
์์ ์๊ฐ ๋น๊ต์์ ๋น๊ต๋๋ ๊ฐ์ ๊ธธ์ด๊ฐ ๋ ธ์ถ๋ ์ ์์ต๋๋ค. ์ค์ ๋ก SHA-256 proof๋ ํญ์ 64์์ด๋ฏ๋ก, ์ด ์ ์ถ์ ๋ฌด์ํ ์ ์์ต๋๋ค.
์ฐ๊ฒฐ๋ณ ์๋ ์ ํ
์ธ์ฆ ์๋ ์นด์ดํฐ๋ ๊ฐ SSH ์ฐ๊ฒฐ์ ๋ก์ปฌ์
๋๋ค. ๊ณต๊ฒฉ์๊ฐ N๊ฐ์ ์ฐ๊ฒฐ์ ์ด๋ฉด N x max_auth_failuresํ์ ์๋๊ฐ ๊ฐ๋ฅํฉ๋๋ค. ๊ถ์ฅ ์ฌํญ: fail2ban, sshd MaxAuthTries, ๋๋ iptables ๊ท์น๊ณผ ํจ๊ป ์ฌ์ฉํ์ธ์.
์ทจ์ฝ์ ์ ๊ณ
๊ณต๊ฐ ์ด์๋ฅผ ํตํด ์ทจ์ฝ์ ์ ์ ๊ณ ํ์ง ๋ง์ธ์. ์ฑ ์ ์๋ ๊ณต๊ฐ๋ฅผ ์ํด ๋ฉ์ธํ ์ด๋์๊ฒ ์ง์ ์ฐ๋ฝํ์ธ์. ์ ์ฐจ๋ ๊ธฐ์ฌ ๊ฐ์ด๋์ ์ค๋ช ๋์ด ์์ต๋๋ค.
์์กด์ฑ
SSH-Frontiรจre๋ ์ต์ ์์กด์ฑ์ ๋ํ ์๊ฒฉํ ์ ์ฑ ์ ๊ฐ์ง๊ณ ์์ต๋๋ค. ๊ฐ ์ธ๋ถ ํฌ๋ ์ดํธ๋ ๊ฐ์ค ๋งคํธ๋ฆญ์ค(๋ผ์ด์ ์ค, ๊ฑฐ๋ฒ๋์ค, ์ปค๋ฎค๋ํฐ, ํฌ๊ธฐ, ์ ์ด ์์กด์ฑ)๋ก ํ๊ฐ๋ฉ๋๋ค.
| ํฌ๋ ์ดํธ | ๋ฒ์ | ์ฉ๋ | ์ ๋นํ |
|---|---|---|---|
serde | 1.x | ์ง๋ ฌํ/์ญ์ง๋ ฌํ | Rust์ ์ฌ์ค์ ํ์ค, JSON ๋ฐ TOML์ ํ์ |
serde_json | 1.x | JSON ์๋ต | ํ๋กํ ์ฝ ์ถ๋ ฅ ํ์ |
toml | 0.8.x | ๊ตฌ์ฑ ๋ก๋ | ๊ตฌ์ฑ์ ์ํ Rust ํ์ค ํ์ |
๊ฐ๋ฐ ์์กด์ฑ: proptest (์์ฑ ํ
์คํธ ์ ์ฉ, ์ต์ข
๋ฐ์ด๋๋ฆฌ์ ํฌํจ๋์ง ์์).
ํ์ฉ๋ ์์ค: crates.io๋ง ๊ฐ๋ฅ. ์ธ๋ถ git ์ ์ฅ์ ์์. cargo deny๋ก ์ ์ฑ
๊ฒ์ฆ.