
AI 에이전트가 점프 호스트(Jump Host) 뒤에서도 작업할 수 있도록 SSH 세션 미들웨어를 구축했습니다
요약
AI 코딩 에이전트가 점프 호스트나 OTP 인증이 필요한 복잡한 서버 환경에서도 작업할 수 있도록 돕는 SSH 세션 미들웨어 'Shellink'를 소개합니다. 이 도구는 로컬 데몬과 CLI를 통해 인간과 에이전트 모두가 안정적으로 세션을 제어하고 파일을 전송할 수 있게 합니다.
핵심 포인트
- 점프 호스트 및 OTP 인증 환경에서도 AI 에이전트의 서버 접근 가능
- Shellink를 통한 SSH 및 로컬 PTY 세션 관리 미들웨어 구축
- SFTP 없이 기존 PTY를 활용한 효율적인 파일 전송 지원
- CLI, TUI, Web UI 및 API를 제공하여 다양한 인터페이스 지원
요즘 저는 AI 코딩 에이전트(AI coding agents)를 활용해 많은 작업을 수행합니다. 코드를 작성하고, 문서를 편집하고, 웹 페이지를 살펴보는 일 등 대부분의 작업은 에이전트가 처리할 수 있습니다. 하지만 에이전트가 지속적으로 한계를 보이는 지점은 바로 **서버(servers)**입니다.
제가 관리하는 대부분의 머신은 하나 이상의 배스천 호스트(bastion / jump hosts) 뒤에 위치하며, 메뉴 선택, OTP 프롬프트, 그리고 가끔은 레거시 로그인 흐름(legacy login flow)을 거쳐야 합니다. 에이전트는 단순히 ssh user@host 명령만으로 접속할 수 없기 때문에, 자동화가 경계 지점에서 끊겨버립니다. 디버깅은 더 최악입니다. 결국 제가 직접 로그인해서 로그를 노트북으로 복사한 뒤, 에이전트에 붙여넣고, 에이전트가 제안하는 단계들을 다시 서버로 돌아가 실행하는 과정을 반복하게 됩니다. 계속해서 말이죠.
그래서 저는 Shellink를 만들었습니다. 이는 SSH 및 로컬 PTY 세션을 관리하는 로컬 데몬(local daemon)이며, 그 위에 안정적인 하나의 CLI(더불어 TUI, Web UI, 그리고 HTTP/WebSocket API 제공)를 갖추고 있습니다. 핵심 아이디어는 인간과 에이전트 모두가 제어할 수 있는 "세션 미들웨어(session middleware)"를 만드는 것입니다.
Repo (MIT): https://github.com/jie123108/Shellink
다음은 에이전트가 Shellink CLI를 통해 완전히 점프 호스트를 거쳐 대상 서버에서 작업하는 모습입니다:

