๋ณด์•ˆ

๋ณด์•ˆ

SSH-Frontiรจre๋Š” ๋ณด์•ˆ ์ปดํฌ๋„ŒํŠธ์ž…๋‹ˆ๋‹ค. ์ˆ˜์‹  SSH ์—ฐ๊ฒฐ์ด ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ์ž‘์—…์„ ์ œํ•œํ•˜๋Š” ๊ฒƒ์ด ์กด์žฌ ์ด์œ ์ž…๋‹ˆ๋‹ค. ์ด ํŽ˜์ด์ง€๋Š” ๋ณด์•ˆ ๋ชจ๋ธ, ๊ตฌํ˜„๋œ ๊ธฐ๋Šฅ, ๊ทธ๋ฆฌ๊ณ  ๋ณด์žฅ๋˜์ง€ ์•Š๋Š” ์‚ฌํ•ญ์„ ๋ฌธ์„œํ™”ํ•ฉ๋‹ˆ๋‹ค.

๋ณด์•ˆ ๋ชจ๋ธ

๊ธฐ๋ณธ ์›์น™: deny by default

๋ช…์‹œ์ ์œผ๋กœ ๊ตฌ์„ฑ๋˜์ง€ ์•Š์œผ๋ฉด ์•„๋ฌด๊ฒƒ๋„ ์‹คํ–‰๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ช…๋ น์ด TOML ํ™”์ดํŠธ๋ฆฌ์ŠคํŠธ์— ์—†์œผ๋ฉด ๊ฑฐ๋ถ€๋ฉ๋‹ˆ๋‹ค. ํ—ˆ์šฉ ๋ชจ๋“œ๋„ ์—†๊ณ , ์…ธ๋กœ์˜ ํด๋ฐฑ๋„ ์—†์Šต๋‹ˆ๋‹ค.

์‹ฌ์ธต ๋ฐฉ์–ด์˜ ์„ธ ๊ณ„์ธต

๊ณ„์ธต๋ฉ”์ปค๋‹ˆ์ฆ˜๋ณดํ˜ธ
1authorized_keys์˜ command= + restrict์ ‘๊ทผ ์ˆ˜์ค€ ๊ฐ•์ œ, ํฌ์›Œ๋”ฉ/PTY ์ฐจ๋‹จ
2SSH-Frontiรจre (๋กœ๊ทธ์ธ ์…ธ)TOML ํ™”์ดํŠธ๋ฆฌ์ŠคํŠธ์— ๋Œ€ํ•ด ๋ช…๋ น ๊ฒ€์ฆ
3sudoers์˜ 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๋กœ ์ž‘์„ฑ๋˜์–ด ์‹œ์Šคํ…œ ํ”„๋กœ๊ทธ๋žจ์—์„œ ๊ฐ€์žฅ ํ”ํ•œ ์ทจ์•ฝ์  ๋ถ„๋ฅ˜๋ฅผ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค:

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 harness9๋น„์ œ์•ฝ ํผ์ง• (๋ฌด์ž‘์œ„ ๋ณ€์ด)

E2E SSH ํ…Œ์ŠคํŠธ๋Š” ์™„์ „ํ•œ ํ”„๋กœํ† ์ฝœ, ์ธ์ฆ, ์„ธ์…˜, ๋ณด์•ˆ, ๊ฒฌ๊ณ ์„ฑ ๋ฐ ๋กœ๊น…์„ ์ปค๋ฒ„ํ•ฉ๋‹ˆ๋‹ค. ์‹ค์ œ SSH ์„œ๋ฒ„๊ฐ€ ์žˆ๋Š” Docker Compose ํ™˜๊ฒฝ์—์„œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

์˜์กด์„ฑ ๊ฐ์‚ฌ

RBAC ์ ‘๊ทผ ์ œ์–ด

์„ธ ๊ฐ€์ง€ ๊ณ„์ธต์  ์‹ ๋ขฐ ์ˆ˜์ค€:

