์๋ฌธ
๊ธฐ์กด ์ ๊ทผ์ ์ด ์๋ฃจ์ ์ ๊ฐ์ฅ ํฐ ๋ฌธ์ ์ ์ ๋ฌด์์ผ๊น์? ๋๋ถ๋ถ์ ์๋ฃจ์ ์ ์ฌ์ฉ์ PC์ ๋ณ๋์ ์์ด์ ํธ๋ฅผ ์ค์นํ๊ณ , GUI ๊ธฐ๋ฐ์ ์ธํฐํ์ด์ค๋ฅผ ํตํด์๋ง ์๋ฒ์ ์ ์ํ ๊ฒ์ ์๊ตฌํฉ๋๋ค. ์ด๋ ๊ธฐ์กด CLI ํ๊ฒฝ์ ์ต์ํ ๊ฐ๋ฐ์์ ์์คํ ๊ด๋ฆฌ์๋ค์ ์ํฌํ๋ก์ฐ๋ฅผ ํฌ๊ฒ ๋ฐฉํดํฉ๋๋ค. ๋จ์ถํค์ ์คํฌ๋ฆฝํธ๋ฅผ ํ์ฉํ ํจ์จ์ ์ธ ์์ ๋ฐฉ์์ ํฌ๊ธฐํ๊ณ GUI ์์ด์ ํธ๋ฅผ ํตํ ์ ์๋ง์ ์ฌ์ฉํด์ผ ํ๋ค๋ฉด, ์ ๋ฌด ํจ์จ์ฑ์ด ํฌ๊ฒ ์ ํ๋ ์๋ฐ์ ์์ต๋๋ค.
QueryPie๋ ์ด๋ฌํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด 'Seamless SSH Connection'์ ๊ฐ๋ฐํ์ต๋๋ค. ์ด ์ ๊ทผ๋ฒ์ ๋ณด์์ฑ์ ์ ์งํ๋ฉด์๋ ์ฌ์ฉ์๋ค์ด ๊ธฐ์กด์ ์ฌ์ฉํ๋ SSH ์ํฌํ๋ก์ฐ๋ฅผ ๊ทธ๋๋ก ํ์ฉํ ์ ์๊ฒ ํด์ค๋๋ค. ๊ฐ๋จํ SSH ์ค์ ํ์ผ ์์ ๋ง์ผ๋ก ์ ๊ทผ์ ์ด๋ฅผ ์ ์ฉํ๋ฉด์ ๋์์ ์ต์ํ CLI ํ๊ฒฝ์ ์ ์งํ ์ ์๋ค๋ ์ ์ด ์ด ์๋ฃจ์ ์ ํต์ฌ์ ๋๋ค.
Host *.querypie.io
Port 22
ProxyCommand qpa ssh %r %h %p
์ ์ค์ ํ์๋ ๊ธฐ์กด์ SSH ์ฌ์ฉ ๋ฐฉ๋ฒ๊ณผ ๋์ผํ ๋ฐฉ๋ฒ์ผ๋ก ํ๊ฒ ์๋ฒ์ ์ ์ํ ์ ์์ต๋๋ค.
ssh ryan@test.querypie.io
Seamless SSH Connection ๋์ ๋ฐฉ์
Seamless SSH์ ๋์ ๋ฐฉ์์ ์ดํดํ๊ธฐ ์ํด์๋ SSH ProxyCommand์ ๋ํ ์ดํด๊ฐ ์ฐ์ ์ ์ผ๋ก ํ์ํฉ๋๋ค.
SSH ProxyCommand
ProxyCommand ๋ SSH ์ฐ๊ฒฐ ๊ณผ์ ์์ ์ค๊ฐ ๋จ๊ณ๋ก ๋ค๋ฅธ ์๋ฒ๋ฅผ ๊ฒฝ์ ํด ์ต์ข
๋ชฉ์ ์ง์ ๋ฐ์ดํฐ๋ฅผ ์ ์กํ๋ ๋ฐฉ์์
๋๋ค. ์ด ๊ธฐ๋ฅ์ SSH ํด๋ผ์ด์ธํธ ์ค์ ์์ ์ง์ ํ ์ ์์ผ๋ฉฐ, SSH ์ฐ๊ฒฐ์ด ProxyCommand์ ์ง์ ๋ ๋ช
๋ น์ ์คํํ์ฌ ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ํตํด ์ต์ข
๋ชฉ์ ์ง์ ํต์ ํฉ๋๋ค.
๋์ ๋ฐฉ์
-
์ฌ์ฉ์ ์คํ: ์ฌ์ฉ์๊ฐ SSH ํด๋ผ์ด์ธํธ๋ฅผ ํตํด ์๊ฒฉ ์๋ฒ์ ์ฐ๊ฒฐ์ ์๋ํฉ๋๋ค. ์ด ๋, SSH ํด๋ผ์ด์ธํธ ์ค์ ์
ProxyCommand๊ฐ ์ง์ ๋์ด ์๋ค๋ฉด, SSH ํด๋ผ์ด์ธํธ๋ ์ฐ์ProxyCommand์ ์ค์ ๋ ๋ช ๋ น์ ์คํํฉ๋๋ค. -
๋ฐ์ดํฐ ์คํธ๋ฆผ ์ฐ๊ฒฐ:
- stdin: SSH ํด๋ผ์ด์ธํธ๋
ProxyCommand๋ฅผ ์คํํ ๋, ํด๋น ๋ช ๋ น์ stdin์ ํตํด ๋ฐ์ดํฐ๋ฅผ ์ ์กํฉ๋๋ค. ์ด ๋ฐ์ดํฐ๋ ์ฌ์ฉ์๋ก๋ถํฐ ์ค๋ ๋ช ๋ น์ด๋ ํ์ผ ์ ์ก ์์ฒญ ๋ฑ์ด ๋ ์ ์์ต๋๋ค. - stdout: SSH ํด๋ผ์ด์ธํธ๋
ProxyCommand๋ฅผ ์คํํ ๋, ํด๋น ๋ช ๋ น์ stdin์ ํตํด ๋ฐ์ดํฐ๋ฅผ ์ ์กํฉ๋๋ค. ์ด ๋ฐ์ดํฐ๋ ์ฌ์ฉ์๋ก๋ถํฐ ์ค๋ ๋ช ๋ น์ด๋ ํ์ผ ์ ์ก ์์ฒญ ๋ฑ์ด ๋ ์ ์์ต๋๋ค.
- ์๋ฐฉํฅ ๋ฐ์ดํฐ ์ ์ก: ์ด ๊ณผ์ ์์,
ProxyCommand๋ stdin์ ํตํด ๋ฐ์ ๋ฐ์ดํฐ๋ฅผ ํ๊ฒ ์๋ฒ์ ์ ์กํ๊ณ , ์๋ฒ๋ก๋ถํฐ์ ์๋ต์ stdout์ ํตํด SSH ํด๋ผ์ด์ธํธ๋ก ๋ค์ ์ ์กํฉ๋๋ค. ๊ฒฐ๊ณผ์ ์ผ๋ก, SSH ํด๋ผ์ด์ธํธ์ ํ๊ฒ ์๋ฒ ์ฌ์ด์ ์๋ฐฉํฅ ํต์ ์ฑ๋์ด ๊ตฌ์ฑ๋ฉ๋๋ค.
ํน์๋ณ์
%rโ SSH ์ปค๋งจ๋์ ์์ฑ๋ ํ๊ฒ ์๋ฒ์ ์ฌ์ฉ์์ ๋๋ค.%hโ SSH ์ปค๋งจ๋์ ์์ฑ๋ ํ๊ฒ ์๋ฒ ์ฃผ์์ ๋๋ค.%pโ SSH ์ปค๋งจ๋์ ์์ฑ๋ ํ๊ฒ ์๋ฒ ํฌํธ ์ ๋๋ค. (์ต์ : -p, ๊ธฐ๋ณธ๊ฐ: 22)