실제로 어떤 역할을 하는가
- SSH 및 커스텀 명령 세션 (SSH and custom command sessions). SSH를 통해 직접 연결하거나, PTY 내부에서 모든 명령/스크립트를 실행할 수 있습니다.
command프로필을 통한 멀티 홉 로그인 (Multi-hop login viacommandprofiles). Bastion 메뉴, OTP, 또는 다단계 홉(multi-level hops)의 경우,command타입 프로필을expect(또는sshpass, 또는ssh -J) 스크립트로 지정합니다. Shellink 자체가 대신 로그인해 주는 것은 아니며, 사용자가 로그인한 이후의 세션을 관리합니다.- SFTP가 아닌 기존 PTY를 통한 파일 전송 (File transfer over the existing PTY, not SFTP). 직접적인 SFTP/SCP 엔드포인트가 없는,
expect기반의 멀티 홉 로그인 환경에서도 업로드/다운로드가 계속 작동합니다. 이것이 제가 가장 필요했던 기능이었으며, "로그를 수동으로 복사해서 내려받는" 반복 작업을 없애주었습니다. - 실제 세션 상태 머신 (A real session state machine).
CONNECTING / OUTPUTTING / WAITING_INPUT / IDLE / DISCONNECTED상태가 기계가 읽을 수 있는 출력(machine-readable output)으로 제공됩니다. 따라서 에이전트는 긁어온 텍스트(scraped text)를 보고 추측하는 대신, 다음 명령을 실행할지, 입력을 보낼지, 기다릴지, 혹은 제어권을 넘길지를 결정할 수 있습니다. - AUTO vs MANUAL 모드. 에이전트는 AUTO 모드로 작동하며, 사람은 OTP 입력이나 민감한 작업이 필요할 때 터미널을 가져갔다가 다시 넘겨줄 수 있습니다. 세션 I/O는 감사(audit) 및 재생(replay)을 위해 히스토리로 유지됩니다.
- 에이전트 기술 (
shellink-cli). 에이전트는 SSH/점프 호스트 로직을 직접 재구현하는 대신, CLI(안정적인--json출력 제공)를 호출하기만 하면 됩니다.
CLI 맛보기
# 셸 히스토리에 자격 증명이 유출되지 않도록 프로필 생성
shellink profile create --input - --json <<'JSON'
{"name":"local-shell","connectType":"command","command":"/bin/sh"}
...
흥미로운 기술적 부분들
PTY를 통한 전송(transfer-over-PTY) 부분이 재미있으면서도 어려운 부분이었습니다. 두 개의 Bastion과 expect 스크립트를 거친 PTY가 서버로 가는 유일한 채널일 때는 SFTP를 사용할 수 없습니다. 따라서 전송 데이터는 동일한 터미널 스트림을 통해 인코딩되어 반대편에서 재조립됩니다. 이는 직접 연결된 SSH 서버와 3단계 홉을 거치는 레거시 서버 모두에서 정확히 동일한 코드 경로가 작동함을 의미합니다.
상태 머신 (State machine)은 들리는 것보다 훨씬 중요합니다. "명령이 완료됨"과 "셸이 입력을 기다리는 중" 사이의 차이가 에이전트가 단순히 '잠자며 희망하기 (sleep-and-hope)' 대신 실제로 행동할 수 있게 만듭니다. Shellink는 정적 기간 휴리스틱 (quiet-period heuristic)과 프롬프트 감지 (prompt detection)를 통해 상태를 도출하며, 이를 명시적으로 노출합니다.
스택: TypeScript, Node 22, Fastify, ssh2, node-pty, SQLite (better-sqlite3 + Drizzle), 네트워크 전송용 MessagePack + Zod, Web UI용 Vue 3 + xterm.js. macOS/Linux용 단일 파일 Bun 바이너리.
솔직한 한계점
- 로그인을 대신 해주지는 않습니다. 멀티 홉 (Multi-hop) / 메뉴 / OTP는 사용자의
expect(또는 ssh/sshpass) 스크립트 영역이며, Shellink는 그 이후에 발생하는 일을 관리합니다. command프로필은 데몬 (daemon) 사용자로 실행됩니다. 신뢰할 수 있는 명령만 실행하고,SHELLINK_TOKEN을 보호하세요.- 에이전트가 운영 환경 (production)에 접근하게 하는 것은 진정으로 위험합니다. 처음에는 읽기 전용/조사 작업이나 비운영 환경 (non-prod)에 먼저 적용할 것을 권장합니다.
- 아직 Windows는 지원하지 않습니다 (macOS/Linux 바이너리만 제공).
사용해보기
curl -fsSL https://raw.githubusercontent.com/jie123108/Shellink/main/install.sh -o /tmp/shellink-install.sh
cat /tmp/shellink-install.sh # 실행하기 전에 읽어보세요
sh /tmp/shellink-install.sh
...
피드백을 받고 싶은 부분
만약 Bastion 서버 뒤에서 작업하신다면: command + expect 방식이 실제 로그인 체인을 충분히 커버하나요, 아니면 기존 설정 중 이 방식이 통하지 않는 부분이 있나요? 그리고 에이전트를 연결해서 사용하신다면: CLI/--json 인터페이스가 충분한가요, 아니면 무엇이 더 필요한가요?
저장소 재공지: https://github.com/jie123108/Shellink — 이슈(Issues)와 PR(Pull Requests)을 환영합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기