์ˆ˜์ค€์šฉ๋„์˜ˆ์‹œ
read์กฐํšŒ ์ „์šฉhealthcheck, status, list
ops์ผ๋ฐ˜ ์šด์˜backup, deploy, restart
admin๋ชจ๋“  ์•ก์…˜๊ตฌ์„ฑ, ๋ฏผ๊ฐํ•œ ๋ฐ์ดํ„ฐ

๊ฐ ์•ก์…˜์—๋Š” ํ•„์š”ํ•œ ์ˆ˜์ค€์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ SSH ์—ฐ๊ฒฐ์—๋Š” ์œ ํšจ ์ˆ˜์ค€์ด ์žˆ์Šต๋‹ˆ๋‹ค(authorized_keys์˜ --level ๋˜๋Š” ํ† ํฐ ์ธ์ฆ์„ ํ†ตํ•ด).

๊ฐ€์‹œ์„ฑ ํƒœ๊ทธ

์ˆ˜์ง์  RBAC์— ๋”ํ•ด, ํƒœ๊ทธ๋กœ ์ˆ˜ํ‰์  ํ•„ํ„ฐ๋ง์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค: forgejo ํƒœ๊ทธ๊ฐ€ ์žˆ๋Š” ํ† ํฐ์€ ops ์ˆ˜์ค€์ด์–ด๋„ forgejo ํƒœ๊ทธ๊ฐ€ ๋‹ฌ๋ฆฐ ์•ก์…˜๋งŒ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ† ํฐ ์ธ์ฆ

๋‘ ๊ฐ€์ง€ ์ธ์ฆ ๋ชจ๋“œ:

์ถ”๊ฐ€ ๋ณดํ˜ธ

๋ณด์žฅ๋˜์ง€ ์•Š๋Š” ์‚ฌํ•ญ

์™„๋ฒฝํ•œ ์†Œํ”„ํŠธ์›จ์–ด๋Š” ์—†์Šต๋‹ˆ๋‹ค. ์•Œ๋ ค์ง„ ๋ฌธ์„œํ™”๋œ ์ œํ•œ ์‚ฌํ•ญ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

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๋Š” ์ตœ์†Œ ์˜์กด์„ฑ์— ๋Œ€ํ•œ ์—„๊ฒฉํ•œ ์ •์ฑ…์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ ์™ธ๋ถ€ ํฌ๋ ˆ์ดํŠธ๋Š” ๊ฐ€์ค‘ ๋งคํŠธ๋ฆญ์Šค(๋ผ์ด์„ ์Šค, ๊ฑฐ๋ฒ„๋„Œ์Šค, ์ปค๋ฎค๋‹ˆํ‹ฐ, ํฌ๊ธฐ, ์ „์ด ์˜์กด์„ฑ)๋กœ ํ‰๊ฐ€๋ฉ๋‹ˆ๋‹ค.

ํฌ๋ ˆ์ดํŠธ๋ฒ„์ „์šฉ๋„์ •๋‹นํ™”
serde1.x์ง๋ ฌํ™”/์—ญ์ง๋ ฌํ™”Rust์˜ ์‚ฌ์‹ค์ƒ ํ‘œ์ค€, JSON ๋ฐ TOML์— ํ•„์š”
serde_json1.xJSON ์‘๋‹ตํ”„๋กœํ† ์ฝœ ์ถœ๋ ฅ ํ˜•์‹
toml0.8.x๊ตฌ์„ฑ ๋กœ๋“œ๊ตฌ์„ฑ์„ ์œ„ํ•œ Rust ํ‘œ์ค€ ํ˜•์‹

๊ฐœ๋ฐœ ์˜์กด์„ฑ: proptest (์†์„ฑ ํ…Œ์ŠคํŠธ ์ „์šฉ, ์ตœ์ข… ๋ฐ”์ด๋„ˆ๋ฆฌ์— ํฌํ•จ๋˜์ง€ ์•Š์Œ).

ํ—ˆ์šฉ๋œ ์†Œ์Šค: crates.io๋งŒ ๊ฐ€๋Šฅ. ์™ธ๋ถ€ git ์ €์žฅ์†Œ ์—†์Œ. cargo deny๋กœ ์ •์ฑ… ๊ฒ€์ฆ.