QueryPie Agent - CLI ํ์ฅ
Seamless SSH Connection์์ ProxyCommand์ ์ฌ์ฉ๋๋ qpa๋ QueryPie Agent์ ์ฌ์ฉ์์ฉ ์์ด์ ํธ ํด๋ผ์ด์ธํธ์ CLI๋ฅผ ํ์ฅํ ๊ฒ์ผ๋ก QueryPie๋ฅผ ํตํด SSH ์ ์์ ํ ์ ์๋๋ก ํฉ๋๋ค. SSH ํด๋ผ์ด์ธํธ์ ์ฐ๊ฒฐ์ Agent๋ฅผ ํตํด ํฐ๋๋ง์ด ๋๋ฉฐ, ์ด๋ฅผ ํตํ ์ฌ์ฉ์ ์ธ์ฆ์ด ๊ฐ๋ฅํ๋๋ก ํฉ๋๋ค.
์ฐ๊ฒฐ ๊ตฌ์กฐ
SSH Client โ Agent CLI โ ARiSA Proxy Server โ Target Server

์ปดํฌ๋ํธ ์ ๋ฆฌ
| ์ปดํฌ๋ํธ | ์ค๋ช |
|---|---|
| SSH | OpenSSH ํด๋ผ์ด์ธํธ ์ ๋๋ค. |
Agent - CLI (qpa) | ProxyCommand ํตํด ์คํ๋๋ ์ ์ปค๋งจ๋์
๋๋ค. Agent์์ SubProcess ๋ผ๊ณ ํ๋ฉฐ MainProcess ๊ฐ ๋ฉ์์ง์ ์ํ IPC ํต์ ์ด ๊ตฌํ๋์ด ์์ต๋๋ค. |
| Agent - Main | ๋ก๊ทธ์ธ ๋ฐ ํฐ๋๋ง ๋ฑ UI ๋ก ์คํ๋๋ ์ฌ์ฉ์ ์์ด์ ํธ ์ ๋๋ค. |
| API | agentService.proto ์ ์์ฑ๋ ์๋น์ค๋ฅผ ๊ตฌํ & ์ ๊ณตํ๋ ์ปดํฌ๋ํธ์ ๋๋ค. |
| TargetServer | ๋ชฉ์ ์๋ฒ ์
๋๋ค. (e.g., test.querypie.com) |
ํ์ฉ ์์
Seamless SSH Connection ๊ธฐ๋ฅ์ ์ด์ฉํ๋ฉด ๊ธฐ์กด์ ์๋ฒ ๊ฐ๋ฐ์๋ค์ด ์ฌ์ฉํ๋ ๋ค์๊ณผ ๊ฐ์ ํ ํฌ๋๋ค์ ์ ๊ทผ์ ์ด ์๋ฃจ์ ์ด ์๋ ํ๊ฒฝ์์๋ ๋์ผํ๊ฒ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด, 1๋ฒ๋ถํฐ 10๋ฒ๊น์ง์ ํ ์คํธ ์๋ฒ์ ๋์ผํ๊ฒ ํน์ ์ค์ ์ ์ ์ฉํด์ผ ํ ๊ฒฝ์ฐ, ssh ์ ์๋ถํฐ ๋ช ๋ น์ด ์ํ๊น์ง์ ์ด๋ฅด๋ ์์ ์ ํ๋ ํ๋์ฉ ์ ๋ ฅํ์ฌ ์ฒ๋ฆฌํ๋ ๊ฒ์ ๋ฒ๊ฑฐ๋กญ์ต๋๋ค. ์ด ๊ฒฝ์ฐ ๋ค์๊ณผ ๊ฐ์ ๋ฐฉ๋ฒ์ ์ด์ฉํด์ ๋์ผ ๋ช ๋ น์ด๋ฅผ ์ฌ๋ฌ ์๋ฒ์ ์ํ๋๋๋ก ํ ์ ์์ต๋๋ค.
iTerm2์ ์ฌ๋ฌ ์ฐฝ์ผ๋ก ๋ถ๋ฆฌ ํ ๋์ ์ปค๋งจ๋ ์ ๋ ฅ
iTerm2์์ cmd + d ๋ฅผ ๋๋ฅด๋ฉด ์ฐฝ์ด ์ธ๋ก๋ก ๋ถํ ๋๊ณ , cmd + shift + d๋ฅผ ๋๋ฅด๋ฉด ์ฐฝ์ด ๊ฐ๋ก๋ก ๋ถํ ๋ฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ option + cmd + i๋ฅผ ์
๋ ฅํ๋ฉด ๋ถํ ๋ ๋ชจ๋ pane์ ๋์ผํ ๋ช
๋ น์ด๊ฐ ์
๋ ฅ๋๋๋ก ์ค์ ํ ์ ์์ต๋๋ค. ์ด๋ฐ ๊ธฐ๋ฅ์ ์ด์ฉํ์ฌ ์ฌ๋ฌ ์๋ฒ์ ์ ์ํ ๋ ์ต์ํ์ ์
๋ ฅ์ผ๋ก ๋น ๋ฅด๊ฒ ๋ช
๋ น์ด๋ฅผ ์
๋ ฅํ ์ ์์ต๋๋ค.

QueryPie์์ ์ ๊ณตํ๋ Seamless SSH Connection ๊ธฐ๋ฅ์ ์ด์ฉํ๋ฉด ๊ธฐ์กด์ ์ฌ์ฉํ๋ ์ด๋ฐ ๋ฐฉ๋ฒ๋ค๋ ์ฌ์ฉ์ฑ์ ๋ณํ ์์ด ๊ทธ๋๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.
์๋ฒ ๋ค์ค ์ ์์ ์ํ ์คํฌ๋ฆฝํธ ์์ฑ
iTerm2์ ํฐ๋ฏธ๋๋ก ์ฌ์ฉํ์ง ์๊ฑฐ๋ ํ๋ก๊ทธ๋จ ์์ฑ์ด ์ฉ์ดํ ๊ฒฝ์ฐ, ์ฌ๋ฌ ์๋ฒ์ ์ ์ํ๊ณ ๋ช ๋ น์ด๋ฅผ ์ํํ๋ ๊ณผ์ ์ ์คํฌ๋ฆฝํธ๋ก ์์ฑํด์ ์ํํ๊ธฐ๋ ํฉ๋๋ค.
#!/bin/bash
# ์๋ฒ ๋ฆฌ์คํธ
SERVERS=("test1.querypie.io" "test2.querypie.io" "test3.querypie.io" "test4.querypie.io")
# ์ฌ์ฉ์ ๊ณ์
USER="ryan"
# ์คํํ ๋ช
๋ น
COMMANDS=(
"echo 'TMOUT=300' >> ~/.bashrc"
"source ~/.bashrc"
)
# ์๋ฒ ์ ์ ๋ฐ ๋ช
๋ น ์คํ
for SERVER in "${SERVERS[@]}"; do
echo "Connecting to ${SERVER}..."
ssh "${USER}@${SERVER}" <<EOF
$(printf "%s\n" "${COMMANDS[@]}")
EOF
if [ $? -eq 0 ]; then
echo "Commands executed successfully on ${SERVER}"
else
echo "Failed to execute commands on ${SERVER}"
fi
done
test ์๋ฒ 1๋ฒ๋ถํฐ 4๋ฒ๊น์ง ์ ์ํด์ ํ์์์ ์ค์ ์ ๋ฐ๊พธ๋ ์คํฌ๋ฆฝํธ์ธ๋ฐ, ๋ชจ๋ ์๋ฒ์ interactive shell์ ๋์ ๋ช ๋ น์ ์ํํ ํ์์์ด ์คํฌ๋ฆฝํธ ํ๋ฒ๋ง ์คํํ๋ฉด ๋๋ฏ๋ก ๊ฐ๋จํ๊ฒ ์์ ์ ํ ์ ์์ต๋๋ค.
tmux ๋ค์ค ์ ์์ ์ด์ฉํ ์ฌ๋ฌ ์๋ฒ ๋์ ์ ์ํ๊ธฐ
tmux-cssh๋ผ๋ ์คํ์์ค๋ฅผ ์ด์ฉํ๋ฉด ์๋์ ๊ฐ์ ๋ช ๋ น์ด๋ฅผ ์ด์ฉํ์ฌ ์ฌ๋ฌ ์๋ฒ์ ๋์์ ์ ์ํ๋ ๊ฒ์ด ๊ฐ๋ฅํฉ๋๋ค.
tmux-cssh -ns -ss
'ssh -oProxyCommand='\''qpa ssh %r %h %p'\''
-oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null'
-u admin test{001..01}.querypie.io

๊ฒฐ๋ก

์ ๊ทผ์ ์ด ์๋ฃจ์ ์ ๋์ ์ ์กฐ์ง์ ๋ณด์์ ๊ฐํํ๋ ์ค์ํ ๋จ๊ณ์ด์ง๋ง, ์ฌ์ฉ์ ๊ฒฝํ์ ์ ํดํด์๋ ์ ๋ฉ๋๋ค. ๊ธฐ์กด GUI ๊ธฐ๋ฐ ์ ๊ทผ์ ์ด ์๋ฃจ์ ์ ๋ณด์์ ๊ฐํํ์ง๋ง, CLI ํ๊ฒฝ์์ ์์ ํ๋ ๊ฐ๋ฐ์์ ์์คํ ๊ด๋ฆฌ์๋ค์ ์์ฐ์ฑ์ ์ ํ์ํค๋ ๋ถ์์ฉ์ด ์์์ต๋๋ค.
QueryPie์ Seamless SSH Connection์ ๋ณด์์ฑ๊ณผ ํธ์์ฑ ๋ ๊ฐ์ง ๋ชฉํ๋ฅผ ๋ชจ๋ ๋ฌ์ฑํฉ๋๋ค. ๋ณด์ ์ ๊ทผ์ ์ด๋ฅผ ์ ์งํ๋ฉด์๋, ์ฌ์ฉ์๋ค์ด ์ต์ํ SSH ์ํฌํ๋ก์ฐ์ ๋๊ตฌ๋ค(iTerm2 ๋ค์ค ์ฐฝ, ์๋ํ ์คํฌ๋ฆฝํธ, tmux ๋ฑ)์ ๊ทธ๋๋ก ํ์ฉํ ์ ์๊ฒ ํด์ค๋๋ค. ๋จ์ํ ์ค์ ๋ณ๊ฒฝ๋ง์ผ๋ก ๊ธฐ์กด ์์ ๋ฐฉ์์ ์ ์งํ ์ ์๋ค๋ ๊ฒ์ ์กฐ์ง ์ ์ฒด์ ์์ฐ์ฑ ์ธก๋ฉด์์ ํฐ ์ด์ ์ ๋๋ค. ์ด๋ฐ ๋ฐฉ์์ผ๋ก QueryPie๋ ๋ณด์์ฑ๊ณผ ์ฌ์ฉ์ฑ ์ฌ์ด์ ๊ท ํ์ ์ฐพ์, ์ฌ์ฉ์๋ค์ด ์ ๊ทผ์ ์ด ์๋ฃจ์ ๋์ ์ผ๋ก ์ธํ ๋ถํธํจ ์์ด ํจ์จ์ ์ผ๋ก ์์ ํ ์ ์๋ ํ๊ฒฝ์ ์ ๊ณตํฉ๋๋ค.
